开发者

Rails: How do I send an object along with a form?

开发者 https://www.devze.com 2022-12-15 02:09 出处:网络
I have a Post model object that has reference to a parent object. The edit, new and reply methods all use 开发者_开发问答the same partial template.

I have a Post model object that has reference to a parent object. The edit, new and reply methods all use 开发者_开发问答the same partial template.

The posts_controller methods:

def edit
  @post = Post.find(params[:id])
end

def reply
  @post = Post.new
  @replypost = Post.find(params[:id])
  @post.title = @replypost.title
  @post.parent = @replypost
end

The partial template code:

<% form_for(@post) do |f| %>
  <%= f.error_messages %>

  <p>
    <%= f.label :title %><br />
    <%= f.text_field :title %>
  </p>
  <p>
    <%= f.label :body %><br />
    <%= f.text_area :body %>
  </p>
  <%= if :parent then f.hidden_field :parent end %>
  <p>
    <%= f.submit "Create" %>
  </p>
<% end %>

If I look at the source HTML generated by the partial template, I can see that I'm passing some sort of object id to my create method.

<input id="post_parent" name="post[parent]" type="hidden" value="#&lt;Post:0x103e3bdf0&gt;" />

The problem is that when I try and save this new object I've created, I get a warning that it was expecting a Post and got a String. I'm sure that I can work around this by setting and getting the parent_id and passing that with my form, but I'm wondering if there isn't a better way to do this, something more elegant and Rails-esque.


try <%= f.hidden_field :parent_id unless @post.parent.nil? %>

This will pass the parent id with the post and you can then .find(params[:post][:parent_id]) if you need the object later.


For people looking to send an object instead of an id (useful when you have an unsaved object), you can do the following:

In your view:

<% form_for(@post) do |f| %>
  ...
  <%= hidden_field_tag :param_name, @object.to_param %>

In your controller:

object = Rack::Utils.parse_nested_query params[:param_name]

Works for nested hashes. Haven't tested with arrays or hashes of arrays.

I found this necessary when constructing an object across multiple views that wouldn't pass validation if I tried to save earlier.

Warning: The data in @object is visible to the user in the hidden_field_tag. They just need to click 'view source'. Consider carefully whatever objects you want to serialize with this method.


From what it looks like,

<%= if :parent then f.hidden_field :parent end %>

isn't able to infer that when you say :parent, you want the value of the hidden field to be the parent post's ID.

You have to explicitly use the :parent_id to generate the hidden field's value because it can't be inferred as it can elsewhere in Rails.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号