Need help understanding this code, as what to my knowledge I know "<<" append to a collection but here it saves the record correctly, how come it does without calling .save method?
#user.rb
 has_many :saved_properties, through: :property_saves, source: :property
#users_controller.rb
def update
  if @user.saved_properties << Property.find(params[:saved_property_id])
        render plain: "Property saved"
end
                In the has_many documentation it says: 
Adds one or more objects to the collection by setting their foreign keys to the collection's primary key. Note that this operation instantly fires update SQL without waiting for the save or update call on the parent object, unless the parent object is a new record.
Maybe looking at the source code will help you. This is my trail of searches based on the << method in activerecord:
def <<(*records)
  proxy_association.concat(records) && self
end
rails/collection_proxy.rb at 5053d5251fb8c03e666f1f8b765464ec33e3066e · rails/rails · GitHub
def concat(*records)
  records = records.flatten
  if owner.new_record?
    load_target
    concat_records(records)
  else
    transaction { concat_records(records) }
  end
end
rails/collection_association.rb at 5053d5251fb8c03e666f1f8b765464ec33e3066e · rails/rails · GitHub
def concat_records(records, should_raise = false)
  result = true
  records.each do |record|
    raise_on_type_mismatch!(record)
    add_to_target(record) do |rec|
      result &&= insert_record(rec, true, should_raise) unless owner.new_record?
    end
  end
  result && records
end
rails/collection_association.rb at 5053d5251fb8c03e666f1f8b765464ec33e3066e · rails/rails · GitHub
  def insert_record(record, validate = true, raise = false)
    set_owner_attributes(record)
    set_inverse_instance(record)
    if raise
      record.save!(validate: validate)
    else
      record.save(validate: validate)
    end
  end
https://github.com/rails/rails/blob/5053d5251fb8c03e666f1f8b765464ec33e3066e/activerecord/lib/active_record/associations/has_many_association.rb#L32
  def insert_record(record, validate = true, raise = false)
    ensure_not_nested
    if record.new_record? || record.has_changes_to_save?
      if raise
        record.save!(validate: validate)
      else
        return unless record.save(validate: validate)
      end
    end
    save_through_record(record)
    record
  end
https://github.com/rails/rails/blob/5053d5251fb8c03e666f1f8b765464ec33e3066e/activerecord/lib/active_record/associations/has_many_through_association.rb#L38
As you can see, in the end, it does call the save method.
Disclaimer: I'm not that familiar with Rails souce code, but you have interesting question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With