Replacing placeholders in Ruby on Rails

David Paluy - Aug 19 '20 - - Dev Community

Many times we need to include dynamic data in our text. There are many ways to do this, just by having gsub method.

I'd like to share my favorite approach for placeholders replacing.

Let's assume we have Article class and we want it to generate a dynamic title that can be used for the SEO purpose.

The "Article" has name:string and reviews_count:integer attributes.
We need to generate a dynamic title: [name] - [reviews_count] reviews. The title pattern can be customized in our back-office.

article.title_patern = '[name] - [reviews_count] reviews'

Let's use the Ruby on Rails metaprogramming techniques to implement this functionality:

class Article < ApplicationRecord
  def title
    title_pattern.gsub(/\[(.*?)\]/) { |key| dynamic_value(key) }.strip
  end

  private

  DYNAMIC_CMDS = %w[
    name
    reviews_count
  ].freeze

  def dynamic_value(key)
    cmd = key[/\[(.*?)\]/, 1]
    DYNAMIC_CMDS.include?(cmd) ? send(cmd) : ''
  end
end
Enter fullscreen mode Exit fullscreen mode

Now, we can do:

article = Article.new(name: 'Amazing Ruby', reviews_count: 123)
article.title # "Amazing Ruby - 123 reviews"
Enter fullscreen mode Exit fullscreen mode

Let's review the code together.

def title
  title_pattern.gsub(/\[(.*?)\]/) { |key| dynamic_value(key) }
end
Enter fullscreen mode Exit fullscreen mode

We are using gsub with a block pattern that helps us to use logic to decide how to replace something. We are searching for any words in square brackets [ANYTHING]. Of course, you can define your own pattern, for example: {{NAME}} or %NAME%. Just change the Regex accordingly.

In our case, the title_patern is [name] - [reviews_count] reviews. So the gsub will search for each key in brackets. We have two keys:

  1. [name]
  2. [reviews_count]

for each key, will call dynamic_value method.

I'm using ruby send. There are various options dynamically call the method or attribute in ruby. But send method has the best performance.

Note: dynamic methods can be dangerous. Especially, send can invoke private methods. This is the reason, DYNAMIC_CMDS check is required to keep your code safe.

. . . . . . . . . . . . . . . .