How to call a Rails Mountable Engine method from a Rails application? - ruby-on-rails

Mountable Engine Controller Method:
module ServiceApi
module Api
module V1
class RequestorController < ApplicationController
def get_details(query_parameters)
#some code here
end
end
end
end
end
Rails app Controller Calling the get_details(params) method from the Mountable Engine
ServiceApi::Api::V1::RequestorController.new.get_details(params)

It seems to me like you're not looking for a controller action, but rather a helper method. For instance, controller actions don't take parameters.
If you still want it to live in the controller as stated, that's fine, but you can extract it to a helper and include that helper in every controller you want to use it in.
For instance,
# [engine]/app/helpers/requestor_helper.rb
module ServiceApi::Api::V1::RequestorHelper
def get_details(query_parameters)
# code
end
end
and then in your controller
include ServiceApi::Api::V1::RequestorHelper
No need to abuse classes when what you want is a module.

Related

Difference between stating helper methods in helper and controller files

In Ruby on Rails we can state a helper method in controllers e.g.
# app/controllers/my_controller.rb
class MyController < ApplicationController
helper_method :helper_method_name
...
private
def helper_method_name
...
end
end
and in helpers e.g.
# app/helpers/my_helper.rb
class MyHelper
def helper_method_name
...
end
end
What's the difference (in relation to access, usage, etc.)?
The method helper_method is to explicitly share some methods defined in the controller to make them available for the view.
This is used for any method that you need to access from both controllers and helpers/views (standard helper methods are not available in controllers).
As ray said. You only want to use the helper_method when you really need to use it in both the controllers and helpers/views.
Generally, you want to use controller concerns and the helpers(views) for the respective methods as that's the convention.

Create an "includable" Rails controller action within helper

Is it possible to make an includable controller action within a Rails Helper through an included block? I'm thinking something like this:
module XablauHelper
included do
def my_shared_action
true
end
end
end
Already tried doing it through class.eval block and through using like a class method i.e. self.my_shared_action but no success, I have already found a solution that is making a parent controller with the desired shared actions and inheriting from it, but for the sake of modular design I would like to make it a more "global" approach, so I could gemify my solution and reuse code, any suggestions that doesn't use inheritance?
Adding controller actions in a helper is probably the wrong choice, as these methods are intended for your views.
Consider using controller concerns instead, and including them where required. For example:
# in app/controllers/concerns/useful_functions_concern.rb
module UsefulFunctionsConcern
extend ActiveSupport::Concern
included do
rescue_from SomeException, with: :handle_access_denied
end
def useful_method
# ...
end
protected
def handle_access_denied
# ...
end
end
# in your controller
class XyzController < ApplicationController
include UsefulFunctionsConcern
def index
useful_method
end
end
Where common controller actions can be shared and the controllers have something in common e.g. they are all API controllers, also consider using inheritance to achieve this. For example:
# parent controller
class ApiController < ApplicationController
def my_shared_action
end
end
class SpecificApiController < ApiController
end

Where to put Ruby helper methods for Rails controllers?

I have some Ruby methods certain (or all) controllers need. I tried putting them in /app/helpers/application_helper.rb. I've used that for methods to be used in views. But controllers don't see those methods. Is there another place I should put them or do I need to access those helper methods differently?
Using latest stable Rails.
You should define the method inside ApplicationController.
For Rails 4 onwards, concerns are the way to go. There was a decent article which can still be viewed via the Wayback Machine.
In essence, if you look in your controllers folder you should see a concerns sub-folder. Create a module in there along these lines
module EventsHelper
def do_something
end
end
Then, in the controller just include it
class BadgeController < ApplicationController
include EventsHelper
...
end
you should define methods inside application controller, if you have few methods then you can do as follow
class ApplicationController < ActionController::Base
helper_method :first_method
helper_method :second_method
def first_method
... #your code
end
def second_method
... #your code
end
end
You can also include helper files as follow
class YourController < ApplicationController
include OneHelper
include TwoHelper
end
You can call any helper methods from a controller using the view_context, e.g.
view_context.my_helper_method
Ryan Bigg response is good.
Other possible solution is add helpers to your controller:
class YourController < ApplicationController
include OneHelper
include TwoHelper
end
Best Regards!
Including helpers in controller will end-up exposing helper methods as actions!
# With new rails (>= 5)
helpers.my_helper_method
# For console
helper.my_helper_method

