简体   繁体   中英

Rails 4 - Polymorphic associations - multiple associations

I am trying to make a Rails 4 app.

I have a comments model which is polymorphic. I also have models for user, profile and article.

The associations are:

article.rb

belongs_to :user
has_many :comments, as: :commentable
accepts_nested_attributes_for :comments

comments.rb

belongs_to :user
belongs_to :commentable, :polymorphic => true

profile.rb

belongs_to :user
has_many :addresses, as: :addressable

user.rb

has_many :articles
has_many :comments
has_one :profile

I'm struggling to understand how this works in practice.

When I use my console to create a comment as follows:

Comment.create(commentable: Article.first, user_id: "1", opinion: "test") Article Load (15.5ms) SELECT "articles".* FROM "articles" ORDER BY "articles"."created_at" DESC LIMIT 1 (0.2ms) BEGIN SQL (6.3ms) INSERT INTO "comments" ("commentable_id", "commentable_type", "user_id", "opinion", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["commentable_id", 3], ["commentable_type", "Article"], ["user_id", 1], ["opinion", "test"], ["created_at", "2016-01-01 01:51:20.711415"], ["updated_at", "2016-01-01 01:51:20.711415"]] (1.3ms) COMMIT => #

That works.

However, when I go to the view and try to create a new comment using the form, I get:

SELECT  "articles".* FROM "articles" WHERE "articles"."id" = $1  ORDER BY "articles"."created_at" DESC LIMIT 1  [["id", 3]]
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1  ORDER BY "users"."id" ASC LIMIT 1  [["id", 1]]
Unpermitted parameter: comment
   (0.2ms)  BEGIN
   (0.1ms)  COMMIT
[ActiveJob] Enqueued Searchkick::ReindexV2Job (Job ID: 4fd1ceb5-7882-4381-a2df-5913082af621) to Inline(searchkick) with arguments: "Article", "3"

Nothing happens.

Further, I tried following the example in this video tutorial (around 7m:30s):

https://gorails.com/episodes/comments-with-polymorphic-associations?autoplay=1

I changed my comments partial, which was working to display comments created in the console (but not in the view form) from:

<% @article.comments.each do | comment | %>
  <div class="well">
    <%= comment.opinion %>
    <div class="commentattribution">
      <%= comment.user.formal_name_and_title %>
    </div>
  </div>
<% end %>

to add a local variable in my articles show page where I render the comments partial:

<%= render 'comments/display', locals: {commentable: @article} %>

and replace @article in the opening line with @commentable:

<% @commentable.comments.each do | comment | %>
  <div class="well">
    <%= comment.opinion %>
    <div class="commentattribution">
      <%= comment.user.formal_name_and_title %>
    </div>
  </div>
<% end %>

Now, when I save that and try to render the article show page, I get this error:

undefined method `comments' for nil:NilClass

I don't understand what this error message means, but it was all working fine until I tried to reference commendable instead of article. The specific line item referenced in the error message is:

<% @commentable.comments.each do | comment | %>

Can anyone see what's going wrong here?

When I try:

<% commentable.comments.each do | comment | %>

I get this error:

undefined local variable or method `commentable' for #<#<Class:0x007fd13b93dac8>:0x007fd134530270>

I have read some other posts where people have had trouble with polymorphic associations belonging to more than one resource. For example, my comments belong to users as well as articles. I've not been able to follow the resolution or properly grasp the issue with that arrangement.

Joe Half Face's solution worked for the comments form, but the only part that isn't working now is getting the name of the user that wrote the article to appear on the page.

In my articles show page, I have:

<div class="articletitle">
                    <%= @article.title %>
                </div>    
                <div class="commentattributionname">
                    <%= @article.user.try(:formal_name) %>
                </div>
                <div class="commentattributiontitle">
                    <%= @article.user.try(:formal_title) %>
                </div>
                <div class="commentattributiondate">
                    <%= @article.created_at.try(:strftime, '%e %B %Y') %>
                </div>

The title, shows and date created shows, but neither of the user attributes appear.

It's just a blank div container showing in the code inspector.

1) If you pass variable to partial, it goes as local, not instance:

<%= render :partial => 'comments/display', locals: {commentable: @article} %>

2) Also note that rendering from controller and rendering from view is different things. In controller you don't have to specify :partial=> as controller in Rails should render entire template, but if you are in view file you should as Rails can render only one template per request

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM