0

我正在尝试为类似按钮构建一个表单。这个like模型对不同类型的模型(评论/帖子/等)是多态的,属于某个用户。

例如,当这个用户正在查看博客项目时,我想在帖子下方显示一个赞按钮。我已经以某种方式设置了我的路由,即类似的路由总是嵌套在它们所指向的多态对象中:

因此,例如帖子:

#routes.rb
resources :posts do
   resources :likes, only: [:create, :destroy]
end

所以一个帖子链接看起来像/posts/:post_id/likes/(方法:帖子)

在控制器中,我创建了一个新的 Like 对象,将其分配给用户并保存。这完美地工作。

问题是当我尝试创建删除表单时。我真的不知道如何创建它,我知道链接应该是/posts/:post_id/like/:id(方法:删除),但是以这种方式配置它会导致错误。

我认为表单也可以重构,但我不知道如何为这些“复杂”关系制作表单。

#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

我认为主要问题是post_like_path(@post)没有正确渲染,因为我不知道:id类似的东西。ActionController::UrlGenerationError所以我在PostsController#show尝试建立链接时不断出错。

4

2 回答 2

2

这应该有效:

= form_for([@post, @post.likes.find_by(user_id: current_user.id)], html: {method: :delete}) do |f|

url: post_like_path(@post)在您的代码中需要第二个参数(like对象)。这就是引发错误的原因。但是,如果将嵌套资源作为数组放在帮助程序的第一个参数中,则实际上不需要它form_for

如果传递给form_for 的记录是资源,即它对应于一组RESTful 路由,例如使用config/routes.rb 中的resources 方法定义。在这种情况下,Rails 将简单地从记录本身推断出适当的 URL。(来源:http ://apidock.com/rails/ActionView/Helpers/FormHelper/form_for )

如果您的资源嵌套在另一个资源中,您可以传递一个资源数组。

现在...您可能也希望将此代码重新用于其他多态模型。您可以通过传递来做到这一点@post,或者@comment像这样传递给您的部分:

= render :partial => 'like_button', locals: {likable: @post}

并像这样重构你的部分:

= form_for([likable, likable.likes.find_by(user_id: current_user.id)], html: { method: :delete}) do |form|
于 2015-10-02T13:46:04.063 回答
1

无需使用实际表单,您可以使用 link_to 来完成。这是一个带有基本文本链接的示例(以确保它正常工作)

- if not @post.is_liked_by current_user
  = link_to 'Like', post_like_path(@post), method: :post
- else
  = link_to 'Delete', post_like_path([@post, @post.likes.find_by(user_id: current_user.id)]), method: :delete

然后你使用图像/按钮作为链接本身。

- if not @post.is_liked_by current_user
  = link_to post_like_path(@post), method: :post do
    # some html image/button
- else
  = link_to post_like_path([@post, @post.likes.find_by(user_id: current_user.id)]), method: :delete do
    # some html image/button

在接受的答案的帮助下更新了此代码,以便将来的任何人都可以使用 link_to。

于 2015-10-02T13:41:57.840 回答