我在那有一个序列化的领域我Rails项目的数据模型:
class Widget < ActiveRecord::Base
serialize :options
end
选项字段可以具有可变数据信息。 例如,这里是从夹具文件中的一个记录的选项字段:
options:
query_id: 2
axis_y: 'percent'
axis_x: 'text'
units: '%'
css_class: 'occupancy'
dom_hook: '#average-occupancy-by-day'
table_scale: 1
我的问题是什么,就是让用户编辑此信息以标准形式观点的正确方法?
如果只是用一个简单的文本区域字段的选项字段,你只会得到一个YAML转储表示和该数据也只是发回为一个字符串。
什么是Rails的编辑这样的序列化的哈希领域最好的/合适的方法是什么?
Answer 1:
如果你知道什么选项键将要提前,你可以像这样特别声明getter和setter方法为他们:
class Widget < ActiveRecord::Base
serialize :options
def self.serialized_attr_accessor(*args)
args.each do |method_name|
eval "
def #{method_name}
(self.options || {})[:#{method_name}]
end
def #{method_name}=(value)
self.options ||= {}
self.options[:#{method_name}] = value
end
attr_accessible :#{method_name}
"
end
end
serialized_attr_accessor :query_id, :axis_y, :axis_x, :units
end
关于这样做的好处是,它暴露的选项数组的属性,它允许您使用Rails的形成佣工像这样的组件:
#haml
- form_for @widget do |f|
= f.text_field :axis_y
= f.text_field :axis_x
= f.text_field :unit
Answer 2:
嗯,我有同样的问题,并试图不要过度设计它。 问题是,尽管可以通过序列化的哈希fields_for,对于功能的领域会认为,这是一个选项哈希(而不是你的对象),并设置表单对象为零。 这意味着,虽然你可以编辑的值,他们不会编辑后出现。 这可能是一个错误或轨道意外的行为,也许固定在未来。
然而,就目前而言,这是很容易得到它的工作(尽管它整个上午带我去弄清楚)。
您可以留下您模型是和在视图中,你需要给字段的对象作为一个开放的结构。 这将正确地设置记录对象(所以f2.object将返回你的选择),其次它可以让text_field建设者从访问你的对象/ PARAMS的值。
自从我列入“|| {}”,它将与新/创建表单的工作了。
= form_for @widget do |f|
= f.fields_for :options, OpenStruct.new(f.object.options || {}) do |f2|
= f2.text_field :axis_y
= f2.text_field :axis_x
= f2.text_field :unit
祝你有美好的一天
Answer 3:
EMH是几乎没有。 我认为Rails的将值返回到窗体字段,但事实并非如此。 所以,你可以把它放在那里手动在“:价值=>”为每个字段参数。 它不漂亮的外观,但它的工作原理。
这是从上到下:
class Widget < ActiveRecord::Base
serialize :options, Hash
end
<%= form_for :widget, @widget, :url => {:action => "update"}, :html => {:method => :put} do |f| %>
<%= f.error_messages %>
<%= f.fields_for :options do |o| %>
<%= o.text_field :axis_x, :size => 10, :value => @widget.options["axis_x"] %>
<%= o.text_field :axis_y, :size => 10, :value => @widget.options["axis_y"] %>
<% end %>
<% end %>
您在“fields_for”添加的任何字段将在序列化哈希露面。 您可以添加或随意删除字段。 他们将的属性中的“选项”哈希值传递和存储YAML。
Answer 4:
我一直在挣扎了非常类似的问题。 我发现这里的解决方案是对我很有帮助。 谢谢@austinfromboston,@基督教Butske,@sbzoom,和大家一样。 不过,我认为这些答案可能是略掉过期。 下面是使用Rails 5为我工作和Ruby 2.3:
形式:
<%= f.label :options %>
<%= f.fields_for :options do |o| %>
<%= o.label :axis_y %>
<%= o.text_field :axis_y %>
<%= o.label :axis_x %>
<%= o.text_field :axis_x %>
...
<% end %>
然后在控制器我不得不更新,像这样的强参数:
def widget_params
params.require(:widget).permit(:any, :regular, :parameters, :options => [:axis_y, :axis_x, ...])
end
这似乎是很重要的序列化的哈希参数来在参数列表的末尾。 否则,Rails会预期未来参数也可以是序列化的哈希值。
在视图中我使用了一些简单的if / then逻辑只显示散列,如果它不是空的,然后仅显示键/值对,其中值不是零。
Answer 5:
无需二传手/ getter方法,我只是在模型中定义:
serialize :content_hash, Hash
然后在视图中,我这样做(与simple_form,但香草Rails的类似):
= f.simple_fields_for :content_hash do |chf|
- @model_instance.content_hash.each_pair do |k,v|
=chf.input k.to_sym, :as => :string, :input_html => {:value => v}
我最后的问题是如何让用户添加一个新的键/值对。
Answer 6:
我会建议一些简单的,因为所有的时间,当用户将节省形成你将得到的字符串。 所以你可以使用例如过滤器之前和解析像这样的数据:
before_save do
widget.options = YAML.parse(widget.options).to_ruby
end
当然,你应该添加验证这是否是正确的YAML。 但它应该工作。
Answer 7:
我试图做同样的事情,我发现这种作品:
<%= form_for @search do |f| %>
<%= f.fields_for :params, @search.params do |p| %>
<%= p.select "property_id", [[ "All", 0 ]] + PropertyType.all.collect { |pt| [ pt.value, pt.id ] } %>
<%= p.text_field :min_square_footage, :size => 10, :placeholder => "Min" %>
<%= p.text_field :max_square_footage, :size => 10, :placeholder => "Max" %>
<% end %>
<% end %>
除了当表单呈现的表单字段不填充。 当表单提交的值来通过就好了,我可以这样做:
@search = Search.new(params[:search])
所以它的“半壁江山”的工作...
Answer 8:
我正面临同样的问题,经过一番研究,我发现,使用Rails的一个解决方案store_accessor
使作为属性访问的序列化列的密钥。
有了这个,我们可以访问序列化列的“嵌套”的属性...
# post.rb
class Post < ApplicationRecord
serialize :options
store_accessor :options, :value1, :value2, :value3
end
# set / get values
post = Post.new
post.value1 = "foo"
post.value1
#=> "foo"
post.options['value1']
#=> "foo"
# strong parameters in posts_controller.rb
params.require(:post).permit(:value1, :value2, :value3)
# form.html.erb
<%= form_with model: @post, local: true do |f| %>
<%= f.label :value1 %>
<%= f.text_field :value1 %>
# …
<% end %>
文章来源: How to edit a Rails serialized field in a form?