Do you have to manually include ApplicationHelper in ApplicationController in Rails 6? - ruby-on-rails

Controller:
class FooController < ApplicationController
def index
bar_method
ApplicationHelper:
module ApplicationHelper
def bar_method
Viewing the index page raises undefined method bar_method.
Does ApplicationHelper need to be manually included?
Rails 6.

You don't need to include helper module. With helpers (in rails 5+), you can access the helper methods. Try this:
class FooController < ApplicationController
def index
helpers.bar_method

It turns out this was an update to Rails before 6.
In previous versions of Rails the controller will include a helper which matches the name of the controller, e.g., MyController will automatically include MyHelper. To return old behavior set config.action_controller.include_all_helpers to false.
https://api.rubyonrails.org/classes/ActionController/Helpers.html

Related

Rails Controller Namespace Inheritance Missing Layout

Using a namespaced controller and the app's Application layout isn't being loaded.
# controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
end
# controllers/servers/base_controller.rb
module Servers
class BaseController < ApplicationController
def initialize
# I noticed params are not accessible here either...
# Only in the child controller.
end
end
end
# controllers/servers/test_controller.rb
module Servers
class TestController < BaseController
def index
end
end
end
A pretty basic setup here. Anytime I route to /servers/:id it loads the page with the parameter, but the application layout does not load. I have a series of a couple controllers I'd like to all inherit from this BaseController to initialize a few things. I also noticed that besides the layout issue, the BaseController doesn't have access to url parameters. The TestController does though... Can anyone explain these two issues I'm seeing?
Rails 5.1.4
ruby 2.4.1p111
Figured out my issue. Don't use an initialize method in your class. Rails doesn't like that. Use before_action instead.

Render a view in Rails 5 API

I generated an API-only rails app with Rails 5 via rails new <application-name> --api. I've decided I want to include a view for testing some things and am having issues getting a view to load.
I created a users/index.html.erb file with some text and my controller is now simply def index; end but there is nothing appearing when I hit the /users URL. I also tried commenting out the # config.api_only = true in config/application.rb but that didn't affect anything. Any suggestions on how to proceed?
You don't need to uncomment config.api_only = true for this purpose, just inherit your controller from ActionController::Base, or do it in your ApplicationController (default for common rails generation).
Code:
For this controller only YourController < ActionController::Base
For all apllication ApplicationController < ActionController::Base
this is from the ActionController::Metal docs https://apidock.com/rails/ActionController/Metal
it says:
ActionController::Metal by default provides no utilities for rendering >views, partials, or other responses aside from explicitly calling of >response_body=, content_type=, and status=. To add the render helpers >you’re used to having in a normal controller, you can do the following:
class HelloController < ActionController::Metal
include AbstractController::Rendering
include ActionView::Layouts
append_view_path "#{Rails.root}/app/views"
def index
render "hello/index"
end
end
So I've tried it myself and adding just by adding the two modules actually work just fine when using it for ActionController::API

How to use reusable controller methods in Rails?

I'm relatively new to Rails and am working on creating a simple user authentication system to get to grips with how Rails works.
I'm currently at the point where I'd like to create some methods that I can use in my controllers like so:
is_logged? # => true
and
current_user_id # => 6
These would be used to interact with sessions, mainly so I'm not repeating myself in the controller.
Where would I define these functions and how would I include them in a controller?
Thanks a lot in advance for any help.
Method 1
You can define these method in helper files, inside app/helpers/my_module.rb. You can create a module there, put all the methods inside of it, and then include the modules in your control to use these method.
module MyMoule
def is_logged?
...
end
end
Then in you class include the module
class MyClassController < ApplicationController
include MyModule
def my_method
#Use it like this
logged_in = MyModule.is_logged?
end
end
Method 2
If you using session related stuff you can always put them inside application_controller.rb. And since all your controller will inherit ApplicationController the methods will be available to you.
class ApplicationController < ActionController::Base
def is_logged?
...
end
end
In your other controller you can use them directly.
class MyClassController < ApplicationController
def my_method
logged_in = is_logged?
end
end

Rails module scope