Missing devise routes helpers inside of rails engine views

I'm building a Rails engine called Engrave.
I have the engine mounted like so:
# Routes.rb of the host app
mount Engrave::Engine => "/engrave", :as => "engrave_engine"
Within this engine I have a controller called "PostsController". When I navigate to this controller to view a post like so: /engrave/posts/1 I get this error:
undefined local variable or method `new_user_session_path'
The PostsController in the engine is inheriting from the engine controller, which is inheriting from the application controller, like so:
module Engrave
class PostsController < ApplicationController
...
end
class Engrave::ApplicationController < ApplicationController
end
The new_user_session_path is being defined by devise, which I have setup like:
devise_for :users
The call to new_user_session_path is in the layouts/application.html.erb template file in the host app
I cannot figure out why this route helper isn't available in this context. What am I doing wrong?
Use
main_app.new_user_session_path
that should work
I've had success doing the following in the main app's application_helper.rb:
module ApplicationHelper
# Can search for named routes directly in the main app, omitting
# the "main_app." prefix
def method_missing method, *args, &block
if main_app_url_helper?(method)
main_app.send(method, *args)
else
super
end
end
def respond_to?(method)
main_app_url_helper?(method) or super
end
private
def main_app_url_helper?(method)
(method.to_s.end_with?('_path') or method.to_s.end_with?('_url')) and
main_app.respond_to?(method)
end
end
I've used this in mountable engines, so you do not have to sacrifice those features.
Working off of this response, I include all helpers found in application_helpers.rb by stating helper "manager/application" inside the controller (if 'manager' is the current namespace of your mountable engine. Just use 'application' if you are calling this from a standard application).

Rails: controller method or instance variable inside a helper

I'm using the bitly gem and would like to have access to the bitly API inside my helper methods (which get called by views and mailers to generate URLs).
I initiate an API connection in this method in my ApplicationController:
(is there a more appropriate place to do this BTW?)
class ApplicationController < ActionController::Base
before_filter :bitly_connect
def bitly_connect
Bitly.use_api_version_3
#bitly ||= Bitly.new(APP_CONFIG['bitly_username'], APP_CONFIG['bitly_api_key'] )
end
end
By default I don't have access to #bitly in my helpers. Can you suggest a way to accomplish that?
The only related thread I found wasn't helpful:
Rails 3 and Controller Instance Variables Inside a Helper
Thanks.
Rails by convention passes instance variables set in the controller actions (and filters) along to the views. The helper methods are available in these views, and should have access to the instance variables you set inside your controller action.
Alternately, you can set a local variable inside your helper method by passing the variable to the method, or by using the Object#instance_variable_get method: http://ruby-doc.org/core/classes/Object.html#M001028
# app/controllers/example_controller.rb
class ExampleController
def index
#instance_variable = 'foo'
end
end
# app/helpers/example_helper.rb
module ExampleHelper
def foo
# instance variables set in the controller actions can be accessed here
#instance_variable # => 'foo'
# alternately using instance_variable_get
variable = instance_variable_get(:#instance_variable)
variable # => 'foo'
end
end
As for your concerns with the placement of the logic, it does not look like it belongs in the controller. Think of the controller as routing requests for your application. Most logic should be performed inside of your model classes. "Skinny controller, fat model.": http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model
If you need a controller method to be accessible as a helper, you can use helper_method
class ApplicationController < ActionController::Base
helper_method :bitly_connect
def bitly_connect
#bitly ||= begin
Bitly.use_api_version_3
Bitly.new(APP_CONFIG['bitly_username'], APP_CONFIG['bitly_api_key'] )
end
end
end
Note that I also altered the method, so that it doesn't call Bitly.use_api_version_3 each time it is called.
As Ben Simpson noted, you should probably move this into a Model though.

Resources