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?