lflores
lflores

Reputation: 3800

Rails polymorphic association error

I'm having problems with a polymorphic association.

A quick explanation about my project. You can see it here: majorfinder.com On my app there will be majors, schools, and careers. I want to be able to add reviews for each. Since I'm just starting out I'm just beginning with adding reviews for majors but creating the association so that when I get to the careers and schools the reviews association will go quickly.

Here are my associations:

models/review.rb

belongs_to :user
belongs_to :reviewable, polymorophic: true

models/user.rb

has_many :reviews

models/major.rb

has_many :reviews, as: :reviewable

My db schema for reviews looks like this:

create_table "reviews", :force => true do |t|
    t.text     "review"
    t.datetime "created_at",      :null => false
    t.datetime "updated_at",      :null => false
    t.integer  "user_id"
    t.integer  "reviewable_id"
    t.string   "reviewable_type"
  end

In my majors controller I've followed this railscast in order to create a url that looks like this www.majorfinder.com/majors/major-name. So part of my majors controller looks like this:

def show
    @major = Major.find_by_slug(params[:id]).includes(:reviews => :user)
end 

In my majors show page I have:

<% @reviews.each do |review| %>
    <div>
      <h3><%= link_to review.review,
        :controller => "reviews", :action => "show", :id => review.id %></h3>
      <small>Posted on <%= review.created_at %> by
        <a href="#"><%= review.user.profile_name %></a></small>
    </div>
  <% end %>

And lastly, here are my routes:

resources :majors, has_many: :reviews

I'm getting the following error:

NoMethodError in MajorsController#show

undefined method `includes' for #<Major:0x007f9466e001a8>

Here it is from the console:

Started GET "/majors/statistics" for 127.0.0.1 at 2013-03-05 07:45:01 -0700
Processing by MajorsController#show as HTML
  Parameters: {"has_many"=>:reviews, "id"=>"statistics"}
  Major Load (24.2ms)  SELECT "majors".* FROM "majors" WHERE "majors"."slug" = 'statistics' LIMIT 1
  CACHE (0.0ms)  SELECT "majors".* FROM "majors" WHERE "majors"."slug" = 'statistics' LIMIT 1
Completed 500 Internal Server Error in 28ms

NoMethodError (undefined method `includes' for #<Major:0x007f8ad51fdd00>):
  app/controllers/majors_controller.rb:16:in `show'

Line 16 in the majors_controller.rb file is this one:

@major = Major.find_by_slug(params[:id]).includes(:reviews => :user)

Can you see what I'm missing or what I should change? It seems like the solution is simple but I am not sure what it is. Thanks in advance for your help!

Upvotes: 0

Views: 320

Answers (1)

rocket scientist
rocket scientist

Reputation: 2447

I believe what you are trying to do is eager load :reviews when you find the Major. You are close but your order is backwards. It needs to be

@major = Major.includes(:reviews => :user).find_by_slug(params[:id])

For more information on eager loading checkout this RailsGuides article.

Upvotes: 1

Related Questions