I am trying to access helper method in my controller using helpers like below:
class MyController < ApplicationController
def index
#foo = 'bar'
helpers.my_helper_method
end
end
Inside Helper method, I am trying to access an instance variable of controller
module MyHelper
def my_helper_method
#some manipulation on foo
#foo.to_i
end
end
But in above scenario #foo is nil. When I call the same method from view, #foo is available. So the instance variable can be passed to helper method only through UI or some other way is there?
Thanks in advance.
UPDATE:
view_context
seems like reasonable solution https://apidock.com/rails/AbstractController/Rendering/view_context
class MyController < ApplicationController
def index
#foo = 'bar'
helpers.my_helper_method(#foo)
end
end
module MyHelper
def my_helper_method(foo)
#some manipulation on foo
foo.to_i
end
end
pass it as argument.
You can access instance variables that you set in a controller in your helpers. If the value is nil, then you need to deal with it in your helper:
module SomeHelper
def do_something
return 0 if !#value
value * 3
end
end
class SomeController
def index
#value = 1
helpers.do_something
end
def show
#value = nil
helpers.do_something
end
end
Related
I have the following class
class EvaluateService
def initialize
end
def get_url
end
def self.evaluate_service
#instance ||= new
end
end
class CheckController < ApplicationController
def index
get_url = EvaluateService.get_url
end
end
The problem here is that i know that i can do evaluate_service = EvaluateService.new and use the object evaluate_service.get_url and it will work fine but i also know that some frown upon the idea of initializing the service object this way and rather there is a way of initializing it via a call, send method in the service class.
Just wondering how do i do this?
I think what you're looking for is something like:
class Evaluate
def initialize(foo)
#foo = foo
end
def self.call(foo)
new(foo).call
end
def call
url
end
private
def url
# Implement me
end
end
Now you can do this in your controller:
class CheckController < ApplicationController
def index
#url = Evaluate.call(params)
end
end
The reason some prefer #call as the entry point is that it's polymorphic with lambdas. That is, anywhere you could use a lambda, you can substitute it for an instance of Evaluate, and vice versa.
There are various ways to approach this.
If the methods in EvaluateService don't need state, you could just use class methods, e.g.:
class EvaluateService
def self.get_url
# ...
end
end
class CheckController < ApplicationController
def index
#url = EvaluateService.get_url
end
end
In this scenario, EvaluateService should probably be a module.
If you want a single global EvaluateService instance, there's Singleton:
class EvaluateService
include Singleton
def get_url
# ...
end
end
class CheckController < ApplicationController
def index
#url = EvaluateService.instance.get_url
end
end
But global objects can be tricky.
Or you could use a helper method in your controller that creates a service instance (as needed) and memoizes it:
class EvaluateService
def get_url
# ...
end
end
class CheckController < ApplicationController
def index
#url = evaluate_service.get_url
end
private
def evaluate_service
#evaluate_service ||= EvaluateService.new
end
end
Maybe even move it up to your ApplicationController.
I have the following helper
module AvatarHelper
# Todo: set a defatul profile-image-path
DEFAULT_PROFILE_IMAGE_PATH = "http://image_here"
def avatar_path(user, size = 24)
..
end
def get_facebook_profile_pic user, size
..
end
def get_gravatar_path user, size
..
end
end
When I try to call the helper method in controller, it results in the following error:
undefined method `avatar_path' for AvatarHelper:Module
Here is my controller for reference:
class DashboardController < ApplicationController
before_action :authenticate_user!
def index
#dashboard = Dashboard.new(current_user)
puts AvatarHelper.avatar_path(current_user)
end
end
When I reference other helpers, I see they don't need to reference the helper elsewhere.
module TitleHelper
SITE_TITLE = 'My Site'
TITLE_SEPARATOR = ' ยท '
DESCRIPTION_CHARACTER_LIMIT = 140
def title(*parts)
parts << SITE_TITLE
provide(:title, parts.compact.join(TITLE_SEPARATOR))
end
end
I can then just add the title method directly in the view.
<% title 'myPage' %>
Module methods cannot be invoked directly. They should be included in the class to invoke. That's why they are called mixins(they can be mixed with others).
Here you can include the module in your controller.
class DashboardController < ApplicationController
include AvatarHelper
def index
#dashboard = Dashboard.new(current_user)
puts avatar_path(current_user)
end
end
def self.avatar_path(user, size = 24)
..
end
you are calling instance method add self before mthod will work for you.
Add the following code in your helper.
module AvatarHelper
extend ActiveSupport::Concern
Now you can directly call your method by name like
puts avatar_path(current_user)
Let us say I have a helper like this:
module ApplicationHelper
def foo
#foo
end
def set_foo(foo)
#foo = foo
end
def foo=(foo)
#foo = foo
end
end
and a controller like this:
class ApplicationController < ActionController::Base
include ApplicationHelper
def index
foo = 'hello'
end
end
I wonder to know why in the controller neither foo = 'hello', nor foo=('hello') invokes the helper's method foo= but set_foo 'hello' does invoke its method set_foo?
The short answer is, it will just set a local variable in the controller method called foo.
If you call self.foo = 'hello' Ruby will know that foo is a method that should be called.
Worth noting is that this is a completely wrong usage of Rails view helpers.
I'm trying to create a custom helper like this:
# app/controllers/my_controller.rb
class MyController < ApplicationController
helper :my
def index
puts foo
end
end
# app/helpers/my_helper.rb
module MyHelper
def foo
"Hello"
end
end
But, I got the following error:
undefined local variable or method `foo' for #<MyController:0x20e01d0>
What am I missing ?
Generally, I do the opposite: I use controller methods as helpers.
class MyController < ApplicationController
helper_method :my_helper
private
def my_helper
"text"
end
end
Helpers are accessed from the views, not the controllers. so if you try to put the following inside your index template it should work:
#my/index.html.erb
<%= foo %>
If you do want to access something from the controller, then you should use the include syntax instead of helper, but do not name it like a helper module in that case.
How about just including the helper as a mixin in the controller...
class MyController < ApplicationController
include MyHelper
def index
puts foo
end
end
my ruby (on rails) class looks like:
class Foo
def self.method1
someAction
end
def self.method2
someAction
end
def someAction
//doSmth
end
end
any ideas how to make this work or achieve the same behavior some other way?
thanks!
If some_action is appropriate as a class method, I'd do it like this:
class Foo
def self.method1
some_action
end
def self.some_action
# do stuff
end
def some_action
self.class.some_action
end
end
If method1 is supposed to be a convenience method, then I'd do like Hates_ said to.
class Foo
def self.method1
self.new.some_action
end
def some_action
# do stuff
end
end
The decision for me is usually whether some_action is more of a utility method (like generating a random key, in which case I'd pick the first form), or if it's an entry point to something more complex (like a parser, in which case I'd pick the second form).
You cannot call an instance method from a class method, without an actual instance of the class itself. You can do it as such:
class Foo
def self.method1
myFoo = Foo.new
myFoo.someAction
end
def someAction
//doSmth
end
end