(This is may be more of a db design question than a rails question.)
Summary:
I'm thinking of creating a single AR class to hold constant symbol
values and use it for :has_many_through relations whenever I need a
constant symbol. Is this a good idea or a bad idea?
Details:
I notice that I have a lot of models that contain just a name string:
create_table "natural_resources", :force => true do |t|
t.string "name"
end
create_table "roles", :force => true do |t|
t.string "name"
end
... etc ...
These moels are always joined through a has_many_through relation to
some other object (e.g. User :has_many :roles, :through => :user_roles),
and the names are treated effectively as constant symbols.
So I'm thinking of consolidating these models into a single one:
create_table :symbols, :force => true do |t|
t.string :name
end
add_index :symbols, :name, :unique=>true
class Util::Symbol < ActiveRecord::Base
validates :name, :presence => true
def self.intern(name)
(r = where(:name => name.to_s)).create!
rescue ActiveRecord::RecordNotUnique
r.first
end
end
... and using this wherever I'd previously used separate classes. This
feels DRYer.
Can anyone give a strong argument for or against this approach?
What problem are you trying to solve by doing this?
Just seems like it would make your code more complicated with no real
benefit.
DRYer code: this approach has fewer distinct tables, fewer distinct
classes, fewer things to test and maintain. But I may be missing
something (which is why I'm asking): what part of the code becomes more
complicated this with this approach?
Do you mean that the only thing in your roles and natural_resources
tables are the names?
If so then you could put them in one table. Consider the situation
where a role and a natural_resource happened to have the same name
however. If you decided to change the name of the role then that
would also change the name of the natural_resource.
Given your examples, I’m not convinced all of the things even need to BE in the database. One question I’d ask to help decide this is, “can an end-user meaningfully add a new one of these through the web interface?”
For example, “roles” typically would NOT be meaningful to add from the web interface - they require additional plumbing (unless you’ve got serious DB-driven RBAC already) in code above and beyond a simple name.
On the other hand, “categories” on a blog are a classic example of something that belongs in the DB; there’s no additional behavior expected, they’re just labels that can be attached to other things.
As to your original question, I’d lean towards “bad idea” - as others have pointed out, if the items in question are supposed to operate in separate domains they should be kept separate. This winds up simplifying lots of stuff - for instance, I can’t think of any reason one would want to display a drop-down with a mishmash of natural resources and user roles, but a list of one or the other makes sense.
If you’re really just looking for the ability to attach context-sensitive labels, you may also want to look at acts_as_taggable_on and friends: