rails new <APP_NAME>
- Coding the views
- Coding the controllers
- Coding the models
3 - 2 - 1
rails g model Song title:string year:integer
rails g model ModelName column_name:column_type column2_name:column2_type
app/models/song.rb # model
db/migrate/XXXXXXX_create_songs.rb # migration
rails db:migrate # Runs all pending (down) migration
6. How do you add a category
(ex: “rock” , “electro” , etc..) to your songs table using the correct Rails generator?
rails g migration add_category_to_songs category:string
db/migrate/XXXXXXX_add_category_to_songs.rb # migration
class AddCategoryToSongs < ActiveRecord::Migration[6.1]
def change
add_column :songs, :category, :string
end
end
rails db:migrate # Runs all pending (down) migration
class Song < ApplicationRecord
# validates(:title, { presence: true })
# validates(:title, presence: true)
validates :title, presence: true
end
sail_away = Song.new(title: "")
sail_away.valid? # sail_away.save # => false
sail_away.title = "Sail Away"
sail_away.valid? # sail_away.save # => true
- The Router is routing the HTTP request to
controller#action
. - The action is getting data from models.
- Everything starts with an HTTP Request.
- The action is rendering the view.
3 - 1 - 2 - 4
VERB # GET / POST / PATCH / PUT /DELETE
URL # google.com
--------- below the surface
HEADERS # Filled by the client/browser
BODY # Optional. Has the data from forms or others...
GET /posts
POST /posts
No. The verb is different.
GET intends to request information about a resource. POST for sending info about a resource. POST should have a body of data.
HTTP request: GET /search?query=thriller
Routing in config/routes.rb: get "/search" => "songs#search"
class SongsController < ApplicationController
# GET /search?query=thriller
# params => { query: "thriller" }
# params[:query] => "thriller"
def search
@songs = Song.where("title ILIKE '%?%'", params[:query])
end
end
HTTP request: GET /songs/named/thriller
Routing in config/routes.rb: get "/songs/named/:name" => "songs#search"
class SongsController < ApplicationController
# GET /songs/named/sail
# GET /songs/named/thriller
# GET /songs/named/:name
# params => { name: "thriller" }
def search
@songs = Song.where("title ILIKE '%?%'", params[:name])
end
end
VERB | PATH | CONTROLLER | ACTION |
---|---|---|---|
GET | /songs | songs | index |
GET | /songs/:id | songs | show |
GET | /songs/new | songs | new |
POST | /songs | songs | create |
GET | /songs/:id/edit | songs | edit |
PATCH/PUT | /songs/:id | songs | update |
DELETE | /songs/:id | songs | destroy |
rails routes
rails routes -g=songs
rails g controller Songs
class SongsController < ApplicationController
def index
@songs = Song.all
end
# GET songs/:id
def show
@song = Song.find(params[:id])
end
end
21. What are the 2 requests needed to create a new song? Implement the songs#new
and songs#create
actions
class SongsController < ApplicationController
def new
@song = Song.new
end
def create
@song = Song.new(song_params)
if @song.save
redirect_to songs_path # song_path(@song)
else
render :new
end
end
private
def song_params
params.require(:song).permit(:title, :year)
end
end
To avoid code unwanted code execution. Users could add form fields otherwise, which could trigger unintended writers in the model.
Imagine that:
@song = Song.new
Now what is the HTML code generated by:
<%= form_for @song do |f| %>
<%= f.text_field :title %>
<%= f.submit %>
<% end %>
<!--- VERB PATH --->
<form method="post" action="/songs">
<input type="text" name="song[title]" value= "">
</form>
Imagine that:
@song
#=> <#Song: id: 18, title: "Hey jude", year: 1968, category: "rock">
Now what is the HTML code generated by:
<%= form_for @song do |f| %>
<%= f.text_field :title %>
<%= f.submit %>
<% end %>
<!--- VERB PATH --->
<form method="patch" action="/songs/18">
<input type="text" name="song[title]" value= "Hey jude">
</form>
rails g model Review content:string song:references
rails db:migrate
class Review < ApplicationRecord
validates :content, presence: true
belongs_to :song
end
class Song < ApplicationRecord
has_many :reviews
end
rails g controller Reviews
resources :songs
resources :reviews, only: [:new, :create]
end
class SongsController < ApplicationController
def new
@song = Song.find(params[:song_id])
@review = Review.new
end
def create
@song = Song.find(params[:song_id])
@review = Review.new(review_params)
@review.song = @song
if @review.save
redirect_to @song
else
render :new
end
end
private
def review_params
params.require(:review).permit(:content)
end
end
<h1><%= @song.title %></h1>
<% @song.reviews.each do |review| %>
<div class="class">
<%= review.content %>
</div>
<% end %>