Ruby on rails 如何获得ActiveRecord验证中配置的最大长度?

Ruby on rails 如何获得ActiveRecord验证中配置的最大长度?,ruby-on-rails,validation,activerecord,Ruby On Rails,Validation,Activerecord,给定一个模型: class Person validates_lenght_of :name, :maximum => 50 end 我有一些显示倒计时的视图代码,并强制执行此最大值。然而,我把数字50硬编码到了视图代码中。有没有办法从模型中提取这个数字 比如: Person.maximum_length_of_name 我试过这个: Person.validators_on(:name) => [#<ActiveRecord::Validations::Unique

给定一个模型:

class Person
  validates_lenght_of :name, :maximum => 50
end
我有一些显示倒计时的视图代码,并强制执行此最大值。然而,我把数字50硬编码到了视图代码中。有没有办法从模型中提取这个数字

比如:

Person.maximum_length_of_name
我试过这个:

Person.validators_on(:name)
 => [#<ActiveRecord::Validations::UniquenessValidator:0x000001067a9840 @attributes=[:name], @options={:case_sensitive=>true}, @klass=Trigger(id: integer, name: string, created_at: datetime, updated_at: datetime, user_id: integer, slug: string, last_update_by: integer)>, #<ActiveModel::Validations::PresenceValidator:0x000001067a6c30 @attributes=[:name], @options={}>, #<ActiveModel::Validations::LengthValidator:0x000001067a3f08 @attributes=[:name], @options={:tokenizer=>#<Proc:0x00000101343f08@/Users/sjors/.rvm/gems/ruby-1.9.2-p0/gems/activemodel-3.0.6/lib/active_model/validations/length.rb:9 (lambda)>, :maximum=>50}>]
Person.validators\u on(:name)
=>[#true},@klass=Trigger(id:integer,name:string,创建时间:datetime,更新时间:datetime,用户id:integer,slug:string,上次更新时间:integer)>,#,##,:max=>50}>]
信息在那里,但我不知道如何提取它:

使用方法


正如@Max Williams所提到的,它只在Rails 3上工作,如果您在Rails 2中,这并不容易。我记得我以前试过这个,没走多远。您可以查看验证对象,但它们没有列出它们用于哪个字段,这对我来说非常奇怪。人们已经为此做了插件(即检查或反思AR对象的验证),例如,@nash answer的问题是,验证程序不拥有特定的顺序。我发现了如何用更多的代码来做同样的事情,但是使用了某种更安全的模式(因为你可以在以后添加更多的验证器,打破你得到它的顺序):


我认为它也只适用于Rails 3。

[Edit 2017-01-17]小心地我的答案是旧的(2012年),适用于Rails 3。对于较新的Rails版本,它可能不起作用/不理想


只需稍微简化一下,您可以创建一个泛型类方法来获取任何属性上的最大“length\u validator”值,如下所示:

在lib目录中创建模块并使其扩展:

在其中添加“模块类方法”,并创建“获取最大值”方法:

编辑1:配置

您还必须在其中一个初始值设定项中添加require

例如,以下是我的配置:

  • 我已将文件放在lib/modules/active\u record/extensions中
  • 我已经在我的自动加载路径中添加了这个:
    config.autoload\u path+=
    %W(#{config.root}/lib/modules)
    注意:这不是必需的,但如果您想将在应用程序之间共享的一些自定义类和模块放在那里,则是最佳做法
  • 在我的一个初始化器(config/initializers/custom.rb)中,我添加了这一行:
    require“active\u record/extensions”
  • 这就应该做到了!重新启动服务器,然后

    结束编辑1

    然后你应该可以做这样的事情:

    <%= form_for @comment do |f| %>
      <%= f.text_area(:body, :maxlength => f.object.class.get_maximum(:body)) #Or just use Comment.get_maximum(:body) %>
    <% end %>
    
    
    f、 object.class.get_max(:body))35;或只使用Comment.get_max(:body)%>
    

    我希望它能帮助别人!:)当然,您可以按照自己的方式自定义该方法,添加选项,并执行一些奇特的操作。;-)

    Kulgar的答案是好的,可能是理想的。对于Rails 4,这里有一个更简单的方法可以做到这一点,它不需要修改任何配置,缺点是您必须为每个想要使用它的模型添加一个include行

    模型/关注点/内省.rb:

    module Introspection
    
      def self.included(base)
        base.extend(ClassMethods)
      end
    
      module ClassMethods
        def max_length(property)
          Resource.validators_on(property.to_sym).
              select{ |v| v.kind_of?(ActiveModel::Validations::LengthValidator) }.
              first.options[:maximum]
        end
      end
    
    end
    
    然后在您的模型中:

    class Comment < ActiveRecord::Base
      include Introspection
      ..
    end
    
    class注释
    然后你可以这样做:

    <%= form_for @comment do |f| %>
      <%= f.text_area(:body, :maxlength => f.object.class.max_length(:body)) %> # Or just use Comment.max_length(:body) %>
    <% end %>
    
    
    f、 object.class.max_length(:body))%>#或仅使用Comment.max_length(:body)%>
    
    更简洁:

    Person.validators_on(:name).detect{v | v.is_a?(ActiveModel::Validations::LengthValidator)}.options[:max]
    
    使用
    检测{}
    代替
    选择{}。首先
    是{u a?
    代替
    类==


    这也适用于Rails 4.1。

    比Kulgar的答案更具动态性的是使用以下内容:

    <%= form_for @comment do |f| %>
      <%= f.text_area(:body, :maxlength => f.object.class.max_length(:body)) %> # Or just use Comment.max_length(:body) %>
    <% end %>
    
    Person.validators\u on(属性)
    .选择{| v | v.class==ActiveRecord::Validations::LengthValidator}
    .选择{v | v.options[:maximum].present?}.first.options[:maximum]
    
    这样您就可以按照您想要的方式订购模型中的验证器

    将其用作Rails助手 然后,您可以使用以下代码编写帮助程序:

    #返回模型给定属性的最大长度
    def get_maxlength(型号、属性)
    model.validators_on(属性)
    .选择{| v | v.class==ActiveRecord::Validations::LengthValidator}
    .选择{v | v.options[:maximum].present?}.first.options[:maximum]
    结束
    
    并像这样使用帮助器:

    <%= form_for @comment do |f| %>
      <%= f.text_area(:body, :maxlength => f.object.class.max_length(:body)) %> # Or just use Comment.max_length(:body) %>
    <% end %>
    
    =f.text_字段:name,maxlength:get_maxlength(f.object.class,:name)#或使用get_maxlength(Person,:name)
    
    这是一个间接的答案,但也是一个替代解决方案,以防它对任何人都有用

    备选方案1
    班级人员
    最大长度={
    姓名:50,,
    #电子邮件:30等。。。
    }.别动
    验证:名称,长度:{maximum:MAX_length.fetch(:name)}
    结束
    #视图文件中的使用示例
    
    备选方案2 。。。或者,如果您喜欢单行程序,或者不使用散列常量

    class Person
      validates :name, length: { maximum: (MAX_NAME_LENGTH = 50) }
      # validates :password, length: {
      #   minimum: (MIN_PASSWORD_LENGTH = 8),
      #   maximum: (MAX_PASSWORD_LENGTH = 70)
      # }
      # ... etc
    end
    
    # usage example in view file
    <%= Person.MAX_NAME_LENGTH %>
    
    班级人员
    验证:名称,长度:{MAX:(MAX_name_length=50)}
    #验证:密码,长度:{
    #最小值:(最小密码长度=8),
    #最大值:(最大密码长度=70)
    # }
    # ... 等
    结束
    #视图文件中的使用示例
    
    我想这只是rails 3。这可能不是问题,Sjors没有指定:)谢谢,我确实使用Rails 3,但它对我不起作用。我将Person.validators的输出添加到我的原始帖子中。在您的案例中,它将是(:name)[2]上的
    Person.validators\u。选项[:最大值]
    这是一个更好的答案。对于更多的“干法”,很容易将此方法添加为ActiveRecord通用方法。我在下面的回答中解释了如何操作。我将代码放在/lib中,设置
    config.autoload\u路径+=%W(#{config.root}/lib)
    并重新启动了服务器,但仍然为#
    获得了
    未定义的方法“get\u max”。还有什么需要配置的吗?文件名限制?是的,我的错,我忘了告诉你必须在一个初始值设定项中要求它。。。我将
    
    <%= form_for @comment do |f| %>
      <%= f.text_area(:body, :maxlength => f.object.class.max_length(:body)) %> # Or just use Comment.max_length(:body) %>
    <% end %>
    
    class Person
      MAX_LENGTHS = {
        name: 50,
        # email: 30, etc...
      }.freeze
    
      validates :name, length: { maximum: MAX_LENGTHS.fetch(:name) }
    end
    
    # usage example in view file
    <%= Person.MAX_LENGTHS.fetch(:name) %>
    
    class Person
      validates :name, length: { maximum: (MAX_NAME_LENGTH = 50) }
      # validates :password, length: {
      #   minimum: (MIN_PASSWORD_LENGTH = 8),
      #   maximum: (MAX_PASSWORD_LENGTH = 70)
      # }
      # ... etc
    end
    
    # usage example in view file
    <%= Person.MAX_NAME_LENGTH %>