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
Related
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
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.
I have a module as a mountable engine mounted to a main app
through
mount MyEngine::Engine, :at => '/myengine'
I have everything namespaced in the negine and the engine has it's own views in engine/app/views/myengine/
Everything works fine when I run rails server then try to access
localhost:3000/myengine
first then go to the root of the main app and come back to the engine through a link in the index view of the main app
However when I start the server, go to localhost:3000 and from there click on the link to the engine module it tries to fetch the views correctly however the methods contained in the engine's helpers raises an error upon call for them being undefined.
I am on rails 4
I used eager_load to load the mountable engine in it's initialized in the main app and everything seems to be working now.
Myengine::Engine.eager_load!
I just ran into this issue as well. I had defined an ApplicationController inside my engine and was seeing NoMethodErrors when I tried to use helper methods inside one of my engine's controllers.
The Problem
The code looked something like this:
in my_engine/app/controllers/my_engine/application_controller.rb
module MyEngine
class ApplicationController < ActionController::Base
helper ApplicationHelper
end
end
in my_engine/app/controllers/my_engine/projects_controller.rb
module MyEngine
class ProjectsController < ApplicationController
def new
# some action code here
end
end
end
in my_engine/app/helpers/my_engine/application_helper.rb
module MyEngine
module ApplicationHelper
def translations_include_tag
javascript_include_tag "translations-#{I18n.locale}.js"
end
end
end
If I navigated to a route in the host rails app, then clicked a link that navigated to my_engine/projects/new, I would get a NoMethodError saying translations_include_tag didn't exist.
The Explanation
I think this was happening because the application had two classes with the same name: ApplicationController in MyEngine and ApplicationController in the host app. When the first route outside the engine is visited, Rails autoloads the ApplicationController from the host app. What that means is Rails associates the main app's ApplicationController with the name "ApplicationController". When you navigate to my_engine/projects/new, Rails lazy loads ProjectsController which also inherits from ApplicationController. Rails/ruby thinks you're referring to the same ApplicationController it has already loaded, so in effect ProjectsController ends up inheriting from the host app's ApplicationController instead of the one in the engine. Since the translations_include_tag method isn't defined in the host app's ApplicationController, ruby raises a NoMethodError when the view tries to call it.
The Solution
I was able to fix the problem by explicitly inheriting from MyEngine's ApplicationController:
in my_engine/app/controllers/my_engine/projects_controller.rb
module MyEngine
# changed from just plain 'ol ApplicationController
class ProjectsController < ::MyEngine::ApplicationController
def new
# some action code here
end
end
end
After fixing the inheritance issue, the NoMethodError went away.
The accepted answer says to use eager loading, which will also fix the problem because it forces the engine's ApplicationController to load first. Since the engine's ApplicationController is namespaced inside MyEngine, it's full name is MyEngine::ApplicationController, which doesn't conflict with the main app's ApplicationController because the constant names are different.
You need to include the helpers explicitely in your lib/engine.rb file:
initializer 'your-gem-name.setup_helpers' do |app|
app.config.to_prepare do
ActionController::Base.send :include, HelperModuleName
end
end
end
I'm having trouble accessing a helper method after upgrading to Rails 4.1.1. I have the following code in my application.
module ApplicationHelper
def last_page_url
session[:last_page]
end
end
class Admin::ArticlesController < ApplicationController
def update
#....more code here
return redirect_to self.last_page_url
end
end
In Rails 4.0.x this code worked fine. After upgrading to Rails 4.1.1 I'm getting an error "undefined method 'last_page_url' whenever my update action runs. Why is this breaking now?
I'm not really sure why this stopped working after upgrading to Rails 4.1.1, but as #steel suggested, it had something to do with the helper method not being included in my particular controller. Adding include ApplicationHelper to the top of my Controller would have worked and I probably could have taken it a step further by adding it to the ApplicationController class since I needed that method available to all controllers. In the end I opted for a different solution:
First, I moved the last_page_url from the ApplicationHelper to the ApplicationController class so all of my controllers could access it. Then I used helper_method to make this method available to all my views. My final code is as follows:
module ApplicationHelper
end
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
def last_page_url
session[:last_page]
end
helper_method :last_page_url
end
If anyone ever figures out something changed from Rails 4.0 to Rails 4.1 I would be interested in learning what happened. In this particular application I'm just using the default Rails 4.1 settings in my development.rb.
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