What is the Rails method for working with polymorphic associations?

In my Rails application, I have few models that:

  • User
  • Photo
  • Album
  • A comment

I need to make belog comments either before Photo, or, Albumand obviously always belong User. I am going to use polymorphic associations for this.

# models/comment.rb

class Comment < ActiveRecord::Base
  belongs_to :user
  belongs_to :commentable, :polymorphic => true
end

The question is, what is the Rails way of describing the action #createfor the new comment. I see two options.

1. Describe the creation of comments in each controller

But this is not a DRY decision. I can make one general partial view for displaying and creating comments, but I will have to repeat that I write comment logic for each controller. So it does not work.

2. Create a new comment. Controller

, , , ,

, , type ,

:

# 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

, , :

# 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 .

, form_for @comment ?

+4
2

, :

# config/routes.rb
resources :photos, :albums do
   resources :comments, only: :create #-> url.com/photos/:photo_id/comments
end

# app/controllers/comments_controller.rb
class CommentsController < ApplicationController
   def create
      @parent  = parent
      @comment = @parent.comments.new comment_params
      @comment.save
   end

   private

   def parent
      Album.find params[:album_id] if params[:album_id]
      Photo.find params[:photo_id] if params[:photo_id]
   end

   def comment_params
      params.require(:comment).permit(:body).merge(user_id: current_user.id)
   end
end

.


@comment, :

#app/controllers/photos_controller.rb
class PhotosController < ApplicationController
   def show
      @photo = Photo.find params[:id] 
      @comment = @photo.comments.new
   end
end

#app/views/photos/show.html.erb
<%= form_for [@photo, @comment] do |f| %>
  ...
+4

.

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 , , .

, .

:

# 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 %>
+5

Source: https://habr.com/ru/post/1626163/


All Articles