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