I have some simple ruby classes that I want to use with rails (they are classes for things like points, lines, rectangles, etc.). How can I use them with a rails controller or an active record model?
Thanks!
The convention is to put them in your-app/lib/. You can have Rails automatically load them by configuring it to do so in config/application.rb. Edit the default to look something like this:
# Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += %W( #{Rails.root}/lib/shapes )
Where your class definition files are in your-app/lib/shapes.
Note: This is for Rails 3. Rails 2.x automatically loads files from lib.
Related
THE SHORT VERSION: How do I tell Rails to autoload an ActiveRecord class called ClassName that isn't located in the default location (app/models/class_name.rb). E.g. what if it's in app/models/subdirectory/class_name.rb and I don't want to rename the class to Subdirectory::ClassName?
THE LONGER VERSION:
I know that, by default in Rails, my class names have to follow a specific structure for Rails to be able to autoload them.
E.g. If my class is called Person, if I put it in app/models/person.rb, Rails can load it fine, but if I put it in e.g. app/models/person_class.rb, it can't. If I namespace it, e.g. Humanity::Person, I need to put it in the right folder app/model/humanity/person.
(Plus I can put classes in lib but I'll leave aside that detail for now)
So far so good. But what happens when I have a ton of ActiveRecord classes clogging up my app/models folder and I want to logically organise them into directory, but don't want to rename or namespace the actual classes? How can I tell Rails to autoload this classes?
Or is there a good reason why I shouldn't do this?
Add this line to config/application.rb
config.autoload_paths += Dir[Rails.root.join('app', 'models', '{**/}')]
Then you can use your model with their name as it is without name-spacing.
Would it be possible to have something like this?
app/models/
app/models/users/user.rb
app/models/users/education.rb
The goal is to organize the /app/models folder better, but without having to namespace the models.
An unanswered question for Rails 3 is here:
Rails 3.2.9 and models in subfolders.
Specifying table_name with namespaces seems to work (see Rails 4 model subfolder), but I want to do this without a namespace.
By default, Rails doesn't add subfolders of the models directory to the autoload path. Which is why it can only find namespaced models -- the namespace illuminates the subdirectory to look in.
To add all subfolders of app/models to the autoload path, add the following to config/application.rb:
config.autoload_paths += Dir[Rails.root.join("app", "models", "{*/}")]
Or, if you have a more complex app/models directory, the above method of globing together all subfolders of app/models may not work properly. In which case, you can get around this by being a little more explicit and only adding the subfolders that you specify:
config.autoload_paths += Rails.root.join("app", "models", "<my_subfolder_name1>")
config.autoload_paths += Rails.root.join("app", "models", "<my_subfolder_name2>")
UPDATE for Rails 4.1+
As of Rails 4.1, the app generator doesn't include config.autoload_paths by default. So, note that the above really does belong in config/application.rb.
UPDATE
Fixed autoload path examples in the above code to use {*/} instead of {**}. Be sure to read muichkine's comment for details on this.
I'm learning rails and I've come across a little quirk that I can't seem to find the answer to anywhere:
Since I'm learning rails, I'll make a few tweaks to the code while the localhost is running (rails s) and then just refresh the browser to see if the change I wanted to make was accurate. This works for changes to the views, css, html, routing, etc.
But now I'm making changes to a controller file that is calling another ruby class that I wrote and when I make changes to the ruby class, they don't show up right away. The way I know this is that I use a variety of printf functions in the Ruby class to show the current state of things and if I add one and re-run, it won't show unless I shut the server down and restart it.
Any thoughts? Is this a known issue?
You must autoload the folder which contains your custom files:
# in config/application.rb:
# Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += %W(#{config.root}/extras)
There you write the folder which you want to be autoloaded.
WARNING: the naming is very important: files in there must be named as the class/modules they define (like models, controllers, etc):
foo.rb must define Foo costant
foo/bar.rb must define Foo:Bar costant
and you cannot autoload files which do not have this naming convention. The reason is linked to the autoload working: when in your code call f.e. the Foo constant, and the constant is missing, Rails tries to see if in its autoload paths there is a file that follows this naming convention, and if there is it loads it.
Using Rails 3.2 and ruby 1.9.3p0
I am trying out the gem delayed_job. I have created a file lib/mailing_job.rb in which I have class MailingJob.
In a controller under app/controllers/requests_controller.rb I am calling
job = MailingJob.new(#request)
but this is returning the error
uninitialized constant RequestsController::MailingJob
I think it is because I need a proper way of referencing a class under a different folder structure.
Any idea how I can isntantiate class MailingJob from a different file (class) in a different folder?
Rails 3 does not include the lib folder within the load path so your application does not know how to find the class.
You can modify config/application.rb and add a line to instruct rails to also look in the lib folder like so
config.autoload_paths += %W(#{config.root}/lib)
In an initializer (e.g. config/initializers/delayed_job.rb), do this (doesnt matter where)
require 'mailing_job'
I have an Array extension method I want to use in my Rails 3 project. Where should it live?
I have a app/classes where I originally put it (array_extensions.rb), and in my config/application.rb I load the path: config.autoload_paths += %W(#{Rails.root}/app/classes). However, when I drop to rails console the extension is not loaded.
Is there a pre-definded place I should put my extension methods for Rails 3? Or, a pre-definded way to add them? I know Rails has it's own extensions methods for Array. Should I add mine to active_support/core_ext/array/conversions.rb?
What's the best practice for Rails 3?
The better way is create your extension in lib/core_ext directory to understand easyly where is your core_ext.
After create an initializer to require this file.
All .rb files in config/initializers are required into the environment at startup; you should be putting extensions in there.