Understanding the basic inheritance in Ruby on Rails - ruby-on-rails

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.

Related

`circular dependency` - inheritance in application controller of Rails 4.2.0 engine

When upgrading engine from Rails 3.2 to Rails 4.2.0, the following inheritance in application controller causes circular dependency error in rspec:
class ApplicationController < ApplicationController
end
We have config.eager_load = false for config/development.rb.
The error:
activesupport-4.2.0/lib/active_support/dependencies.rb:492:in `load_missing_constant': Circular dependency detected while autoloading con
stant Authentify::ApplicationController (RuntimeError)
Here is the Rails engine document (ch:4.3.2) explaining this type of code practice. As I understand, the purpose of this inheritance is to allow the engine to access methods in Rails app or other engine which the current engine is mounted to. We would like to do the same in Rails 4.2.0 engine. How to fix this problem?
your applicationController is clearly trying to inherit from itself, it should rather look like
class ApplicationController < ActionController::Base
In rails 4 engine, the right format is:
class ApplicationController < ::ApplicationController
end
assume the class is within module MyEngine. Or
class MyEngineName::ApplicationController < ::ApplicationController
end

How to mock a Rails subclass contant in Rspec?

I have a BaseController that I want to superclass other controllers with. I also superclass some controllers with the standard ApplicationController.
For example, I may have:
class AController < ApplicationController
end
as well as...
class BController < BaseController
end
When testing, I sometimes need to create an arbitrary "mock" or "fake" class to test before_filters, module includes, etc. I don't do this often, but on occasion it's helpful.
I created one in my specs like so:
class FakeController < ApplicationController
end
That's fine.
But now, I need to create another one of these FakeController classes, but this time as a subclass of my BaseController class.
Unfortunately the FakeController constant is already registered and I'm getting superclass mismatch errors.
I don't want to do something like FakeController2 -- as I think this opens a bad can of worms.
Any suggestions?
I don't see the issue with using FakeController2 or any other name, but the only public alternative I can think of is to introduce a module so that your second FakeController exists in a different namespace, as in:
module Foo
class FakeController < ApplicationController
end
end
There is a private method remove_const defined on Kernel which can be used to unregister a constant from an object. So, if FakeController is defined on Object, you can unregister it with the call:
Object.send(:remove_const, :FakeController)
At that point, you can define the constant again as you would if it had never never been defined in the first place. (Remember: Ruby is an interpreted language.)
An alternative to subclassing your controllers is to use the anonymous controller mechanism provided by the rspec-rails gem.

Rails 3 engine application controller

I have a rails engine that expose the following controller:
class ActsAsAssets::AssetsController < ApplicationController
..........
The main application uses devise into the ApplicationController. From the main application I use to extend the Engine Controller normally like this:
class MainApplicationController < ActsAsAssets::AssetsController
.......
What I was aspecting is that MainApplicationController was extending the main application ApplicationController via the engine.
Note that the engine does not have any ApplicationController so I was expecting ActsAsAssets::AssetsController < ApplicationController to actually extend the ApplicationController of the rails app that uses the engine.
Looks like I am wrong.
Any suggestion?
Basically what I want to achieve is that a controller from my main app extends a rails engine controller that extends the main ApplicationController cause does not have one inside the engine.
Hoper is clear.
Change the declaration to look like this:
class ActsAsAssets::AssetsController < ::ApplicationController
That instructs the controller to extend the non-namespaced ApplicationController from the main application.

Error when removing '::Base' from ActionController

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.

Accessing Rails helpers from a presenter/module?

There are many questions about accessing Rails helpers from a model, all of which rightfully state that the answer is not to do that. This is not that question.
I have some fairly complex controller and view code that I want to abstract into a presenter class. But that class isn't a descendant of ApplicationController. How can I get access to, say, devise's current_user?
It appears there's no "official right" way to do this at the moment. Two possibilities:
It's hacky, but you can store the current controller in ApplicationController, and reference it in your presenters to get at the helpers:
class ApplicationController < ActionController::Base
prepend_before_filter { ##current_controller = self }
end
class YourPresenter
def current_user
ApplicationController.current_controller.current_user
end
end
Jeff Casimir is working on a great Decorator/Presenter gem called draper that encapsulates the whole idea:
https://github.com/jcasimir/draper

Resources