Namespacing models in a Rails application - ruby-on-rails

I had a discussion recently with a friend of mine who is also a RoR developer. We argued about how Rails models should be managed. Personally I like to leave in the default namespace only the root models (e.g. User, Article, Bill etc.), and the dependent models go to a module (e.g. User::Profile, User::Activity) with the name of the root model they are associated with.
On the other hand, I've seen many projects which had like 100 models in the default namespace called like user_profile, user_activity and so on. Judging by Java (Spring) development, java community tends to organize class in packages and have them grouped logically, which I find very appealing.
So the question is: are there any drawback in grouping models in modules (except the extra :class_name in relation definition) and are there any specific reasons why people usually don't do it?

Although namespacing has its advantages, it does require adding exceptions throughout your models. Foo::Bar presumes a table name of bars and likewise bar_id for associations, whereas you might prefer foo_bars and foo_bar_id to be used instead.
If you really feel strongly about this, you might want to see if there's an add-on that fixes this for you, or implement your own extension that does.
The only case when I've used namespaces is for add-ons that are to be used in third party applications where I don't want to claim root-level model names as that would be annoying. The extra effort in this case is worth-while.
If you're bothered by seeing 100+ model files without any grouping, you'll probably be equally annoyed by seeing 100+ tables with no grouping, and that's generally something you can't fix.
Controllers lend themselves to grouping quite naturally, but models aren't as easily accommodated, at least not with stock ActiveRecord.

Related

How do I partition Rails app into logical parts?

So I am a fairly seasoned Django developer and I've been using Ruby on Rails for about a year. I'm working on a project with, let's say, 100 models. In my actual scenario, I'm writing a "component" to the app, which requires 2 models, one of which I wanted to call Event, however there is another piece of the software which uses an Event model in a totally different context. In Django, this is resolved by splitting the "components" into "apps", and models can have the same name because they are in a different app.
Is there is a similar pattern in Rails to separate some models in their own package to avoid name conflicts, but also so that each separate component can have it's own README which describes how that component behaves? I don't require that it have it's own controllers/views, since right now we have a single frontend interface, but I would be interested to hear if there is a pattern for that too. I've heard the term "engines" in Rails, but that seems to imply a total decoupling and unidirectional dependency scheme like for a generic 3rd party app, where as in my case, there is still some coupling between this "component" and the rest of the app, but it still seems reasonable to have some way of grouping models logically.
Also, I'm wondering how this case is handled in general. When a web application grows organically to have tons and tons of models, is there a standard pattern for managing this complexity?
You can use namespacing using modules for your models.
For example Foo::Bar or Baz::Bar like this:
module Foo
class Bar < ApplicationRecord
end
end
To associate this model with table foo_bars, you can implement the method:
module Foo
class << self
def table_name_prefix
'foo_'
end
end
end

Sharing AR models between Rails applications

I have a problem that I have been trying to solve for a while now. I have 4 different Rails applications using the same database, meaning they need to use the same models and have the same migrations. I initially solved the problem by creating a Rails engine packaged into a gem, which then carries all the models and migrations with it. Now I realize that there are pieces of functionality that only one application needs, but the others do not - like for example the admin application needs to have methods for providing sortable tables for all models - the other applications do not need this functionality at all.
So my idea was to find a way where I can provide the "base" models from the gem, while augmenting these base models in my specific applications to add additional functionality when needed. What I tried first was inheritance:
class User < Base::User
end
This does not work though, because now you have 2 User models in your load path (User and Base::User) and when querying associations, it always picks the "closest" class for the associated record class - meaning when you have an Model::Account which belongs_to :user, it will pick Model::User as the association class, not User. I tried reversing the AR type compute method but this only resulted in more problems.
I can technically provide all of my models from the base engine (gem), but the issue here is that how do i extend these models in my application? .class_eval feels really really dirty, inheritance does not work, providing base functionality as mixins means the "base" models do not feel and look like models at all. My goal would be to cause as little friction as possible for the other developers, I want them to be able to define their models in the gem like they do normally and then also have an easy way to extend that functionality in other applications.
Has anyone solved this problem before or have any suggestions? Or how do you guys solve this problem in your larger applications? Any help would be appreciated.
This is mentioned in the Rails guides. It describes class modification with the Decorator pattern.

How to handle similar items in rails MVC?

