2011-11-14 5 views
2

J'ai des problèmes avec une association polymorphe dans Rails. J'ai une application où il devrait être possible de commenter sur différents modèles, tels que Posts, Images, ProjectsRails 3.1: Association polymorphe @commentable - comment le faire correctement?

En ce moment j'ai juste des postes à commenter sur. Sur la page d'accueil il y a une vue d'index des derniers messages et chaque poste a un petit commentaire sous pour commenter via Ajax, un peu comme Facebook.

Mes modèles ressemblent à ceci:

class Post < ActiveRecord::Base 
    belongs_to :post_category 
    belongs_to :user 

    has_many :comments, :as => :commentable 

    validates_presence_of :user_id 
    validates_presence_of :post_category_id 
    validates_presence_of :title 
    validates_presence_of :body 

end 

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

Maintenant dans mon contrôleur Commentaires j'ai ajouté la méthode suivante (je pense que je l'ai pris de Railscasts ou quelque chose), que je suppose essaie de trouver la @commentable dynamique lors de la création d'un commentaire Mais cela renvoie toujours l'erreur undefined method commentaires pour nil: NilClass`

# find commentable (parent) item 
    def find_commentable 
     params.each do |name, value| 
     if name =~ /(.+)_id$/ 
      return $1.classify.constantize.find(value) unless name == 'user_id' 
     end 
     end 
     nil 
    end 

    def create 
    @commentable = find_commentable 
    @comment = @commentable.comments.build(params[:comment]) 
    if @comment.save 
     redirect_to @comment, :notice => 'Comment was successfully created.' 
     redirect_to :id => nil 
    else 
     render :action => "new" 
    end 
    end 

Les deux choses que j'ai essayé dans ma partie étaient:

  1. laissant l'info commentable sur la forme

    = form_for [@commentable, Comment.new],: remote => true do | f | # nouveau_comment.add_comment = f.hidden_field: id_utilisateur,: valeur => utilisateur_utilisateur.id = f.texte_fichier: contenu,: taille => 55,: valeur => 'laisser un commentaire ...',: class = > 'comment_form' = f.submit "envoyer"

et 2. passer le commentable_id et commentable_type

= form_for [@commentable, Comment.new], :remote => true do |f| 
    #new_comment.add_comment 
     = f.hidden_field :user_id, :value => current_user.id 
     = f.hidden_field :commentable_id, :value => post_id 
     = f.hidden_field :commentable_type, :value => 'Post' 
     = f.text_field :content, :size => 55, :value => 'leave a comment...', :onfocus => 'this.select()', :class => 'comment_form' 
     = f.submit "send" 

fois sans chance. Toute aide serait très appréciée. l'ensemble du code du contrôleur de commentaires est dans ce sens: https://gist.github.com/1334286

Répondre

2

Il semble que le commentaire ne soit pas affecté correctement dans le contrôleur de commentaires. Cela pourrait avoir plusieurs raisons. Voici une configuration qui devrait fonctionner pour vous:

Dans le contrôleur Posts, par ex. action « show »:

@post = Post.find(params[:id]) 

Dans les postes/show vue sous forme de commentaires:

= form_for [@post, @post.comments.new], :remote => true do |f| 

Vous devriez pouvoir utiliser votre contrôleur de commentaires comme - mais vous devez changer le render à, par exemple redirect_to :back dans l'action create car le contrôleur de commentaires n'aura très probablement pas de "nouvelle" vue (dépendante du commentaire)

De même, assurez-vous d'avoir des itinéraires imbriqués pour toutes les ressources pouvant agir comme commentable, comme ceci:

resources :posts do 
    resources :comments do 
end 

resources :comments do 
    resources :comments # subomments 
end 

mis à jour pour refléter les informations dans les commentaires

+0

le probelem est en fait que '@commentable' est toujours nul .. ainsi les commentaires ne peuvent pas être appelés dessus. – tmaximini

+0

Le commentaire est votre message, vous devez donc vous différencier si vous êtes dans PostsController ou CommentsController. La méthode "find_commentable" doit être utilisée dans le CommentsController pour obtenir l'objet Post (vous ne savez pas avec certitude dans le CommentsController qu'il s'agit d'un Post - c'est pourquoi vous l'avez abstrait dans un "commentable"). Pour faire une histoire courte: Dans votre PostsController, ajoutez quelque chose comme "@commentable = Post.find (params [: id])" dans l'action de show. – emrass

+0

Mis à jour ma réponse. Le codage fourni devrait être suffisant pour vous diriger dans la bonne direction. – emrass

0

ne pas utiliser @commentable dans la vue du spectacle de poste, car il est défini que dans le contrôleur de commentaires.

Pour ce faire, à la place:

_comment.html.erb: (le commentaire partielle dans la vue du spectacle post)

<%= form_for ([comments, @vote]), remote: true do |f| %> 

messages/posts_controller.rb:

<%= form_for ([@post, @vote]), remote: true do |f| %> 
Questions connexes