Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does `only:` at `before_action` work in Rails?

After scaffold generation we usually get a line like that:

before_action :set_newsletter_email, only: [:show, :edit, :update, :destroy]

Could someone explain to me how exactly this only: symbol works?

like image 903
Karol Selak Avatar asked Aug 10 '17 13:08

Karol Selak


People also ask

What does Before_action do in Rails?

When writing controllers in Ruby on rails, using before_action (used to be called before_filter in earlier versions) is your bread-and-butter for structuring your business logic in a useful way. It's what you want to use to "prepare" the data necessary before the action executes.

What is before action?

A 'before action review' (BAR) is a tool to help a team asses the current knowledge and experience they already have as a way to inform the planning stages of a new project.

What are filters in rails?

Rails filters are methods that run before or after a controller's action method is executed. They are helpful when you want to ensure that a given block of code runs with whatever action method is called. Rails support three types of filter methods: Before filters. After filters.


3 Answers

The only option of before_action defines one action OR a list of actions when the method/block will be executed first.

Ex:

# defined actions: [:show, :edit, :update, :destroy]
before_action :set_newsletter_email, only: [:show, :edit]

The set_newsletter_email method will be called just before the show and edit actions.


The opposite option except define when NOT to execute the method/block.

# defined actions: [:show, :edit, :update, :destroy]
before_action :set_newsletter_email, except: [:show, :edit]

The set_newsletter_email method will be called for all existing actions EXCEPT show and edit.


only / except is just a kind of whitelist/blacklist.

like image 168
MrYoshiji Avatar answered Oct 18 '22 01:10

MrYoshiji


Option :only runs a method, ':set_newsletter_email' in this example, when any of the action defined in the list in square brackets [:show, :edit, :update, :destroy] is called in the current controller and runs before the actions is run. Any other action defined in the controller will not execute :set_newsletter_email method.

You can also do the opposite with :except option to define method that will run on every actions defined in the controller except the one's that are listed.

You can also do after_action that will run after the action in the controller

You can read about the filters and all the options here: http://guides.rubyonrails.org/action_controller_overview.html#filters

like image 31
meshin Avatar answered Oct 17 '22 23:10

meshin


When a user navigates only to those routes, it will trigger the :set_newsletter_email function, usually at the end of that controller file.

So when the user navigates to the index method, it will not trigger it because :set_newsletter_email is only called for the methods on brackets.

In this case that callback is needed because it sets the resource in the single resource views before it is rendered.

For example:

/newsletter/2 route will trigger the :set_newsletter_email that will first get the id from the link params and then it will look for the resource and set an instance variable with it.

I don't know what is your concern about security in this case, but this callback only gets the id param to set the resource and because you're using scaffolds it also generates a params function (also at the end of the file) that whitelists the parameters you defined earlier while generating the scaffold.

You can find more info here: http://api.rubyonrails.org/classes/AbstractController/Callbacks/ClassMethods.html

If you want me to explain more or clarify something just ask 👍🏼

like image 39
salsadeanguila Avatar answered Oct 18 '22 00:10

salsadeanguila