I'm working on building a pretty simple site mainly as an exercise in
learning more about rails. You can see my rough progress at
statific.com. It's working pretty much as I wanted it for
keeping track of server information, but now I'd like to expand it to
other things, next on the list being firewalls.
I can pretty easily duplicate all the models, views, etc.. that I have
for my servers. The problem I see with that is that it isn't very DRY
since most of the code would look the same, the only difference would
be the attributes I have setup for firewalls would be different than
for servers.
I know in plain ruby this is pretty simple, you can have a 'Product'
w/ common attributes ('manufacturer', 'model') and then have children
with more specific attributes. Does the same type of concept exist
for rails, or am I just over thinking this?
Use STI (please don't poke me to death. I'm just kidding).
All common functionality should be moved to modules and included into different models (server, firewall, etc.) as needed. In this particular situation you could have a module Hardwareable and include it into your server and firewall models. And leave different attribute to appropriate models.

Is this a legitimate use of Rails' Single Table Inheritance?

I've just been reading Chad Fowler's blog post about 20 Rails Development No-Nos. On Single Table Inheritance he comments:
The storage of a column called “type” which holds a class name is a pretty good indicator that something fishy is going on. It’s fishy but not always bad. I think, though, that any time you use it you should ask yourself more than once if it’s the right solution. Databases don’t do what they do best as well when you have lots of STI and polymorphic associations.
I'm writing a blog application and I'm considering using STI for the comments that can be made on a post and for the contact messages that visitors can post if they want to get in touch with me. My Message model will inherit from my Comment model. They both share common attributes, except that Message will have an extra subject field. Another commonality is that both will be submitted to Akismet for spam checking.
Rather than just ask myself more than once if it's the right solution as Chad suggests, I thought I'd get some opinions from the Stack Overflow experts as well! Does what I'm proposing sound like a good fit for STI?
I've used STI a number of times. Consider a CMS which might have Page, NewsItem, BlogItem etc.
They could each descend from a common class which in turn inherits from ActiveRecord. The table for each would be the same (title, body, tags, published_at) but each model might have different associations, or different statuses, or a different workflow so each has custom code in their own class. Yet they all share a common table and parent class. It also allow me to use the parent class to do a cross class search and have the resulting Array of records automatically type cast.
There are other ways to tackle this and maybe not the best example but there are certainly times when STI is handy for situations where object behavior may differ but persisted state is the same. Of course you have to be sure this is also true in the future.
In your case comments and contact messages are different. It sounds like there is there no benefit by having them in the same table. Maybe put shared code in a parent class or better still in a module in /lib.

Namespaced models in Rails: What's the state of the union?

Since the beginning, Rails has had issues with namespaced models. As time went on, pretty much everybody gave up on using it. Myself included.
With Rails 2.3 out, I'd like an update on the situation. Specifics questions I have in mind are:
first off, is it good to go?
table naming, what rule to follow?
associations, how to declare them with the least verbosity? how to name foreign key columns?
auto-requiring, does it work if you put the model files in a subdir matching the namespace? or, how to name and where to place the files?
generation, does the model generator handles namespaces successfully and correctly?
generation, how about the scaffold generator, which includes controllers?
any incompatibilities/quirkinesses one should be aware of?
The best writeup I've seen on the issue is from Strictly Untyped. To my knowledge 2.3 hasn't resolved any issues, which means they're still unreliable.
We recently had a big debate about this inside our company. I think at the end of the day, we figured that if you can't namespace tables inside a database, it makes no sense to namespace the models. We settled on prefixing our models (User, UserAddress, UserEmailAddresses) and putting them into the users directory, then using:
config.load_paths << "#{RAILS_ROOT}/app/models/users"
to load the models. To control the verbosity in our models, we do this frequently:
has_many :addresses, :class_name => "UserAddress"
When generating, we create it as if there was no namespace (script/generate model UserAddress) then manually copy it to the user directory.
Shrug. I guess in the end all this really gives you is a cleaner directory structure, which is actually more trouble for a VIM user like me, but nice for TextMaters.
I would still stay away from it. Anything gained (which I'm not sure what that would honestly be) would definitely be lost when you consider the hassle and loss of brevity and clarity in your code.
My latest app has 87 resources, and includes administrative features all over the place. I see no need for namespacing, IMHO.

Resources