Rails 预览更新关联而不保存到数据库
Rails preview update associations without saving to database
我想预览保存时模型的外观,但当前未保存到数据库。
我正在使用 @event.attributes =
,因为它会将 @event
的属性分配但不会保存到数据库。
但是,当我也尝试分配 audiences
关联时,Rails 将新记录插入 audiences_events
连接 table。不酷。有没有办法在不插入连接的情况下预览这些新关联的外观 table?
型号
class Event < ActiveRecord::Base
has_and_belongs_to_many :audiences # And vice versa for the Audience model.
end
控制器
class EventsController < ApplicationController
def preview
@event = Event.find(params[:id])
@event.attributes = event_params
end
private
def event_params
params[:event].permit(:name, :start_time, :audiences => [:id, :name]
end
end
可能的解决方案?
我想到但不知道怎么做的可能解决方案:
- 使用某种分配关联但不持久化关联的方法。
- 为此操作禁用所有数据库写入(我不知道该怎么做)。
- 在此操作结束时回滚所有数据库更改
任何有关这些的帮助都会很棒!
更新:
阅读下面的精彩答案后,我最终编写了此服务 class,它将非嵌套属性分配给事件模型,然后在每个嵌套参数上调用 collection.build。我做了一个小要点。很高兴收到 comments/suggestions.
在这些docs中你有:
When are Objects Saved?
When you assign an object to a has_and_belongs_to_many association, that object is automatically saved (in order to update the join table). If you assign multiple objects in one statement, then they are all saved.
If you want to assign an object to a has_and_belongs_to_many association without saving the object, use the collection.build
method.
这是 Rails 3 的一个很好的答案,它解决了一些相同的问题
Rails 3 has_and_belongs_to_many association: how to assign related objects without saving them to the database
交易
创建 transactions 非常简单:
Event.transaction do
@event.audiences.create!
@event.audiences.first.destroy!
end
或
@event.transaction do
@event.audiences.create!
@event.audiences.first.destroy!
end
注意 "bang" 方法 create!
和 destroy!
的使用,与 create
不同 returns false create!
会引发异常如果失败导致事务回滚。
您还可以通过引发 ActiveRecord::Rollback
在事务中的任何位置手动触发回滚。
建造
build
实例化一个新的相关对象而不保存。
event = Event.new(name: 'Party').audiences.build(name: 'Party People')
event.save # saves both event and audiences
我知道这是一个很老的问题,但我找到了一个非常适合我的解决方案,希望它能为其他人节省时间:
class A
has_many :bs, class_name 'B'
end
class B
belongs_to :a, class_name: 'A'
end
a.bs.target.clear
new_bs.each {|new_b| a.bs.build new_b.attributes.except('created_at', 'updated_at', 'id') }
您将避免 Rails 在您执行 a.bs = new_bs
时执行的自动保存
我想预览保存时模型的外观,但当前未保存到数据库。
我正在使用 @event.attributes =
,因为它会将 @event
的属性分配但不会保存到数据库。
但是,当我也尝试分配 audiences
关联时,Rails 将新记录插入 audiences_events
连接 table。不酷。有没有办法在不插入连接的情况下预览这些新关联的外观 table?
型号
class Event < ActiveRecord::Base
has_and_belongs_to_many :audiences # And vice versa for the Audience model.
end
控制器
class EventsController < ApplicationController
def preview
@event = Event.find(params[:id])
@event.attributes = event_params
end
private
def event_params
params[:event].permit(:name, :start_time, :audiences => [:id, :name]
end
end
可能的解决方案?
我想到但不知道怎么做的可能解决方案:
- 使用某种分配关联但不持久化关联的方法。
- 为此操作禁用所有数据库写入(我不知道该怎么做)。
- 在此操作结束时回滚所有数据库更改
任何有关这些的帮助都会很棒!
更新:
阅读下面的精彩答案后,我最终编写了此服务 class,它将非嵌套属性分配给事件模型,然后在每个嵌套参数上调用 collection.build。我做了一个小要点。很高兴收到 comments/suggestions.
在这些docs中你有:
When are Objects Saved?
When you assign an object to a has_and_belongs_to_many association, that object is automatically saved (in order to update the join table). If you assign multiple objects in one statement, then they are all saved.
If you want to assign an object to a has_and_belongs_to_many association without saving the object, use the
collection.build
method.
这是 Rails 3 的一个很好的答案,它解决了一些相同的问题
Rails 3 has_and_belongs_to_many association: how to assign related objects without saving them to the database
交易
创建 transactions 非常简单:
Event.transaction do
@event.audiences.create!
@event.audiences.first.destroy!
end
或
@event.transaction do
@event.audiences.create!
@event.audiences.first.destroy!
end
注意 "bang" 方法 create!
和 destroy!
的使用,与 create
不同 returns false create!
会引发异常如果失败导致事务回滚。
您还可以通过引发 ActiveRecord::Rollback
在事务中的任何位置手动触发回滚。
建造
build
实例化一个新的相关对象而不保存。
event = Event.new(name: 'Party').audiences.build(name: 'Party People')
event.save # saves both event and audiences
我知道这是一个很老的问题,但我找到了一个非常适合我的解决方案,希望它能为其他人节省时间:
class A
has_many :bs, class_name 'B'
end
class B
belongs_to :a, class_name: 'A'
end
a.bs.target.clear
new_bs.each {|new_b| a.bs.build new_b.attributes.except('created_at', 'updated_at', 'id') }
您将避免 Rails 在您执行 a.bs = new_bs