I have the following module/class defined in my lib folder
module Service::Log
extend ActiveSupport::Concern
module ClassMethods
def logger
Rails.logger
end
end
end
class Service::MyService
include Service::Log
end
When I try to invoke logger method via an object instance I get an error message - NoMethodError: undefined method `logger' for - Service::MyService:0x007fdffa0f23a0
Service::MyService.new.logger
What am I doing wrong? I am using Rails 4.0.2.
You are defining the logger method as a class method, instead of a normal method. This should work:
module Service::Log
extend ActiveSupport::Concern
def logger
Rails.logger
end
end
class Service::MyService
include Service::Log
end
Service::MyService.new.logger
The way you were defining the method before allowed you to use the logger method on the class directly, such as:
Service::MyService.logger
Related
Happened on ruby 3.1.2 & rails 7.0.4
module:
app/models/concerns/password_regeneratable.rb
module PasswordRegeneratable
extend ActiveSupport::Concern
module ClassMethods
def generate_password
SecureRandom.urlsafe_base64(self.class::DEFAULT_PASSWORD_LENGTH)
end
end
end
model:
app/models/user.rb
class User < ApplicationRecord
include PasswordRegeneratable
DEFAULT_PASSWORD_LENGTH = 30
end
When I try to call User.generate_password it gives me this error:
/app/app/models/concerns/password_regeneratable.rb:6:in `generate_password': uninitialized constant Class::DEFAULT_PASSWORD_LENGTH (NameError)
Did you mean? Class::DEFAULT_SETTINGS
I want to use module so I can reuse this generate_password method and possible some other methods for other model classes in the future. Is this kind of implementation correct?
module PasswordRegeneratable
extend ActiveSupport::Concern
module ClassMethods
def generate_password
SecureRandom.urlsafe_base64(self::DEFAULT_PASSWORD_LENGTH)
end
end
end
In a class method self is the class. Thus self.class gives you the confusingly named Class class since in Ruby classes are instances of Class.
I want to call polymorphic_path in a helper module located at lib/my_module.rb.
I tried the following from this answer, which works in a model, but not in my module:
module MyModule
include ActionDispatch::Routing::PolymorphicRoutes
include Rails.application.routes.url_helpers
def link(model)
polymorphic_path(model)
end
end
I get:
undefined method `polymorphic_path' for MyModule:Module
Btw, I load my module through config.autoload_paths += %W(#{config.root}/lib) in config/application.rb.
Turns out you have to create a class to properly include stuff in ruby, for example:
class MyClass
include ActionDispatch::Routing::UrlFor
include Rails.application.routes.url_helpers
def link(model)
polymorphic_path(model)
end
end
I want to include a module in a rails helper(is also a module).
The helper is:
module SportHelper
.....
end
And the module is:
module Formula
def say()
....
end
end
Now, I want to use the method say in SportHelper. What should I do?
If I write like this:
module SportHelper
def speak1()
require 'formula'
extend Formula
say()
end
def speak2()
require 'formula'
extend Formula
say()
end
end
This will work, but I don't want to do so, I just want to add the methods on the helper module,not every methods.
You need just to include this module in your helper:
require 'formula'
module SportHelper
include Formula
def speak1
say
end
def speak2
say
end
end
Maybe you don't need this line require 'formula', if it's already in the load path. For check this you can inspect $LOAD_PATH variable. For more information see this answer.
Basic difference between extend and include is that include is for adding methods to an instance of a class and extend is for adding class methods.
module Foo
def foo
puts 'heyyyyoooo!'
end
end
class Bar
include Foo
end
Bar.new.foo # heyyyyoooo!
Bar.foo # NoMethodError: undefined method ‘foo’ for Bar:Class
class Baz
extend Foo
end
Baz.foo # heyyyyoooo!
Baz.new.foo # NoMethodError: undefined method ‘foo’ for #<Baz:0x1e708>
And if you use extend inside the object method, it will adding methods to an instance of a class, but they would be available only inside this one method.
I think directly include should work
module SportHelper
include SportHelper
.........
end
end
I tested like below:
module A
def test
puts "aaaa"
end
end
module B
include A
def test1
test
end
end
class C
include B
end
c = C.new()
c.test1 #=> aaaa
It should work.
I am writing my first Rails gem, which adds a method to ActiveRecord. I can't seem to figure out a simple way to call other methods from within the method I am adding to ActiveRecord. Is there a pattern for this I should be using?
module MyModule
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def my_class_method
# This doesn't work
some_utility_method
end
end
def some_utility_method
# Do something useful
end
end
ActiveRecord::Base.send(:include, MyModule)
Once you've included MyModule, ActiveRecord::Base will have my_class_method as a class method (equivalently, an instance method of the Class object ActiveRecord::Base), and some_utility_method as an instance method.
So, inside my_class_method, self is the Class ActiveRecord::Base, not an instance of that class; it does not have some_utility_method as an available method
Edit:
If you want a utility method private to the Module, you could do it like this:
module MyModule
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def my_class_method
# This doesn't work
MyModule::some_utility_method
end
end
def self.some_utility_method
# Do something useful
end
end
ActiveRecord::Base.send(:include, MyModule)
I have a custom plugin (I didn't write it) that is not working on rails 3, however it did work with rails 2. It is for a custom authentication scheme, here is what the main module looks like:
#lib/auth.rb
module ActionController
module Verification
module ClassMethods
def verify_identity(options = {})
class_eval(%(before_filter :validate_identity, :only => options[:only], :except => options[:except]))
end
end
end
class Base
#some configuration variables in here
def validate_identity
#does stuff to validate the identity
end
end
end
#init.rb
require 'auth'
require 'auth_helper'
ActionView::Base.send(:include, AuthHelper)
AuthHelper contains a simple helper method for authenticating, base on a group membership.
When I include 'verify_identity' on an actioncontroller:
class TestController < ApplicationController
verify_identity
....
end
I get a routing error: undefined local variable or method `verify_identity' for TestController:Class. Any ideas how I can fix this? Thanks!
It worked in 2.3 because there was an ActionController::Verification module back there. It's not working in 3.0 because this module doesn't exist. Rather than relying on Rails to have a module that you can hook into, define your own like this:
require 'active_support/concern'
module Your
module Mod
extend ActiveSupport::Concern
module ClassMethods
def verify_identity(options = {})
# code goes here
end
end
end
end
and use:
ActionController::Base.send(:include, Your::Mod)
To make its functions available. ActiveSupport::Concern supports you having a ClassMethods and InstanceMethods module inside your module and it takes care of loading the methods in these modules into the correct areas of whatever the module is included into.