Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails Engine: Namespacing foreign key references to other models in the same engine

I've set up a namespaced Rails 3.2.19 engine w/ MySQL for the DB called TestAppTv with 2 models: Post and Comment.

I want Comments to belong to Posts, but I want it to refer to TestAppTv::Post specifically. I know that I can do this by specifying class_name along with my belongs_to/has_many calls.

module TestAppTv
  class Comment < ActiveRecord::Base
    belongs_to :post, class_name: "TestAppTv::Post"
    attr_accessible :text
  end
end

module TestAppTv
  class Post < ActiveRecord::Base
    has_many :comments, class_name: "TestAppTv::Comment"
    attr_accessible :text, :title
  end
end

Now, my confusion is in the database. It seems that the foreign_key by default in the test_app_tv_comments table is "post_id". However, it seems to me that this isn't following the same namespacing idea as the rest of the application. It seems like it would be ambiguous whether post_id was referring to test_app_tv_posts.id or some base posts.id table from the base application or another engine.

Is there some proper way to namespace the foreign_key that rails will use by default for all of the built-in magic?

When I've tried to use foreign_key to manually specify the key as test_app_tv_post_id, I end up running into lots of issues around "inverse", and the default magic helpers not working anymore. For example, doing TestAppTv::Comment.create(post: TestAppTv::Post.first, text: "test") doesn't work, and I have to specify the foreign_key field automatically.

Thanks for any advice or help on this topic! I appreciate it!

like image 458
Andrew Shogren Avatar asked Oct 14 '14 21:10

Andrew Shogren


1 Answers

If anyone finds this post in the future and was confused as I was at why the foreign key wasn't namespaced the same, the answer is that it doesn't matter that it's not namespaced.

Since Ruby handles class lookups by first looking within the current module and then up the module tree to the base namespace, models that are defined within the same Rails engine are used before any models defined in the base application the engine is included in. This means that a field of "post_id" is sufficient for namespaced engines referring to a particular TestAppTv::Post since TestAppTv::Post is what is found first when a lookup for the class "Post" is made within the TestAppTv engine's module.

This wasn't mentioned anywhere as far as I know, so I think this is probably something that is just assumed to be common ruby knowledge. I hope this can help others out there.

like image 103
Andrew Shogren Avatar answered Oct 01 '22 18:10

Andrew Shogren