Substituir tag por dados do banco utilizando Ruby on Rails
Publicado em Ruby on Rails em May 19th, 2010 por Vinicius Ebersol – 1 ComentárioMuitas 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.