I'm writing a rails application, and in this one controller I need to specify the layout to render due to inheriting from ActionController::Base. In some of my other controllers I just have ActionController and it automatically uses the application layout. Whenever I remove the ::Base, I get the following message when accessing the page superclass must be a Class (Module given).
Why does inheriting from ActionController::Base in this controller matter, but not in the others?
To directly answer your question ActionController is not a controller class, it's a namespacing module that powers the entire controller stack. You would not interact with the ActionController module during typical Rails development. ActionController::Base is actually the class that controllers inherit from. This is why you can't inherit from ActionController.
But I think there are two controllers in play here. ActionController::Base and ApplicationController. I think you might be mistaking ApplicationController for being ActionController without the ::Base.
ActionController::Base is the main controller class where all of your Rails functionality comes from. ApplicationController is a generalized controller that you can add methods to and have all of your other Rails controllers inherit from.
You could do the following to use a different layout in one of your controllers:
class AuthenticationController < ApplicationController
layout 'authentication'
end
You can either use the AuthenticationController directly, or have new controllers inherit from AuthenticationController.
Your controllers should inherit from ApplicationController. This will allow them to automatically render the application layout. ApplicationController extends ActionController::Base.
Related
I have a module ApplicationHelper in app/helpers/application_helper.rb
defined like this
module ApplicationHelper
def some_method(arg)
end
end
and i have my view file is here
app/views/v1/admin/messages/show.json.jbuilder
So i am trying to access the
some_method()
in view file but it doesn't reflect!
Is this due to namespacing? or what i am not able to understand.
It would be Great if someone explains the concept.
Thanks in advance!
it says undefined method error
what could be the reason?
You didn't include your controller code, but we'll assume it ultimately inherits from ActionController::API (as it should it if it is an API controller). If so, that is the root of it rather than namespacing, etc. Per the ActionController documentation:
An API Controller is different from a normal controller in the sense
that by default it doesn't include a number of features that are
usually required by browser access only: layouts and templates
rendering, flash, assets, and so on. This makes the entire controller
stack thinner, suitable for API applications. It doesn't mean you
won't have such features if you need them: they're all available for
you to include in your application, they're just not part of the
default API controller stack.
One of the side effects of the thinner API controller is that they don't automatically include helpers like a standard Rails controller. You can easily add that back in, though.
messages_controller.rb
class Api::V1::MessagesController < ActionController::API
include ActionController::Helpers
helper ApplicationHelper
def show
# whatever
end
end
app/helpers/application_helper.rb
module MessagesHelper
def some_method(arg)
# whatever
end
end
app/views/messages/show.json.jbuilder
json.bogus do
thing1: some_method('banana')
end
If you have lots of API controllers, you can of course stick it in a base controller class they all inherit from like so:
class Api::V1::ApiController < ActionController::API
include ActionController::Helpers
helper ApplicationHelper
end
I am new to Ruby on Rails Development and was trying to understand inheritance in Rails, I understood how do a class inherit from a parent class
For Example MyController < ActionController, in this Action Controller is the parent class. But I dont understand this syntax
ApplicationController < ActionController::Base
Specifically what is the purpose of ::Base
This syntax is used to indicate that Base is a class inside of ActionController namespace.
I have five controllers that share common code. Is it best to let them inherit from a parent controller, or use concerns? For example:
class PostsController < ApplicationController
before_action :authenticate, :set_project
layout 'projects'
end
class CommentsController < ApplicationController
before_action :authenticate, :set_project
layout 'projects'
end
# three other controllers, etc...
I could let the controllers inherit from one controller that declares the before_actions and the layout, or I could stuff the common code into a concern.
What's the criteria from one choice or the other? Is it defined?
My rule of thumb is:
If the controllers share the same namespace in the URL (for example /projects/... or /admin/...), than I use inheritance from an Projects::BaseController or Admin::BaseController.
If they just share methods or declarations and do not share a namespace, than I use mixins.
And sometimes I prefer duplicated code. Because code in place is easier to understand than a mixin with a meaningless name. Do you have a good name for a concern that covers authentication and layout?
In most cases I use mixins for adding features and inheritance for customizing features.
e.g.:
If I need to override current_user I choose inheritance. If I got only some shared methods, then I choose mixins.
I've created a number of controllers & views under an 'admin' namespace, but they are still pulling from the application layout. how can I make a layout that applies to all the views in the namespaced routes, and still use the current layout for the other pages?
I usually have a Base controller class in my namespace, and then have all controllers in that namespace inherit from it. That allows me to put common, namespace specific code in Base and all the controllers in that namespace can take advantage. For example:
class Admin::BaseController < ApplicationController
layout 'admin'
before_filter :require_admin_user
end
class Admin::WidgetsController < Admin::BaseController
# inherits the 'admin' layout and requires an admin user
end
Generally speaking, Rails will use the application layout if there isn't a layout that matches the controller. For example, if you had a PeopleController, Rails would look for layouts/people.html.erb and if it didn't find that, application.html.erb.
You can explicitly specify a specific layout if you want to override this convention.
class Admin::PeopleController
layout 'some_layout'
end
That controller will then use some_layout.html.erb rather than looking for people.html.erb and application.html.erb.
But this might be a better way if you're looking to group things: If you have a base AdminController that inherits from ApplicationController, you can have your, say, Admin::PersonController inherit from the AdminController and it will inherit the admin layout.
I don't know the specifics of your code, but you might have:
class AdminController
def show
#render a template linking to all the admin stuff
end
end
app/controllers/admin/people_controller.rb:
class Admin::PeopleController < AdminController
#your awesome restful actions in here!
end
views/layouts/admin.html.erb:
Hello from the Admin!
<%= yield %>
The one thing to realize is that Admin::PeopleController will inherit any actions that AdminController has defined (just as anything defined in ApplicationController becomes available in all sub-classes). This isn't generally a problem since you'll likely be overwriting the methods anyway, but just to be aware of it. If you don't have an AdminController, you can make one with no actions just for the purposes of the layout.
I've got a CopiesHelper module with a method cc.
In my ApplicationController, I have
helper :all
helper_method :cc #just tried putting this in recently
If in another one of my Controllers, I try using the cc method, I get
undefined method 'cc' for #<OtherController:0xblublublublub>
Am I missing a step here?
If you want to use your CopiesHelper in one of your controller, simply do :
in {app_dir}/app/controllers/your_controller.rb
class YourController < ApplicationController
include CopiesHelper
If you want to use your CopiesHelper in every controller of your app just do :
in {app_dir}/app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
include CopiesHelper
Well, seems like helpers aren't generally used in controllers!