Полиморфная ассоциация с комментариями - Ruby on Rails - PullRequest
2 голосов
/ 22 сентября 2010

У меня возникли проблемы с тем, чтобы эти полиморфные ассоциации работали полностью. Я следовал этому уроку www.railscasts.com / episodes / 154-polymorphic-association , но, похоже, это работает, только если я пишу путь / controller / ID # / при создании нового сообщения. Если я пытаюсь отобразить форму частичного комментария прямо на / controller / ID #, я получаю эту ошибку при создании комментария:

undefined method `comments' for #<ActiveSupport::HashWithIndifferentAccess:0x10341b2d0>

У меня есть три модели:

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


class Post < ActiveRecord::Base
    belongs_to :user
    has_many :comments, :as => :commentable
end

class Article < ActiveRecord::Base
    belongs_to :user
    has_many :comments, :as => :commentable
end

И это мой взгляд на / article / # {ID}

<%= @article.title %>
<%= @article.content %>
<%= @article.user.login %>
<%= link_to 'Edit Article', edit_article_path(@article) %>

<h2>Comments</h2>
<%= render "comments/comments" %>
<%= render "comments/comment" %>

А вот мой частичный комментарий:

<div class="post_comment">
<%= form_for [@commentable, Comment.new] do |f| %>
    <%= f.text_area :content %>
    <%= f.submit "Post" %>
<% end %>
</div>

Вот мой метод создания в контроллере комментариев:

def create
    @commentable = find_commentable
    @comment = @commentable.comments.build(params[:comment])
    @comment.user_id = current_user.id
    if @comment.save
        redirect_to :id => nil
    else    
        flash[:notice] = "something went wrong"
        redirect_to @commentable
    end 
end

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

Мне кажется, я понимаю, в чем проблема, но не знаю, как ее исправить. Эта форма ищет @commentable, но если путь не является вложенным, он не может найти @commentable (может быть неправильным).

Вот мои маршруты:

devise_for :users do
        get "login", :to => "devise/sessions#new"
        get "register", :to => "devise/registrations#new"
    end

    resources :posts do
        resources :comments
        resources :tags
    end

    resources :articles do
        resources :comments
        resources :tags
    end

    resources :users do 
        resources :articles
        resources :comments
        resources :tags
        resources :posts
    end 

    resources :comments

    root :to => "home#index"

end

Ответы [ 2 ]

2 голосов
/ 30 декабря 2010

Ваша проблема в том, что find_commentable возвращает сам хэш params, потому что оператор return никогда не срабатывал.

Я вывел это из сообщения об ошибке, потому что params.class == ActiveSupport::HashWithIndiffrentAccess

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

Я бы добавил что-то вроде

def find_commentable
    params.each do |name, value|
        if name =~ /(.+)_id$/
            return $1.classify.constantize.find(value)
        end
    end
    raise ActiveRecord:NoRecord.new("Couldn\'t find it captain!")
end

Приведенный выше тип исключения, я думаю, является правильным, если не посмотреть, что вызывает Comment.find_by_id (-1) или что-то подобное. Должно быть что-то в этом роде.

Редактировать

Причина, по которой я предлагаю повысить исключение, заключается в том, что ApplicationController должен отлавливать их и обрабатывать их изящно, когда люди начинают искать информацию и переходить на example.com/posts/9001

0 голосов
/ 28 октября 2011
devise_for :users do
        get "login", :to => "devise/sessions#new"
        get "register", :to => "devise/registrations#new"
    end

    resources :posts do
        resources :comments
        resources :tags
    end

    resources :articles do
        resources :comments
        resources :tags
    end

    resources :users do 
        resources :articles
        resources :comments
        resources :tags
        resources :posts
    end 

    #REMOVE IT resources :comments

    root :to => "home#index"

end

и добавьте

def index
    @commentable = find_commentable #this
    @comments = @commentable.comments

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @comments }
    end
  end
...