【问题标题】:Rails model validationRails 模型验证
【发布时间】:2014-06-14 20:15:37
【问题描述】:

我将如何在以下场景中验证模型。我们有账户、时间日志和项目三种模型。一个帐户有_many 个项目,一个项目属于_to 个帐户。

当用户创建时间日志时,他们可以从与该帐户关联的项目列表中进行选择,输入更多详细信息并保存日志。

我们的一位开发人员指出,可以在保存时间日志时操纵返回控制器的代码,如果您将属于另一个帐户的项目的 ID 传递回控制器,则该项目名称然后在视图中变得可见。这样你就可以建立一个其他帐户的项目列表,这并不酷。

所以我想要实现的是验证正在保存的记录,以确保项目 id 实际上是与 current_account 关联的项目。

我将如何实现这一目标?

目前,这就是我构建时间日志的方式

def create
    @log = @employee.time_logs.build(params[:employee_time_log])
    @log.account_id = current_account.id

    if @log.save
      flash[:notice] = "Time log sucessfully saved."
      redirect_to employee_time_logs_path(@employee)
    else
      render :form
    end
end

时间日志模型看起来像这样

class EmployeeTimeLog < ActiveRecord::Base

  #validations
  validates :date, presence: true
  validates :description, presence: true

  #associations
  belongs_to :employee
  belongs_to :account
  belongs_to :company_project
end

【问题讨论】:

  • 我认为这是控制器的工作,因为模型不知道 current_account 是什么。但是,如果 current_account 在模型中以某种方式可用,您可以创建 a custom validator
  • current_account 目前在模型中不可用,虽然我喜欢在其中进行验证,但我不喜欢将 current_ 信息传递回模型,因为我已经被它咬住了过去。您将如何在控制器中以最简洁的方式进行操作?
  • 查看我的答案以获取控制器中的解决方案...
  • 为清晰起见添加了代码

标签: ruby-on-rails


【解决方案1】:

您在这里谈论的是权限提升案例。

Rails Security Guide 对此有一些提示:

这对于某些 Web 应用程序来说是可以的,但如果用户无权查看所有项目,则肯定不行。如果用户将 id 更改为 42,并且不允许他们查看该信息,则无论如何他们都可以访问它。相反,也查询用户的访问权限:

@project = @current_user.projects.find(params[:id])

在您的情况下,您希望允许这样做:

@log = @employee.time_logs.build(project_id: 'good', …)

并禁止这样做:

@log = @employee.time_logs.build(project_id: 'bad', …)

属于一个帐户的所有项目都按如下方式查询:

current_account.projects

可用于进一步查询:

current_account.projects.find('good')
#=> returns a record because ID belongs to account

current_account.projects.find('bad')
#=> raises ActiveRecord::RecordNotFound

这就是确保将正确的 project_id 传递给控制器​​的方法!

user_supplied_project_id = params[:project_id]
timelog_params = params.merge(project_id: current_account.projects.find(user_supplied_project_id))
@log = @employee.time_logs.build(timelog_params)

【讨论】:

  • 您能否再解释一下,对不起!
  • 获取未知属性:保存时为 utf8。
  • 好的,现在可以工作了,但是如果没有输入,验证会失败。如何有条件地进行验证?
【解决方案2】:

感谢所有帮助。这就是最终的解决方案

user_supplied_project_id = params[:employee_time_log][:company_project_id]
timelog_params = user_supplied_project_id == '' ? params[:employee_time_log].merge(company_project_id: '') : params[:employee_time_log].merge(company_project_id: current_account.company_projects.find(user_supplied_project_id).id)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多