How the object of controller classes is created in Rails? - ruby-on-rails

When we navigate through pages in a rails app, inturn we call one of the functions defined in the controller class. Lets say we access localhost:3000/articles/new then new action (method) of the ArticlesController class is called/invoked.It's simple.
But what i can't figure out is that since ArticlesController class is a pure Ruby class with some methods and we need an instance of this class to call one of it's methods. But we never explicitly do that.
Then how the function call of any controllerclass is made possible ?

The controller is initialized automatically by rails. Specifically, this calls the action method on the controller class, which does the actual initialization.

The RouteSet generates instances of any controller on demand based on the needs of the ActionDispatch routing system. See here for how this is done.
So unless you are testing a controller directly, you can rely on the router to supply you with a controller instance. And if you are testing one directly, you should be using an ActiveController::TestCase to do this work for you.

Related

How to access session variables from a Draper decorator in Rails?

I want to be able to access a session variable from the Decorator. Now I can't do so, nor can I access controller instance variables, let's say #session_variable.
Is there a clean way to achieve this?
Thanks!
When I need any object other than a controller to have access to request information, I like to use what I think of as the Context pattern. It looks like this:
Write a singleton class that has only the interface that your decorator needs (following the Interface Segregation Principle). As an example, let's say that your decorator needs to know whether the user is logged in. Make a LoginContext singleton with an instance method user_is_logged_in?. The decorator can find out whether a the user is logged in by calling LoginContext.instance.user_is_logged_in?.
Add an before_filter to your ApplicationController that sets the singleton's user_is_logged_in attribute to true or false according to the session before running the action. Optionally, if you want to make sure that nothing uses the LoginContext outside of a request, make the filter an around_filter and set the attribute to nil after running the action, and write the user_is_logged_in? accessor so that it raises an error if the attribute is nil.
The above is for single-threaded Rails application servers, but you can write the same functionality around a thread-specific singleton if you use a threaded application server.

where can i find the class definition for action controller base?

I am just a bit curious how application controller and action controller objects work in rails. Is there anywhere I can view the complete class templates for these objects? I was wondering if methods like "show" and "index" are just hook methods that are called inside the initialize of the object. Is this why we define our instance members from these? Are they basically just empty methods called in the init that will then define the instance variables as the objects are selected from the routes.rb file?

call update action from another controller

I have two controllers: ControllerA and ControllerB.
Is it possible to call the ControllerA.update function from ControllerB? Something as demonstrated below:
class ControllerB < ApplicationController
def foo
ControllerA.update args
end
end
You can call another class method of another controller as any other classes. Actions are defined as instance methods and you should therefore instantiate a controller just by doing ControllerA.new.
That said, you shouldn't do that. I strongly discourage to got that road, that is not how the controllers are meant to be used.
If some logic in your application are to be shared between controllers, put it elsewhere, maybe in a model or a service (or something else) depending of what you want to achieve.
No, you can not call it directly, but you can redirect to another controller action.
The answer is no. You can redirect to that controller's function.
I don't know what you want to do in that update, but check if you cannot insert that function into "aModel".

Rails Controller/Model methods

I am watching Code School Rails testing course. There is an instance of the class zombie. The zombie model has a method:
def avatar_url
...
end
Within the test, .rb file has the following:
z.avatar_url
When I call a method like this, how does Rails distinguish if I'm calling a controller or model method? I hadn't thought of calling a model method from other than a controller, and only like Model.method and not object.method.
If both my controller and my model have a method with the same name, how would Rails know which one to call?
Update:
Lets take the class String as example, it is not a model, right?
So I could say:
s = String.new
s.capitalize
If this call doesn't go to a model and not to a controller, where does it go then? Where would a class like String be defined in the Rails directory?
A method inside a controller can only be called via URL.
Example:
/things/super_action
Should call the def super_action inside ThingsController.
As for Model methods, they can be accessed anywhere. Just note if they are instance or class methods:
Model.ultra_method
This is a class method call, it is probably defined as def self.ultra_method.
m = Model.new
m.instance_method
This is a instance method call, and it is probably defined as def ultra_method.
UPDATE
String is a core class of ruby language. As is Array, Number, etc. In your example you are creating an instance of String and calling an instance method of the String class.
It seems like you're new to Ruby as well as Rails. In Ruby, a class is sort of like a description of a type of object (although the class itself is an object, too). Whenever there is a class defined, you can create new instances of it, as with String.new. Note that classes always have capitalized names.
Class methods are methods that work on the class itself. You can tell when a method is a class method because it will be attached to the capitalized name of the class (just like String.new). On the other hand, instance methods only work on an instance of the class, not on the class itself (eg str = String.new; str.capitalize!). Usually there are more instance methods than class methods, because instances are the things that you're actually working with (new is the most common class method you'll see).
As others have mentioned here, String is not a Rails model; it's a basic Ruby class. When you're working in Rails, you have access to all the regular Ruby classes as well as other classes and methods that are defined within Rails' source code. So String is not defined in Rails itself, but Rails does provide some useful instance methods for strings (eg str.to_date).
A model in Rails is really just a Ruby class. To understand the workings of a model, you should make sure you understand how Ruby classes work. What makes Rails models special is that they inherit from a class defined in Rails' source code known as ActiveRecord (any class in Ruby can inherit from another class, this is just one example of that). ActiveRecord has a number of class and instance methods, which are also available to your models because they inherit from ActiveRecord. For example, if you have a class (model) called Person, you can automatically use the Person.find(id) class method to look up a particular instance of the Person class in the database. You also have the person.save instance method to save the instance to the database.
All of this was confusing to me when I first started, so my best advice is to familiarize yourself with Ruby as you learn Rails.
You can call Model class/instance methods from anywhere in Rails. Model are just the mapping to your database and acts as a proxy for your database. When you are calling
z.avatar_url
you are calling a method on "z" model instance. So not matter from where you call it will always call the model's method.
If you define a method with same name in both controller and model, you would always be calling a model's method with model instance or model class. Controller methods are simply action in Rails they are never referred directly from anywhere. They are used for Rails routing.
Hope I am clear.

Why are Controller Constructors fired before the Initialize method

I have a base Controller ApplicationController that needs to grab the URL Host and do some processing before the child controllers are fired. Since controller constructors are fired before RequestContext is initialized I have to override Initialize method to do my processing.
ApplicationController:
Protected Overrides Sub Initialize(ByVal requestContext As System.Web.Routing.RequestContext)
MyBase.Initialize(requestContext)
Dim host as String
host = Request.Url.Host.ToString
End Sub
What is the logic behind having Controller Constructors fire before the Initialize method?
Also what are the rules to what should be placed in the Initialize Method.
Assuming that constructors are the first instance method ever to be fired in a .NET class, that shouldn't come as a surprise and is not really something MVC specific. It's more how the .NET framework works.
The MVC framework needs to first instantiate a controller and then initialize it => it calls the constructor first. And because performing lots of code that could potentially might throw exceptions, etc... is not always best to be put in a constructor => the presence of the Initialize method. As far as this method is concerned I must admit that I have written lots of ASP.NET MVC code and never had to use it. Action filters always seemed like a better alternative.
So to answer your question:
Also what are the rules to what should be placed in the Initialize Method.
I've never ever put any code and never ever need to override this method. I've always preferred using action filters because this way I am no longer in the obligation of deriving from a common base controller (not that this is a problem).
Sometimes, maybe you would want your request to initialize your variables, so in this case you should use the Initialize method.
For example, if you want to initialize some variables in a different way when the request is local or not, etc.

Resources