在 Rails 中,有没有办法指定您希望 attr_accessor 成为的类型,并使用内置的 Rails 验证对其进行验证?

Posted

技术标签:

【中文标题】在 Rails 中,有没有办法指定您希望 attr_accessor 成为的类型,并使用内置的 Rails 验证对其进行验证?【英文标题】:In Rails, is there a way to specify a TYPE you'd like an attr_accessor to be, and validate it using built-in Rails validation? 【发布时间】:2011-07-24 17:10:27 【问题描述】:

我从来没有找到一个很好的方法来做到这一点,所以我想我会问。

例如,在 ActiveRecord 模型中,数据库支持的属性会自动类型转换为适当的数据库支持类型。如果我有一个Category 模型,并且它有几个属性,比如namecategory_id,如果我这样做:

Category.new(params[:category])

Rails 知道 name 是一个字符串,category_id 是一个整数。

假设我有几个要验证的瞬态/综合属性,它们有特定的类型。我想从表单提交它们,并且我希望它们根据它们的定义方式自动转换为字符串、整数或日期(例如)。

如果我要在 Rails 模型中声明一些东西,例如:

attr_accessor :some_number_variable
attr_accessor :some_date

有没有一种内置方式告诉 Rails “我希望你将前者转换为整数,而将后者转换为日期,当我转到 Category.new(params[:category]) 时”,只要 params[:category][:some_number_variable]params[:category][:some_date]是提交给控制器的数据的一部分(我意识到 Date 示例可能有点棘手,因为那里有许多日期格式)。

【问题讨论】:

【参考方案1】:

从 Rails 5 开始,您可以像这样使用 Attribute API:

class SomeModel < ActiveRecord::Base
  attribute :a_checkbox_name, :boolean, default: false
end

您可以设置默认值,定义您自己的类型,以及其他不错的功能。然后,您可以像任何其他数据库支持的属性一样验证这些属性(虚拟或非虚拟)。

【讨论】:

【参考方案2】:

attr_accesor 只是创建读/写方法,它来自Ruby,而不是 Rails。我认为经常被混淆的 Rails 方法是attr_accessible,它服务于a different purpose。如果你想在读取属性时进行强制转换,你可以覆盖阅读器。

attr_accessor :some_number_variable

def some_number_variable
  @some_number_variable.to_i
end

这至少会给你免费的作家。对于您所描述的(我认为),这是我所知道的最佳解决方案。

编辑:就验证而言,我相信如果您使用的是 Rails 3,对这些属性执行验证会容易得多(我没有这样做,所以我不能说当然)。现在验证没有直接绑定到 ActiveRecord,我相信这是可能的。

【讨论】:

是的,我知道 attr_accessor 是一种 Ruby 方法,并且我知道 attr_accessible 是指定哪些属性允许批量分配。我认为您对 Rails 3 的看法是正确的——鉴于现在验证发生在 ActiveRecord 之外,这样做可能会更容易。【参考方案3】:

我假设“瞬态/合成”属性是指虚拟属性?

如果是这样,我可以临时想到没有内置的 Rails 函数可以做到这一点,但一种解决方案是为这些属性编写一个模块并将其包含在模型中。或者如果它必须是动态的,您可以调用类似 :some_variable_integer 的属性,然后使用 method_missing 处理这些动态属性,读取方法名称,并将其转换为所需的类型。

在我看来,这些有点混乱,所以如果你想要做的事情能够支持它们,那么模型中的验证确实是你最好的选择。

【讨论】:

是的 - 我的意思是虚拟的,我想它们对我来说都是一样的。我绝对可以通过某种形式的元编程来处理转换甚至验证,但我想知道我是否缺少内置的东西。【参考方案4】:

这两个回复都没有完全回答这个问题。我相信这些问题的正确答案只是“不”。这些答复都针对问题的答案是“否”这一事实提出了潜在的解决方法,并且两者都是有效的 cmets / 想法。

【讨论】:

【参考方案5】:

使用before_create..

class Category
  attr_accessor :some_number_variable, :some_date
  before_create :validate

 private

   def validate
     return unless !!params[:category]
     #do variable casting here
   end
end

【讨论】:

这根本没有解决问题,这与自动让 rails 将属性类型转换为所需类型有关。 然后检查这个答案...***.com/a/8940255/536984...他写了自己的 attr_accesor.. 因为 ruby​​ attr_accessor 它只是用于设置值...它不关心变量类型... 【参考方案6】:

将以下内容添加到您的模型中:

columns_hash["birth_date"] = ActiveRecord::ConnectionAdapters::Column.new("birth_date", nil, "date")

参考:Rails ActiveRecord::MultiparameterAssignmentErrors

【讨论】:

以上是关于在 Rails 中,有没有办法指定您希望 attr_accessor 成为的类型,并使用内置的 Rails 验证对其进行验证?的主要内容,如果未能解决你的问题,请参考以下文章

在 Rails 中嵌套资源时的不同视图

Rails STI 和视图重用

在 Rails 中动态添加活动类到引导 li

Rails 批量赋值定义和 attr_accessible 使用

Rails:从自定义验证器调用标准验证

在 Rails 4 中如何使用 attr_accessible?