Created
October 4, 2016 23:24
-
-
Save sergiomaia/2e653b8ee0eee666e9df670f68a777ab to your computer and use it in GitHub Desktop.
Add Hashtag
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# para esse exemplo pressupõe-se que você tenha um recurso post com o campo >> content:string | |
#Primeiro criamos um model Tag | |
rails g model Tag name:string | |
# >> crie uma tabela CreatePostsTags com post_id e tag_id (para nosso relacionamento has_and_belongs_to_many) | |
rails g migration CreatePostsTags post:references tag:references | |
# >> modifique a migration CreatePostsTags add :id => false, já que não precisaremos de id nesta tabela | |
class CreatePostsTags < ActiveRecord::Migration[5.0] | |
def change | |
create_table :posts_tags, :id => false do |t| # :id => false | |
t.references :post, foreign_key: true | |
t.references :tag, foreign_key: true | |
end | |
end | |
end | |
# >> crie a tabela | |
rake db:migrate | |
# >> add o relacionamento em Post.rb | |
class Post < ActiveRecord::Base | |
has_and_belongs_to_many :tags | |
end | |
# >> add o relacionamento em Tag.rb | |
class Tag < ActiveRecord::Base | |
has_and_belongs_to_many :posts | |
end | |
# >> criamos, em post.rb um callback after_create que faz um scan no texto e encontra palavras iniciadas com # e salva como uma tag | |
after_create do | |
post = Post.find_by(id: self.id) | |
hashtags = self.content.scan(/#\w+/) | |
hashtags.uniq.map do |hashtag| | |
tag = Tag.find_or_create_by(name: hashtag.downcase.delete('#')) | |
post.tags << tag | |
end | |
end | |
# >> ainda em post.rb criamos um callback after_update, faz o mesmo que o código acima, na action update | |
before_update do | |
post = Post.find_by(id: self.id) | |
post.tags.clear #deleta tudo e cria novamente | |
hashtags = self.content.scan(/#\w+/) | |
hashtags.uniq.map do |hashtag| | |
tag = Tag.find_or_create_by(name: hashtag.downcase.delete('#')) | |
post.tags << tag | |
end | |
end | |
# >> agora criamos uma rota para renderizar a view que irá mostrar os posts com as mesmas tags | |
get '/posts/hashtag/:name', to:'posts#hashtags' | |
# >> agora criamos no controle de posts, a action hashtags que especificamos na rota acima. | |
class PostsController < ApplicationController | |
. | |
. | |
. | |
def hashtags | |
tag = Tag.find_by(name: params[:name]) | |
@posts = tag.posts | |
end | |
end | |
# >> crie o template hashtags (app/views/posts/hashtags.html.erb) com o conteúdo idêntico a app/views/posts/index.html.erb | |
# >> dentro desses templates, modifique a seguinte linha | |
<%= post.content %> | |
<%= display_with_hashtags(post.content) %> | |
# >> e por último, crie o helper display_with_hashtags que usamos acima (posts_helper.rb) para mostrar as tags como link | |
module PostsHelper | |
def display_with_hashtags(content) | |
content.gsub(/#\w+/){|word| link_to word, "/posts/hashtag/#{word.delete('#')}"}.html_safe | |
end | |
end | |
# Valeu o/ | |
Ótima sugestão cara. Obrigado.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Muito bacana isso. Se me permite dar uma sugestão, você pode colocar o código do
callbacks
em um model privado e só chamar esse método no create e update, assim:Assim você não precisa repetir o código