Rails: ruby class name must base on file name? - ruby-on-rails

I'm learning rails 5.0. When I learn Ruby, I know that ruby file name can be different with class name inside. But when I move to rails, I see that ruby file name and class name must have same format. For example, a class name CheckInDetail will be in check_in_detail.ruby. I also see that the module name must be matched with directory name. For example, module authentication must be inside authentication directory. Some example for my conclusion is:
rspec: class name must base on file name.
grape: class name must base on file name. Also module name must be matched with directory.
If I don't follow those convention, when compiling rails will throw exception. I don't see those conventions on those library github pages. Will this true for whole rail project, with all libraries ?

With rails there is a convention how you should define classes and file names. A class named ManageOrder should reside inside a file named manage_order.rb. This is a standard convention that rails follows otherwise rails won't be able to load the class.

Related

Mogoid 7.0.4 returns Unable to autoload constant (Mongoid ~6 worked fine)

When I try to upgrade to Mongoid ~7, it throws this error:
Unable to autoload constant User::AuditSession, expected ./testapp/app/models/user/audit_session.rb to define it
I indeed have this file, but it defines AuditSession, not User::AuditSession. I put all the user related models into this directory which worked in Mongoid ~6, but it seems to no longer work in Mongoid ~7.
Is there any workaround I can do to get the old behaviour? - My goal is to avoid moving all my model files or editing all my class names.
Per the Rails conventions, if the model is defined in user/audit_session.rb, the class name should be User::AuditSession.
A workaround is to preload the class so that it is loaded by the time it is needed. Depending on where the class is used from, this could be as simple as placing
require 'user/audit_session'
in the file that uses AuditSession.
Alternatively you could define a top-level audit_session.rb which includes the other file (i.e. just has the above include in it).

Same controller name in two different directories

From 'Agile Web Development with Rails 4' pag.272.
If an incoming request has
a controller named (say) admin/book, Rails will look for the controller called
book_controller in the directory app/controllers/admin. That is, the final part of the
controller name will always resolve to a file called name_controller.rb, and any
leading path information will be used to navigate through subdirectories,
starting in the app/controllers directory.
Imagine that our program has two such groups of controllers (say, admin/xxx
and content/xxx) and that both groups define a book controller. Thereā€™d be a
file called book_controller.rb in both the admin and content subdirectories of
app/controllers. Both of these controller files would define a class named BookController. If Rails took no further steps, these two classes would clash.
To deal with this, Rails assumes that controllers in subdirectories of the
directory app/controllers are in Ruby modules named after the subdirectory.
My question is: how could the two book_controller.rb files clash?
I have two different URLs: ..../admin/book and ..../content/book, how can they clash? In the previous paragraph it explicit says
[..] any leading path information will be used to navigate through subdirectories, starting in the app/controllers directory
The file names do not matter. What matter are the constant names.
It's totally okay to have two files with identical names, like controllers/admin/books_controller.rb, and controllers/books_controller.rb.
However, the class names inside those controller should be different. You can add namespace to differentiate them. For example
class Admin::BooksController
class BooksController
Imagine the filepaths like this
../app/controllers/admin/book_controller.rb
&&
../app/controllers/content/book_controller.rb
Rails uses convention over configuration: http://en.wikipedia.org/wiki/Convention_over_configuration
Like it states in the last paragraph
If Rails took no further steps, these two classes would clash. To deal
with this, Rails assumes that controllers in subdirectories of the
directory app/controllers are in Ruby modules named after the
subdirectory.
Someone please correct me if I'm wrong but rails would look for models named admin.rb and content.rb

Rails Module/Folder Naming Convention

I'm having a problem with a module name and the folder structure.
I have a model defined as
module API
module RESTv2
class User
end
end
end
The folder structure looks like
models/api/restv2/user.rb
When trying to access the class, I get an uninitialized constant error. However, if I change the module name to REST and the folder to /rest, I don't get the error.
I assume the problem has to do with the naming of the folder, and I've tried all different combos of /rest_v_2, /rest_v2, /restv_2, etc.
Any suggestions?
Rails uses the 'underscore' method on a module or class name to try and figure out what file to load when it comes across a constant it doesn't know yet. When you run your module through this method, it doesn't seem to give the most intuitive result:
"RESTv2".underscore
# => "res_tv2"
I'm not sure why underscore makes this choice, but I bet renaming your module dir to the above would fix your issue (though I think I'd prefer just renaming it to "RestV2 or RESTV2 so the directory name is sane).
You'll need to configure Rails to autoload in the subdirectories of the app/model directory. Put this in your config/application.rb:
config.autoload_paths += Dir["#{config.root}/app/models/**/"]
Then you should be able to autoload those files.
Also, your likely filename will have to be app/model/api/res_tv2/user.rb, as Rails uses String.underscore to determine the filename. I'd just call it API::V2::User to avoid headaches, unless you have more than one type of API.

Ruby - :: in class name

I'm working with some legacy RoR code, which has four related classes, each defined in its own file. All of these classes are parser classes, and live in app/models/parsers. Each file name ends with _parser.rb.
Here's an example class def line from file adf_parser.rb:
class Parsers::AdfParser
I'm lost as to what the Parsers:: part of that is doing.
There's no explicit module called Parsers defined anywhere that I can find.
I don't see any documentation about implicitly creating modules just by adding module specifications to class names.
The only external dependency is "require 'csv'".
There are include statements within the class def, but I don't think they have anything that would explain the class name.
I created a new RoR test project and put stubs of these files in a parallel directory, and they won't run from the command line due to a
name error.
I don't see any examples online of classes named in this way.
I'm sure this isn't rocket surgery, but I've lost most of my morning trying to figure this out, and I'd love it if someone could just tell me what's going on with it.
Update: It sounds like this is just a bit of Rails magic, based on the subdirectory name. I think the reason that I got an error in my test app is that I just ran the files through the ruby interpreter, rather than invoking them with Rails in some way.
class Parsers::AdfParser is in practice equivalent to:
module Parsers
class AdfParser
For this to work properly, and the file to be autoloaded its location should be parsers/adf_parser.rb, whether under app/models or lib. Basically the file path needs to mimic the class hierarchy.
It's in the parsers sub-directory of modules; Rails namespaces for you by convention.

Ruby Rails Lib Folder Naming Convention

I seem to be having trouble with the naming conventions of the Lib Folder in Rails, and the error messages provided to me do not help. [For example, I have received a message saying that XXX::YYY::TextBox is expected to be defined xxx/yyy/text_box.rb, even though it clearly was defined there.] I think I'm getting the convention wrong.
Let's say I am working on YourModule::MyModule::MyClass. I clearly get that this file should be located in
lib/your_module/my_module/my_class.rb
But what should the actual file here look like? Which one of these (if either) are correct?
#your_module/my_module/my_class.rb
module YourModule
module MyModule
class MyClass
...
end
end
end
Or
#your_module/my_module/my_class.rb
class MyClass
...
end
In other words, do I need to nest the class inside of the module structure or not?
The lib folder has few conventions, as it is not autoloaded. So, how you organize the files is up to you, but you do have to name the classes correctly. Your first example is correct.
To get the files included you need to specify you want them in your application.rb file, see this example: Best way to load module/class from lib folder in Rails 3?
I would recommend making a folder just called lib/modules, since you probably won't have very many. Name the file my_class.rb. Then in application.rb you need:
config.autoload_paths += %W(#{config.root}/lib/modules)
That should take care of your issue.

Resources