Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails输入来自ActiveRecord限制的文本最大长度_Ruby On Rails_Activerecord_Form Helpers - Fatal编程技术网

Ruby on rails Rails输入来自ActiveRecord限制的文本最大长度

Ruby on rails Rails输入来自ActiveRecord限制的文本最大长度,ruby-on-rails,activerecord,form-helpers,Ruby On Rails,Activerecord,Form Helpers,在我们的Rails应用程序中,我们希望防止用户在文本字段中实际输入的字符数超过相应数据库字段中记录的字符数。这似乎比让他/她打字太多,然后被告知事后再试要友好得多 换句话说,所有视图输入文本字段的maxlength=属性集应等于相应ActiveRecord模型varchar字段的:limit 有没有办法使这种情况自动发生 如果没有,是否有一种枯燥的习惯用法、帮助函数或元编程技巧可以让它成为现实?类似以下未经测试的猴子补丁可能会有所帮助 module ActionView module Hel

在我们的Rails应用程序中,我们希望防止用户在文本字段中实际输入的字符数超过相应数据库字段中记录的字符数。这似乎比让他/她打字太多,然后被告知事后再试要友好得多

换句话说,所有视图输入文本字段的maxlength=属性集应等于相应ActiveRecord模型varchar字段的:limit

有没有办法使这种情况自动发生


如果没有,是否有一种枯燥的习惯用法、帮助函数或元编程技巧可以让它成为现实?

类似以下未经测试的猴子补丁可能会有所帮助

module ActionView
  module Helpers

    old_text_field = instance_method(:text_field)                                                           # store a reference to the original text_field method

    define_method(:text_field) do |object_name, method, options = {}|                                       # completely redefine the text_field method
      klass     = InstanceTag.new(object_name, method, self, options.delete(:object)).retrieve_object.class # get the class for the object bound to the field
      column    = klass.columns.reject { |c| c.name != method.to_s }.first if klass.present?                # get the column from the class
      maxlength = column.limit if defined?(column) && column.respond_to?(:limit)                            # set the maxlength to the limit for the column if it exists

      options.reverse_merge!( maxlength: maxlength ) if defined?(maxlength)                                 # merge the maxlength option in with the rest

      old_text_field.bind(self).(object_name, method, options)                                              # pass it up to the original text_field method
    end
  end
end

类似以下未经测试的猴子补丁可能会有所帮助

module ActionView
  module Helpers

    old_text_field = instance_method(:text_field)                                                           # store a reference to the original text_field method

    define_method(:text_field) do |object_name, method, options = {}|                                       # completely redefine the text_field method
      klass     = InstanceTag.new(object_name, method, self, options.delete(:object)).retrieve_object.class # get the class for the object bound to the field
      column    = klass.columns.reject { |c| c.name != method.to_s }.first if klass.present?                # get the column from the class
      maxlength = column.limit if defined?(column) && column.respond_to?(:limit)                            # set the maxlength to the limit for the column if it exists

      options.reverse_merge!( maxlength: maxlength ) if defined?(maxlength)                                 # merge the maxlength option in with the rest

      old_text_field.bind(self).(object_name, method, options)                                              # pass it up to the original text_field method
    end
  end
end
Rails 4解决方案 以下各项经过测试并正常工作:

config/initializers/text_field_extensions.rb 模块操作视图 模块助手 模块标签 类文本字段 别名\u方法:render\u old,:render def渲染 prototype=@object.class 除非prototype==NilClass 最大长度=零 validator=prototype.validators.detect do|v| v、 ActiveModel::Validations::LengthValidator的实例&& v、 属性。包括?@method\u name.to\u sym&& v、 选项。包括?:最大值 终止 如果验证器。零? maxlength=验证器。选项[:最大值] 其他的 column=prototype.columns.detect do|c| c、 名称==@方法\u名称&& c、 回应?:限制 终止 maxlength=column.limit,除非column.nil? 终止 @选项。反向合并!maxlength:maxlength,除非maxlength.nil? 终止 使你变老 终止 终止 终止 终止 终止 此解决方案借鉴了ActionView的TextField类,但将补丁应用于该类。所有其他基于文本的输入类型password\u field、email\u field、search\u field等都使用从TextField继承的标记,这意味着此修复程序也将应用于它们。唯一的例外是text_area方法,它使用不同的标记,除非此修补程序单独应用于ActionView::Helpers::Tags::TextArea,否则不会以相同的方式运行

