将accepts_nested_attributes_for与belongs_to关联一起使用,并使用find_or_create_by_attr行为
我正在构建一个 Rails 应用程序,它允许用户创建一个引用多个其他模型的对象,如果它们不存在则创建它们,并且只关联到已经存在的模型:(
# app/models/upload.rb
class Upload < AR:B
belongs_to :user
belongs_to :observed_property
belongs_to :sensor
accepts_nested_attributes_for :observed_property, :sensor
validates_presence_of :observed_property, :sensor
end
与sensor和observed_property的关联只是单向的,没有 has_many 返回。)
控制器没什么特别的,只是一个标准的 RESTful 7,我认为可以在保留模型中的大部分逻辑的同时正确地做到这一点。
我没有让用户填写多个不同的表单,然后分别引用这些对象,而是尝试使用 accepts_nested_attributes_for
使用 fields_for< 将它们嵌入到
Upload
表单中/code>:
# app/views/uploads/new.html.erb
<% form_for @upload, :url => user_uploads_path(@user) do |f| %>
<%= f.error_messages %>
<% f.fields_for :observed_property do |builder| %>
<fieldset>
<legend>Observed Property</legend>
<p><%= builder.label :_id, "Observed Property ID" %><br />
<%= builder.text_field :_id %></p>
<p><%= builder.label :description %><br />
<%= builder.text_area :description, :rows => 5 %></p>
</fieldset>
<% end %>
<% f.fields_for :sensor do |builder| %>
<fieldset>
<legend>Sensor</legend>
<p><%= builder.label :_id, "Sensor ID" %><br />
<%= builder.text_field :_id %></p>
<p><%= builder.label :description %><br />
<%= builder.text_area :description, :rows => 5 %></p>
</fieldset>
<% end %>
<%= f.submit "Submit", :class => "button" %>
<% end %>
但这不起作用,因为 fields_for
没有显示任何表单。我尝试应用 这个答案,但模型无法保存,因为缺少关联。
我尝试了一些黑客行为,例如覆盖 sensor=
和 observed_property=
方法并缓存 before_save
的哈希值,但这并没有真的感觉这是正确的做事方式。
I am building a Rails application which allows a user to create an object that refers to multiple other models, creating them if they do not exist, and just associating to ones that already exist:
# app/models/upload.rb
class Upload < AR:B
belongs_to :user
belongs_to :observed_property
belongs_to :sensor
accepts_nested_attributes_for :observed_property, :sensor
validates_presence_of :observed_property, :sensor
end
(The associations to sensor and observed_property are just one-way, there are no has_many returning.)
The Controller is nothing special, just a standard RESTful seven, and I would think it would be possible to do this properly while keeping most of the logic in the Model.
Instead of having the user fill out multiple different forms and then reference those objects separately, I have attempted to use accepts_nested_attributes_for
to embed them into the Upload
form using fields_for
:
# app/views/uploads/new.html.erb
<% form_for @upload, :url => user_uploads_path(@user) do |f| %>
<%= f.error_messages %>
<% f.fields_for :observed_property do |builder| %>
<fieldset>
<legend>Observed Property</legend>
<p><%= builder.label :_id, "Observed Property ID" %><br />
<%= builder.text_field :_id %></p>
<p><%= builder.label :description %><br />
<%= builder.text_area :description, :rows => 5 %></p>
</fieldset>
<% end %>
<% f.fields_for :sensor do |builder| %>
<fieldset>
<legend>Sensor</legend>
<p><%= builder.label :_id, "Sensor ID" %><br />
<%= builder.text_field :_id %></p>
<p><%= builder.label :description %><br />
<%= builder.text_area :description, :rows => 5 %></p>
</fieldset>
<% end %>
<%= f.submit "Submit", :class => "button" %>
<% end %>
This however does not work, as no form is displayed for the fields_for
. I tried to apply what was mentioned in this answer, but the model would just fail to save, citing missing associations.
I have attempted a few hackish things such as overriding the sensor=
and observed_property=
methods and caching the hashes for before_save
, but that doesn't really feel like the right way to do things.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我最终使用了以下解决方案,它似乎确实有效。我创建了一个要点来保存具有匹配规范的解决方案,以定义我正在寻求的行为。
http://gist.github.com/437939
I ended up using the following solution, and it does seem to work. I created a gist to hold the solution with a matching spec to define the behaviour I was seeking.
http://gist.github.com/437939