flyingL123
flyingL123

Reputation: 8076

Where to set default variables in Rails 4 controller

I would like to declare some values in my controller that will be used by a method in its parent class. What is the best way to do this? My parent controller has an index method that provides pagination, for example:

class BaseController < ApplicationController
  def index  
    @collection = model_class.paginate(page: params[:page], per_page: @per_page || 50) # I want this per_page value to come from the child controller, or use 50 if it's not set
  end

  private

  def model_class
    @model_class ||= controller_name.classify.constantize
  end
end

class ChildController < BaseController

end

Where in the ChildController is it best to set the @per_page value and how do I implement it? I will have lots of child controllers, so I'm looking for the most straight forward way.

My only thought is to change it from @per_page to per_page, and then define this method in each child controller:

def per_page
  20 # Or whatever value is needed for that controller
end

I suppose then I would need to also define this method in the parent controller to provide the default, so that would look like this:

class BaseController < ApplicationController
  def index  
    @collection = model_class.paginate(page: params[:page], per_page: per_page) # I want this per_page value to come from the child controller, or use 50 if it's not set
  end

  private

    def per_page
      50
    end

    def model_class
      @model_class ||= controller_name.classify.constantize
    end
end

class ChildController < BaseController
  private

    def per_page
      20
    end
end

Is there a better pattern for this?

Upvotes: 1

Views: 531

Answers (4)

VPaul
VPaul

Reputation: 1013

A little late to answer but I've been doing something similar in my app. If you're using will_paginate gem, just create an initializer for it named will_paginate.rb and put the following line in it:

WillPaginate.per_page = 50

The same approach is also mentioned in the Wiki for the gem. If you want to override this default, just do the customization in your model and not your controller. The model level setting will happen in the model.rb file as below:

self.per_page = 10

Now, It'll use the global settings when the model specific setting is not present.

Upvotes: 0

Wayne Chu
Wayne Chu

Reputation: 308

You can write a module and use class method to set per_page just like code below:

controllers/concerns/paginate_concern.rb

  require 'active_support/concern'

  module PaginateConcern
    extend ActiveSupport::Concern

    included do
      set_per_page 50 # default 50
    end

    class_methods do
      def set_per_page(value)
        append_before_action {
          @per_page = value
        }
      end
    end
  end

base_controller.rb

    class BaseController < ApplicationController
      include PaginateConcern
    end

child_controller.rb

  class ChildController < BaseController
    set_per_page 20 # override 50 to 20

    def index
      @children = Children.paginate(page: params[:page], per_page: @per_page)
    end
  end

Upvotes: 0

Richard Peck
Richard Peck

Reputation: 76774

If you wanted to set a "default" in the controller itself (I don't see any context as to which pagination gem you're using), you could use a class variable:

#app/controllers/base_controller.rb
class BaseController < ApplicationController
   @@per_page = 50
end

This will set a class variable (different than an instance variable in that it's available whether the class has been invoked or not). This value will act as the default which you can build upon:

#app/controllers/child_controller.rb
class ChildController < BaseController
   private

   def per_page
      @@per_page || 20 #-> if the "default" is not set, put it to 20
   end
end

--

If you were using will_paginate - or I think kaminari does this too - you can set the per_page default in the config of your application before the entire app loads:

#config/application.rb
...
WillPaginate.per_page = 50

Kaminari is similar, although I've lost the code right now.

Upvotes: 1

alebian
alebian

Reputation: 782

You can add it on your Rails application secrets and use it everytime you need that value, that is if that value is not going to change dynamically.

Once I created a table in the db called app_configurations where I stored all of this values. This is only recommended if you let the client change the values in an admin page or something (so he doesn't bother you often with such little changes)

If you consider those option bad, you can create a Ruby module with the methods you want and include it in your controller of wherever you want:

module Pagination
  def per_page
    50
  end
end

And then

include Pagination

Upvotes: 1

Related Questions