I have a module called user_searches. It performs some searches that aren't core to the user model, thus, why I'm putting the responsibility somewhere else. I want to organize all my models like this that perform non-core user functions in a lib subfolder called user. Right now to include the module's methods in the User model I have to put...
require 'user/user_searches'
class User < ActiveRecord::Base
include UserSearches
end
...I don't need the require if the file is directly in the lib folder, but do if it's in the subfolder. What do I have to do so I don't need the require?
You could put the necessary require lines into lib/user.rb that way, all requirements are loaded recursively on application launch.
Alternatively, you could put something like this into an initializer:
# put into config/initializers/load_lib.rb
Dir["#{RAILS_ROOT}/lib/**/*.rb"].each { |f| require(f) }
It will require all ruby files in your lib folder. You just have to make sure if this is really what you want :)
This is works that cause
in file rails-2.2.2/lib/initializer.rb in method default_load_paths initialized to load path just the lib folder without subdirectories, to solve this you can edit your project ` environment.rb config file and push into config.load_path array all subdirs.
Related
In one of my controllers I would like to use a Service-Class that I located inside of: services/cars/strategies/unload_car_strategy.rb
Although the unload_car_strategy.rb is located inside the folders, I don't want to use namespacing: The class right now looks like this:
class UnloadCarStrategy
....
end
When I call in my controller UnloadCarStrategy.new I get the error:
NameError: uninitialized constant UnloadCarStrategy
How can I instruct Rails to load this Class?
By default everything under your app/ dir gets auto- and eager- loaded when your application starts. So you got your services dir loaded when the application started.
Even though if you add as many folders and files in those folders you want, Rails will load them for you until you follow the namespacing.
Since you are not using the namespacing the class UnloadCarStrategy doesn't get loaded.
You have to explicitly require it either in the respective controller where it is needed or in the application.rb file.
you either add
require "#{Rails.root}/app/services/cars/strategies/unload_car_strategy" in the controller from where it has to be called
or add the below line to application.rb
config.autoload_paths += %W({config.root}/app/services/cars/strategies/unload_car_strategy.rb)
source : https://gist.github.com/maxim/6503591#if-you-add-a-dir-under-appsomething
If i need to add (project specific) classes to my controler in rails, what is the correct way/place to put and "include" them/there .rb files? (quotes for: not the ruby keyword include)
I am new to rails, and did not find the correct way. LIB sounds like for more public libraries and - what I have learned - is not reloaded per default in dev mode.
sure, I could put all in controler.rb, but ...
the anser for me:
First: there are no rules, if you keep in mind (or learn like me) the rails rules:
NameOfCla -> name_of_cla(.rb) <-- not using class as word for clearence
name your class how you like:
class ExtendCon #<--- not using controller here for clearence
....
put it in a file extend_con.rb, wait for the path explaination, please. if you named your class 'MYGreatThing' it will be 'm_y_great_thing' (never testet that), so avoid chineese charachters
if your controller uses
#letssee=ExtendCon.new
rails learns that class and file (extend_con) on its own. i still did not figure out if a server restart is needed. (the first time)
choose the path to put the file: (I preferre Daves way) app/myexten or what you like, making it 'app' specific and still distquishes to standard rails 'things'
if you are not lasy like me (i put it in app/ontrollers)
put the path you have choosen into
config/application.rb like (comments are there to find it)
# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/app/controllers)
config.autoload_paths += %W(#{config.root}/app/myexten)
this one workes for me in all modes including "developer" and i did not need to put "my own" things in app/lib
It depends.
I tend to put library code used explicitly (e.g., instantiated, injected, etc. into app-level artifacts) into app/xxx where xxx signifies the "type" of thing, like decorators, services, etc.
Magic stuff tends to end up in lib, like monkey patches, architectural-level artifacts, and so on.
Code anywhere can be added to the autoload paths, required automatically by an initializer, etc.
Rails 4 comes with an internal directory for controllers called concerns. You could try using that.
app/controlls/concerns
If you have concerns/foo_bar.rb, you include it as follows:
class FooController < ApplicationController
include FooBar
end
Models also have their own concerns directory. I find this approach useful, and it can be applied to Rails 3. You just have to add the directories to your load paths.
I have a class sitting in /lib folder.
It's in a file called mailing.rb
And I would like to use this class in codes from app/controller.
How do i do this?
Rails 3 no longer automatically loads the files from lib.
In your application.rb file, you can add lib to your autoload_paths:
config.autoload_paths += Dir["#{Rails.root}/lib"]
This way, your mailer.rb and all other files in lib will be available to the rest of your application.
I believe you need to add an initializer file with the require statement in it, for example if your lib file is /lib/some_module.rb you would need to create an initialiser file in /config/initializers/require_libs.rb...
# /config/initializers/require_libs.rb
require 'some_module'
I've created a module in the /lib folder:
Module CookieHelper
$str = cookies["shoppingcart"]
def get_all_cookie_info()
end
end
But this isn't working. If I move the code into a controller it works fine.
Also, I'm trying to invoke the method within this module. I've tried:
require CookieHelper
CookieHelper::get_all_cookie_info()
to use methods from a module inside of an other class (such as a controller), you do something like this:
include CookieHelper
Once you do that inside of your controller's class, you can call get_all_cookie_info() with just the method name.
It sounds like you might be trying to something odd, so if you want to spell out what get_all_cookie_info is supposed to do, then maybe I can offer more advice.
CookieHelper::get_all_cookie_info is the correct way to call this method.
include CookieHelper
get_all_cookie_info
is another valid way, if you want include all of the methods in cookie helper available without having to namespace them (once the file lib/cookie_helper has been loaded).
What the issue probably is, is that the lib file isn't even required yet, this is because rails3 doesn't automatically load files in lib anymore. You can tell it to do so by editing your application.rb file, and setting inside class Application < Rails::Application
config.autoload_paths += %W( #{config.root}/lib )
I'm trying to write a plugin that will extend InheritedResources.
Specifically I want to rewrite some default helpers.
And I'd like it to "just work" once installed, w/o any changes to application code.
The functionality is provided in a module which needs to be included in a right place. The question is where? :)
The first attempt was to do it in my plugin's init.rb:
InheritedResources::Base.send :include, MyModule
It works in production, but fails miserably in development since InheritedResource::Base declared as unloadable and so its code is reloaded on each request. So my module is there for the first request,
and then its gone.
InheritedResource::Base is 'pulled' in again by any controller that uses it:
Class SomeController < InheritedResource::Base
But no code is 'pulling in' my extension module since it is not referenced anywhere except init.rb which is not re-loaded on each request
So right now I'm just including the module manually in every controller that needs it which sucks.
I can't even include it once in ApplicationController because InheritedResources inherites from it and so it will override any changes back.
update
I'm not looking for advice on how to 'monkey patch'. The extension is working in production just great. my problem is how to catch moment exactly after InheritedResources loaded to stick my extension into it :)
update2
another attempt at clarification:
the sequence of events is
a) rails loads plugins. my plugin loads after inherited_resources and patches it.
b) a development mode request is served and works
c) rails unloads all the 'unloadable' code which includes all application code and also
inherited_resources
d) another request comes in
e) rails loads controller, which inherites from inherited resources
f) rails loads inherited resources which inherit from application_controller
g) rails loads application_contrller (or may be its already loaded at this stage, not sure)
g) request fails as no-one loaded my plugin to patch inherited_resources. plugin init.rb files are not reloaded
I need to catch the point in time between g and h
The Rails::Configuration, config in the environment files, allows registering a callback on the dispatcher that runs before each request in development mode, or once when in production mode.
config.to_prepare do
# do something here
end
The problem is, I don't think your plugin has access to config when the init.rb file is run. Here is a way to register your callback directly in the dispatcher. Just put this in the init.rb file.
require 'dispatcher'
::Dispatcher.to_prepare do
puts "hi there from a plugin"
end
Warning: I don't know what side effects this may have. If possible, try to get access to config and register the callback tha right way.
What you are attempting to do is usually called "MonkeyPatch" - changing the way one module or class is working by "overriding" methods.
It is a common practice in Rails, but it doesn't mean it is the best way to do things - when possible, it is better to use common inheritance (it is more explicit about the changes you make).
Regarding your questions about "where to put the files": it is usually the lib/ directory. This can mean the lib of the rails app, or a lib directory inside a gem or plugin, if you are into that sort of thing.
For example, if the file you want to change is lib/generators/rails/templates/controller.rb of inherited resources, the first thing you have to do is replicate that directory structure inside your lib/ folder ('lib/generators/rails/templates/controller.rb')
Inside that new file of yours, (empty at the beginning) you can override methods. However, you must also the modules/classes hierarchy. So if the original gem had this:
module foo
module bar
def f1
...
end
def f2
...
end
end
def f3
...
end
end
And you wanted to modify f1, you would have to respect the foo-bar modules.
module foo
module bar
def f1
... # your code here
end
end
end
Now the last thing you need is to make sure this code is executed at the right time. If you are using the application's lib/ folder, you will need to create an entry on the initializers/ folder and require your new file. If you are developing a gem/plugin, you will have a init.rb file on the "root" folder of that plugin. Put the 'require' there.
I'm not very familiar with this unloadable stuff; maybe I'm asking something obvious but- have you tried making your extension module unloadable, too? (You shouldn't need this if you monkeypatched the module instead of creating a new one)