Given the following controller structure:
# application_controller.rb
class ApplicationController < ActiveController::Base; end
# pages_controller.rb
class PagesController < ApplicationController; end
# admin/application_controller.rb
module Admin
class ApplicationController < ::ApplicationController; end
end
# admin/pages_controller.rb
module Admin
class PagesController < ApplicationController; end
end
One would expect Admin::PagesController to inherit from Admin::ApplicationController and it does. But I have noticed that sometimes it inherits from ::ApplicationController.
So I decided not to risk it and changed declaration of all controllers in /admin to specifically target Admin::ApplicationController
# admin/pages_controller.rb
module Admin
class PagesController < Admin::ApplicationController; end
end
Okay that works, but from what I know it was correct in the first place. Why Rails inherits from a wrong controller sometimes?
Admin::PagesController sometimes inherits from ApplicationController instead of Admin::ApplicationController despite both being in the same module Admin
The problem here is rails' development mode code loading: in general code is loaded when you try to do something with a constant (eg subclass from it) and that constant doesn't exist. This results in const_missing being called and rails uses it this to try to load the class (for a detailed description see the guide).
If neither ApplicationController nor Admin::ApplicationController exist then when you access your admin pages controller ruby will hit that const_missing and try to load admin/application_controller.rb
However if ApplicationController is already loaded then ruby won't fire const_missing since it perfectly legal for a class in the admin module to inherit from something at the toplevel.
The solution as you say is to make explicit what you are inheriting from. Personally in my own apps I use Admin::BaseController as the base class.
Another option is to use require_dependency to point Rails to the correct file:
# admin/application_controller.rb
require_dependency 'admin/application_controller'
module Admin
class PagesController < ApplicationController
end
end

"undefined method" when calling helper method from controller in Rails

Does anyone know why I get
undefined method `my_method' for #<MyController:0x1043a7410>
when I call my_method("string") from within my ApplicationController subclass? My controller looks like
class MyController < ApplicationController
def show
#value = my_method(params[:string])
end
end
and my helper
module ApplicationHelper
def my_method(string)
return string
end
end
and finally, ApplicationController
class ApplicationController < ActionController::Base
after_filter :set_content_type
helper :all
helper_method :current_user_session, :current_user
filter_parameter_logging :password
protect_from_forgery # See ActionController::RequestForgeryProtection for details
You cannot call helpers from controllers. Your best bet is to create the method in ApplicationController if it needs to be used in multiple controllers.
EDIT: to be clear, I think a lot of the confusion (correct me if I'm wrong) stems from the helper :all call. helper :all really just includes all of your helpers for use under any controller on the view side. In much earlier versions of Rails, the namespacing of the helpers determined which controllers' views could use the helpers.
I hope this helps.
view_context is your friend, http://apidock.com/rails/AbstractController/Rendering/view_context
if you wanna share methods between controller and view you have further options:
use view_context
define it in the controller and make available in view by the helper_method class method http://apidock.com/rails/ActionController/Helpers/ClassMethods/helper_method
define it in a shared module and include/extend
Include ApplicationHelper in application_controller.rb file like this:
class ApplicationController < ActionController::Base
protect_from_forgery
include ApplicationHelper
end
This way all the methods defined in application_helper.rb file will be available in the controller.
You can also include individual helpers in individual controllers.
Maybe I'm wrong, but aren't the helpers just for views? Usually if you need a function in a controller, you put it into ApplicationController as every function there is available in its childclasses.
As said by gamecreature in this post:
In Rails 2 use the #template variable.
In Rails 3 use the controller method view_context
helpers are for views, but adding a line of code to include that helper file in ApplicationController.rb can take care of your problem. in your case, insert the following line in ApplicationController.rb:
include ApplicationHelper
As far as i know, helper :all makes the helpers available in the views...
Try appending module_function(*instance_methods) in your helper modules, after which you could directly call those methods on the module itself.
though its not a good practice to call helpers in controller since helpers are meant to be used at views
the best way to use the helpers in controller is to make a helper method in application_controller and call them to the controller,
but even if it is required to call the helper in a controller
then Just include the helper in the controller
class ControllerName < ApplicationController
include HelperName
...callback statements..
and call the helper methods directly to the controller
module OffersHelper
def generate_qr_code(text)
require 'barby'
require 'barby/barcode'
require 'barby/barcode/qr_code'
require 'barby/outputter/png_outputter'
barcode = Barby::QrCode.new(text, level: :q, size: 5)
base64_output = Base64.encode64(barcode.to_png({ xdim: 5 }))
"data:image/png;base64,#{base64_output}"
end
Controller
class ControllerName < ApplicationController
include OffersHelper
def new
generate_qr_code('Example Text')
end
end
hope this helps !
I had the same problem...
you can hack/bodge around it, put that logic into a model, or make a class specially for it. Models are accessible to controllers, unlike those pesky helper methods.
Here is my "rag.rb" model
class Rag < ActiveRecord::Base
belongs_to :report
def miaow()
cat = "catattack"
end
end
Here is part of my "rags_controller.rb" controller
def update
#rag = Rag.find(params[:id])
puts #rag.miaow()
...
This gave a catattack on the terminal, after I clicked "update".
Given an instantiation, methods in the model can be called. Replace catattack with some codes. (This is the best I have so far)
:helper all only opens helpers up to views.
This shows how to make a class and call it.
http://railscasts.com/episodes/101-refactoring-out-helper-object?autoplay=true
Try this to access helper function directly from your controllers view_context.helper_name
You can include your helper methods into a controller with a helper keyword syntax
class MyController < ApplicationController
helper ApplicationHelper
end

Resources