0

I have a model named Post and a model named Category. Relationship between Post and Category is many-to-many. So I create a join table as following:

create_table :categories_posts do |t|
  t.integer :post_id, index: true
  t.integer :category_id, index: true

  t.timestamps
end

Here is my model Post (file name: post.rb)

class Post < ApplicationRecord
  has_many :categories, :through => :categories_posts
  has_many :categories_posts
end

Here is my model CategoryPost (file name: category_post.rb)

class CategoryPost < ApplicationRecord
  self.table_name = "categories_posts"
  belongs_to :post
  belongs_to :category
end

But when I try: Post.last.categories or Post.last.categories_posts I meet exception:

NameError: uninitialized constant Post::CategoriesPost

Please tell me where I am wrong.

Thanks

Trần Kim Dự
  • 5,872
  • 12
  • 55
  • 107

1 Answers1

3

NameError: uninitialized constant Post::CategoriesPost

The plural form of CategoryPost is CategoryPosts, so you should use category_posts instead of categories_posts when defining associations

class Post < ApplicationRecord
  has_many :category_posts
  has_many :categories, :through => :category_posts
end

However, if you want to use categories_posts, you can do with by defining class_name on the association

class Post < ApplicationRecord
  has_many :categories_posts, class_name: "CategoryPost"
  has_many :categories, :through => :categories_posts
end
Pavan
  • 33,316
  • 7
  • 50
  • 76
  • thanks. It works. The thing I don't understand is: I use `categories_posts` because it follows rails convention. why it doesn't work ? thanks. – Trần Kim Dự Jul 22 '17 at 05:48
  • the join table I also use `categories_posts` – Trần Kim Dự Jul 22 '17 at 05:51
  • @TrầnKimDự There is no convention when defining a third model for `has_many :through`. It should be a correct plural form when defining associations. You can check in console with `"CategoryPost".pluralize` – Pavan Jul 22 '17 at 05:51
  • I have read at this: `https://stackoverflow.com/questions/11590469/rails-naming-convention-for-join-table` – Trần Kim Dự Jul 22 '17 at 05:58
  • So it looks like if I follow this convention for defining relationship, I must manually set class name or table name in model, right. – Trần Kim Dự Jul 22 '17 at 06:00
  • @TrầnKimDự That convention is for *HABTM* association not for `has_many :through` – Pavan Jul 22 '17 at 06:01
  • so in case I need `accepts_nested_attributes` I will define `accepts_nested_attributes_for :categories_posts`, right? and when inserting, the attributes should be: `categories_posts_attributes`? thanks. – Trần Kim Dự Jul 22 '17 at 06:26
  • @TrầnKimDự Yes, thats right. Please accept my answer :) – Pavan Jul 22 '17 at 06:28
  • `accepts_nested_attributes_for :categories_posts` I have defined this. but when I run, I meet following exception, do you know why: `ArgumentError (No association found for name `categories_posts'. Has it been defined yet?):` – Trần Kim Dự Jul 22 '17 at 08:31
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/149873/discussion-between-pavan-and-trn-kim-d). – Pavan Jul 22 '17 at 08:45
  • @TrầnKimDự Let me know when you are available, we can discuss the issue in the chat and close this :) – Pavan Jul 23 '17 at 07:32
  • thanks. I can resolve by myself :D thanks so much for supporting me. – Trần Kim Dự Jul 24 '17 at 04:26