Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 7826

Show
Ignore:
Timestamp:
10/10/07 19:11:50 (2 years ago)
Author:
xal
Message:

find_and_(initialize|create)_by methods can now properly initialize protected attributes

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/activerecord/CHANGELOG

    r7812 r7826  
    11*SVN* 
     2 
     3* find_and_(initialize|create)_by methods can now properly initialize protected attributes [Tobias Luetke] 
    24 
    35* belongs_to infers the foreign key from the association name instead of from the class name.  [Jeremy Kemper] 
  • trunk/activerecord/lib/active_record/base.rb

    r7802 r7826  
    12701270                end 
    12711271              end 
    1272             } 
     1272            }, __FILE__, __LINE__ 
    12731273            send(method_id, *arguments) 
    12741274          elsif match = /^find_or_(initialize|create)_by_([_a-zA-Z]\w*)$/.match(method_id.to_s) 
     
    12851285                  find_attributes = attributes = construct_attributes_from_arguments([:#{attribute_names.join(',:')}], args) 
    12861286                end 
    1287                  
     1287                                 
    12881288                options = { :conditions => find_attributes } 
    12891289                set_readonly_option!(options) 
    12901290 
    1291                 find_initial(options) || send(:#{instantiator}, attributes) 
     1291                record = find_initial(options) 
     1292                if record.nil? 
     1293                  record = self.new { |r| r.send(:attributes=, attributes, false) }  
     1294                  #{'record.save' if instantiator == :create} 
     1295                  record 
     1296                else 
     1297                  record                 
     1298                end 
    12921299              end 
    1293             } 
     1300            }, __FILE__, __LINE__ 
    12941301            send(method_id, *arguments) 
    12951302          else 
     
    18421849      # from this form of mass-assignment by using the +attr_protected+ macro. Or you can alternatively 
    18431850      # specify which attributes *can* be accessed in with the +attr_accessible+ macro. Then all the 
    1844       # attributes not included in that won't be allowed to be mass-assigned. 
    1845       def attributes=(new_attributes
     1851      # attributes not included in that won't be allowed to be mass-assigned.  
     1852      def attributes=(new_attributes, guard_protected_attributes = true
    18461853        return if new_attributes.nil? 
    18471854        attributes = new_attributes.dup 
     
    18491856 
    18501857        multi_parameter_attributes = [] 
    1851         remove_attributes_protected_from_mass_assignment(attributes).each do |k, v| 
     1858        attributes = remove_attributes_protected_from_mass_assignment(attributes) if guard_protected_attributes 
     1859         
     1860        attributes.each do |k, v| 
    18521861          k.include?("(") ? multi_parameter_attributes << [ k, v ] : send(k + "=", v) 
    18531862        end 
  • trunk/activerecord/test/finder_test.rb

    r7510 r7826  
    470470    assert sig38.new_record? 
    471471  end 
     472   
     473  def test_find_or_initialize_from_one_attribute_should_set_attribute_even_when_protected 
     474    c = Company.find_or_initialize_by_name_and_rating("Fortune 1000", 1000) 
     475    assert_equal "Fortune 1000", c.name 
     476    assert_equal 1000, c.rating 
     477    assert c.valid? 
     478    assert c.new_record?     
     479  end 
     480 
     481  def test_find_or_create_from_one_attribute_should_set_attribute_even_when_protected 
     482    c = Company.find_or_create_by_name_and_rating("Fortune 1000", 1000) 
     483    assert_equal "Fortune 1000", c.name 
     484    assert_equal 1000, c.rating 
     485    assert c.valid? 
     486    assert !c.new_record?     
     487  end 
    472488 
    473489  def test_dynamic_find_or_initialize_from_one_attribute_caches_method 
  • trunk/activerecord/test/fixtures/computer.rb

    r388 r7826  
    22  belongs_to :developer, :foreign_key=>'developer' 
    33end 
     4