ruby-on-rails - 使用多态关联的 Rails 方法是什么?

标签 ruby-on-rails ruby ruby-on-rails-4 activerecord polymorphic-associations

我的 Rails 应用程序中有几个模型,它们是:

  1. 用户
  2. 照片
  3. 相册
  4. 评论

我需要将评论添加到 PhotoAlbum,并且显然始终属于 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_idcommetable_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/

相关文章:

ruby-on-rails - 堆栈级别太深,因为递归

ruby-on-rails - 在 Rails 3 上设置文件下载权限的最佳方法

css - 修改 twitter bootstrap navbar

ruby-on-rails - Rails 4 Devise 3.1.1 ActionController::UnknownFormat 在 Devise::RegistrationsController#new

ruby-on-rails - 空行出现语法错误

jquery - 轨道上的 Ajax 4

ruby-on-rails - Rails 5.0.0.beta1 - 从未过滤的请求参数生成 URL 是不安全的

ruby-on-rails - 如何在 Ruby on Rails 中将数据存储在内存中

Ruby 的 "foo = true if !defined? foo"不会按预期工作

ruby-on-rails - 在一个模型上创建多个条目 - Ruby on Rails(非嵌套)