I have a small problem that I can't quite get my head around. Since I want to reuse a lot of the methods defined in my Class i decided to put them into an Helper, which I can easily include whenever needed. The basic Class looks like this:
class MyClass
include Helper::MyHelper
def self.do_something input
helper_method(input)
end
end
And here is the Helper:
module Helper
module MyHelper
def helper_method input
input.titleize
end
end
end
Right now I can't call "helper_method" from my Class because of what I think is a scope issue? What am I doing wrong?
I guess that is because self pointer inside of do_something input is InternshipInputFormatter, and not the instance of InternshipInputFormatter. so proper alias to call helper_method(input) will be self.helper_method(input), however you have included the Helper::MyHelper into the InternshipInputFormatter class as an instance methods, not a singleton, so try to extend the class with the instance methods of the module as the signelton methods for the class:
class InternshipInputFormatter
extend Helper::MyHelper
def self.do_something input
helper_method(input)
end
end
InternshipInputFormatter.do_something 1
# NoMethodError: undefined method `titleize' for 1:Fixnum
As you can see, the call has stopped the execution inside the helper_method. Please refer to the document to see the detailed difference between include, and extend.
Related
The question can be stupid, but I always develop in C# and now I need to develop in Ruby.
And I don't really understand how to call a method from an another class.
I mean, I've this structure :
- model
|_________ my_model.rb
|_________ helper
|____ my_helper_class
my_model.rb
def self.create_new_ticket(member_to_update)
# I want to call here my_helper_class
MyHelperClass.generate_guid
end
my_helper_class :
class MyHelperClass
def generate_guid
return "So haaard"
end
end
And I don't have access to my method named generate_guid from my other class.
I've this type of error :
uninitialized constant
I would like to have an access with a static class or whatever. The initilize method doesn't work too (given argument problem ??)
So I think I understand bad something with Ruby and the manipulation of objects because of my habits in C#.
Can you help me please ? With some good documentations or an example here ?
Thanks a lot guys.
I think your error is straightforward. Your generate_guid is not a "static method" or "class method". You have to put self in front of it in the definition which will make it a class method.
Another important thing to notice is you have created /helper folder inside /model so you have to implement helper class inside a module named Helper which should be same as folder name.
Helper class should be
module Helper
class MyHelperClass
def self.generate_guid
return "So haaard"
end
end
end
An alternate way to define class methods would be:
module Helper
class MyHelperClass
class << self
def generate_guid
"So haaard"
end
def some_other_class_method
"some thing"
end
end
end
end
So, whenever you have to call static method you have to call it with full scope like Helper::MyHelperClass.generate_guid
I defined a helper method: MembersHelper
module MembersHelper
def current_segment
Segment.where(current: true).first
end
end
then included it in a class call Base in app/service/enum_data/base.rb file
module EnumData
class Base
include MembersHelper
end
end
And used it from Base's subclass: GetAll in app/service/enum_data/get_all.rb file
module EnumData
class GetAll < Base
def self.call
reference_data = current_segment.entities.all
end
end
end
But I got an error
undefined local variable or method 'current_segment' for EnumData::GetByCategory:Class
I fixed it by moving current_segment method to Base class, but I want to know why it doesn't work when I include that helper method? Did I miss something?
You are using include, which makes current_segment an instance method in the including classes while what you need, is a class instance method (singleton method). In order to achieve it you should use extend:
module EnumData
class Base
extend MembersHelper
end
end
I'm trying to call a method in one controller helper (a module) from another controller helper. It seems to be not possible, even if that method is under the module_function.
I guess I'm missing a fundamental principle in Ruby since I'm pretty newbie. Also it feels like I'm missing the point of how to write right OOP under Rails.
Update: here is an example:
I have FirstController and SecondController, and helper module for each
module FirstHelper
module_function
def methodA
...
end
end
module SecondHelper
def methodB
FirstHelper.methodA
end
end
The call for FirstHelper.methodA from SecondHelper is returning an error:
undefined method `methodA' for SecondHelper:Module
A module is a collection of methods and constants. It basically provides a namespace and prevents name clashes. You need to include or extend your First module inside your Second module.
Include is for adding methods to an instance of a class and Extend is for adding class methods. Read this for more information or this. In your case you can do something like this:
module FirstHelper
def self.methodA
...
end
end
module SecondHelper
include FirstHelper
def methodB
FirstHelper.methodA
end
end
Helper methods are instance methods and cannot be accessed via module, but only vie classes they are included in. All the helpers are included within the view context object, so you should be able to access them simply by name:
module SecondHelper
def methodB
methodA
end
end
use require instead of include it will work
module FirstHelper
class << self
def methodA
...
end
end
end
require 'lib/first_helper'
module SecondHelper
def methodB
FirstHelper.methodA
end
end
My model, Widget.rb, has include ApplicationHelper and my instance methods have no trouble using any method defined in application_helper.rb
However, when I try to use one of the helper methods in any of my class methods such as
def self.send_broadcast(guid)
track_guids(guid) # defined in application_helper.rb
end
I get No Method error.
Is there some secret handshake to permit use of a ApplicationHelper method inside a class method?
ApplicationHelper is just a module:
module ApplicationHelper
def track_guids(something)
end
end
class Widget
extend ApplicationHelper
def self.send_broadcast(guid)
track_guids(guid)
end
end
Now you should have access to the module methods from a class method. I'm not sure if you can both extend and include the same module though... not really sure what that'd do.
Edit to add:
I'm not sure what will happen if you try both extending and including the same module into the class. With extend you get the module included at the class-level, with include it is included at the instance-level. It might give you the methods at both class and instance if you do both... or it might die horribly. Give it a try?
I don't think you can access instance methods unless self is an instance. You could make an instance of Widget and call a class method from that, or you could try to call the methods from the module directly.
I have a model, Show and a module Utilities
class Show < ActiveRecord::Base
include Utilities
...
def self.something
fix_url("www.google.com")
end
end
My Utilities file is in lib/utilities.rb
module Utilities
def fix_url(u)
!!( u !~ /\A(?:http:\/\/|https:\/\/)/i ) ? "http://#{u}" : u
end
end
But Rails is throwing a NoMethodError for "fix_url" when I call it in my show class. Do I have to do something different when including a module in my model?
Thanks!
try injecting that mixin via the extend instead of include. Basically, because you are calling the mixin method from a class method, but including a mixin only makes its instance methods available. You can use the extend style to get class methods.
Search around for Ruby include and extend to learn the differences. A common pattern is to do it like here:
http://www.dcmanges.com/blog/27
Where you use the included hook to mixin both instance and class level methods.
#Tony - this works for me
class User < ActiveRecord::Base
extend Utilities
def self.test
go()
end
end
module Utilities
def go
puts "hello"
end
end
From console:
>> User.test
hello
=> nil
At no point do I have to explicitly call a method with self.
It worked for me. Have you tried restarting your server/console session?
Edit: If you want to just call Utilities.fix_url you can do that - no include/extend necessary.