在Rails中分配受保护的属性

时间:2012-06-12 01:27:37

标签: ruby-on-rails mass-assignment attr-accessible attr-protected

我的用户模型上有一个受保护的字段,因为它确定了清除级别。因此它应该保留,而不是可分配的。因此,即使属性在3.2中默认受到保护,这实际上也是我想要的行为。

但是,在一个控制器方法中,我想允许管理员分配此字段,例如用户创建或用户更新。

如何为特定控制器操作分配该属性?

例如,我有我的控制器:

# app/controllers/admin/users_controller.rb

def create
    @user = User.new(params[:user])
# ...
end

现在我要做的就是从clearance中排除params[:user],但它似乎会在达到该行之前被过滤掉并引发异常(我尝试将debugger置于右侧在该行之前甚至将其评论出来,它仍然引发了异常)。

保护属性在何处被捕获,如果不是,则在调用User#new

2 个答案:

答案 0 :(得分:4)

The Rails way这样做是为了在没有保护的情况下分配属性或使用管理员角色:

@user = User.new
@user.assign_attributes(params[:user], :without_protection => true)
@user.save

然而,我发现这有点单调乏味,所以我写了一个名为sudo_attributes的宝石,它给我(在我看来)一个更好的API:

@user = User.sudo_new(params[:user])
@user.save

它模仿所有Rails实例化,创建和更新方法(new,build,create,create!,update_attributes等)。

答案 1 :(得分:0)

在过去,我倾向于给这种操作提供自己包含的方法,只设置这个值:

# app/controllers/admin/users_controller.rb

def full_clearance
  User.find(params[:id]).update_attribute(:clearance, 'full')
end

def restricted_clearance
  User.find(params[:id]).update_attribute(:clearance, 'restricted')
end

现在看一下提到的the Rails way Beerlington,我宁愿使用角色,让特定的动作访问清除属性:

# /app/models/user.rb

attr_accessible :attributes_accessible_by_default, ..., :clearance, :as => :manager

# app/controllers/admin/users_controller.rb

def create
    @user = User.new(params[:user].merge(:as => :manager)
# ...
end

在这种情况下,甚至可以根据用户的角色属性提供访问权限:

# app/controllers/admin/users_controller.rb

def create
    @user = User.new(params[:user].merge(:as => current_user.role.to_sym)
# ...
end

但这可能会导致再次出现错误。