Também usando HAML, SASS, Bootstrap e Twitter OmniAuth...
Antes de começarmos - Aqui está o código do GitHub para este aplicativo...
Recentemente, tivemos nossa terceira conferência Couchbase em São Francisco, que, a propósito, foi um grande sucesso e um dia e uma noite fantásticos. Na conferência, apresentei uma sessão de 80 minutos com base no aplicativo de exemplo que vamos criar hoje. O objetivo da minha palestra foi mostrar como podemos modelar documentos JSON no Couchbase e utilizar todos os recursos de Map/Reduce para criar um aplicativo de ponta a ponta.
Este blog pressupõe conhecimento de Rails e algum uso do Twitter Developer Portal. Se você nunca usou o Couchbase ou a gem Couchbase-Model antes, não se preocupe, eu o orientarei nessa parte, mas vale a pena ler sobre Modelo Couchbase Primeiro!
A ideia geral por trás desse aplicativo é que os usuários possam publicar seus próprios vídeos do Vine, que serão votados pelo público para ver quem tem os vídeos mais engraçados do Vine em todo o mundo. Os usuários devem ser autenticados antes de enviar um Vine, e precisamos controlar qual Vine pertence a qual usuário por meio de IDs referenciais. Ou seja, cada Vine deve ter um User_ID em seu documento JSON, para que saibamos a quem ele pertence.
Portanto, sem mais hesitações, vamos nos aprofundar e ver como podemos criar um aplicativo gamificado sobre o Couchbase usando Ruby e Rails. A ideia de ter um aplicativo social com uma tabela de classificação e um elemento competitivo é um caso de uso muito comum, mas não necessariamente bem documentado (especialmente para nós da comunidade Ruby!).
Pré-requisitos:
- Servidor Couchbase 2.0+
- Ruby 1.9.3+
- Rails 3+
Em vez de publicar cada gem individual do nosso aplicativo Rails aqui, basta clique aqui para visualizar meu Gemfile e ver quais Ruby Gems precisamos empacotar para nosso aplicativo.
Uma observação a ser feita aqui é minha escolha de servidor Ruby. Estou usando o Puma. Isso não é necessariamente uma vantagem nesse pequeno caso de uso, é mais um hábito pessoal. O Puma é um servidor da Web concorrente e com threads para Ruby que inicia na porta :9292 por padrão. Você pode usar qualquer servidor Web com o qual se sinta confortável e simplesmente iniciar seu aplicativo com 'rails s' ou 'rails server'.
Agora, antes de começarmos com nosso código, vamos criar um bucket em nossa instância do Couchbase chamado "rvine". Não é necessário se preocupar com o dimensionamento desse bucket, portanto, dependendo da quantidade de RAM alocada no cluster, basta fornecer 200 MB ou mais.
Então, vamos gerar um novo aplicativo Rails. Vamos acrescentar ao nosso comando usual o sinalizador '-O'. Isso serve para ignorar as inclusões do active_record. (Não podemos usar o active_record com o Couchbase, mas é por isso que temos a gem Couchbase-Model!)
Trilhos novos rvine -O
Agora, então, vamos nos certificar de que você copiou o Gemfile do repositório vinculado acima. A importância disso é garantir que tenhamos o Couchbase e o Modelo Couchbase empacotado. O Couchbase-Model é uma abstração sobre a gem do Couchbase que permite padrões de design semelhantes aos do Active-Record. Isso torna muito fácil para nós começarmos a trabalhar com o Rails e o Couchbase. Não deixe de clicar no link acima e ler os detalhes da gem para saber mais.
Quando soubermos que temos as duas gemas em nosso Gemfile, execute "bundle install". Depois de fazer isso, configuramos nosso aplicativo rails com o Couchbase como backend. No diretório do rails, no Terminal, execute o comando:
Rails geram couchbase:config
Isso gerará um arquivo couchbase.yml em nosso diretório de configuração que vincula nosso aplicativo ao backend do banco de dados. Vá em frente, edite esse arquivo e insira nossas credenciais de bucket. Seu arquivo de configuração deve refletir isso:
Nome do host: localhost
porto: 8091
nome de usuário:
senha:
pool: defaultdevelopment:
< bucket: rvine
teste:
< bucket: rvine
# defina estas variáveis de ambiente em seu servidor de produção
produção:
nome do host: <%= ENV['COUCHBASE_HOST'] %>
porto: <%= ENV['COUCHBASE_PORT'] %>
nome de usuário: <%= ENV['COUCHBASE_USERNAME'] %>
senha: <%= ENV['COUCHBASE_PASSWORD'] %>
piscina: <%= ENV['COUCHBASE_POOL'] %>
balde: <%= ENV['COUCHBASE_BUCKET'] %>
Ok, agora que isso foi feito, devemos ter um projeto Rails barebone, que está conectado ao Couchbase como seu armazenamento de dados de backend. Parece simples? Isso é porque o Couchbase-Model torna nossa vida 1000 vezes mais fácil quando se trata de modelagem de dados!
Agora, a próxima coisa que precisamos fazer é configurar nosso Classes de usuário e autenticação.
Primeiro, vamos criar nosso modelo de usuário. Crie o arquivo /app/models/user.rb
classe Usuário < Couchbase::Modelo
atributo :nome
atributo :twit_username
atributo :avatar
def autônomo.find_or_create_from_auth_hash(hash)
usuário = User.find_by_id(hash[:uid])
a menos que usuário
usuário = User.criar!(:id => hash[:uid],
:nome => hash[:info][:nome],
:twit_username => hash[:info][:nickname],
:avatar => hash[:info][:imagem])
final
usuário
final
final
O atributos neste documento são os campos que desejamos incluir em nosso documento JSON. Estamos coletando o nome do usuário, o nome de usuário do Twitter e o avatar. Precisamos fornecer uma chave exclusiva para cada usuário em nosso banco de dados. Nesse caso, estamos fazendo isso coletando o UID do Twitter do usuário e criando um hash a partir dele para gerar uma chave para o nosso documento User. É importante lembrar que a chave de cada documento em nosso banco de dados deve ser exclusiva. Além disso, vale a pena observar a classe que criamos. 'find_or_create_from_auth_hash' Essa classe está fazendo exatamente o que diz na lata! Se existir um usuário, faça a autenticação dele. Se não existir, criamos o usuário com base nos detalhes do Twitter que recebemos.
Você deve ter notado que optamos por usar o Twitter-Omniauth para isso, para economizar muito tempo em vez de escrever uma classe Auth do zero! A primeira coisa a fazer aqui é ir até o Twitter Dev e pegar algumas chaves de aplicativo! Se você nunca fez isso antes, faça login com sua conta do Twitter. Crie um novo aplicativo chamado "rvine" e, depois de fazer isso, você receberá duas chaves de aplicativo.
Crie um arquivo de configuração em config/initializers/omniauth.rb. Depois de criar esse arquivo, abra-o e insira o seguinte código:
provedor :twitter, "CONSUMER_KEY", "CONSUMER_SECRET"
final
Isso deve significar que agora temos o Omniauth configurado com as chaves do nosso aplicativo do Twitter e quase pronto para ser usado. A próxima coisa que precisamos fazer é criar uma rota em nosso aplicativo Rails para lidar com o processo de autenticação. Então, vamos abrir nosso arquivo config/routes.rb e digitar o seguinte:
Agora, estamos dizendo ao Rails para enviar nosso retorno de chamada do Twitter Auth'd para nosso controlador de sessões.... Que controlador de sessões? Precisamos criá-lo agora.
Vá em frente e crie o arquivo app/controllers/sessions_controller.rb
def criar
usuário = User.find_or_create_from_auth_hash(auth_hash)
sessão[:user_id] = usuário.id
flash[:sucesso] = "Bem-vindo ao clube!"
redirect_to dashboard_path
finalprotegida
def auth_hash
solicitação.env['omniauth.auth']
final
final
Como você pode ver nesse código, nosso método "Create" está chamando a classe que definimos em nosso User.rb para inicializar uma sessão quando um usuário clica para se autenticar no frontend ou criar o usuário se ele ainda não existir. Uma vez autenticado, estamos redirecionando o usuário para o seu painel. (Que criaremos em breve!)
Em seguida, vamos atualizar nosso application_controller.rb para incluir classes auxiliares para nossa autenticação, inclusive um método auxiliar para definir um Current_User e um método auxiliar para garantir que um usuário esteja conectado.
proteger_de_falsificaçãodef autenticar!
se signed_in?
retorno verdadeiro
mais
flash[:error] = "Você não está autorizado a acessar esta página"
redirect_to(caminho_da_raiz)
final
final
def usuário_atual
@current_user ||= Usuário.find_by_id(sessão[:user_id])
final
método_ajudante :current_user
def signed_in?
!!current_user
final
método_ajudante :signed_in?
final
Em seguida, precisamos criar o Dashboard para o qual nossos usuários serão redirecionados após a autorização. Para isso, vamos usar um comando Rails Generate.
Agora, vamos abrir o arquivo app/controladores/dashboards_controller.rb e digite o seguinte:
classe DashboardsController < Controlador de aplicativos
def show
final
final
Vamos abrir nossa visualização de front-end do Dashboard e editá-la. No meu caso, será um arquivo HAML. Independentemente de você escolher ERB ou HAML, o arquivo terá praticamente a mesma aparência! Em app/views/dashboards - basta criar o arquivo show.haml ou show.erb.
.página–cabeçalho
– se signed_in?
%h1
Olá, #{current_user.name}
%p
%imagem{:src => current_user.avatar, :alt => "Avatar"}
%p= link_to("Todas as videiras", "/vines")
– mais
%h1
Olá, estranho
%p
= link_to("Entre com sua conta do Twitter", "/auth/twitter")
%p
Agora que já temos nosso painel de controle, precisamos configurar mais alguns roteamentos e, em seguida, podemos testar as coisas! Abra o config/routes.rb e adicione o seguinte:
Depois de fazer isso, salve, execute o aplicativo e autentique-se como um usuário.
Ótimo! Agora podemos ver que nossa autenticação funciona e que nossos usuários têm um painel. Se abrirmos o console do Couchbase, também veremos que um usuário foi criado dentro do nosso bucket do Rvine!
Agora que já temos os usuários e a autenticação instalados, vamos passar para a parte principal do aplicativo: Os vídeos do Vine! Para começar, precisaremos criar um modelo para os Vines. Infelizmente, o Couchbase-Model ainda não é compatível com o rails Generator nessa ação. Portanto, precisamos criar manualmente /app/models/vine.rb
Depois de fazer isso, vamos preencher o seguinte:
exigir 'uri'
exigir "nokogiriclasse Videira < Couchbase::Modelo
after_save :extract_video_url
pertence_a :usuário
atributo :title
atributo :vine_url
atributo :video_url
#Voting API
atributo :score, :default => 1
validates_presence_of :title, :vine_url
privado
def extract_video_url
doc = Nokogiri(aberto(vine_url).ler)
autônomo.video_url = doc.css("fonte").primeiro["src"]
save_without_callbacks
final
final
Como podemos ver no código acima, estamos incluindo open-uri, uri e nokogiri. Isso ocorre porque o Vine não tem uma API pública, mas precisamos obter esses vídeos de alguma forma! Assim, com a ajuda dessas bibliotecas, escrevemos um script atrevido para extrair a fonte de um vídeo do Vine e pegar o URI mp4 exato quando um usuário digita o URL do Vine.
A classe extract_video_url é chamado usando o método after_save. Pelo código, podemos ver que o Nokogiri está abrindo o URL inserido pelo usuário ao postar um Vine. Em seguida, ele pesquisa a fonte da página do Vine para encontrar a linha que declara o URI mp4 real do Vine.
Além disso, podemos ver que cada Vine pertence a um usuário, tem atributos para o título, URL do Vine (inserido pelo usuário) e URL do vídeo (URI mp4 real). Também temos um atributo Score. (O atributo mais importante). Observe também que estamos configurando cada vídeo para começar com uma pontuação de 1.
Agora, vamos gerar um controlador e exibições para o nosso modelo Vine. Executar:
Nesse momento, você pode receber um erro de conflito dizendo que o modelo já existe. Não se preocupe, basta dizer "N" para não sobrescrevê-lo. Você também poderá ver um erro Couchbase not found (Couchbase não encontrado). Novamente, não se preocupe com isso, pois, como afirmei acima, o Couchbase-Model não é compatível com o gerador de modelos do Rails.
Se tudo correu conforme o planejado, agora você deve ter um vines_controller.rb e uma pasta inteira de visualizações para vinhas com os arquivos HAML ou ERB de front-end. Vá em frente e abra o vines_controller.rb e certifique-se de que ele reflita o arquivo aqui.
Em nosso arquivo de controle, você deve ter notado um método chamado 'upvote'. Esse é o mecanismo de votação para nossos vídeos do Vine. Para concluir a implementação desse sistema de votação e realmente dar aos vídeos do Vine um lugar para morar, abra o arquivo app/views/vines/show.haml(ou .erb)
Certifique-se de que o arquivo seja afetado encontrado aqui…
Antes que nosso sistema de votação funcione completamente, precisamos adicionar o seguinte ao nosso rotas.rb arquivo:
membro fazer
colocar :upvote
final
final
Ok, agora nossos vídeos do Vine podem ser exibidos e o mecanismo de votação está funcionando! A próxima coisa que precisamos fazer é configurar a página principal do aplicativo - A tabela de classificação! Nossa tabela de classificação, embora seja o principal recurso do aplicativo, é incrivelmente simples. Abra o arquivo app/views/vines/index.haml (ou .erb) e verifique se ele corresponde ao código aqui.
Agora, se este fosse um aplicativo Rails relacional comum, nós deve em teoria, temos uma tabela de classificação já criada, listando cada vídeo do Vine em nosso banco de dados. MAS Esse não é o caso aqui.
No Couchbase, precisamos criar nossa tabela de classificação usando Visualizações no Couchbase e utilizando a técnica Map/Reduce antes de obtermos uma tabela de classificação que realmente funcione corretamente! Então, vamos fazer isso! Antes de prosseguirmos, se você não tiver usado as visualizações do Couchbase antes disso, recomendo que leia esses documentosO objetivo é fornecer a você um pouco de conhecimento sobre o que são as visualizações do Couchbase, como as usamos e para facilitar o uso delas neste aplicativo Rails.
Para o nosso aplicativo, precisamos criar uma visualização no Couchbase que produza cada vídeo do Vine, com sua pontuação e título. Eles também precisam ser ordenados, de forma decrescente, por Score, para que o vídeo do Vine com a pontuação mais alta fique naturalmente no topo da tabela de classificação.
SE você já usou as visualizações do Couchbase antes, talvez as tenha criado no próprio console de administração. As visualizações podem ser criadas a partir da interface do usuário do administrador, de qualquer um dos nossos clientes SDK e por meio da API REST. Nesse caso, o Couchbase-Model tem uma maneira única e brilhante de nos permitir gerar visualizações para nosso aplicativo. Dê uma olhada rápida em esses documentos para ver como isso pode ser feito e como estamos prestes a fazê-lo.
No Terminal, basta executar:
Agora, em seu aplicativo/modelos você deverá ter um novo subdiretório chamado vine, com um subdiretório chamado all. Esse diretório contém dois arquivos .js: o map.js e o reduce.js. Por enquanto, só estamos interessados no arquivo map.js. Vá em frente, abra-o e digite o seguinte:
se (doc.tipo == "videira" && doc.título) {
emitir(doc.pontuação, doc.título);
}
}
Como podemos ver nessa função Map, estamos envolvendo tudo em uma instrução IF. Essa é uma prática recomendada no Couchbase para verificar os atributos antes de tentar emitir linhas em nosso índice. Nesse caso, nossa instrução IF está garantindo que somente os documentos com o atributo type == "vine" (tipo == "videira") e garantindo que a videira tenha um título. A função emit está criando uma linha em nosso índice usando o documento Pontuação como a chave indexada. Também estamos gerando o título do documento como valor de saída.
O motivo pelo qual estamos gerando o Pontuação como a chave indexada, é que podemos aproveitar a classificação Unicode que o Couchbase aplica automaticamente a esse campo. No nosso caso, precisamos garantir que a pontuação seja decrescente, para colocar o Vine com a maior pontuação no topo da tabela de classificação. Essa função de mapa funcionará bem por si só e, se você executar o aplicativo agora, terá uma lista de vídeos do Vine, mas eles estarão na ordem errada!
Chegou a hora de aplicar outro recurso do Couchbase para aprimorar nosso Leaderboard e garantir que ele funcione como deveria. É hora de Consultar nossa visualização para criar nosso produto final. Mais uma vez, o Couchbase-Model nos permite fazer isso diretamente do nosso código Rails. Abra seu arquivo de modelo vine.rb e adicione a seguinte linha logo acima da declaração "private":
Esse código não só é necessário para adicionar parâmetros de consulta à nossa visualização, mas também deve ser adicionado ao nosso arquivo Vine.rb com ou sem parâmetros de consulta para garantir que nosso aplicativo saiba qual(is) visualização(ões) deve(m) ser usada(s) em nosso aplicativo. Nesse caso, podemos ver que não só estamos definindo qual visualização nosso aplicativo deve usar, mas também adicionamos os parâmetros de consulta:
Ao fazer isso, estamos limitando a saída da visualização a 10 resultados e estamos garantindo que o Pontuação está em ordem decrescente.
É isso aí! Se você preencher seu banco de dados com alguns vídeos do Vine, verá que tem um aplicativo Rate my Vine totalmente funcional. Ao longo deste artigo, vimos como podemos modelar dados com a gem Couchbase Rails Couchbase-Model do Couchbase, vimos como podemos usar visualizações no Couchbase para criar aplicativos interativos e vimos como podemos consultar essas visualizações para obter subconjuntos específicos de dados para uso em nosso aplicativo.
Sei que nem tudo dentro do aplicativo está neste artigo (estilo etc.), mas isso não é importante. Espero ter abordado os pontos principais (Couchbase-Model, Modelagem de documentos, Visualizações e Consultas) o suficiente para que você sinta que pode iniciar seu próprio aplicativo Rails usando a gem Couchbase-Model.
Se você é nativo de Londres, não deixe de participar do nosso Encontro do Couchbase em Londres Nas próximas semanas, realizaremos eventos sobre Modelagem de documentos, Couchbase Mobile e muitos outros tópicos.
Se você leu até aqui, só posso parabenizá-lo! Sei que este foi um artigo LONGO! Se você tiver alguma dúvida, como sempre, ficarei feliz em respondê-la. Entre em contato comigo no Twitter em @Rbin e me envie qualquer pergunta por lá!
Robin Johnson
Defensor do desenvolvedor, Europa.
ótima postagem! obrigado por compartilhar
Obrigado. Usei isso com o omniauth do Facebook e funciona muito bem. :)
Olá, Robin,
Estou trabalhando em um aplicativo Rails e estou tendo problemas para armazenar imagens como blobs/documentos binários no couchbase. Tentei salvar os blobs em um atributo no Couchbase-model, mas parece que ele não lida com isso corretamente. Pretendo me aprofundar no Couchbase-model para ver se há uma maneira simples de armazenar e recuperar imagens do couchbase, mas gostaria de saber se você conhece alguma coisa. Obrigado
[...] Postagem de blog da semana #1: Aplicativo de amostra - Ruby on Rails e Couchbase-Model para um modelo de... [...]