application helper method invoking in another helper - ruby-on-rails

I am stuck in a weird Design problem,
I'm facing issues when I'm trying to invoke a application helper method in another helper which have multiple class and want to access application helper method.
what is the better approach?
Thoughts about what can I do?
my code looks similar like this,
## app/helpers/application_helper.rb
module ApplicationHelper
def my_name
"stackoverflow"
end
end
Another helper with sub classes
## app/helpers/my_helper.rb
module MyHelper
class MyTestclass
def want_myname
my_name ## giving undefined method-- how can i call myname method here?
end
end
end
undefined method `myname' for MyHelper::MyTestclass

Here is a brief explanation of your problem and how to use modules:
To 1. A module is created/opened by simply saying:
module MyModule
def first_module_method
end
end
To 2. The lib folder. If you want to organize your modules in the lib folder, you can put them into modules themselves. For example, if you wanted a subfolder super_modules your modules would be defined as follows:
module SuperModules
module MyModule
def first_module_method
end
end
end
To 3./5. When including the module in a class you can simply call the modules methods as if they were defined within the class:
class MyClass
include MyModule
def some_method
first_module_method #calls module method
end
end
To 4. Frst, make sure that your module is really needed in every class of your application. If it isn't it makes sense to only include it where it is need so as not to bloat the classes that don't need it anyways. If you really want the module everywhere, include look at the class hierarchy of your classes in the app. Do you want the module in all models? You could open ActiveRecord::Base and add add your module there.

Related

Decorate a Rails engine's helper to include a concern from the main app

I would like to include an ActiveSupport::Concern from an app in an engine, by decorating one of the engine's helper modules.
Here is the Helper from the engine:
module MyEngine
module MyHelper
end
end
Here is the Concern from the main app :
module MyConcern
extend ActiveSupport::Concern
def do_this
end
def do_that
end
end
Below is the decorated engine helper that needs to include the concern (for use in the engine views) - it is declared in the main app, using the decorator pattern described in the Rails guides :
module MyEngine
module MyHelper
include MyConcern
def do_stuff
end
end
end
The decorated helper is properly loaded by the engine, but the engine views are only able to call "do_stuff". The methods from MyConcern are unavailable, and I'm having a hard time figuring out why.
I also tried to include the concern by embedding it in a MyEngine::MyHelper.module_eval call, but that didn't work either.
Has anyone faced this kind of issue before ? Am I taking this the wrong way ?
I renplaced MyHelper from module to class
module MyConcern
extend ActiveSupport::Concern
def do_this
"do this"
end
def do_that
"do that"
end
end
module MyEngine
class MyHelper
include ::MyConcern
def do_stuff
"do stuff"
end
end
end
When calling :
MyEngine::MyHelper.new.do_stuff
MyEngine::MyHelper.new.do_this
MyEngine::MyHelper.new.do_that
The result will be :
do stuff
do this
do that
I think you may be reasoning about this backwards.
If your engine provides:
module MyEngine
module MyHelper
def foo
end
end
end
You can extend the method (you could call it decorate but i'm not sure if this is technically the decorator pattern) in your main app:
module MainApp
module MyHelper
extend ::MyEngine::MyHelper
def foo
super
do_something_else
end
end
end
When using the module-mixin pattern (which is what ActiveSupport::Concern does) you extend modules with modules and include modules in classes.
If you engine and main app "share a partial" - it should just be placed in the engine as Rails will first look for the view when rendering in the app/views directory of the application before looking for it the mounted engines.
The main app can thus always override the functionality provided by the engine while the inverse is not true.
If you want to make a method provided by an engine configurable a better idea is to use a Rails configuration setting (or a seperate module configuration) or just method arguments rather than some crazy circular dependency circus.
So I finally found a way to do this in a "clean" way, as mentioned in the following comment : https://groups.google.com/g/rubyonrails-core/c/PaABJDXnxyo/m/k-QUJEi9a9wJ
The idea is to add an empty placeholder helper in the engine, for example :
module MyEngine
module ExtendableHelper
end
end
And then override it in the main app, by adding methods or including concerns, other gems' helpers, etc...
module MyEngine
module ExtendableHelper
extend OtherGemFromMainApp::UsefulHelper
include MainAppConcern
def other_useful_method
...
end
end
end
Thus the helper used by the engine is the one provided by the app, and the UsefulHelper methods can be called in the engine views.

self.included – including class methods from a module in Ruby

I read this post: Ruby modules - included do end block – but still don't get when you would use the self.included do ... end block in a module.
The post says that code in the block will be ran when you include the module, but what's the point of that if a module's sole purpose is to be included? Wouldn't that code need to be run anyway? That block doesn't need to be there in order for that code to be run, right?
What would be the difference between the two below:
module M
def self.included(base)
base.extend ClassMethods
base.class_eval do
scope :disabled, -> { where(disabled: true) }
end
end
module ClassMethods
...
end
end
vs.
module M
def self.some_class_method
...
end
scope :disabled, -> { where(disabled: true) }
end
What's the difference between the two examples?
The first code block adds the class methods in ClassMethods to the including class and calls the scope method on it as well. The second one does neither of these things and will result in a NoMethodError because the module has no scope class method. self.some_class_method will not be available on the including class once the module is included.
For the full story on how module inclusion works in Ruby, read my answer here:
Inheriting class methods from modules / mixins in Ruby
What's the point of self.included if a module's sole purpose is to be included?
Inclusion is not the only purpose of modules. They are also used for other things such as namespacing or simply storing various class methods that are then callable on the module itself.
Why doesn't Ruby include class methods automatically?
Theoretically Ruby could automatically add all class methods defined in a module to the including class, but in practice that would be a bad idea, because you would not get to choose anymore whether you want to include class methods — all class methods would be included every time, whether or not they are intended to be included. Consider this example:
module M
def self.class_method
"foo"
end
def self.configure_module
# add configuration for this module
end
end
class C
include M
end
Here, the configure_module method is obviously not supposed to be added to C, as its purpose is to set the configuration for the module object. Yet, if we had auto-inclusion for class methods, you would not be able to prevent it from being included.
But all instance methods are already included! How is that okay then?
Instance methods in a module are only really useful if they are included into a class, since modules cannot have instances, only classes can. So in a module every instance method is expected to be included somewhere to work.
A "class" method on a module is different, because it can be called on the module itself, so it can be used just fine regardless of whether it's also added to the including class. That is why it is better that you have a choice there.
module M
# self.included is the hook which automatically runs when this module is included
def self.included(base)
puts 'this will be printed when this module will be included inside a class'
base.extend ClassMethods
base.class_eval do
scope :disabled, -> { where(disabled: true) }
end
end
def print_object_class
self.class.name # here self will be the object of class which includes this module
end
module ClassMethods
def print_class_name
self.name # Here self would be the class which is including this module
end
end
end
I tried to modify the above module to help you understand how a module(concern) can be helpful in code reusability
self.included is a hook which runs automatically when a module is included inside a class.
any method declare in the module ClassMethods will become class methods for the class including this module
any method declare outside the module ClassMethods will become instance methods for the class including this module
For Ex suppose there is a class Product and you have included the module in it
class Product < ActiveRecord::Base
include M
puts 'after including M'
end
If you try this example in you rails console you will notice that as soon as the module M gets included in class Product included hook of module run and
this will be printed when this module will be included inside a class this is printed on console
after that after including M this will be printed on the console.
Also you can try following commands
Product.disabled # a scope with name 'disabled' is avaialble because of including the module M
Product.print_class_name # Outputs => 'Product' This method is available to class with the help of module M
Product.new.print_object_class #Outputs => 'Product'
It also offers reusability, include this module M in any class and that class gets access to all those methods described in the module.
Whereas your second example is a mere example of basic module
module N
def self.abc
puts 'basic module'
end
end
Now abc method define in module can be accessible using only this module
N.abc # outputs 'basic module'
class Product < ActiveRecord::Base
include N
end
Product.abc #raises exception, No method found on class Product
Product.new.abc #raises exception, No method found on object of class Product
I hope this may help you understand the concept of module better.
Please let me know if you still have any doubts.

Rails undefined method for Module

In Rails, how do you use a specific method from a module. For eg,
# ./app/controllers/my_controller.rb
class MyController < ApplicationController
include MyModule
def action
MyModule.a_method
end
private
def a_method
...
end
end
# ------------------------------------------------ #
# ./app/helpers/my_module.rb
module MyModule
def a_method
...
end
end
MyController includes MyModule. And in action ,I want to use MyModule.a_method (Please note I also have a private a_method in MyController and I don't want to use this.)
Things I've tried :
1) Defining the method in the module as self.
def self.a_method
end
2) Using the :: notation in controller (MyModule::a_method)
The error that I keep getting is
Undefined method:a_method for MyModule:module
For now, I've resorted to using a different name for the modules method. But I'd like to know how to namespace the function with either the Module:: or Module. notation
[UPDATE - 11/24/2014]
adding file structure in code, since Rails heavily relies on convention.
So I am not really sure what you are trying to accomplish with your module but a quick solution to get it working is below.
Move my_module.rb out of helpers and into lib/my_module.rb. The helpers directory is for methods that you use in your views. The convention is to utilize helpers that are namespaced after their respective controller or the application_helper.rb for global methods for your views. Not sure if that's what you are trying to accomplish with your module but wanted to throw that out there.
Create an initializer (you can all it whatever) in config/initializers/custom_modules.rb and add require 'my_module'
Update the a_method back to be self.a_method
You can now call MyModule.a_method in your app
Don't forget to restart your server for changes to lib/my_module.rb to take effect.
Also, a lot of people reference this post by Yehuda Katz as guidance on where to store code for your app. Thought it might be a helpful reference.
if you include MyModule into MyController, all the "instance methods" of the first will be mixed-in into the 2nd.
So if you only want to call MyModule.a_method, no need to include your module.
Then you'd want to require (or better autoload) your module before using it. To do so place it in controllers/concerns/my_module.rb, rails (4 at least) should autoload it, otherwise require its file in an intializer
# my_module.rb
module MyModule
def self.a_method
...
end
end
should work, but doing
# my_module.rb
module MyModule
extend self
def a_method
...
end
end
is more clean to me. You'd like to have a look to rails active support concern to understand the "rails way" on this topic.

How to automatically include a module in a class based on its name (like helpers are included in views)

In my app I am having to interface with some 3rd party software I hope one day to replace. So, rather than keeping all the code that maps between my models' data and the form it needs to be in for the 3rd party software in the models themselves, I've created a mapper module for each model, isolating the code somewhere that's easy to delete when the time comes.
So I have something like the following:
app/
models/
people.rb
mappers/
people_mapper.rb
Ideally, I'd like to automatically include the modules in the model class with the matching name, the same way that helpers are automatically included in views of the same name. How/where are the helpers automatically included, and is this also the best place for me to add my own code?
you can try something like this :
module Mapper::Core
def self.included( base )
base.extend( ClassMethods )
end
module ClassMethods
# model class method to include matching module
# this will throw an error if matching class constant name does not exist
def has_mapping
#mapper_class = Kernel.const_get( "Mapper::#{self}Mapper" )
include #mapper_class
end
# an accessor to the matching class mapper may come in handy
def mapper_class
#mapper_class
end
end
end
then then require and include the module in ActiveRecord::Base in an initializer (make sure that your Mapper module requires all the files in your 'mappers' folder, or use config.autoload_paths).
If you don't want to use the has_mapping class method at all, you can try to override ActiveRecord::Base's self.inherited callback, but it might become dangerous:
def self.included( base )
base.extend( ClassMethods )
base.instance_eval <<-EOF
alias :old_inherited :inherited
def self.inherited( subclass )
subclass.has_mapping
old_inherited( subclass )
end
EOF
end
I did not try any of this, so proceed with caution.
EDIT :
i was tired when i wrote this. there is a much simpler way to autoinclude the matching module :
module Mapper::Core
def self.included( base )
begin
mapper_class = Kernel.const_get( "Mapper::#{base.name}Mapper" )
base.instance_eval( "include #{mapper_class}" )
rescue
Logger.info "No matching Mapper Class found for #{base.name}"
end
end
end
initialize this with :
ActiveRecord::base.instance_eval( 'include Mapper::Core' )
all inheriting class will now include Mapper::Core, which will trigger inclusion of matching class.

Trying to understand how a Controller uses a Plugin/Module

Ok so I am using some module/lib/plugin (not sure of the exact name), let's say its a authentication/authorization plugin like: http://github.com/technoweenie/restful-authentication
class HomeController < ApplicationController
some_module_name_here
end
Now just from adding the code above 'some_module_name_here', I can access to methods from that module.
What is that line of code doing that gives me access to methods/objects from the module?
Is that declaring a variable like in say java/c#:
public SomeModule _someModule;
I know that plugins/modules basically extend the class under the covers, but how does it do this with a single line of code?
Is it called in the constructor somehow?
When you create a ruby plugin, and load it into the rails app via environment.rb, bundler, or a require call, the methods are loaded as "modules" that can be called. The ones that act like you're talking about will have an extra method called acts_as_list or something similar. All that method does is include the methods of the module into the class where that line was called.
Here's an example, which you could include in your app's lib folder and play with:
module Bellmyer
module Pointless
def self.included(base)
base.extend PointlessMethods
end
module PointlessMethods
def acts_as_pointless
unless included_modules.include? InstanceMethods
extend ClassMethods
include InstanceMethods
end
end
end
module ClassMethods
def pointless_class?
true
end
end
module InstanceMethods
def pointless_instance?
true
end
end
end
end
The module is available to any ruby class in your app, but the methods don't actually get loaded until you call acts_as_pointless, which then includes and extends your class with the methods listed. Only the acts_as_pointless method is immediately available to the model. This is the standard pattern for an ActiveRecord plugin.
That's not how it works.
When the plugin or gem is loaded it adds a class method to, in this case, ApplicationController named some_module_name. When you call that methods, a bunch of other class and instance methods are included.
Check out your favourite gem or plugin to see how they do it exactly.

Resources