Como meu projeto em flask
foi considerado insuficiente, foi solicitado a criação do mesmo, mas com minha stack príncipal que é RubyOnRails
, apesar de não domina o framework de ponta a ponta nem ter um conhecimetno 100%, gostaria de me provar nessa aplicação.
├── .ruby-lsp/
├── app/
│ ├── assets/
│ ├── channels/
│ ├── controllers/
│ ├── helpers/
│ ├── jobs/
│ ├── mailers/
│ ├── models/
│ ├── views/
├── bin/
├── config/
├── db/
├── lib/
├── log/
├── public/
├── storage/
├── test/
├── tmp/
├── vendor/
├── .dockerignore
├── .gitattributes
├── .gitignore
├── .ruby-version
├── config.ru
├── Dockerfile
├── Gemfile
├── Gemfile.lock
├── Rakefile
└── README.md
- Dependências para execução
- Criação da estrutura do projeto e as Gems
- Utilizando o scaffoding
- Troca de banco
- Rollback de banco
- Problemas com o TailwindCSS
- Problemas com rotas aninhadas
- Novo método usado no destroy
- Criação de login
- Login no controller
Para iniciar o app é necessário que sua versão do ruby seja a 3.4.4, a versão do seu rails seja 7.1.5. Siga o passo a passo abaixo:
gem install bundler
bundle install
rails db:create
rails db:migrate
rails db:seed
rails s
Para criação da estrutura do projeto foi usado o comando rails new <nome projeto> --database=<o banco escolhido, foi postgres> --css=<framework css desejado>
rails new to-doListRails --database=postgres --css=tailwind
O scaffold
é um comando CLI do Rails para criar arquitetura MVC de uma forma simples e prática, aplicando diretamente, com base nos atributos infromados. No meu caso foi a criação de duas tabelas e uma enum com valor boolean para true
e false
. Por padrão o Scaffold usa o SQLITE e como foi pedido alterei para o postgres na próxima seção falo melhor sobre a mudança.
rails g scaffold todo-item todo-list:belongto text completed:boolean
Por padrão o scaffold
faz a criação das tabela do banco para o SQLITE
, sendo assim de forma local. Utilizei no Gemfile a gem pg
para usar o postgres. Após o uso do Gem no Gemfile usei o bundle install
para atulizar e installar nova dependências do projeto. Mudei o banco de forma simples, como o scaffold já criou minhas tabelas locais basta apenas miagra com um db:migrate
, isso após preencher os parâmetros no database.yml
para a conexão do seu usuario com o postgres, utilizei o default, já que não irei utlizar de gitflow.
gem 'pg', '~> 1.5', '>= 1.5.6'
bundle install
db:migrate
default: &default
adapter: postgresql # Aptar para o seu banco (MySQL, SQLITE, POSTGRES, MARIADB...)
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: seu usuario
password: sua senha
host: seu host
port: porta
Caso você não saiba seu usuário do postgres utilize o comando abaixo no pgadmin
SELECT current_user;
Aqui é algo breve, porém importante. Caso seja desejado alterar as tabela na mão via arquivo do schema.rb
, usei o rails rollback
para voltar a versão anterior, adc o que deseja, após use o db:migrate
rails rollback
Algumas complicações na instalação padrão do TailwindCSS, ficou corrompido. Presume que tinha sido a versão do rails
e a gem tailwind
estava atualizada para versão mais nova, porém para minha supresa não foi, executei novamente o comando CLI
para reinstalar o tailwind e felizmente sucesso. Carregou todos os styles dentro dos arquivos html.erb
bin/rails tailwindcss:install
Bem, eu queria colocar para fica de uma forma ordenada, onde para ver o item você deve passar pelas lista primeiro, já que é a lógica Todo_list -> Todo_items
, meu erro foi ter esquecido que Todo_list
é o pai de Todo_items
, já que agora eu coloquei o Todo_items
dentro de Todo_list
, e passei na rota.
Rails.application.routes.draw do # Para seguir o padrão e aninha por ordem o todo_list a após o todo_items
resources :todo_lists do # Pai
resources :todo_items # Filho
end
get "up" => "rails/health#show", as: :rails_health_check # Nosso end point HTTP
end
Um exemplo de heranção para a funcionalidade dos items que dependem totalmente da lista.
<%= form_with(model: [@todo_list, todo_item], class: "contents") do |form| %>
Havia um eve problema quando acontecia a exclusão de um item, já que o usuário ficava na página antiga de itens e não volta para a sua lista de origem, então foi adicionado ao destroy.
def destroy
@todo_item.destroy # remove o item do banco de dados
respond_to do |format| # Depois, o usuário é redirecionado para a página da lista
format.html { redirect_to todo_list_path(@todo_list), notice: "Item excluído com sucesso." } # Uma mensagem de sucesso é exibida
format.json { head :no_content }
end
end
Deixa claro que antes de executar o destroy, Rails executa os métodos set_todo_list
para carregar a lista correta com base no todo_list_id
da URL e set_todo_item
para carregar o item correto dentro da lista
Foi utilizada a gem devise
para a criação de login de forma simples, no Gemfile
foi adicionada a nova gem, após isso usei o bundle install
para instalação e para gera os arquivo do banco foi usado o rails generate devise:install
. Criando o model do usuario e importanto com o rails db:migrate
, para gerar o templete foi usado o rails generate devise:views
.
gem 'devise'
bundle install
rails generate devise:install
rails generate devise User
db:migrate
rails generate devise:views
Foi até que tranquilo usando o devise, era só passar um belongs_to :user
em todo_list.rb
para indicar que tal item pertence a tal usuário, e um has_many
em user.rb
já que um usuário pode ter múltiplas listas de tarefas, após fui configurar o meu controller para que cada usuario só possa criar, editar ou excluir as lista com sua conta. Foi passado current_user
antes de todos os métodos para garantir que o usuario mexa apenas em suas listas.
class TodoList < ApplicationRecord
belongs_to :user
has_many:todo_items, dependent: :destroy # adc um has many para puxar os dados da tabela todo_items e um destroy para que a tarefa seja removida independete dos itens dentro dela
alias_attribute :items, :todo_items # adc um alias para fica mais simples a chamada da classe
end
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :todo_lists, dependent: :destroy
end
def index
@todo_lists = current_user.todo_lists.all # garante que cada usuário só veja as listas dele.
end