Posted over 6 years ago. Visible to the public.

Whitelisting with ActiveSupport module method presence_in

Let's say your app presents a list of articles and offers multiple ways of sorting them: by upload date, by the number of upvotes and number of comments. One of the possible techniques to support this behavior is defining three types of scopes on your Article model:

Copy
class Article < ActiveRecord::Base scope :newest, -> { order(updated_at: :desc) } scope :top, -> { order(upvotes_count: :desc) } scope :most_commented, -> { order(comments_count: :desc) } end

You'll want to call those scopes depending on the query parameter passed to your controller, e.g. /articles?sort_by=newest. The easiest way to implement this in our controller would be:

Copy
class ArticlesController < ApplicationController def index @articles = Article.public_send(params[:sort_by]) end end

However, you don't want to send those user inputs directly to your model because you would leave yourself vulnerable to remote code execution. An evildoer could send you a request such as /articles?sort_by=destroy_all and destroy your records. As a responsible developer, you sanitize that input:

Copy
class ArticlesController < ApplicationController def index @articles = Article.public_send(sorting_technique) end private def sorting_technique params[:sort_by].presence_in(%w(newest most_commented top)) || :newest end end

DESCRIPTION:

Returns the receiver if it's included in the argument. Otherwise, it returns nil. The argument has to be any object which responds to #include?.

SOURCE:

Copy
def presence_in(another_object) self.in?(another_object) ? self : nil end

Owner of this card:

Avatar
Alexander M
Last edit:
over 6 years ago
by Alexander M
Posted by Alexander M to Ruby and RoR knowledge base
This website uses short-lived cookies to improve usability.
Accept or learn more