11

Dati i percorsi:Rotta preoccupazione e modello polimorfico: come condividere controller e viste?

Example::Application.routes.draw do 
    concern :commentable do 
    resources :comments 
    end 

    resources :articles, concerns: :commentable 

    resources :forums do 
    resources :forum_topics, concerns: :commentable 
    end 
end 

E il modello:

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

Quando ho modificare o aggiungere un commento, ho bisogno di tornare l'oggetto "commentabile". Ho i seguenti problemi, però:

1) Il redirect_to nel comments_controller.rb sarebbe diversa a seconda dell'oggetto genitore

2) I riferimenti sulle viste avrebbero differiscono così

= simple_form_for comment do |form| 

è esiste un modo pratico per condividere viste e controller per questa risorsa comment?

risposta

10

È possibile trovare il padre in una prima del filtro come questo:

comments_controller.rb

before_filter: find_parent 

def find_parent 
    params.each do |name, value| 
    if name =~ /(.+)_id$/ 
     @parent = $1.classify.constantize.find(value) 
    end 
    end 
end 

Ora è possibile reindirizzare o fare quello che vuoi in base al tipo genitore.

Ad esempio, in una vista:

= simple_form_for [@parent, comment] do |form| 

O in un controller

comments_controller.rb

redirect_to @parent # redirect to the show page of the commentable. 
+0

Grazie per l'idea; Ci provo anche se potrei avere più di un genitore. Per esempio ho bisogno di 'simple_form_for [forum, forum_topic, comment]'; o 'redirect_to [forum, forum_topic]'. Giocherò con gli splats e vedrò dove mi arriva. – amencarini

+0

@amencarini Potresti ancora fare un favore ad Arjan e accettare la sua risposta! – Wukerplank

16

In Rails 4 è possibile passare le opzioni alle preoccupazioni. Quindi, se si esegue questa operazione:

# routes.rb 
concern :commentable do |options| 
    resources :comments, options 
end 


resources :articles do 
    concerns :commentable, commentable_type: 'Article' 
end 

Poi, quando si rake routes, si vedrà che si ottiene un percorso come

POST /articles/:id/comments, {commentable_type: 'Article'}

Questo sovrascriverà qualsiasi cosa la richiesta tenta di impostare per mantenerlo sicuro. Poi, nel tuo CommentsController:

# comments_controller.rb 
class CommentsController < ApplicationController 

    before_filter :set_commentable, only: [:index, :create] 

    def create 
    @comment = Comment.create!(commentable: @commentable) 
    respond_with @comment 
    end 

    private 
    def set_commentable 
    commentable_id = params["#{params[:commentable_type].underscore}_id"] 
    @commentable = params[:commentable_type].constantize.find(commentable_id) 
    end 

end 

Un modo per testare un tale controller con RSpec è:

require 'rails_helper' 

describe CommentsController do 

    let(:article) { create(:article) } 

    [:article].each do |commentable| 

    it "creates comments for #{commentable.to_s.pluralize} " do 
     obj = send(commentable) 
     options = {} 
     options["#{commentable.to_s}_id"] = obj.id 
     options["commentable_type".to_sym] = commentable.to_s.camelize 
     options[:comment] = attributes_for(:comment) 
     post :create, options 
     expect(obj.comments).to eq [Comment.all.last] 
    end 

    end 

end 
+0

grazie per la tua risposta, è stato molto utile! Purtroppo ho trovato un errore: in routes.rb devi usare un problema usando il metodo 'preoccupazioni', come questo: "preoccupazioni: commentabile, tipo commentabile: 'Articolo'". –

+0

sei corretto, modifica. – chris

Problemi correlati