需要帮助理解这段代码,据我所知,我知道"<<"附加到集合但是这里它正确地保存了记录,如果没有调用.save方法怎么办呢?
#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
答案 0 :(得分:7)
在has_many
documentation中说:
通过设置外部对象,将一个或多个对象添加到集合中 集合主键的键。注意这个操作 立即触发更新SQL而无需等待保存或更新 调用父对象,除非父对象是新记录。
答案 1 :(得分:7)
也许查看源代码会对你有所帮助。这是我基于function navigate(e) {
var grid = e.sender;
grid.select(grid.tbody.find(e.element.parent()));
}
中的<<
方法的搜索记录:
activerecord
rails/collection_proxy.rb at 5053d5251fb8c03e666f1f8b765464ec33e3066e · rails/rails · GitHub
def <<(*records)
proxy_association.concat(records) && self
end
rails/collection_association.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
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
正如您所看到的,最终它会调用 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
方法。
免责声明:我对Rails的源代码并不熟悉,但你有一个有趣的问题。
答案 2 :(得分:2)
在has_many
关系中,链接信息保存在目标记录中。这意味着<<
必须修改该记录才能将其添加到集合中。
如果作业很方便,ActiveRecord会在作业完成时自动为您保存这些内容。例外情况是新记录,它们所关联的记录没有任何标识符,因此必须延迟。当最终创建与它们关联的记录时,它们将被保存。
这可能有点令人困惑,也许是意料之外的,但它实际上是99%的时间你想要发生的事情。如果您不希望这种情况发生,您应该手动操作链接:
property = Property.find(params[:saved_property_id])
property.user = @user
property.save!
这基本上相当,但更冗长。