Rails表单验证旨在最容易进入模型。但我需要确保当前用户具有提交帖子所需的权限,current_user
变量只能在控制器和视图中访问。
我在similar question中找到了这个答案:
您可以为
:user_gold
定义Book
虚拟属性,将其设置在您有权访问current_user
的控制器中,然后将其合并到Book
验证中。
如何使用我的帖子和用户控制器进行设置,以便模型中可以访问current_user
变量?
从应用程序设计的角度来看,这一切都是错误的,因为@ Deefour的回答指出。我改变了它,所以除非条件成立,否则我的视图不会渲染表单。
答案 0 :(得分:4)
"类似问题"说你可以做这样的事情
class YourModel < ActiveRecord::Base
attr_accessor :current_user
# ...
end
然后在您的控制器操作中,您可以执行类似
的操作@your_model = YourModel.find(params[:id])
@your_model.current_user = current_user
@your_model.assign_attributes(params[:your_model])
if @your_model.valid?
# ...
然后,您可以在self.current_user
的验证方法中使用YourModel
。
注意我不认为这是你应该做的事情,因为我不会考虑这个&#34;验证&#34;和&#34;授权&#34; 一样多。未经授权的用户甚至无法获得您的操作的一部分,可以保存YourModel
实例的此类更新。
至于根据要求对Pundit进行授权,您在app/policies/your_model.rb
class YourModelPolicy < Struct.new(:user, :your_model)
def update?
user.some_privilege == true # change this to suit your needs, checking the "required privileges" you mention
end
end
在您的ApplicationController
class ApplicationController < ActionController::Base
include Pundit
# ...
end
然后,在您的控制器操作中,您只需
即可def update
@your_model = YourModel.find(params[:id])
authorize @your_model
# ...
authorize
方法将调用YourModelPolicy
的{{1}}方法(默认情况下,它会调用与您的操作匹配的方法+ update?
)如果返回一个假值,将导致403错误。
答案 1 :(得分:2)
不应在模型中进行授权。你认为模特已经承担了很多责任吗?
这是一个控制器的东西,实际上你可以使用像cancan这样的宝石在其他地方使用逻辑,并且在你的控制器中你会做类似的事情:
authorize! :create, Post
答案 2 :(得分:1)
您可以在模型中定义“虚拟属性”,如下所示:
class Book < ActiveRecord::Base
attr_accessor :current_user
end
它的值可以直接在控制器中设置,如下所示:
class BooksController < ApplicationController
def create
book = Book.new
book.current_user = current_user
book.save!
end
end
在模型的验证例程中,您可以像任何其他ActiveRecord字段一样访问它:
def validate_user_permission
errors[:current_user] = "user does not have permission" unless current_user.is_gold?
end
我不记得ActiveRecord是否属于这种情况,但您可以通过质量分配方法设置虚拟属性,例如create
,update
和new
在控制器中:
def create
Book.create!(current_user: current_user)
end
为了做到这一点,您可能需要在模型中添加以下行以启用该虚拟属性的批量分配:
attr_accessible :current_user
答案 3 :(得分:0)
我同意Ismael - 这通常是在控制器中完成的。它不是模型的属性,它是权限问题并且与控制器业务逻辑相关。
如果你不需要像CanCan这样的宝石的所有力量,你可以自己扮演角色。
class BooksController < ApplicationController
before_filter :gold_required, :only => :create
def create
book = Book.new
book.save!
end
# Can be application controller
private
def gold_required
return current_user && current_user.is_gold?
end
end
您可能也希望将过滤器放在'new'方法上。