Introdução
Ruby on Rails é um framework de aplicação web escrito em Ruby que oferece aos desenvolvedores uma abordagem opinativa para o desenvolvimento de aplicativos. Trabalhar com Rails proporciona aos desenvolvedores:
- Convenções para lidar com coisas como roteamento, dados em estado de sessão e gerenciamento de ativos.
- A firm grounding in the model-view-controller (MCV) architectural pattern, which separates an application’s logic, located in models, from the presentation and routing of application information.
Ao adicionar complexidade às suas aplicações Rails, é provável que você trabalhe com vários modelos, que representam a lógica de negócios da sua aplicação e interagem com o seu banco de dados. Adicionar modelos relacionados significa estabelecer relacionamentos significativos entre eles, o que então afeta como as informações são transmitidas pelos controladores da sua aplicação e como são capturadas e apresentadas aos usuários por meio das visualizações.
Neste tutorial, você vai construir em cima de uma aplicação Rails existente que oferece aos usuários fatos sobre tubarões. Esta aplicação já possui um modelo para lidar com dados de tubarões, mas você adicionará um recurso aninhado para postagens sobre tubarões individuais. Isso permitirá que os usuários expandam um corpo maior de pensamentos e opiniões sobre tubarões individuais.
Pré-requisitos
Para seguir este tutorial, você precisará:
- A local machine or development server running Ubuntu 18.04. Your development machine should have a non-root user with administrative privileges and a firewall configured with
ufw
. For instructions on how to set this up, see our Initial Server Setup with Ubuntu 18.04 tutorial. - O Node.js e o npm instalados em sua máquina local ou servidor de desenvolvimento. Este tutorial usa a versão 10.16.3 do Node.js e a versão 6.9.0 do npm. Para orientações sobre como instalar o Node.js e o npm no Ubuntu 18.04, siga as instruções na seção “Instalando Usando um PPA” de Como Instalar o Node.js no Ubuntu 18.04.
- O Ruby, o rbenv, e o Rails instalados em sua máquina local ou servidor de desenvolvimento, seguindo os Passos 1-4 em Como Instalar o Ruby on Rails com rbenv no Ubuntu 18.04. Este tutorial usa o Ruby 2.5.1, rbenv 1.1.2, e Rails 5.2.3.
- O SQLite instalado, e uma aplicação básica de informações sobre tubarões criada, seguindo as instruções em Como Construir uma Aplicação Ruby on Rails.
Passo 1 — Criando o Modelo Aninhado
A nossa aplicação aproveitará as associações do Active Record para estabelecer uma relação entre os modelos Shark
e Post
: os posts pertencerão a tubarões específicos e cada tubarão poderá ter vários posts. Portanto, os modelos Shark
e Post
estarão relacionados através das associações belongs_to
e has_many
.
O primeiro passo para desenvolver a aplicação desta maneira será criar um modelo Post
e os recursos relacionados. Para fazer isso, podemos usar o comando rails generate scaffold
, que nos fornecerá um modelo, uma migração de banco de dados para alterar o esquema do banco de dados, um controlador, um conjunto completo de visualizações para gerenciar operações padrão de Criação, Leitura, Atualização e Exclusão (CRUD) e modelos para partials, helpers e testes. Teremos que modificar esses recursos, mas o uso do comando scaffold
economizará algum tempo e energia, já que gera uma estrutura que podemos usar como ponto de partida.
Primeiro, certifique-se de que você está na pasta sharkapp
para o projeto Rails que você criou nos pré-requisitos:Post
com o seguinte comando:
Crie seus recursos Post
com o seguinte comando:
rails generate scaffold Post body:text shark:references
Com body:text
, estamos informando ao Rails para incluir um campo body
na tabela posts
do banco de dados – a tabela que se relaciona ao modelo Post
. Também estamos incluindo a palavra-chave :references
, que configura uma associação entre os modelos Shark
e Post
. Especificamente, isso garantirá que uma chave estrangeira representando cada entrada de tubarão na tabela sharks
seja adicionada à tabela posts
do banco de dados.
Depois de executar o comando, você verá a saída confirmando os recursos que o Rails gerou para o aplicativo. Antes de continuar, você pode verificar o arquivo de migração do banco de dados para analisar a relação que agora existe entre seus modelos e tabelas do banco de dados. Use o seguinte comando para verificar o conteúdo do arquivo, substituindo o carimbo de data e hora do seu próprio arquivo de migração pelo mostrado aqui:
Você verá a seguinte saída:
Outputclass CreatePosts < ActiveRecord::Migration[5.2]
def change
create_table :posts do |t|
t.text :body
t.references :shark, foreign_key: true
t.timestamps
end
end
end
Como você pode ver, a tabela inclui uma coluna para uma chave estrangeira de tubarão. Essa chave assumirá a forma de model_name_id
– em nosso caso, shark_id
.
O Rails estabeleceu a relação entre os modelos em outro lugar também. Dê uma olhada no novo modelo Post
gerado com o seguinte comando:
cat app/models/post.rb
Outputclass Post < ApplicationRecord
belongs_to :shark
end
O belongs_to
associação estabelece uma relação entre modelos em que uma única instância do modelo declarado pertence a uma única instância do modelo nomeado. No caso do nosso aplicativo, isso significa que um único post pertence a um único tubarão.
Além de estabelecer essa relação, o comando rails generate scaffold
também criou rotas e visualizações para posts, assim como fez para nossos recursos de tubarão em Etapa3 de Como Construir um Aplicativo Ruby on Rails.
Este é um bom começo, mas precisaremos configurar algumas rotas adicionais e consolidar a associação do Active Record para o modelo Shark
para que a relação entre nossos modelos e rotas funcione como desejado.
Etapa2— Especificando Rotas Aninhadas e Associações para o Modelo Pai
Para adicionar a associação has_many
ao modelo Shark
, abra app/models/shark.rb
usando nano
ou seu editor favorito:
Adicione a seguinte linha ao arquivo para estabelecer o relacionamento entre tubarões e posts:
Uma coisa que vale a pena pensar aqui é o que acontece com os posts uma vez que um determinado tubarão é excluído. Provavelmente, não queremos que os posts associados a um tubarão excluído persistam no banco de dados. Para garantir que quaisquer posts associados a um determinado tubarão sejam eliminados quando esse tubarão for excluído, podemos incluir a opção dependent
com a associação.
class Shark < ApplicationRecord
has_many :posts
validates :name, presence: true, uniqueness: true
validates :facts, presence: true
end
Adicione o seguinte código ao arquivo para garantir que a ação destroy
em um determinado tubarão exclua quaisquer posts associados:
Depois de terminar de fazer essas alterações, salve e feche o arquivo. Se estiver usando nano
, você pode fazer isso pressionando CTRL+X
, Y
, depois ENTER
.
class Shark < ApplicationRecord
has_many :posts , dependent: :destroy
validates :name, presence: true, uniqueness: true
validates :facts, presence: true
end
Em seguida, abra seu arquivo config/routes.rb
para modificar o relacionamento entre suas rotas de recursos:
Atualmente, o arquivo se parece com isto:
# Para detalhes sobre a DSL disponível dentro deste arquivo, consulte http://guides.rubyonrails.org/routing.html
Rails.application.routes.draw do
resources :posts
resources :sharks
root 'sharks#index'
# Para obter detalhes sobre o DSL disponível neste arquivo, consulte http://guides.rubyonrails.org/routing.html
end
O código atual estabelece uma relação independente entre nossas rotas, quando o que gostaríamos de expressar é uma relação dependente entre tubarões e seus posts associados.
Vamos atualizar nossa declaração de rota para tornar :sharks
o pai de :posts
. Atualize o código no arquivo para ficar da seguinte forma:
Rails.application.routes.draw do
resources :sharks do
resources :posts
end
root 'sharks#index'
# Para obter detalhes sobre o DSL disponível neste arquivo, consulte http://guides.rubyonrails.org/routing.html
end
Salve e feche o arquivo quando terminar de editar.
Com essas alterações em vigor, você pode passar para a atualização do seu controlador posts
.
Etapa3— Atualizando o Posts Controller
A associação entre nossos modelos nos fornece métodos que podemos usar para criar instâncias de posts novos associados a tubarões específicos. Para usar esses métodos, precisaremos adicioná-los ao nosso controlador de posts.
Abra o arquivo do controlador de posts:
Atualmente, o arquivo se parece com isto:
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
@posts = Post.all
end
# GET /posts/1
# GET /posts/1.json
def show
end
# GET /posts/new
def new
@post = Post.new
end
# GET /posts/1/edit
def edit
end
# POST /posts
# POST /posts.json
def create
@post = Post.new(post_params)
respond_to do |format|
if @post.save
format.html { redirect_to @post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: @post }
else
format.html { render :new }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if @post.update(post_params)
format.html { redirect_to @post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: @post }
else
format.html { render :edit }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
@post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
@post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:body, :shark_id)
end
end
Como no nosso controlador de tubarões, os métodos deste controlador trabalham com instâncias da classe associada Post
. Por exemplo, o método new
cria uma nova instância da classe Post
, o método index
pega todas as instâncias da classe e o método set_post
usa find
e params
para selecionar uma postagem específica por id
. No entanto, se quisermos que nossas instâncias de postagem estejam associadas a instâncias de tubarão específicas, então precisaremos modificar este código, já que a classe Post
está atualmente operando como uma entidade independente.
Nossas modificações usarão duas coisas:
- Os métodos que se tornaram disponíveis para nós quando adicionamos as associações
belongs_to
ehas_many
aos nossos modelos. Especificamente, agora temos acesso ao métodobuild
graças à associaçãohas_many
que definimos em nosso modeloShark
. Este método nos permitirá criar uma coleção de objetos de post associados a um determinado objeto de tubarão, usando a chave estrangeirashark_id
que existe em nosso banco de dados deposts
. - As rotas e ajudantes de roteamento que se tornaram disponíveis quando criamos uma rota aninhada
posts
. Para obter uma lista completa de rotas de exemplo que se tornam disponíveis quando você cria relacionamentos aninhados entre recursos, consulte a documentação do Rails. Por enquanto, será suficiente para nós saber que para cada tubarão específico — digamossharks/1
— haverá uma rota associada para postagens relacionadas a esse tubarão:sharks/1/posts
. Também haverá ajudantes de roteamento comoshark_posts_path(@shark)
eedit_sharks_posts_path(@shark)
que se referem a essas rotas aninhadas.No arquivo, começaremos escrevendo um método, get_shark
, que será executado antes de cada ação no controlador. Este método criará uma variável de instância local@shark
encontrando uma instância de tubarão porshark_id
. Com esta variável disponível para nós no arquivo, será possível relacionar postagens a um tubarão específico nos outros métodos.
No arquivo, começaremos escrevendo um método, get_shark
, que será executado antes de cada ação no controlador. Esse método criará uma variável de instância local @shark
encontrando uma instância de tubarão por shark_id
. Com essa variável disponível para nós no arquivo, será possível relacionar postagens a um tubarão específico nas outras métodos.
Acima dos outros métodos private
no final do arquivo, adicione o seguinte método:
. . .
private
def get_shark
@shark = Shark.find(params[:shark_id])
end
# Use callbacks para compartilhar configurações comuns ou restrições entre ações.
. . .
Em seguida, adicione o filtro correspondente no topo do arquivo, antes do filtro existente:
class PostsController < ApplicationController
before_action :get_shark
Isso garantirá que get_shark
seja executado antes de cada ação definida no arquivo.
Em seguida, você pode usar essa instância @shark
para reescrever o método index
. Em vez de pegar todas as instâncias da classe Post
, queremos que esse método retorne todas as instâncias de postagens associadas a uma instância de tubarão específica.
Modifique o método index
para ficar assim:
. . .
def index
@posts = @shark.posts
end
. . .
O método new
precisará de uma revisão semelhante, já que queremos que uma nova instância de postagem seja associada a um tubarão específico. Para conseguir isso, podemos usar o método build
, junto com nossa variável de instância local @shark
.
Altere o método new
para ficar assim:
. . .
def new
@post = @shark.posts.build
end
. . .
Esse método cria um objeto de postagem que está associado à instância de tubarão específica da método get_shark
.
Atualize o método create
para ficar assim:
Em seguida, dê uma olhada no método update
. Este método utiliza uma variável de instância @post
, que não é definida explicitamente no próprio método. De onde vem essa variável?
def create
@post = @shark.posts.build(post_params)
respond_to do |format|
if @post.save
format.html { redirect_to shark_posts_path(@shark), notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: @post }
else
format.html { render :new }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
Dê uma olhada nos filtros no topo do arquivo. O segundo filtro before_action
auto-gerado fornece uma resposta:
O método update
(assim como show
, edit
e destroy
) recebe uma variável @post
do método set_post
. Esse método, listado sob o método get_shark
com nossos outros métodos private
, atualmente se parece com isso:
class PostsController < ApplicationController
before_action :get_shark
before_action :set_post, only: [:show, :edit, :update, :destroy]
. . .
Para manter os métodos que já utilizamos em outras partes do arquivo, precisaremos modificar este método para que @post
se refira a uma instância específica na build
em mente aqui – graças às associações entre nossos modelos, e os métodos (como build
) que estão disponíveis para nós em virtude dessas associações, cada uma de nossas instâncias de post faz parte de uma coleção de objetos que está associada a um tubarão específico. Portanto, faz sentido que ao consultar um post específico, consultemos a coleção de posts associada a um tubarão específico.set_post
para ficar assim:Post
por id
, procuramos por um id
correspondente na coleção de posts associados a um tubarão específico.
. . .
private
. . .
def set_post
@post = Post.find(params[:id])
end
. . .
Em conformidade com os métodos que utilizamos em outras partes do arquivo, precisaremos modificar esse método para que @post
se refira a uma instância específica na coleção de postagens que está associada a um tubarão específico. Tenha em mente o método build
aqui – graças às associações entre nossos modelos e os métodos (como build
) que estão disponíveis para nós em virtude dessas associações, cada uma de nossas instâncias de postagem faz parte de uma coleção de objetos que está associada a um tubarão específico. Portanto, faz sentido que ao consultar uma postagem específica, consultemos a coleção de postagens associada a um tubarão específico.
Atualize set_post
para ficar assim:
. . .
private
. . .
def set_post
@post = @shark.posts.find(params[:id])
end
. . .
Em vez de encontrar uma instância específica de toda a classe Post
pelo id
, procuramos um id
correspondente na coleção de postagens associada a um tubarão específico.
Com esse método atualizado, podemos analisar os métodos update
e destroy
.
O método update
faz uso da variável de instância @post
de set_post
e a usa com os post_params
que o usuário inseriu no formulário edit
. No caso de sucesso, queremos que o Rails envie o usuário de volta à visualização index
das postagens associadas a um tubarão específico. No caso de erros, o Rails renderizará o modelo edit
novamente.
Neste caso, a única alteração que precisaremos fazer é na instrução redirect_to
, para lidar com atualizações bem-sucedidas. Atualize-a para redirecionar para shark_post_path(@shark)
, que redirecionará para a visualização index
das postagens do tubarão selecionado:
. . .
def update
respond_to do |format|
if @post.update(post_params)
format.html { redirect_to shark_post_path(@shark), notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: @post }
else
format.html { render :edit }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
. . .
Em seguida, faremos uma alteração semelhante no método destroy
. Atualize o método redirect_to
para redirecionar as solicitações para shark_posts_path(@shark)
em caso de sucesso:
. . .
def destroy
@post.destroy
respond_to do |format|
format.html { redirect_to shark_posts_path(@shark), notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
. . .
Esta é a última alteração que faremos. Agora você tem um arquivo de controlador de postagens que se parece com isto:
class PostsController < ApplicationController
before_action :get_shark
before_action :set_post, only: [:show, :edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
@posts = @shark.posts
end
# GET /posts/1
# GET /posts/1.json
def show
end
# GET /posts/new
def new
@post = @shark.posts.build
end
# GET /posts/1/edit
def edit
end
# POST /posts
# POST /posts.json
def create
@post = @shark.posts.build(post_params)
respond_to do |format|
if @post.save
format.html { redirect_to shark_posts_path(@shark), notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: @post }
else
format.html { render :new }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if @post.update(post_params)
format.html { redirect_to shark_post_path(@shark), notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: @post }
else
format.html { render :edit }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
@post.destroy
respond_to do |format|
format.html { redirect_to shark_posts_path(@shark), notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def get_shark
@shark = Shark.find(params[:shark_id])
end
# Use callbacks para compartilhar configurações comuns ou restrições entre ações.
def set_post
@post = @shark.posts.find(params[:id])
end
# Nunca confie em parâmetros provenientes da internet assustadora, permita apenas a lista branca.
def post_params
params.require(:post).permit(:body, :shark_id)
end
end
O controlador gerencia como a informação é passada dos modelos de visualização para o banco de dados e vice-versa. Nosso controlador agora reflete a relação entre nossos modelos Shark
e Post
, em que as postagens estão associadas a tubarões específicos. Podemos passar para a modificação dos próprios modelos de visualização, que são onde os usuários inserirão e modificarão informações de postagens sobre tubarões específicos.
Passo 4 — Modificando Visualizações
Nossas revisões de modelo de visualização envolverão a alteração dos modelos relacionados a postagens e também a modificação de nossa visualização show
de tubarões, já que queremos que os usuários vejam as postagens associadas a tubarões específicos.
Vamos começar com o modelo fundamental para nossas postagens: o parcial form
que é reutilizado em vários modelos de postagens. Abra esse formulário agora:
Em vez de passar apenas o modelo post
para o auxiliar de formulário form_with
, passaremos tanto o modelo shark
quanto o modelo post
, com post
definido como recurso filho.
Altere a primeira linha do arquivo para ficar assim, refletindo a relação entre nossos recursos tubarão e postagem:
<%= form_with(model: [@shark, post], local: true) do |form| %>
. . .
Em seguida, apague a seção que lista o shark_id
do tubarão relacionado, já que esta não é informação essencial na visualização.
O formulário concluído, completo com nossas edições na primeira linha e sem a seção shark_id
deletada, ficará assim:
<%= form_with(model: [@shark, post], local: true) do |form| %>
<% if post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% post.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :body %>
<%= form.text_area :body %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
Salve e feche o arquivo quando terminar de editar.
Em seguida, abra a visualização index
, que mostrará as postagens associadas a um tubarão específico:
Em seguida, altere o redirecionamento do Show
para direcionar os usuários para a visualização do show
associado ao tubarão, pois eles provavelmente vão querer uma maneira de navegar de volta para o tubarão original. Podemos fazer uso da variável de instância @shark
que definimos no controlador aqui, já que o Rails torna as variáveis de instância criadas no controlador disponíveis para todas as visualizações. Também vamos alterar o texto do link de Show
para Show Shark
, para que os usuários entendam melhor sua função.
Atualize esta linha para o seguinte:
Na próxima linha, queremos garantir que os usuários sejam roteados para o caminho aninhado correto quando forem editar um post. Isso significa que, em vez de serem direcionados para posts/post_id/edit
, os usuários serão direcionados para sharks/shark_id/posts/post_id/edit
. Para fazer isso, vamos usar o auxiliar de roteamento shark_post_path
e nossos modelos, que o Rails tratará como URLs. Também atualizaremos o texto do link para tornar sua função mais clara.
Atualize a linha do Edit
para se parecer com o seguinte:
. . .
<tbody>
<% @posts.each do |post| %>
<tr>
<td><%= post.body %></td>
<td><%= post.shark.name %></td>
. . .
Em seguida, vamos fazer uma alteração semelhante ao link Destroy
, atualizando sua função na string e adicionando nossos recursos shark
e post
:
Finalmente, na parte inferior do formulário, vamos atualizar o caminho do New Post
para levar os usuários ao caminho aninhado apropriado quando quiserem criar um novo post. Atualize a última linha do arquivo para fazer uso do auxiliar de roteamento new_shark_post_path(@shark)
:
. . .
<tbody>
<% @posts.each do |post| %>
<tr>
<td><%= post.body %></td>
<td><%= post.shark.name %></td>
<td><%= link_to 'Show Shark', [@shark] %></td>
Salve e feche o arquivo quando terminar de editar.
As outras edições que faremos nas visualizações de postagens não serão tão numerosas, já que nossas outras visualizações usam o parcial form
que já editamos. No entanto, queremos atualizar as referências link_to
nos outros modelos de postagem para refletir as mudanças que fizemos em nosso parcial form
.
. . .
<tbody>
<% @posts.each do |post| %>
<tr>
<td><%= post.body %></td>
<td><%= post.shark.name %></td>
<td><%= link_to 'Show Shark', [@shark] %></td>
<td><%= link_to 'Edit Post', edit_shark_post_path(@shark, post) %></td>
Abra app/views/posts/new.html.erb
:
. . .
<tbody>
<% @posts.each do |post| %>
<tr>
<td><%= post.body %></td>
<td><%= post.shark.name %></td>
<td><%= link_to 'Show Shark', [@shark] %></td>
<td><%= link_to 'Edit Post', edit_shark_post_path(@shark, post) %></td>
<td><%= link_to 'Destroy Post', [@shark, post], method: :delete, data: { confirm: 'Are you sure?' } %></td>
Atualize a referência link_to
no final do arquivo para usar o auxiliar shark_posts_path(@shark)
:
. . .
<%= link_to 'New Post', new_shark_post_path(@shark) %>
Salve e feche o arquivo quando terminar de fazer essa alteração.
<p id="notice"><%= notice %></p>
<h1>Posts</h1>
<table>
<thead>
<tr>
<th>Body</th>
<th>Shark</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @posts.each do |post| %>
<tr>
<td><%= post.body %></td>
<td><%= post.shark.name %></td>
<td><%= link_to 'Show Shark', [@shark] %></td>
<td><%= link_to 'Edit Post', edit_shark_post_path(@shark, post) %></td>
<td><%= link_to 'Destroy Post', [@shark, post], method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Post', new_shark_post_path(@shark) %>
Em seguida, abra o modelo edit
:
Além do caminho Back
, vamos atualizar Show
para refletir nossos recursos aninhados. Altere as duas últimas linhas do arquivo para ficar assim:
Salve e feche o arquivo.
Em seguida, abra o modelo show
:Edit
e Back
no final do arquivo:show
para nossos tubarões para que as postagens sejam visíveis para tubarões individuais. Abra esse arquivo agora:Posts
ao formulário e um link Add Post
no final do arquivo.
. . .
<%= link_to 'Back', shark_posts_path(@shark) %>
Salve e feche o arquivo quando terminar de fazer essa alteração.
Em seguida, abra o modelo edit
:
Além do caminho Back
, atualizaremos o Show
para refletir nossos recursos aninhados. Altere as duas últimas linhas do arquivo para ficar assim:
. . .
<%= link_to 'Show', [@shark, @post] %> |
<%= link_to 'Back', shark_posts_path(@shark) %>
Salve e feche o arquivo.
Em seguida, abra o modelo show
:
nano app/views/posts/show.html.erb
Faça as seguintes edições nos caminhos Edit
e Back
no final do arquivo:
. . .
<%= link_to 'Edit', edit_shark_post_path(@shark, @post) %> |
<%= link_to 'Back', shark_posts_path(@shark) %>
Salve e feche o arquivo quando terminar.
Como um passo final, queremos atualizar a visualização show
para nossos tubarões para que as postagens sejam visíveis para tubarões individuais. Abra o arquivo agora:
Nossas edições aqui incluirão adicionar uma seção Posts
ao formulário e um link Add Post
no final do arquivo.
Logo abaixo das Facts
de um determinado tubarão, adicionaremos uma nova seção que itera por cada instância na coleção de postagens associadas a este tubarão, exibindo o body
de cada postagem.
Adicione o seguinte código abaixo da seção Facts
do formulário e acima dos redirecionamentos no final do arquivo:
. . .
<p>
<strong>Facts:</strong>
<%= @shark.facts %>
</p>
<h2>Posts</h2>
<% for post in @shark.posts %>
<ul>
<li><%= post.body %></li>
</ul>
<% end %>
<%= link_to 'Edit', edit_shark_path(@shark) %> |
. . .
Em seguida, adicione um novo redirecionamento para permitir que os usuários adicionem uma nova postagem para este tubarão específico:
. . .
<%= link_to 'Edit', edit_shark_path(@shark) %> |
<%= link_to 'Add Post', shark_posts_path(@shark) %> |
<%= link_to 'Back', sharks_path %>
Salve e feche o arquivo quando terminar de editar.
Você acabou de fazer alterações em seus modelos, controladores e views do aplicativo para garantir que os posts estejam sempre associados a um tubarão específico. Como um passo final, podemos adicionar algumas validações ao nosso modelo Post
para garantir a consistência nos dados que são salvos no banco de dados.
Etapa 5 – Adicionando Validações e Testando o Aplicativo
Na Etapa 5 de Como Construir um Aplicativo Ruby on Rails, você adicionou validações ao seu modelo Shark
para garantir a uniformidade e consistência nos dados que são salvos no banco de dados sharks
. Agora, daremos um passo semelhante para garantir garantias para o banco de dados posts
também.
Abra o arquivo onde seu modelo Post
é definido:
Aqui, queremos garantir que os posts não estejam em branco e que eles não dupliquem o conteúdo que outros usuários possam ter postado. Para conseguir isso, adicione a seguinte linha ao arquivo:
class Post < ApplicationRecord
belongs_to :shark
validates :body, presence: true, uniqueness: true
end
Salve e feche o arquivo quando terminar de editar.
Com essa última alteração em vigor, você está pronto para executar suas migrações e testar o aplicativo.
Primeiro, execute suas migrações:
Em seguida, inicie seu servidor. Se você estiver trabalhando localmente, pode fazer isso executando:
Se você estiver trabalhando em um servidor de desenvolvimento, execute o seguinte comando em vez disso:
Navegue até a raiz do seu aplicativo em http://localhost:3000
ou http://sua_ip_do_servidor:3000
.
O tutorial prévio do projeto Rails guiou você pela adição e edição de uma entrada de Tubarão Branco. Se você não adicionou mais tubarões, a página inicial do aplicativo ficará assim:
Clique em Mostrar ao lado do nome do Tubarão Branco. Isso o levará à visualização show
para esse tubarão. Você verá o nome do tubarão e seus fatos, e um cabeçalho Posts sem conteúdo. Vamos adicionar um post para preencher essa parte do formulário.
Clique em Adicionar Post abaixo do cabeçalho Posts. Isso o levará à visualização index
do post, onde você terá a chance de selecionar Novo Post:
Graças aos mecanismos de autenticação que você implementou no Passo 6 do Como Construir um Aplicativo Ruby on Rails, você pode ser solicitado a se autenticar com o nome de usuário e senha que criou naquele Passo, dependendo de você ter criado uma nova sessão ou não.
Clique em Nova Postagem, o que o levará ao seu modelo de postagem novo
:
No campo Corpo, digite “Esses tubarões são assustadores!”
Clique em Criar Postagem. Você será redirecionado para a visualização índice
de todas as postagens que pertencem a esse tubarão:
Com nossos recursos de postagem funcionando, agora podemos testar nossas validações de dados para garantir que apenas os dados desejados sejam salvos no banco de dados.
A partir da visualização índice
, clique em Nova Postagem. No campo Corpo do novo formulário, tente inserir “Esses tubarões são assustadores!” novamente:
Clique em Criar Postagem. Você verá o seguinte erro:
Clique em Voltar para retornar à página principal de postagens.
Para testar nossa outra validação, clique em Nova Postagem novamente. Deixe a postagem em branco e clique em Criar Postagem. Você verá o seguinte erro:
Com seus recursos aninhados e validações funcionando corretamente, agora você tem um aplicativo Rails funcional que pode ser usado como ponto de partida para o desenvolvimento adicional.
Conclusão
Com sua aplicação Rails em funcionamento, agora você pode trabalhar em coisas como estilização e desenvolvimento de outros componentes de front-end. Se você gostaria de aprender mais sobre roteamento e recursos aninhados, a documentação do Rails é um ótimo lugar para começar.
Para aprender mais sobre a integração de frameworks de front-end com sua aplicação, dê uma olhada em Como Configurar um Projeto Ruby on Rails com um Frontend React.