Rails CRUD
- form_for
If you do form for, instead of httml source,
techinally it works same as like HTML source
but it do connect to next page, and set method stuff for us
If form_for(@resto)
has id X ===> next: create / method: push
has id O ===> next: update / method: patch
<!-- app/views/restaurants/_form.html.erb -->
<%= form_for(@restaurant) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :address %>
<%= f.text_field :address %>
<%= f.submit %>
<% end %>
short cut for form_for for same pages
<!-- app/views/restaurants/new.html.erb -->
<%= render 'form' %>
<!-- app/views/restaurants/edit.html.erb -->
<%= render 'form', restaurant: @restaurant %>
- What rails do for me?
1) rails new APP_NAME
2) rails generate model Restaurant name:string address:strinng
3) rails db:migrate
4) Edit details of model
5) rails db:migrate
6) rails generate controller Restarant method_name method_name method_name
rails db:drop # Drops the database (lose all your data!)
rails db:create # Creates the database with an empty schema
rails db:migrate # Runs pending migrations on the database schema
rails db:seed # Runs seeds.rb file
rails db:rollback # Revert the last migration
rails db:reset # Drops database + replays all migration + runs seed
3.If I need edit Migration
put this line in Terminal
rails generate migration AddAddressToRestaurants address:string
- About CRUD
Make it 7 CRUD routes for me
Rails.application.routes.draw do
resources :restaurants
end
In case of only need specific pages
Rails.application.routes.draw do
resources :restaurants, only: [:index, :show]
end
- UPDATE
Because any user can access or edit data form in HTML, make ‘params’ locked.
Make theparams.require(:model).permit(:method)
on the last line,
and mark it as to private
class RestaurantsController < ApplicationController
def update
restaurant = Restaurant.find(params[:id])
restaurant.update(restaurant_params)
redirect_to restaurant_path(restaurant)
end
[...]
private
def restaurant_params
params.require(:restaurant).permit(:name, :address, :stars)
end
end
- before action filter
When we need exact same line in Method,
using before action like below.
In this case
# app/controllers/restaurants_controller.rb
class RestaurantsController < ApplicationController
def show
@restaurant = Restaurant.find(params[:id])
# ...
end
def edit
@restaurant = Restaurant.find(params[:id])
# ...
end
def update
@restaurant = Restaurant.find(params[:id])
# ...
end
def destroy
@restaurant = Restaurant.find(params[:id])
# ...
end
end
1) Make set_restaurant Method in Private
2) Add it right after the class line
# app/controllers/restaurants_controller.rb
class RestaurantsController < ApplicationController
before_action :set_restaurant, only: [:show, :edit, :update, :destroy]
def show
# ...
end
def edit
# ...
end
def update
# ...
end
def destroy
# ...
end
private
def set_restaurant
@restaurant = Restaurant.find(params[:id])
end
end
+++) sample
- routes
Rails.application.routes.draw do
# CREATE
get 'tasks/new', to: "tasks#new", as: "new_task"
post 'tasks', to: "tasks#create", as: "tasks"
# READ
get 'tasks/:id', to: "tasks#show", as: "task"
get 'tasks', to: "tasks#index"
# UPDATE
get 'tasks/:id/edit', to: "tasks#edit", as: "edit_task"
patch 'tasks/:id', to: "tasks#update"
# DELETE
delete 'tasks/:id', to: "tasks#destroy"
end
- Controller
class TasksController < ApplicationController
before_action :find_id, only: [:show, :edit, :update, :destroy]
# CREATE
def new
@task = Task.new # This is for rendering form_for
end
def create
@task = Task.new(user_params)
@task.save
redirect_to task_path(@task)
end
# READ
def show
# @task = Task.find(params[:id])
end
def index
@tasks = Task.all
end
# UPDATE
def edit
# @task = Task.find(params[:id])
end
def update
# @task = Task.find(params[:id])
@task.update(user_params)
redirect_to task_path(@task)
end
# DELETE
def destroy
# @task = Task.find(params[:id])
@task.destroy
redirect_to tasks_path # index
end
private
def find_id
@task = Task.find(params[:id])
end
# returns a hash of cat attributes that are safe
def user_params
params.require(:task).permit(:title, :details, :completed)
end
end
- View_ show
<h1>Tasks#show</h1>
<div class="card">
<h3><%= @task.details %></h3>
<% if @task.completed %>
<input type="checkbox" checked> This task is finished<br>
<% else %>
<input type="checkbox"> This task needs to be finished<br>
<% end %>
</div>
<%= link_to "⬅️", tasks_path %>
<%= link_to "⚙️", edit_task_path %>
- HTML_index
<h1>MY TASK</h1>
<div class="card">
<ul>
<% @tasks.each do |task| %>
<li>
<input type ="checkbox" <%= "checked" if task.completed %>>
<%= link_to task.title, task_path(task) %>
<%= link_to "🔪", task_path(task), method: :delete, data: { confirm: "You really want?"} %>
</li>
<% end %>
</ul>
</div>
<%= link_to "➕", new_task_path %>