Deefour的解决方案通过查看ActiveRecord数据库列来确定最大长度。虽然这完美地回答了Gene的问题,但我发现数据库列的限制通常与字段无关,即高于我们实际需要的限制。最理想的最大长度通常来自我们在模型上设置的LengthValidator。因此,首先,此修补程序在模型上查找LengthValidator,其中a应用于用于字段的属性,b提供最大长度。如果它没有从中得到任何东西,它将使用数据库列上指定的限制

最后,像Deefour的回答一样,@options.reverse\u merge!表示可以通过在选项参数中指定:maxlength来覆盖字段的maxlength属性:

25 %> 设置:maxlength为nil将完全删除该属性

最后,请记住,提供TextField的maxlength选项将自动将输入元素的size属性设置为相同的值。就我个人而言,我认为size属性已经过时了,而且已经被CSS淘汰了,所以我选择删除它。为此,请替换包含@options.reverse\u merge的行!以下是:

@选项。反向合并!maxlength:maxlength,大小:nil,除非maxlength.nil? Rails 4解决方案 以下各项经过测试并正常工作:

config/initializers/text_field_extensions.rb 模块操作视图 模块助手 模块标签 类文本字段 别名\u方法:render\u old,:render def渲染 prototype=@object.class 除非prototype==NilClass 最大长度=零 validator=prototype.validators.detect do|v| v、 ActiveModel::Validations::LengthValidator的实例&& v、 属性。包括?@method\u name.to\u sym&& v、 选项。包括?:最大值 终止 如果验证器。零? maxlength=验证器。选项[:最大值] 其他的 column=prototype.columns.detect do|c| c、 名称==@方法\u名称&& c、 回应?:限制 终止 maxlength=column.limit,除非column.nil? 终止 @选项。反向合并!maxlength:maxlength,除非maxlength.nil? 终止 使你变老 终止 终止 终止 终止 终止 此解决方案借鉴了ActionView的TextField类,但将补丁应用于该类。所有其他基于文本的输入类型password\u field、email\u field、search\u field等都使用从TextField继承的标记,这意味着此修复程序也将应用于它们。唯一的e 与此不同的是text_area方法,它使用不同的标记,除非此修补程序单独应用于ActionView::Helpers::Tags::TextArea,否则不会以相同的方式运行

Deefour的解决方案通过查看ActiveRecord数据库列来确定最大长度。虽然这完美地回答了Gene的问题,但我发现数据库列的限制通常与字段无关,即高于我们实际需要的限制。最理想的最大长度通常来自我们在模型上设置的LengthValidator。因此,首先,此修补程序在模型上查找LengthValidator,其中a应用于用于字段的属性,b提供最大长度。如果它没有从中得到任何东西,它将使用数据库列上指定的限制

最后,像Deefour的回答一样,@options.reverse\u merge!表示可以通过在选项参数中指定:maxlength来覆盖字段的maxlength属性:

25 %> 设置:maxlength为nil将完全删除该属性

最后,请记住,提供TextField的maxlength选项将自动将输入元素的size属性设置为相同的值。就我个人而言,我认为size属性已经过时了,而且已经被CSS淘汰了,所以我选择删除它。为此,请替换包含@options.reverse\u merge的行!以下是:

@选项。反向合并!maxlength:maxlength,大小:nil,除非maxlength.nil?
这在Rails 5.2.1中似乎仍然有效。我一直想知道为什么没有插件来做这件事,或者为什么它从来没有内置到Rails中。这似乎在Rails 5.2.1中仍然有效。我一直想知道为什么没有插件来做这件事,或者为什么它从来没有内置到Rails中。