How to use new_record?, changed? and persisted? methods in rails in this example

11,234

Solution 1

You can try first_or_initialize along with assign_attributes

new_data.each do |c|
 car =  Cars.where(:brand => c[:brand]).first_or_initialize
 new_records +=1 if car.new_record?
 car.save # first save the initialized AR
 car.assign_attributes(c)
 changed_records +=1 if car.changed?
 car.save
end

Solution 2

I might not answer your question directly but I will try explain the Activerecord lifecyle methods.

new_record?

car = Car.new # => initialize a new Car object
car.new_record? # => true

persisted?

car.save
car.persisted? # => true

changed?

car.model = 'New release model S'
car.changed? # => true

destroyed?

car.destroy
car.destroyed? # => true
Share:
11,234
Admin
Author by

Admin

Updated on June 09, 2022

Comments

  • Admin
    Admin almost 2 years

    Trying to undestand new record?,changed ? and persisted ? on the example below.

    How, this code has this result:

     # NOW
     # there is 0 new record after running new_data array
     # there is 0 changed record(s) after running new_data array
     # there is 3 persisted record(s) after running new_data array
    

    Trying to come to this result:

    # WANT
    #there is 1 new record(s) after running new_data array
    #there is 1 changed record(s) after running new_data array
    #there is 2 persisted record(s) after running new_data array
    

    *Question is: *

    How to do it?. Want to record the number of changed and new records.

    Cars.delete_all
    
    original_data = [
        {:brand => 'Mercedes', :used => false, :year => 2000 },
        {:brand => 'Honda',    :used => true , :year => 2000 },
        {:brand => 'Nissan',   :used => false, :year => 2000 }
    ]
    
    new_data = [
        # updating year to 2013
        {:brand => 'Mercedes', :used => false, :year => 2013 },
        # new record
        {:brand => 'Tesla', :used => false, :year => 2013  },
        # same data
        {:brand => 'Nissan', :used => false, :year => 2000 }
    ]
    
    
    # create new cars
    original_data.each do |c|
      Cars.create(c)
    end
    
    # updates
    persisted =   0
    new_records = 0
    changed_records = 0
    new_data.each do |c|
     car =  Cars.where(:brand => c[:brand]).first_or_create
     persisted   +=1 if car.persisted?
     new_records +=1 if car.new_record?
     changed_records +=1 if car.changed?
    end
    
    puts "there is #{new_records} new record(s) after running new_data array"
    puts "there is #{changed_records} changed record(s) after running new_data array"
    puts "there is #{persisted} persisted record(s) after running new_data array"
    

    *UPDATE*

    code according to answer: - attempt to change only 1 record, not 2.

    # updates
    persisted =   0
    new_records = 0
    changed_records = 0
    new_data.each do |c|
     car =  Cars.where(:brand => c[:brand]).first_or_initialize
     car.assign_attributes(c)
     persisted   +=1 if car.persisted?
     new_records +=1 if car.new_record?
     changed_records +=1 if car.changed?
     car.save
    end
    
    there is 1 new record(s) after running new_data array
    there is 2 changed record(s) after running new_data array
    there is 2 persisted record(s) after running new_data array
    
  • NBSamar
    NBSamar over 2 years
    Car.new_record?, here we need to check for Car's instance, which is stored in car variable here. So, the correct way would be car.new_record?
  • Kaka Ruto
    Kaka Ruto over 2 years
    You were right @NBSamar. Updated!