This message was imported from the Ruby/Rails Modularity Slack server. Find more info in the import thread.
Hello folks! We’re currently evaluating packs-rails, experimentally extracting a first pack (roughly at the level of a typical Rails engine). One of the first tricky dependency bits we encountered was about associations between models within and the pack and models in the main pack. Any pointers on handling dependencies between Rails models (the fundamental, app-wide ones) in terms of public/private API?
We’re currently in the middle of doing the exact same thing and have been looking at namespacing our models to achieve this.
By adding a module (using the name of the pack) around the models of the pack, we have to specify class_name for any associations defined outside of the module, but we end up being very explicit that we are crossing a pack boundary.
Something else that’s interesting about this is we can also start having pack “variants” of models. For example we could have a base User model and then have a Pack::User < User model. For any associations to :user defined within the Pack namespace Rails will automatically use Pack::User and not User without having to specify a class_name
A downside of this is that STI and polymorphic type data stored in the database either needs to be migrated or, what we found works pretty well, we need to add self.store_full_class_name = false on the models that require this.
We would love to hear other teams’ approaches on this as well
We have a similar pattern. Suppose you have Foo and Pack::Bar and Pack::Bar belongs to Foo. The pattern I’ve been using (but am not super happy with) is to define both ends of the relationship in packs/bar.rb, e.g.
module Packs
class Bar < ActiveRecord::Base
belongs_to :foo
end
end
Foo.class_eval do
has_one :pack_bar, class_name: "Pack::Bar", dependent: :destroy
end
It’s working fine for us, but it feels kinda gross
Yeah, it’s a shame it’s not possible to set up a mapping for the values stored in type columns for STI / polmyorphic associations. But I’m getting sidetracked.
Thanks for your feedback! I guess it’s one of those things where dependencies are more implicit and cannot easily be discovered by static analysis like in Packwerk. Having to specificy a class_name is a good thing then, I agree.
If the underlying question here is what to do with cyclical associations, seeing that packwerk doesn’t allow cyclical dependencies, I would encourage people to take a look at DDD aggregates. They are essentially trees.
No, not so much about cycles, although that’s also interesting with AR associations, true. “Not discovered”: I meant associations defined based on conventions, without a class_name .
Packwerk has special handling for associations and should understand things like has_one :product. Is that what you mean by associations defined based on conventions?