允许管理员帐户的其他参数

时间:2015-01-22 13:29:38

标签: ruby-on-rails strong-parameters

我有许多具有普通用户无法更改的属性的模型,但管理员应该。例如(虽然这不是我的问题域),普通用户不应该更改Post的{​​{1}},但应允许管理员这样做。

在视图级别处理这个很简单 - 我可以显示或不显示字段,具体取决于用户是否是管理员 - 但我不知道如何在控制器的强参数处理中处理它。我能提出的唯一解决方案(和解决方案offered previously)是重复自己,你尝试不在Rails中的东西:

user_id

有没有更好的方法来解决这个问题?

3 个答案:

答案 0 :(得分:1)

我没有看到您当前的实施有任何问题。话虽这么说,如果你想在不同的控制器(例如Api :: PostsConrtoller)中重用这些属性权限,干掉它的一种方法就是将代码提取到它自己的类中。这是Ryan Bates在Railscast about Strong Parameters中使用的方法(注意:需要专业帐户)。

# app/models/permitted_params.rb

class PermittedParams < Struct.new(:params, :user)
  def post
    if user && user.admin?
      params.require(:post).permit(:title, :text, :date, :user_id)
    else
      params.require(:post).permit(:title, :text, :date)
    end
  end
end

然后,您可以在ApplicationController

中实例化此类
# app/controllers/application_controller.rb

def permitted_params
  @permitted_params ||= PermittedParams.new(params, current_user)
end

然后在需要该权限逻辑的任何控制器中使用它,而不重复逻辑。

# app/controllers/posts_controller.rb

def update
  @post = Post.find(params[:id])
  if @post.update_attributes(permitted_params.post)
    ...
  else
    ...
  end
end

这个解决方案的真正优点在于,您还可以通过稍微修改PermittedParams类来使用它来干扰您的观看。

# app/models/permitted_params.rb

class PermittedParams < Struct.new(:params, :user)
  def post
    params.require(:post).permit(*post_attributes)
  end

  def post_attributes
    if user && user.admin?
      [:title, :text, :date, :user_id]
    else
      [:title, :text, :date]
    end
  end
end

并将permitted_params方法公开为视图助手。

# app/controllers/application_controller.rb

def permitted_params
  @permitted_params ||= PermittedParams.new(params, current_user)
end
helper_method :permitted_params

最后,在视图中使用它来显示/隐藏表单字段。

# app/views/posts/edit.html.erb

<% if permitted_params.post_attributes.include? :user_id %>
# show the user_id field
<% end %>

答案 1 :(得分:0)

您不需要为了防止坏用户而使用两个不同的参数列表。 相反,你应该考虑使用cancan宝石。

统一使用单个参数列表(无论用户角色如何)。

在此限制/保护您的操作(基于用户角色),请尝试使用cancan gem.

在ability.rb文件中定义您的个人角色授权。

示例能力文件如下所示:

 #ability.rb 

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new

    if user.is?(:Administrator) # Access for Admin user
        can :access, :all
    elsif user.is?(:"Finance Manager") #Access for Finance Manager
        can :access, [:subjects, :researchsubjects, :visits, :sessions]
    elsif user.is?(:"Research Director") # Access for Research Director
    else
      #do something
    end
  end
end

请查看cancan gem以获取更多信息。

答案 2 :(得分:0)

我对之前的任何答案都不满意。我真正想做的是:

params.require(:post).permit(:title, :text, :date, user_id: admin?)

所以我决定让这成为可能。首先我尝试修补Rails核心,但他们对接受补丁不感兴趣:

  

这个API很精致,有几个方向可以发展,它可以轻易失控,不一致,或创建扩展扩展的期望......我们现在更喜欢保持原样。< / p>      

通常,我们更喜欢通过常规编程来解决API不直接支持的用例。在这种情况下,它将是

pkeys = [:title, :body]
pkeys << :author_id if admin?
params.require(:post).permit(*pkeys)
     

或该行中的某些内容(当然,您已经知道这是可能的,但只是用一个例子来说明这一点)。

所以我turned it into a gem instead,只要我想保留它,我就会拥有它。遗憾的是,这个功能不会成为我编写的每个未来Rails应用程序的一部分,但至少我可以从我的Gemfile中获取它。

gem 'rails_conditional_params'