Substituir tag por dados do banco utilizando Ruby on Rails

Muitas vezes procuramos dar mais independência ao cliente, possibilitando o mínimo de intervenção possível em uma aplicação, por menor que seja. Hoje pela manhã, enquanto pesquisava algum CMS simples em Rails, encontrei uma funcionalidade muito interessante no Radiant, que permite ao usuário adicionar tags. Ele mostra uma popup com tags disponíveis que são métodos como: escape_html, author, date. Estes métodos são próprios do CMS e não era exatamente o que eu estava procurando no momento.

O que eu pensei era permitir que um usuário comum pudesse facilmente exibir um dado contido dentro do modelo Post. Por exemplo, você deseja pôr a data da última atualização dos dados. Seu objeto Post tem um campo chamado updated_at. Para pôr isso no texto a idéia é que você utilize uma tag especial que será substituída pelo dado capturado do banco. Foi pensando nisso e baseado nas tags do Radiant que eu fiz o código abaixo:

class Post < ActiveRecord::Base
  belongs_to :category
  validates_presence_of :name, :title, :body, :permalink, :user_id, :category_id

  # Method to replace your special tag.
  def self.replace_special_tags(object, field)
    text = eval('object.'+field)
    if !text.blank?
      tags = self.get_tags(text)
      if !tags.blank?
        tags.each do |tag|
          text = text.gsub(tag.to_s, self.get_param(tag, object))
        end
      end
    end
    return text
  end

  # After catch your tags, pass the tag and object that you need to use.
  def self.get_param(tag, object)
    pattern = /[^<r:].*[^ \/>]/
    param = tag.to_s[pattern]
    replace = object.respond_to?(param.split('.').first) ? eval('object.'+param) : nil
    if !replace.blank?
      return replace.to_s
    else
      return '<!-- wrong field -->'
    end
  end

  # Get all special tags on text
  def self.get_tags(text)
    pattern = /(<r:[a-z\.]+ \/>)/
    if !text.scan(pattern).blank?
      text.scan(pattern)
    end
  end
end

O modelo acima permite exibir dados direto do banco ao passar um objeto e o respectivo campo de texto que contém as tags especiais. Vejamos como funciona na prática:

Post.replace_special_tags(@post, 'body')

Assim, todas as tags especiais que eu adicionar ao campo body serão substituídas pelo campo correspondente no objeto @post. Vejamos um exemplo do nosso objeto:


>> @post
=> #<Post id: 1, name: "Minha página de teste", title: "Titulo da minha página de teste", body: "<p>Ah!!</p>\r\n\r\n<ul>\r\n  <li><strong>Nome da categori...", permalink: "minha-pagina-de-teste", active: false, public: nil, user_id: 1, category_id: 26, created_at: "2010-05-19 21:39:52", updated_at: "2010-05-19 21:39:52">

Nesse caso, o post pertence a uma categoria:


>> @post.category
=> #<Category id: 26, name: "Minha categoria de teste", permalink: "minha-categoria-de-teste", parent_id: nil, created_at: "2010-05-19 22:09:16", updated_at: "2010-05-19 22:09:16">

Portanto, você pode utilizar, por exemplo:

  • <r:title />
  • <r:user_id /> * em breve, um relacionamento poderá permitir acesso aos dados do usuário. Mas cuidado com as permissões aqui. É muito importante limitar o uso deste recurso.
  • <r:category.name />
  • <r:category.permalink />

Na prática, seu campo body ser assim:

<p>My replace tags test</p>
<dl>
  <dt>My category name:</dt>
  <dd><r:category.name /></dd>
  <dt>My category permalink:</dt>
  <dd><r:category.permalink /></dd>
  <dt>My post permalink:</dt>
  <dd><r:permalink /></dd>
</dl>
<div class="breadcrumb">
  <a href="/categories/<r:category.permalink>"><span><r:category.name></span></a> |
  <a  href="/categories/<r:category.permalink>/post/<r:permalink>"><span><r:name></span></a>
</div>

Acima estão somente alguns exemplos de dados que você pode utilizar. Como o método que eu criei não limita a utilização de campos, tudo que você chamar do objeto @post será exibido, se existir. O interessante a partir daqui é pensar em criar uma lista dos dados “acessíveis” para permitir chamar somente estes, tornando a utilização deste método muito mais segura.

Ps.: Desculpem pelo título, porém não encontrei nada que pudesse descrever isso em poucas palavras e da forma correta. Recebo sugestões.

One comment

  1. Primo, viu que a Micro$oft tá destruindo o RUBY ??? Com o tal de Iron Ruby, eles estão fazendo a mesma coisa que fizeram com o Java, lembra ???

    Abraços!!!

    Ahhh, tem TCHELinux este findi.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>