Ruby on Rails - Controller


Controller takes model data from the database and then displays it on the view.

A controller is a Ruby class which inherits from ApplicationController and has methods just like any other class. When your application receives a request, the routing will determine which controller and action to run, then Rails creates an instance of that controller and runs the method with the same name as the action.

E.g. if a user goes to /clients/new in your application to add a new client, Rails will create an instance of ClientsController and call its new method. Then Rails will by default render the new.html.erb view unless the action says otherwise.

Only public methods are callable as actions. It is a best practice to lower the visibility of methods (with private or protected) which are not intended to be actions.


There are two kinds of parameters possible in a web application. The first are parameters that are sent as part of the URL, called query string parameters. The query string is everything after "?" in the URL. The second type of parameter is usually referred to as POST data. This information usually comes from an HTML form (name attribute in the form e.g. <input type="text" name="client[name]" value="Acme" />) which has been filled in by the user.

Rails does not make any distinction between query string parameters and POST parameters, and both are available in the params hash in your controller. In this way, controller can access data sent in by the user. e.g. assuming that you're sending the data to CompaniesController, it would then be wrapped within the :company key.

Parameters can contain nested arrays and hashes. e.g. GET /clients?ids[]=1&ids[]=2&ids[]=3

The actual URL in this example will be encoded as "/clients?ids%5b%5d=1&ids%5b%5d=2&ids%5b%5d=3" as the "[" and "]" characters are not allowed in URLs. Keep this in mind if you ever want to test POST data manually, by manipulating the URL parameters.

Another example of params data available to controller:

get '/clients/:status', to: 'clients#index', foo: 'bar'

In this case, when a user opens the URL /clients/active, params[:status] will be set to "active". When this route is used, params[:foo] will also be set to "bar", as if it were passed in the query string. Your controller will also receive params[:action] as "index" and params[:controller] as "clients".

Note: instead of using params[:controller], use controller_name. Similarly, instead of params[:action], use action_name to access these values.

Strong Parameters

With strong parameters, Action Controller parameters are forbidden to be used in Active Model mass assignments until they have been permitted. This means that you'll have to make a conscious decision about which attributes to permit for mass update. This is a better security practice to help prevent accidentally allowing users to update sensitive model attributes.


class PeopleController < ActionController::Base
  # This will raise an ActiveModel::ForbiddenAttributesError exception
  # because it's using mass assignment without an explicit permit
  # step. (mass assignment means updating ALL attributes of a model).
  def create
Use following logic in the controller:
    # Using a private method to encapsulate the permissible parameters
    # is just a good pattern since you'll be able to reuse the same
    # permit list between create and update. Also, you can specialize
    # this method with per-user checking of permissible attributes.
    def person_params
      params.require(:person).permit(:name, :age)
The permitted scalar types are String, Symbol, NilClass, Numeric, TrueClass, FalseClass, Date, Time, DateTime, StringIO, IO, ActionDispatch::Http::UploadedFile, and Rack::Test::UploadedFile.

Otherwise, the key is going to be filtered out, so arrays, hashes, or any other objects cannot be injected.

To declare that the value in params must be an array of permitted scalar values, map the key to an empty array:

params.permit(id: [])
CAUTION: Do not use permit! e.g. params.require(:person).permit!
This marks the :person parameters hash and any sub-hash of it as permitted and does not check for permitted scalars, anything is accepted. Extreme care should be taken when using permit!, as it will allow all current and future model attributes to be mass-assigned.

Imagine a scenario where you have parameters representing a product name and a hash of arbitrary data associated with that product, and you want to permit the product name attribute and also the whole data hash: In that case, use curly braces.

def product_params
  params.require(:product).permit(:name, data: {})