我有许多具有普通用户无法更改的属性的模型,但管理员应该。例如(虽然这不是我的问题域),普通用户不应该更改Post
的{{1}},但应允许管理员这样做。
在视图级别处理这个很简单 - 我可以显示或不显示字段,具体取决于用户是否是管理员 - 但我不知道如何在控制器的强参数处理中处理它。我能提出的唯一解决方案(和解决方案offered previously)是重复自己,你尝试不在Rails中的东西:
user_id
有没有更好的方法来解决这个问题?
答案 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'