Namespaced models in Rails: What's the state of the union? - ruby-on-rails

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.

Related

Cleanly Setting up multiple models in FactoryGirl for a test/spec

I have been picking up on Rails best practices and learning to write good tests for my rails application.
I am using rspec + FactoryGirl to test at the moment.
For a while I was writing basic model and controller specs which usually required to set up only a couple of models and associations.
Now I have a Model with a complex algorithm which does a lot of calculations based on different models.
To test this method, I almost need all the models of my app to exists in test database with all associated relationships built between them.
Now things are getting overwhelming. I need to keep track if all factories are correctly referencing each other. Also I need to verify if all factories have been created properly.
Also a lot of FactoryGirl.create(:model) calls in my before(:each) method.
I have a feeling that I am not doing things right. What is the best way to go about this situation? Most books and examples only cover only the very basic cases.
Any pointers ideas and approches are welcomed.(Hope this question is not too wide in scope)
Example:
My application has multiple projects. Each project has_many indexes , companies and mastertags. Each company has_many channels. Every channel has_many channel_tag_weights across different mastertags. Also every channel has_many Rawdatas.
This could be an example of a minimum model setup required.
I wrote a gem for this called stepford.
In your gemfile:
group :test do
gem 'stepford'
#...
end
Then bundle install.
Back up your factories.rb or existing multiple files containing factories. In fact, you need to move them out of the way because if it loads other factories, that can interfere.
Then: bundle exec stepford factories --path spec (if want to put factories.rb in the spec dir- there are other options to create a factory per model, etc. though).
We had problems with dependencies that needed to be created where there were foreign key constraints. In the process, I wrote the modelist gem that can help identify circular dependencies, which you might want to check out and run if you are working with legacy data. And Stepford's deep creation methods get around these issues. But, we've started to steer away from using the deep_* methods of Stepford, even though we still use it a little. It is just better to be specific about what you are doing and use factory girl directly, even though it can make test code more brittle and overly-complicated looking.
You could also look at fixtures, or machinist. It really just depends on what you need.
If you need to actually create all of the code for the models, that is a different problem. I wrote a script to generate models for the local legacy schema (which was quite large), and it did help, but it took months of iterative work. The thing is that the schema itself is not (necessarily) the definitive description of the associations or setup in the models. To give you an idea of what I'm talking about, I wrote a number of gems to assist with some of the things that legacy apps, etc. were doing/had done that we had to deal with like undeletable, activerecord-define_nils, mark_only, activerecord-custom_timestamps, activerecord-native_db_types_override, and some others in earlier attempts. And we use some great gems that already existed like composite_primary_keys and foreigner.
Some other things we grappled with was using of MTI (multiple table inheritance), which despite a few gems out there that try to help, we ended up handling it ourselves in our models via hooks, etc. And we merged some schemas (not something to take lightly, but the divisions weren't necessary, and apartment, second_base and similar gems would be adding to the complexity, not even considering inability to join, use normal queries).
Please note: in our case we had a lot of tables. If you don't have quite as many, you still might use Stepford to maybe make the first creation of factories a little easier, but then I think you will be ok.
Whenever I get into this type of situation, I try to make sure that all of my FactoryGirl models take advantage of FactoryGirl's built in association methods:
https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#associations
That way the associated models that are required in order for a single model to validate properly are present. FactoryGirl will go through the process of populating your database with the extra test data.
Because you are using has_many associations, you will want to study the after(:create) method of the factory definition in order to set up your associations properly. This will also allow you to create definitions specific to these deeply integrated specs, and keep simpler factories independent for the simpler specs.
If you are testing only a method, that is unit testing.
I don't think you need to setup too many things.
A method has input and output, you just feed it with examples of inputs created by you manually, and expect it to generate right output.
If a method has too much things to concern, you can split it into several methods, and unit testing each one.
When times for integration testing, the whole environment should be setup. And yes, you need to prepare all the factories needed.

Namespacing models in a Rails application

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.

Un-bloating models in rails 3.1

Just learning rails, developing first app and having trouble finding a straight answer to this question!
I want to keep my models as lean as possible and really only want to use them to represent objects that I might want to render in my views. Therefore, I want to remove some of the logic from one particular model and store it in a separate file. I have seen numerous guides (on this site and others) that suggest the following;
never "require" anything from inside a rails app
Store additional files in the lib folder - they used to be auto loaded in older rails releases but now you need to add an extra line in a config file to get this to happen (Example.
So I added the line, stuck the file in the lib folder, and it all worked fine. So on to the question;
I can't shake the feeling that the fact that I had to go and put some bespoke code into the config file means I'm doing this wrong (given convention over configuration). Why are people having to faff around editing configuration files to get rails to do something so basic?
Is that the best way or are there additional considerations that I'm just not seeing? Should I in fact be creating an "extras" directory rather than still sticking things in lib?
If anyone can point me in the direction of a definitive article on the matter I'd be much obliged!
There is nothing wrong with having non active record models in the model folder. If your domain is best modeled by a business logic layer and a persistence layer, then model it that way in your model folder with appropriate naming conventions. Personally I wouldn't be overly concerned with getting it perfect. Try something and see how you like it.. learn from your mistakes and keep getting better! Above all, enjoy the process.
what I do is this: keep the model logic in the model and keep the controllers as thin as possible
If there are things that should belong to your model but are somewhat distant to it (for example you have an Account model and you're working on some payments system which relates to the Account - for example you might want to call account.has_subscription?, you could use a gem called concerned_with which would split your model's main actions from others like the ones handling payments (this is just an example I recently had to take care of).

Helpers in rails

I'm just starting out in Rails and there's a lot I still need to learn so I'm likely to be on Stackoverflow more often than normal asking beginner Rails / Ruby questions.
I'm just trying to figure out how Helpers work in Rails. From what I've seen so far, Helpers are intended to be used with Views and not so much with your Controllers.
However I would like to make a simple function that will validate the user input given in params (check if certain params are defined and optionally check if their value is valid).
Can anyone explain to me what would be the best way of implementing this? (Keeping in mind that I will want to use this in many different controllers so it should be globally available.)
I also noticed that by default Rails does not generate a lib folder in the main application folder. Are developers to place their libs outside the app folder in the main folder, or does Rails use libraries differently?
With regards to your validation issue, it depends on what you are validating.
If the data makes up objects from your problem domain, also known as models, then you should use the built in validators from ActiveModel. This is probably what you should do, but its hard to say without knowing the exact problem. See the Rails Guides on Validations. You can tell if this is the case by asking yourself if the data that needs validation will be stored after you get it. If so, its most definitely a model. An example of this kind of data would be the title and text fields of a blog post being sent to Rails from a browser form.
If the data is something tertiary to your models, or specific to presentation, then you should be fine using helpers. You noticed that helpers are used mostly in the views, and although this is true, theres nothing stopping you from using them in the controllers, you just have to declare that you will use them using the ActiveController#helper method. Inside the ApplicationController class, a lot of devs will put helper :all to just include all the helpers in all the controllers. Once the code has been required once, it doesn't really incur that big a performance hit.
Do note that almost all incoming data can be modeled using a model. A big school of thought in the Rails world subscribes to the Fat Model idea. People say that putting as much code as possible in the model and as little in the controller as possible separates concerns properly and leads to more maintainable code. This suggests that even if you don't think the incoming data is modelable (in the sense that you can create a model to represent it), you should try to make it a model and encapsulate the logic around validating it. However, you may find that making a helper function is faster, and either will work.
Your notion of validating user input is a good one. I get the feeling that as you are new to Rails you are used to doing these things yourself, but that doesn't quite apply here. In the Rails world, a lot of the common stuff like validations is handled by the framework. You don't have to check for presence in the params array, instead you call validates_presence_of on the model and let Rails spit the error out to the user. It makes things easier in the long run if you let the framework do what it is designed to.
With regards to your question about the lib folder, it doesn't really matter. You can put miscellaneous support files and libraries in the lib folder in the root directory and they will be available for use in your application (the files in the app folder). You can also choose to abstract your code into a plugin or a gem and include it that way, which a lot of people opt to do. My suggestion for this would be to read up on the notion of gems and plugins before diving in.
Want you want is probably a custom validator (in Rails3):
http://railscasts.com/episodes/211-validations-in-rails-3
You can either add libs in a lib folder you create, or add them to config/initializers in a file you add. Files in the initializers directory are automatically loaded by Rails.

Models in Rails are implicit, is this an annoying thing?

Considering models in Rails:
class Organization < ActiveRecord::Base
belongs_to :OrgType
end
Does it bother you that models in Rails don't include the fields that made the entity?
I know this is done for DRY's sake but you have to check the data base tables schema every time you want to check model's fields.
If you prefer a declarative style of ORM model, you might want to check out DataMapper or Sequel, both of which are easy to plug in to Rails 3.
Not annoying for me... ever since I started using the annotate-models gem to automatically add comments to the top of my model files, listing the fields associated with that model.
I was listening to a podcast a few months ago where the guy hosting the cast and the guest were advocating that Rails should take this path, and do away with migrations. The guy kept repeating "migrations must die", suggesting there be a way to specify your schema on the model instead.
I cannot disagree more, and I hope Rails never takes this path. Not only is it not DRY, but I like the fact that Rails encourages you to be aware of your own databases schema and structure.
In addition, there would be no way to keep a history of your schema if models were what controlled it, without having them be extremely cluttered. Migrations are essentially version control for your database that evolves with your application...and I wouldn't want to not have that.
Let's assume that OrgType has a field called position. This is common when you want to present a select list to the users who will be choosing a type. It's highly unlikely that your Organization will ever care about this field. Now extrapolate this to other related models with fields that other models don't care about, and add in the fact that if you ever wanted to change one of these fields you'd then have to hunt down each declaration of them, not just each place where they are used.
It's a mess.
Open up your db tool and look at your fields when you want to know what they are. Keep your models clean and readable. If you see code like this:
organization.org_type.name
It's pretty obvious that OrgType has a name field, without having to look it up, and without having to wade through configuration clutter in each model.

Resources