andreobrown
andreobrown

Reputation: 156

Rails has_and_belongs_to_many ActiveRecord::UnknownPrimaryKey

I am having difficulties getting a has_and_belongs_to relationship working.

Category model:

class Category < ActiveRecord::Base 
  has_and_belongs_to_many :products
end

Product model:

class Product < ActiveRecord::Base
  has_many :orders, foreign_key: 'sku', primary_key: 'sku' 
  has_and_belongs_to_many :categories       
end

I'm using an existing database, and created models for all the data needed, mapping the columns to the rails naming convention.

Here is the structure of the views:

Categories view:

categories
    id
    name
    category_parent

Products view:

products
    id
    sku
    price
    title

Categories Products merge view:

categories_products
    category_id
    product_id

Here is what I've tested this with at the console, and the error produced:

2.0.0p247 :017 > Product.first.categories
  Product Load (1.0ms)  SELECT `products`.* FROM `products` LIMIT 1
ActiveRecord::UnknownPrimaryKey: Unknown primary key for table categories in model Category.

I have tried removing the other association from the product, just to eliminate any possibility of conflict:

has_many :orders, foreign_key: 'sku', primary_key: 'sku' 

But the result is the same without it.

The other association works fine:

Order.first.product
  Order Load (2.9ms)  SELECT `orders`.* FROM `orders` ORDER BY `orders`.`id` ASC LIMIT 1
  Product Load (5.7ms)  SELECT `products`.* FROM `products` WHERE `products`.`sku` = '826663144369' LIMIT 1
 => #<Product id: 218464, sku: "1234567890", price: #<BigDecimal:7fabdb577428,'0.2195E2',18(18)>, title: "Blah blah blah"> 

I'm using Ruby 2.0.0p247, and Rails 4.0.0

Upvotes: 4

Views: 2122

Answers (4)

Koen.
Koen.

Reputation: 27009

I ran into this issue when creating join tables for a 'has many through' relation without an id column.

class CreateMemberships < ActiveRecord::Migration
  def change
    create_table :memberships, id: false do |t|
      t.references :project, index: true
      t.references :user, index: true
    end
  end
end

The fix was setting the primary_key to both project_id and user_id, so in the model:

class Membership < ActiveRecord::Base
  self.primary_key = [:project_id, :user_id]
  belongs_to :project
  belongs_to :user
end

Upvotes: 0

Jamie Folsom
Jamie Folsom

Reputation: 1297

I ran into this issue just now myself, and in my case it was due to the fact that I had restored data from a production application to a local copy that had additional views not present in the production version. On restore, the data (including the correct schema) from production were imported, but the more recent schema I had in my local development db still included a view which was created by a migration that lived in another branch of the app. Deleting the local database completely, and rerunning the pg_restore on a fresh copy of the development database removed the view the branch of the app I am on doesn't know about. Hope that helps.

Upvotes: 0

andreobrown
andreobrown

Reputation: 156

I got it working with the following addition to the Category and Products models:

self.primary_key = :id 

I'm guessing that rails cannot identify the primary key to use for the association since I'm using a view, and views don't have keys.

Upvotes: 3

phoet
phoet

Reputation: 18845

i have a lot of questions and there is not enough space in the comments, so i just write an answer for that.

you say that

I'm using an existing database, and created models for all the data needed, mapping the columns to the rails naming convention.

do you mean that you create VIEWS in the database to map things to the rails naming conventions?

i'm also a little confused why the sku column is used as a foreign-key and the primary-key eventhough the table has an id column. but it looks like this relation works fine.

the only reason that i know of (there are probably a lot more) for a ActiveRecord::UnknownPrimaryKey error is when one of the model tables is missing an id column, but both, categories and products seem to have one from what you write.

Upvotes: 0

Related Questions