Search code examples
ruby-on-railsruby-on-rails-3html-tablebelongs-to

Rails linked tables belongs_to or has_many not working


I have three tables User, User_types and Purchases.

  • user: id etc

  • user_purchase_types: id, typename, user_id

  • purchases: id, user_id, user_purchase_type_id, note

Users can have any number of purchases and user_types. A purchase can have one user_purchase_type.

Users can log in, create types, do purchases etc - this all works fine

However I want, when listing purchases, to see the user_purchase_types.typename, rather than the id number. Simple I think, use belongs_to, they already have the right id fields, should just work. But it doesn't

I have tried a million variations of belongs_to, has_many , has_many through etc etc but cannot get the right relationship and so show the typename rather than the id.

There are the right foreign_key id fields in the tables so this should work.

When listing the purchases in the purchase controller I use @purchase = current_user.purchases. When looping this to display in the view I think I should be able to use purchase.user_purchase_type.typename but this gives me a 'NoMethodError'.

What am I doing wrong or should I just denormalise the DB and have done with it?

EDIT Models as req

class UserPurchaseType < ActiveRecord::Base
  belongs_to :user
  belongs_to :purchase
  attr_accessible :typename, :id
end

class User < ActiveRecord::Base
   devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable

  has_many :purchases, :dependent => :destroy
  has_many :user_purchase_types, :dependent => :destroy
end

class Purchase < ActiveRecord::Base
   belongs_to :user
  has_many :user_purchase_types
  attr_accessible :date, :user_purchase_type_id, :note 
end

index.erb file

<% @purchases.each do |purchase| %>    #this works
  <tr>  
   <td><%= purchase.user_purchase_type.typename %></td>  #this fails
    <td><%= purchase.date %></td>
    <td><%= purchase.note %></td>
   </tr><p>
<% end %>

purchase controller

def index
  @user_purchase_types = current_user.user_purchase_types           # this works
  @purchases = current_user.purchases              #this works

Solution

  • You just need to add foreign key in your existing association.

    class Purchase < ActiveRecord::Base
      belongs_to :user
      has_many :user_purchase_types, :foreign_key => 'user_purchase_type_id'
      attr_accessible :date, :user_purchase_type_id, :note 
    end