11

Biorąc pod uwagę trasy:Problem dotyczący trasy i model polimorficzny: jak udostępniać kontroler i widoki?

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 

A model:

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

Kiedy mogę edytować lub dodać komentarz, muszę wrócić do "commentable" obiektu. Mam następujące problemy, ale:

1) redirect_to w comments_controller.rb będzie różna w zależności od obiektu nadrzędnego

2) odniesienia w widokach będzie się różnić także

= simple_form_for comment do |form| 

Czy istnieje praktyczny sposób udostępniania widoków i kontrolerów dla tego zasobu comment?

Odpowiedz

10

można znaleźć dominującego w przed filtrem tak:

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 

Teraz można przekierować lub zrobić cokolwiek prosisz zależności od typu macierzystego.

Na przykład w widoku:

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

Albo w kontrolerze

comments_controller.rb

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

Dzięki za pomysł; Dam ci szansę, chociaż mógłbym mieć więcej niż jednego rodzica. Na przykład potrzebuję 'simple_form_for [forum, forum_topic, comment]'; lub 'redirect_to [forum, forum_topic]'. Będę grał ikonami i zobaczę, gdzie mnie to zaprowadzi. – amencarini

+0

@amencarini Nadal możesz zrobić Arjanowi przysługę i przyjąć jego odpowiedź! – Wukerplank

16

w szynach 4 Można przekazać opcje do obaw. Więc jeśli to zrobić:

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


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

Wtedy, kiedy rake routes, zobaczysz dostać trasą jak

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

To zastąpi wszystkie żądania próbuje ustawić, aby utrzymać go bezpieczne. Następnie w 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 

Jednym ze sposobów, aby przetestować taki kontroler z rspec jest:

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

dzięki za odpowiedź, było bardzo pomocne! Niestety znalazłem błąd - w routes.rb musisz użyć obawy za pomocą metody "dotyczy", na przykład: "dotyczy: commentable, commentable_type:" Article "". –

+0

jesteś poprawny, edycja. – chris