Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails form_for that uses STI base class

I've got a pretty simple (I think) single-table inheritance (STI) setup in my Rails app.

There is a User model with a nested resource Post. Using STI, I have it so that some Posts can be Post::Urgent objects.

I noticed that my URL helpers like <%= [@user, @post] %> needed to be hard-coded to <%= user_post_path[@user, @post] %> or else I'd end up seeing errors about Rails not finding the user_post_urgent_path method. Okay, that was reasonably easy.

(An alternate way of doing this is also <%= [@user, post: @post] %>.)

Well, for some reason I'm not able to figure out how to make the form_for method adjusted in the same way. When I write simply

<%= form_for [@user, @post] do |f| %>

, I get similar errors to the URL helper case, but in the form context: undefined method 'user_post_urgen_path'.

I fixed this by specifying:

<%= form_for [@user, @post], url: :user_post do |f| %>

But this doesn't completely work, because when I go to submit the form, I get problems in my controller, saying that strong parameters line params.require(:post) failed:

param is missing or the value is empty: post

If I inspect the params I find that the form is passing a post_urgent object and not a post object.

I could, of course, manually put in some logic that always says if !params[:post] and params[:post_urgent], then params[:post] = params[:post_urgent]. But that just seems way too hacky, especially for Rails.

Is there a better way to make a form like this "just work" regardless of what subclass of the Post model it actually happens to be?

like image 639
isthmuses Avatar asked Oct 24 '15 01:10

isthmuses


1 Answers

Not sure if you found a solution already, but I am using the following for my forms

= form_for [@user, @post.becomes(Post)] do |f|
  - f.object = @post.becomes @post.class

reference: http://thepugautomatic.com/2012/08/rails-sti-and-form-for/

like image 142
AxelTheGerman Avatar answered Oct 20 '22 07:10

AxelTheGerman