1

Rails 表单验证旨在最容易地进入模型。但我需要确保当前用户具有提交帖子所需的权限,并且该current_user变量只能在控制器和视图中访问。

我在一个类似的问题中找到了这个答案:

您可以为 定义一个:user_gold虚拟属性Book,将其设置在您可以访问的控制器中current_user,然后将其合并到您的Book验证中。`

如何使用我的帖子和用户控制器进行设置,以便current_user在模型中可以访问变量?

解决方案:

正如@Deefour 的回答所指出的那样,从应用程序设计的角度来看,这整个事情都是错误的。我更改了它,因此除非条件为真,否则我的视图不会呈现表单。

4

4 回答 4

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_userwithinYourModel的验证方法。


请注意,我认为这不是您应该做的,因为我不认为这种“验证”与“授权”一样多。未经授权的用户甚至不应该能够获得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

将 Pundit 包含在您的ApplicationController

class ApplicationController < ActionController::Base
  include Pundit
  # ...
end

然后,在您的控制器操作中,您可以简单地执行

def update
  @your_model = YourModel.find(params[:id])
  authorize @your_model

  # ...

authorize方法将调用YourModelPolicy'supdate?方法(它调用与您的操作相匹配的方法 +?默认情况下),如果返回虚假值,将导致 403 错误。

于 2013-01-12T02:31:28.603 回答
2

授权不应该在模型中进行。模特已经有很多责任了,你不觉得吗?

那是控制器的事情,实际上您可以使用诸如cancan之类的 gem 在其他地方使用逻辑,并且在控制器中您可以执行以下操作:

authorize! :create, Post
于 2013-01-12T02:34:17.103 回答
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 是否属于这种情况,但您可以通过控制器中的批量分配方法(如createupdate和)设置虚拟属性new

def create
  Book.create!(current_user: current_user)
end

为此,您可能必须在模型中添加以下行以启用该虚拟属性的批量分配:

attr_accessible :current_user
于 2013-01-12T02:44:35.480 回答
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

您可能还想将过滤器放在“新”方法上。

于 2013-01-12T05:20:45.313 回答