我正在关注PeepCode的(现在稍微过时的)Meet Rails 3教程,并且无法获得与Rails 3.2一起使用的一些教程建议。
本教程让您创建属于Role
的<{1}}模型:
Project
routes.rb 文件会嵌套class Role < ActiveRecord::Base
belongs_to :project
validates :project_id, :presence => true
attr_protected :project_id
end
个资源,因此您必须在Role
的上下文中使用Role
:
Project
请注意,在上面的模型代码中,教程建议您使用resources :projects do
resources :roles
end
来保护attr_protected
字段,因为可以通过创建:project_id
中的每个Role
来“更安全地”设置它。项目的上下文,如 roles_controller.rb :
class RolesController < ApplicationController
⋮
def create
@role = project.roles.new(params[:role])
⋮
问题是,用Formtastic创建的用于创建Role
的HTML表单包含用于选择项目的project_id
字段。因此,当project.roles.new(params[:role])
尝试使用表单中的参数来填充新的Role
对象时,它会尝试使用质量分配设置project_id
,并失败并显示:
ActiveModel :: MassAssignmentSecurity :: RolesController中的错误#create
无法批量分配受保护的属性:project_id
实施此方法的可接受方式是什么?保护project_id
属性是个坏主意吗?或者是否有某种方法可以使用表单数据填充新Role
而不包括project_id
?
答案 0 :(得分:0)
如果您通过project
而不是params[:project_id]
获得params[:role][:project_id]
,那么无论如何您实际上都可以设置相互冲突的值。
Mass Assignment希望保护这一点的原因是为了防止用户输入project_id
的任意值,该值可能允许project
不受此用户控制。你有几个选择。
如果您在对象上附加了user
或account
,则可以添加before_save
回调,例如self.project_id = nil unless user.projects.find(project_id)
。
既然你没有,我会使用哈希中的project_id
来查找项目,然后回到路由ID(我不确定它是project_id
还是只是id
我的头顶。)
def create
user.
projects.
find(params[:role].delete(:project_id) || params[:project_id] || params[:id]).
create(params[:role])
最简单的方法是从表单中删除选择框,因为他们在选择创建新角色时选择了一个项目 - 它是一个嵌套资源。