所以通常的方法是让多个输入字段的名称为“obj_ids []”,然后rails中的值最终会神奇地将它们压缩成一个数组。
只有一个字段,rails是否有一些秘密的方式交替执行此操作?
我需要将输入字段与实际表单分开,所以现在我基本上抓住它们,并在它们上运行JS连接以单独的形式作为一个字段发送。我可以将它们全部复制为隐藏字段,但这似乎有点多。显然也可以在控制器中进行拆分,但我很好奇是否有另一种方式。
答案 0 :(得分:1)
根据您的具体需求,有很多方法可以在rails中执行此类操作
像@jrochkind所提到的那样黑客攻击是一种方式,但有几种更优雅的解决方案在模型中创建虚拟属性
class SomeModel
attr_reader :my_field
def my_field= value_as_comma_delimited_string
# here the the_field_i_really_want_set is an array type which is supported in mongo and postgres for exampld
self.the_field_i_really_want_set = value_as_comma_delimited_string.split(",")
end
end
你可以在before_validation回调中做同样的事情,在这种情况下你不需要创建一个访问者
class User < ActiveRecord::Base
before_validation :normalize_name, on: :create
protected
def normalize_name
self.name = self.name.downcase.titleize # or whatever transformation you need
end
端
我发现的另一种非常有用且与我展示的第一种技术类似的技术是直接覆盖访问器方法。这里my_field是模型模式中的实际字段。
class SomeModel
def my_field= value_as_comma_delimited_string
self.write_attribute(:my_field,value_as_comma_delimited_string.split(","))
end
end
答案 1 :(得分:0)
我不会想到另一种方式,我之前已经研究过,对于其他情况。
对于您的情况,如果我理解正确,您正在使用JS构建表单并使用JS提交表单,并且由您决定是否在一个输入中构建具有多个值的表单(将变为一个URL查询参数),以逗号或单独的字段/参数分隔。
我只是选择单独的字段/参数。
否则,在控制器端,您可以在before_filter而不仅仅是action方法中执行它,即使在application_controller上适用于所有操作的before_filter中,您甚至可以让before_filter mutate Rails拥有params hash。
before_filter :split_commas
def split_commas
params[:my_field] = params[:my_field].split(",")
end
这应该有用,虽然像这样的变体类似的哈希导致了我这么多令人沮丧的错误,我不愿意这样做。
答案 2 :(得分:0)
按照@hraynaud的建议,将另一个setter添加到模型(或覆盖现有的setter)是一种可能性。但是在我看来,支持一些非标准的输入格式更像是控制器的责任而不是模型。因此,我不会将这种逻辑放入模型中。
相反,我引入另一个控制器的方法来返回预处理的参数。适用于强参数。
protected
def preprocessed_params
p = params.deep_dup
p[:obj_ids] = p[:obj_ids].split(",") if p[:obj_ids]
p
end
def permitted_params
preprocessed_params.permit(:obj_ids => [])
end
可以使用alias_method_chain
进一步修改此代码段,以便可以通过params
访问预处理的参数,而原始的参数保存在params_without_preprocessing
或其他内容。