I'm trying to build a form for a like button. This like model is polymorphic to different types of Models (comments / posts / etc.) and belongs to a certain user.
When this user is viewing a blog item for instance, I want to show a like button below the post. I've set-up my routes in a way that the like routes are always nested inside the polymorphic object for which they are destined:
So for posts for instance:
#routes.rb
resources :posts do
resources :likes, only: [:create, :destroy]
end
So a post link would look like /posts/:post_id/likes/ (method: Post)
In the controller I create a new Like object, assign it to a user and save it. This works perfectly.
The problem is when I'm trying to create delete form. I really have no clue how to create that, I know the link should be /posts/:post_id/like/:id (method: Delete), but configuring it this way results in an error.
I think the form could also be refactored, but I have no clue on how making forms for these kind of 'complex' relationships.
#shared/_like_button.html.haml
- if not @post.is_liked_by current_user
= form_for(@post.likes.build, url: post_likes_path(@post)) do |f|
= f.submit
- else
= form_for(@post.likes.find_by(user_id: current_user.id), url: post_like_path(@post), html: {method: :delete}) do |f|
= f.submit
I think the main problem is that post_like_path(@post) doesn't get rendered correctly because I'm not aware of the :id of the like. So I keep getting an ActionController::UrlGenerationError in PostsController#show error when trying to build the link.
This should work:
url: post_like_path(@post)in your code expects a second argument (thelikeobject). That's what throws the error. But you don't need it actualy if you put the nested resources as an array in the first argument of theform_forhelper.You can pass an array of resources if your resource is nested within another resource.
Now... You probably want to re-use this code for your other polymorphic models as well. You can do this by passing
@post, or@commentto your partial like this:and refactor your partial like this: