Nadiya
Nadiya

Reputation: 1527

Method from another controller

Let's say I have a libraries controller and a books controller.

Part of libraries_controller.rb:

def report
  #some code here
end

Part of books_controller.rb:

def create
  @library.report
end

Is it possible to call another controller's method? If not, how do I make a library generate some sort of report after a book is created.

Upvotes: 0

Views: 903

Answers (3)

ConnorCMcKee
ConnorCMcKee

Reputation: 1645

You do not want to create controller action that calls another controller action. This is possible (with, as Mohamad put it, ugly hackery), but will give you a lot of problems. The only really acceptable way to jump from one controller action to another is via redirect_to, and that is not going to solve the problems you described.

In an MVC framework (such as rails), what you're going to want to do is move the reused parts of the report#create action into the reprt model, and then reference this from both report#create and book#create. This could be a method like Report.define_report( my_params ), or simply the existing Report.create() method.

Behaviour such as what you described belongs in the Model. The Controller should simply be calling this, as the Controller's purpose is generally to set up the View.

References:

Upvotes: 1

Max Williams
Max Williams

Reputation: 32933

No, you can't call a different controller's method, and you shouldn't. You can, however, put methods into ApplicationController, which will mean they are inherited by all other controllers.

In your code, however, it looks like you're trying to call an instance method on a model object, assuming that's what @report is, and that is not a controller method.

Upvotes: 1

Mohamad
Mohamad

Reputation: 35339

It's possible with ugly hackery, but you should not do that. You can issue a redirect to the other controller instead. You should pass along any params you need in the URL.

class BooksController < ApplicationController
  def create
    # ...
    redirect_to report_library_path(param: :foo)
  end
end

If you have functionality that should be shared. Say you want to generate a book report, for example, then you should extract this common functionality into a concern and mix it into the controllers.

# app/concerns/reports.rb
module Reports
  extend ActiveSupport::Concern

  def generate_report
    # do stuff here
  end
end

You can now mix this into your controllers and use the generate_report method you wrote.

class BooksController < ApplicationController
  include Report

  def create
  end
end

class LibrariesController < ApplicationController
  include Report

  def report
  end
end

Upvotes: 1

Related Questions