Handling namespace models (classes) in namespace - ruby-on-rails

I am using Ruby on Rails 3 and I would like to handle models (classes) namespaces within namespaces. That is, if I have a namespace named NS1 and a "sub-namespace" of that namespace named NS2, I would like to handle models (classes) in NS2.
If I run a scaffold
rails generate scaffold ns1/ns2/Article id:integer title:string
it will generate following model files:
models/ns1/ns2/article.rb file
models/ns1/articles.rb
The models/ns1/articles.rb contains:
module Ns1::Articles
def self.table_name_prefix
'ns1_articles_'
end
end
What is the models/ns1/articles.rb file? How and why can I use that? Have you advices about using that?
And, in general, what is "the best" way to handle "composed" classes in namespaces using Ruby on Rails?

The
models/ns1/articles.rb
is basically setting the table name prefix for all the model classes under that namespace. Thats its use. It's more DRY'ish to do in there (in a single file), rather than setting the prefix in every model class under that namespace.
I am not a big fan of using namespaces in my models. However you could refer to the following articles to gain a better understanding about using namespaces in modules.
Namespaced models and controllers
Some alternatives to using namespaces in models
A simple alternative to namespaced models
Hope this helps.

Related

Rails 5 - Namespacing models

I am using namespacing in my Rails 5 app to try to keep resources organised.
I've been generating resources using the command line by adding the namespace folder to the generate command.
This makes a folder in the models folder for the main folder which the namespaced files are saved in.
I've since been reading posts from others that suggest namespacing models is not a good idea.
An example of what I currently have is:
class Stance::Assessment < ApplicationRecord
It seems to work alright so far.
What is the problem with namespacing models?
If it is a problem, does that mean I can't organise my models into folder groups, or does it mean that the model class doesnt need to be named wiht the "Stance::"?
There is a certain cost of complexity involved with "namespacing" your models. Ruby does not actually have true namespaces. Rather it has has modules which provide encapsulation.
Rails and ActiveRecord was designed around placing your application code in the Main object (the global object). While this might seem like a bad practice it is very simple and works well with the convention over configuration approach. It also allows a much simpler autoloading scheme and avoids the need to nest every single file in an additional folder.
Namespacing does have great organizational merits though and lets you avoid collisions. But there are a few minor aches in the backside:
table prefixes, having the generated table names like my_app_projects_tasks is really inconvenient when you need to write a custom join.
You need to override ActiveModel::Naming so that it does not look for paths like my_app_projects_tasks_path when using the polymorphic route helpers.
You need to explicitly set the class_name option when creating associations or override how ActiveRecord resolves constant names.
you can prefix your models, so instead of Stance::Assessment you would have StanceAssessment. not as clean as a namespace but it's pretty close to it

Default namespace of models in Rails

After upgrading my Rails app, I have run into a problem where the name of one of my models are conflicting with another class in Rails, namely Configuration.
Is there a way for me to (from a controller) explicit use my model class Configuration instead of ActiveSupport::Configurable::Configuration? What is the default namespace for my models?
You can use ::Configuration to call your class. It means that you're referring to the constant Configuration from the toplevel namespace. But I think it's annoying. You can rename your class to avoid this.

Classes in subfolders in app/models don't get loaded?

I would like to have a folder of related Models in my Rails 4 app. Why don't classes in app/models/debt_models get loaded?
I guess there is a work around by how come Rails just doesn't recursively go through folders under app/models? Is there a reason? Seems like this is something Rails should do without me having to tell Rails to do that.
You just have to follow conventions. If you put models in debt_models, it means you namespace them like:
module DebtModels
class Foo
Path: app/models/debt_models/foo.rb

Models with reserved keywords

I want to create a model called 'File', but it is a reserved model name is rails. I can't think of anything else sane to call the model, so I was wondering if there is a standard way of dealing with this issue, for example adding a prefix or suffix (_File, FileItem, etc)?
This problem is addressed with modules:
Modules are a way of grouping together methods, classes, and
constants. Modules give you two major benefits:
Modules provide a namespace and prevent name clashes.
Modules implement the mixin facility.
[...]
Modules define a namespace, a sandbox in which your methods and
constants can play without having to worry about being stepped on by
other methods and constants.
In your case:
module MyRailsApp
class File
...
end
end
whereby your File class is used as MyRailsApp::File. This is the typical solution in Ruby, in Ruby on Rails this might be handled differently, please see the following references for an in depth discussion:
Handling namespace models (classes) in namespace
ActiveRecord: Can haz namespaces?
Namespaced models and controllers
Namespaced models
A simple alternative to namespaced models

Is it a bad idea do divide the models into directories?

I have a over 100 models in my rails application, and just for organization, I'm dividing them into folders, all still under the main model folder, just to make it simpler to navigate on the project and see files that are related.
Is this a bad idea? What is the rails way to do this?
No, it's not a bad idea. Many people do it and I couldn't live without it in large applications.
There are two ways of doing it:
The first is to just move your models. You will, however, have to tell Rails to load the wayward models (as it won't know where they are). Something like this should do the trick:
# In config/application.rb
module YourApp
class Application < Rails::Application
# Other config options
config.autoload_paths << Dir["#{Rails.root}/app/models/*"]
end
end
The first way is easy, but is not really the best way. The second way involves namespacing your models with groups they're in. This means that instead of having User and UserGroup and UserPermissions, you have User, User::Group and User::Permission.
To use this, generate a model like this: rails generate model User::Group. Rails will automatically create all of the folders for you. An added benefit is that with this approach, you won't have to spell out the full model name for associations within a namespace:
class User < ActiveRecord::Base
belongs_to :group # Rails will detect User::Group as it's in the same namespace
end
class User::Group < ActiveRecord::Base
has_many :users
end
You can specify however many levels of namespacing as you want, so User::Group::Permission would be possible.
For 100 models, it's practically a requirement. 100 models is noisy in one directory.
Try this to get an idea of the Rails Way (tm)
rails new MultiDirectoryExample
cd MultiDirectoryExample
rails generate scaffold User::Photo description:string
Watch the script output and view the generated files.

Resources