call update action from another controller - ruby-on-rails

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".

Related

DRY Form Processing on Different Controllers in Rails 4

I have two forms/views which share similar input parameters; but each view is supposed to be processed by a separate controller because additional logic unique to each view is required. Each controller has plenty of input parameters associated with it. What is the best practice?
I know this question may sound like the "Sharing variables between controllers" thing; But if i use the before_filter method; I have to declare every input parameter from the form again. If I define a new method in the parent application controller or create a helper method for input parameter extraction; other methods in the child controller cannot access the variables... Is there a more elegant solution?
I often find cases where I need some reusable business logic outside of a controller. In those cases I'll define a new object in my /lib folder so I can use it multiple places. For example,
# lib/my_business_logic/do_stuff.rb
module MyBusinessLogic
class DoStuff
def self.dostuff(params)
# do stuff
end
end
end
Then I can call:
result = MyBusinessLogic::DoStuff.dostuff(params)

How the object of controller classes is created in 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.

Rails - How do Controllers pass instance variables to Views...can it be stopped?

I understand and appreciate that by putting # in front of a variable name in a Controller that it becomes available in whatever View is loaded. This is wonderfully useful, but I would like to understand the magic. How does it happen, and can it be stopped?
I am trying to DRY my CRUDdy resource controllers using inheritance, placing most of the logic in ApplicationController. The superclass should refer to the abstract variables #resource (for a single resource), #resources (for a collection of resources), and #parent_resource (for the parent resource when #resource is nested), but ideally the view would get more concrete names, for example;#customer, #customers, and #sales_territory respectively. Can this be done without sending duplicates of all objects (once in the abstract name, and once in the concrete name) to the view?
As I write this, the possibilities that come to mind are;
protected instance variables...does Ruby have such a thing, and
if so does the Controller magic hand them to the View?
setting the generic named variables to nil before render/redirect
using a protected empty method defined in the subclass to instead of
abstract named instance variables
What is the right choice in how to implement this?
What I'm assuming is happening here, is that there's a bunch of controllers in your app that literally just do the same thing and so you are wanting to make use of inheritance to DRY it up.
That being said, I'm not entirely sure the ApplicationController is the right place to dump all of this functionality as in the future if you had new controllers, they would also inherit all of this functionality without necessarily needing it.
I would do something like this:
Assuming you have controllers like this:
lions_controller.rb
tigers_controller.rb
hippos_controller.rb
and they pretty much have similar functionality... I would create a "Base" controller and then setup inheritance on child controllers. I would then also make an action that sets the "logical" defaults of child controllers, something like this.
AnimalsController.rb
class AnimalsController < ApplicationController
class_attribute :resource_class, :parent_resource_class
protected
def self.set_resource_attributes(options={})
self.resource_class = options[:resource_class]
self.parent_resource_class = options[:parent_resource_class]
end
end
LionsController.rb
class LionsController < AnimalsController
#call methods in AnimalsController here, start with setting the resource name
set_resource_attributes :resource_class => Lion, :parent_resource_class => Animal
end
and so on and so forth... the other thing that may be useful is to make use of the methods "instance_variable_set" so that you can set instance variable names in the view that actually make sense... You can make use of the class variables you just set to do this... so for example, lets re-open the AnimalsController.rb class:
class AnimalsController < ApplicationController
def show
instance_variable_set("##{self.resource_class.name.underscore}".to_sym, self.resource_class.find(params[:id]))
#... all the regular show stuff
end
end
This way, when you go to the lions#show path, what you will get in your view is access to a variable named #lion which will be set and contain an instance of the Lion class found through ActiveRecord.
Of course this pseudo code I threw in here can be cleaned up and DRY'd a bit more, but hopefully you get where I'm going with it. Hopefully this helps.

Is there a convention for the location of a base controller class?

I have a GridDataController class that handles all of my data requests from my jqGrids.
I think my application would be easier to maintain if I busted that class apart, put the relevent actions in their respective controllers, keep the grid specific functions in a base controller class and then inherit from that class when I need to retrieve grid data in my controllers.
It doesn't seem right for the Base Controller class to reside in the Controllers folder as I do not want any of it's actions to be called.
Is there a convention for this?
No conventions. It would be easier for everybody though if you put it under Controllers, since its a controller, want it or not :). However, you can put it anywhere and refer to it inside your controllers by using and by inheriting from it (if that's what you want to do).
If you don't want its actions to be called, declare it appropriately as abstract class ...
So, no right answer to your question, but before putting it anywhere, thing twice and change your mind and put it back into Controllers :)

When to add method to application_controller.rb

My shopping site has a header that's common across all pages.
I have added a shopping cart icon in the header, with a number that updates based on the contents in the current cart.
Because this icon requires a definition for current_cart, I now need to add this to every controller action. Is this unwise/unsafe? I'm new to rails, and don't quite understand the security repercussions of adding methods to applications.rb
Also, is the best way to do this to add this once to application_controller.rb, or to add it separately to each relevant controller action?
Thanks in advance for the feedback!
Having DRY in mind it's definitely better to add this method once, one level up in yours controller inheritance tree. If all controllers need that method then application_controller.rb is a good place. If just some of them then you may consider to create controller which inherits from ApplicationController, store that method in it, and all controllers that requiers that method should inherits form it.
All of your controllers inherit from the application controller. This means that any method you define in the application controller is available in all of your other controllers.

Resources