through references rails has_one has_many has_and_belongs_to_many example belongs_to ruby-on-rails ruby-on-rails-4 rails-activerecord polymorphic-associations

ruby-on-rails - has_one - rails model references



Preocupación de la ruta y modelo polimórfico: ¿cómo compartir el controlador y las vistas? (2)

Puede encontrar el elemento primario en un filtro anterior como este:

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

Ahora puede redirigir o hacer lo que quiera dependiendo del tipo principal.

Por ejemplo en una vista:

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

O en un controlador

comments_controller.rb

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

Dadas las rutas:

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

Y el modelo:

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

Cuando edito o agrego un comentario, necesito volver al objeto "commentable". Tengo los siguientes problemas, sin embargo:

1) El redirect_to en los comments_controller.rb sería diferente dependiendo del objeto principal

2) Las referencias en las vistas diferirían también

= simple_form_for comment do |form|

¿Hay alguna forma práctica de compartir vistas y controladores para este recurso de comment ?


En Rails 4 puede pasar opciones a las preocupaciones. Entonces, si haces esto:

# routes.rb concern :commentable do |options| resources :comments, options end resources :articles do concerns :commentable, commentable_type: ''Article'' end

Luego, cuando rake routes , verás que obtienes una ruta como

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

Eso anulará todo lo que la solicitud intente establecer para mantenerlo seguro. Luego en tu 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

Una forma de probar dicho controlador con rspec es:

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