在 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
模型,并且它有几个属性,比如name
和category_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 验证对其进行验证?的主要内容,如果未能解决你的问题,请参考以下文章