Rails: Overriding const_missing within a module - ruby-on-rails

Within my Rails application I have a module defined this way:
module WhateverModule
class WhateverClass
...
end
end
This file (whatever_class.rb) is located under /app/models/whatever_module
const_missing is being overriden by Rails and despite I did some workarounds, involving initializers, I wish I could make it in a better way.
My aim is to get a WhateverModule::Foo (Foo being undefined) to be resolved by a custom const_missing method.
Any help will be greatly appreciated. Thanks in advance!!

The following seems to work fine for me in Rails 2.2.2
module WhateverModule
def self.const_missing(c)
# handle missing constant
end
end

Related

Rails 3 trouble with namespaces & custom classes (uninitialized constant)

I have a file in my Rails 3.2.11 project called app/queries/visible_discussions.rb which looks like the following:
class VisibleDiscussions
...
end
I'd like to namespace the query so that I can call it using something like Queries::VisibleDiscussions so I tried to do the following:
module Queries
class VisibleDiscussions
...
end
end
However, I'm getting a uninitialized constant Queries (NameError) when I try to call Queries::VisibleDiscussions from the rails console.
Any ideas?
if you add lib to your autoload_paths then it will respect the namespacing under lib - lib/query/visible_discussions.rb
or create a new dir under app - say src and then nest your code there - app/src/query/visible_discussions.rb
i would use the 3rd style in your post for either of these, i.e.
module Query
class VisibleDiscussions
...
end
end
both of these solutions are annoying to me, there might be a way to tell rails to namespace directories under app, but i have no clue how it would be done
Rails needs to know what directories to load (a part from the defaults). Try:
#config.application.rb
config.autoload_paths += %W(#{config.root}/queries)

Rails, Custom Folders and Namespaces

I'm running Rails 3.2.7,
I have a folder '/app/jobs'
and the following in my 'config/application.rb' file
config.autoload_paths += %W(#{Rails.root}/app/jobs)
And everything is okay.
However if I want to namespace my classes eg
class Jobs::UpdateGameStatus
#methods etc
end
Rather than
class UpdateGameStatus
#methods etc
end
Then I get
uninitialized constant Jobs (NameError)
It's not the end of the world but I'd love to know why...
I fixed it in the end, wrapping all my classes with a Jobs module was what I needed to do.
my files were located in 'app/jobs'
and looked like this
module Jobs
class JobName
#methods etc
end
end
and are used like so
Jobs::JobName.method(args)
I know you have already sorted this out, and this is old, but in ruby, it is also possible to declare the namespaced class directly using class Jobs::JobName. It's a little less typing, and achieves the same result.
Edit: As #D-side pointed out, Jobs has to already be defined. My own code that uses this is based around STI, which presumes that the previous class/module I am extending already exists.

Uninitialized constant trying to reopen a Class

I am using a plugin in Rails, and I call its methods without problems:
plugin_module::class_inside_module.method_a(...)
I want to re-open the class_inside_module and add a new method, I tried in many different ways. I can't figure out why in this way doesn't work:
class plugin_module::class_inside_module
def new_method
puts 'new method'
end
end
I get the error: uninitialized constant plugin_module, but how is possible if I can call without problem plugin_module::class_inside_module.any_methods ?
Do you know why I get that error ? why "uninitialized constant" ? (it is a class declaration :-O )
Do you have any ideas how I can add a new methods in a class inside a module (that is part of a plugin) ?
Thank you,
Alessandro
If you have written your class and module-names like you did, so plugin_module instead of PluginModule this is against ruby/rails standards, and rails will not be able to automatically find the class and module.
If you write something like
module MyModule
class MyClass
end
end
Rails will expect this file to be located in lib\my_module\my_class.
But this can always easily be overwritten by explicitly doing a require.
So in your case, when you write
module plugin_module::class_inside_module
Rails will not know where to find the module plugin_module.
This way of writing only works if module plugin_module is previously defined (and loaded).
So either add the correct require, or rename your modules to standard rails naming, or write it as follows:
module plugin_module
class class_inside_module
This way will also work, because now the order no longer matters.
If the module is not known yet, this will define the module as well.
Either you are re-opening the class, or you define it first (and the actual definition will actually reopen it).
Hope this helps.
Have you tried reopening the module that's wrapping the class, rather than relying on ::?
module plugin_module
class class_inside_module
def new_method
puts 'new_method'
end
end
end
By the way, you know that the proper name for modules and classes is use CamelCase with a capital first letter?
module PluginModule
class ClassInsideModule
def new_method
puts 'new_method'
end
end
end

Why can't I locate this method in the rails api docs?

I'm studying some Rails 3 code from Spree:
module Spree
module Generators
class SiteGenerator < Rails::Generators::Base
source_root File.expand_path("../../templates", __FILE__)
desc "Configures an existing Rails application to use Spree."
def create_lib_files
template 'spree_site.rb', "lib/spree_site.rb"
end
def additional_tweaks
remove_file "public/index.html"
append_file "public/robots.txt", <<-ROBOTS
.... continues ....
This works with Rails 3, but I've looked up Rails::Generators::Base, following the inherited modules to Rails::Generators::Actions and the Thor classes, but still can't seem to find api documentation on the #template method. I can figure out what it does, but I'm troubled that I can't find the docs on it. It's got me feeling like a real newbie (though, since I haven't worked with Rails in quite awhile, I guess in some ways I am).
Any help would be appreciated. Please tell me why I'm not able to find this (and other) methods in the Rails api docs. What am I missing???
The template method is an instance method included with Thor::Actions and can be found at http://rubydoc.info/gems/thor/0.14.6/Thor/Actions:template

Ruby Module Include Question

I have a CommonFunctions Module inside the lib/ folder. I have a Question Model, which includes the CommonFunctions module. Now I am trying to access the favorite function of the CommonFunctions like Question.favorite. But I am getting NoMethodError. I have included the code. Can anyone please tell me where I am doing the mistake
Error
NoMethodError: undefined method `favorite' for Class:0x00000100e11508
Inside lib/CommonFunctions.rb
module CommonFunctions
def favorite(object_id)
end
end
Inside app/models/Question.rb
require 'lib/CommonFunctions.rb'
class Question
extend CommonFunctions
end
I am executing the following code from the script/console
Question.favorite(1)
Thanks
This was a duplicate of How do I properly include a module and call module functions from my Rails model?
Your code is correct. Make sure you have the current version of the classes loaded in the console (try reload!).
As a sidenote: if you rename CommonFunctions.rb to common_functions.rb, it will be autoloaded by rails and you don't need the require.
The module method is an instance method when you want it to be a class method. Use the code below instead
module CommonFunctions
def self.favorite(object_id)
end
end
Using the word "self" defines the method as a class method (or static)

Resources