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)
Related
I'm trying to create a gem, my gem requires a different gem that I have added into the gemspec.
My issue is when I try to call a method inside the code, ruby automatically adds the module namespace to the method I am calling, then I get an uninitialized constant error. I put a basic example of what is going on below.
lib/example_gem.rb
module FooModule
def bar
# this is the method I am trying to run
BAZ::Request.execute(123)
end
end
class Test
include FooModule
end
x = Test.new
x.bar
=>>>>>>>> uninitialized constant FooModule::Baz (NameError)
I'm not trying to call FooModule::Baz, I want to call BAZ::Request.execute(123). Any help would be appreciated
Try:
::BAZ::Request.execute(123)
The keyword is "constant lookup operator". I assume BAZ isn't wrapped into another class or module, so you need to look for it on the topmost level. Therefore you prepend ::.
And now you understand why the request (BAZ::Request) needs to be within BAZ.
I've written a tiny game in the form of a Class. I've placed that file in the lib folder and I've set the appropriate loader in config/application.rb . But when I try to call Game.new in my controller it says undefined method 'new' for Game:Module. I want to be very clear THIS IS NOT A MODULE. Why the heck is it treating my class as a module? How can I fix it?
class Game
def initialize
end
end
See... this is a class with the .new method. It loads fine in IRB, but not in Rails.
I got it. It turns out I had named the class the same name as my rails project name. So it would only accept a module for that name. I renamed the class and file and now I'm good to go.
I have a file under /lib with its own method.
# lib/file.rb
class File < ApplicationController
def my_method
...
end
end
However I can't reach the method through the console
ruby-1.9.2-p290 :044 > File.my_method
NoMethodError: undefined method `my_method' for File:Class
Any idea how?
my_method is an instance method of the File class. It means that you can call it only on the instance of the File class.
file = File.new
file.my_method
You can declare my_method as class method using def self.my_method syntax.
class File < ApplicationController
def self.my_method
...
end
end
File.my_method
But in class methods you can't use instance variables of the File object.
You're trying to call my_method as a class method, but you've defined it as an instance method.
You should either define it as def self.my_method, or create an instance of the controller to call it as an instance method.
In addition, you are going to run into problems for a couple of reasons - (1) Rails expects controllers to be named like FilesController, and (2) File is a class in the standard library. I would encourage you to change the class name to FilesController, and rename the file itself to files_controller.rb to prevent both issues.
Well... there are several interesting things going on with this example. The first would be that this class name is call File which is already defined in Ruby.
That is most likely why when you are in the console you didn't get an undefined class error. Since my_method is not defined on Ruby's File class, this is why you are seeing undefined method.
Now to your question. I would try naming your class something different first and trying again from lib. I believe it should be loaded by default again with the rails environment. For a version or two that functionality was taken out but I want to say it's back in. If not, just go into your config/application.rb file and look for a declaration along the lines of config.autoload_paths. Add the lib directory there and you should be good to go.
Lastly, is there a reason you want a controller in lib?
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
There is an ApplicationHelper in an engine we're using that looks like this:
module ApplicationHelper
def page_title()
# ...
end
end
This gets called by a number of views in the engine. I'd like to override this method in my application to provide a different default title. How do I do this? Simply defining my own ApplicationHelper didn't seem to work.
Did you define the page_title method in your ApplicationHelper module? Just having an ApplicationHelper by itself won't do it.
By default, your ApplicationHelper module should already be in app/helpers/application_helper.rb. Your app files are required by rails after it requires the plugins you are using. That means any method you define in app/helpers/application_helper.rb should override methods defined in the plugins code.
This behavior arises out of ruby's open class structure. Any time, anywhere any class/module/object can be reopened to add methods and attributes to it. More or less.
Could you post some of the code you are trying to override the engine method with?
Are other methods defined in your ApplicationHelper available?
If yes, the engine helper is probably loaded before your ApplicationHelper, and your method overwritten.
If no, Rails may never have loaded your module because it thinks it already knows about ApplicationHelper and doesn't try to load it again.