我的 Rails 应用程序中有几个模型,它们是:
- 用户
- 照片
- 相册
- 评论
我需要将评论添加到 Photo
或 Album
,并且显然始终属于 User
。我要使用 polymorphic associations为此。
# models/comment.rb
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :commentable, :polymorphic => true
end
问题是,Rails 为新评论描述#create
操作的方法是什么。我看到了两个选项。
<强>1。描述每个 Controller 中的评论创建
但这不是 DRY 解决方案。我可以制作一个通用的局部 View 来显示和创建评论,但我将不得不重复自己为每个 Controller 编写评论逻辑。所以它不起作用
<强>2。创建新的 CommentsController
这是我猜的正确方法,但据我所知:
To make this work, you need to declare both a foreign key column and a type column in the model that declares the polymorphic interface
像这样:
# schema.rb
create_table "comments", force: :cascade do |t|
t.text "body"
t.integer "user_id"
t.integer "commentable_id"
t.string "commentable_type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
因此,当我编写非常简单的 Controller 时,它将接受来自远程表单的请求:
# controllers/comments_controller.rb
class CommentsController < ApplicationController
def new
@comment = Comment.new
end
def create
@commentable = ??? # How do I get commentable id and type?
if @comment.save(comment_params)
respond_to do |format|
format.js {render js: nil, status: :ok}
end
end
end
private
def comment_params
defaults = {:user_id => current_user.id,
:commentable_id => @commentable.id,
:commentable_type => @commentable.type}
params.require(:comment).permit(:body, :user_id, :commentable_id,
:commentable_type).merge(defaults)
end
end
我如何获得 commentable_id
和 commetable_type
?我想,commentable_type
可能是模型名称。
此外,从其他 View 制作 form_for @comment
的最佳方法是什么?
最佳答案
我会使用嵌套路由和良好的旧继承。
Rails.application.routes.draw do
resources :comments, only: [:show, :edit, :update, :destroy] # chances are that you don't need all these actions...
resources :album, shallow: true do
resources :comments, only: [:new, :index, :create], module: 'albums'
end
resources :photos, shallow: true do
resources :comments, only: [:new, :index, :create], module: 'photos'
end
end
class CommentsController < ApplicationController
before_action :set_commentable, only: [:new, :index, :create]
def create
@comment = @commentable.comments.new(comment_params) do |c|
c.user = current_user
end
# ...
end
# ...
end
class Albums::CommentsController < ::CommentsController
private
def set_commentable
@commentable = Album.find(param[:id])
end
end
class Photos::CommentsController < ::CommentsController
private
def set_commentable
@commentable = Photo.find(param[:id])
end
end
虽然您可以简单地让 CommentsController
查看参数以确定“可评论”资源是什么,但我更喜欢这种解决方案,因为 CommentsController
否则最终会处理更多而不是单一的资源,并且可以膨胀成一个神类。
当您有索引操作并需要根据父资源执行连接时,或者当事情变得复杂时,这会非常有用。
使用 partials 制作可重用的表单非常简单:
# views/comments/_form.html.erb
<%= form_for([commentable, commentable.comment.new]) do |f| %>
<%= f.label :body %>
<%= f.text_field :body %>
<% end %>
然后您可以像这样包含它:
<%= render partial: 'comments/form', commentable: @album %>
关于ruby-on-rails - 使用多态关联的 Rails 方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35037114/