[Guide] Rails101 簡易建立步驟
[ Chapter 1. 環境安裝 ]
1-1 確認ruby版本
ruby -v
1-2 安裝 gem rails 4.2.0
gem install rails -v 4.2.0 --no-ri
1-3 建立一個新 Rails 專案 ( 版本 4.2.0 )
rails _4.2.0_ new rails101 -T
1-4 進入新建好的專案, 並建立 git 做版本控制
cd rails101
git init
git add .
git commit -m "Initial Commit"
[ Chapter 2. 建立基礎網站(僅架構) ]
2-1 建立一個討論版(group)
2-1.1 建立一個 controller: groups (要加s)
rails g controller groups
2-1.2 建立一個 Model: group (不加s)
rails g model group title:string description:text
2-1.3 將資料庫建立起來
rake db:migrate
2-1.4 設定 routes 並建立 groups/index 為首頁 ( 內容是 Hello World! )
# [path] config/routes.rb
+ root 'groups#index' # 這行代表把 localhost:3000/groups 這個網址設成首頁
+ resources :groups
這時候啟動 rails s
前往 http://localhost:3000/
2-2 建立必要頁面
2-2.1 設定 action ‘index’
# [path] app/controllers/groups_controller.rb
+ def index
+ end
2-2.2 設定 groups/index.html.erb
<!-- [path] app/views/groups/index.html.erb -->
<h1>Hello World!</h1>
2-3 套入前端套件 Bootstrap
2-3.1 安裝 gem ‘bootstrap-sass’
https://github.com/twbs/bootstrap-sass
# [path] Gemfile
+ gem 'bootstrap-sass'
執行 bundle install
2-3.2 將 Bootstrap 的 CSS 套件裝進專案裡面
mv app/assets/stylesheets/application.css app/assets/stylesheets/application.css.scss
/* app/assets/stylesheets/application.css.scss */
+ @import "bootstrap-sprockets";
+ @import "bootstrap";
重開 rails s
2-4 幫你的專案裝上 Navbar 跟 Footbar
2-4.1 新增兩檔案
<!-- app/views/common/_navbar.html.erb -->
<nav class="navbar navbar-default" role="navigation">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<a class="navbar-brand" href="/">Rails 101</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li> <%= link_to("登入", '#') %> </li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<!-- [path] app/views/common/_footer.html.erb-->
<footer class="container" style="margin-top: 100px;">
<p class="text-center">Copyright ©2016 Rails101
<br>Design by <a href="courses.growthschool.com/courses/rails-101/" target=_new>xdite</a>
</p>
</footer>
2-4.2 修改 app/views/layouts/application.html.erb
<!-- [path] app/views/layouts/application.html.erb -->
- <%= yield %>
+ <div class="container-fluid">
+ <%= render "common/navbar" %>
+ <%= yield %>
+ </div>
+ <%= render "common/footer" %>
2-5 建立 notice_message
2-5.1 將 Boostrap 的 js 套件: alert 裝進專案裡面
// [path] app/assets/javascripts/application.js
+//= require bootstrap/alert
2-5.2 建立 helper: notice_message
# [path] app/helpers/application_helper.rb
+ def notice_message
+ alert_types = { notice: :success, alert: :danger }
+
+ close_button_options = { class: "close", "data-dismiss" => "alert", "aria-hidden" => true }
+ close_button = content_tag(:button, "×", close_button_options)
+
+ alerts = flash.map do |type, message|
+ alert_content = close_button + message
+
+ alert_type = alert_types[type.to_sym] || type
+ alert_class = "alert alert-#{alert_type} alert-dismissable"
+
+ content_tag(:div, alert_content, class: alert_class)
+ end
+
+ alerts.join("\n").html_safe
+ end
2-5.3 把 notice_message 放進 application.html.erb 裡面
<!-- [path] app/views/layouts/application.html.erb -->
<div class="container-fluid">
<%= render "common/navbar" %>
+ <%= notice_message %>
<%= yield %>
</div>
2-5.4 如何使用 notice_message 的功能
# [path] app/controllers/groups_controller.rb
class GroupsController < ApplicationController
def index
+ flash[:notice] = "早安!你好!"
+ flash[:warning] = "這是 warning 訊息!"
+ flash[:alert] = "晚安!該睡了!"
end
end
[ Chapter 3. 手動實作出討論版的 CRUD 功能 ]
3-1 安裝 gem “simple_form”
3-1.1 加入gem
# [path] gemfile
+ gem "simple_form"
bundle install
3-1.2 安裝 simple_form for bootstrap 的設定
rails generate simple_form:install --bootstrap
重開 rails s
3-2 可以總覽所有討論版 ( 建立 action index )
3-2.1 建立 action index
# [path] app/controllers/groups_controller.rb
def index
+ @groups = Group.all
end
3-2.2 建立 index.html.erb
<!-- [path] app/views/groups/index.html.erb -->
<div class="col-md-12">
<div class="group">
<%= link_to("New group", new_group_path, class: "btn btn-primary pull-right") %>
</div>
<table class="table table-hover">
<thead>
<tr>
<td>#</td>
<td>Title</td>
<td>Description</td>
</tr>
</thead>
<tbody>
<% @groups.each do |group| %>
<tr>
<td>#</td>
<td><%= link_to(group.title, group_path(group)) %></td>
<td><%= group.description %></td>
<td>
<%= link_to("Edit", edit_group_path(group), class: "btn btn-sm btn-default")%>
<%= link_to("Delete", group_path(group), class: "btn btn-sm btn-default",
method: :delete, data: { confirm: "Are you sure?" } )%>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
3-2 可以新增討論版 ( 建立 action new, create )
3-2.1 action ‘new’
# [path] app/controllers/groups_controller.rb
+ def new
+ @group = Group.new
+ end
3-2.2 erb ‘new’
<!-- [path] app/views/groups/new.html.erb -->
<div class="col-md-4 col-md-offset-4">
<h1>新增討論版</h1>
<hr>
<%= simple_form_for @group do |f| %>
<div class="form-group">
<%= f.input :title, input_html: { class: "form-control"} %>
<%= f.input :description, input_html: { class: "form-control"} %>
</div>
<%= f.submit "Submit", class: "btn btn-primary", data: { disable_with: "Submitting..." } %>
<% end %>
</div>
3-2.3 action ‘create’
# [path] app/controllers/groups_controller.rb
+ def create
+ @group = Group.create(group_params)
+
+ if @group.save
+ redirect_to groups_path
+ else
+ render :new
+ end
+ end
+ private
+
+ def group_params
+ params.require(:group).permit(:title, :description)
+ end
3-3 可以瀏覽單一討論版 ( 建立 action show )
3-3.1 action show
# [path] app/controllers/groups_controller.rb
+ def show
+ @group = Group.find(params[:id])
+ end
<!-- [path] app/views/groups/show.html.erb -->
<div class="col-md-12">
<div class="group">
<%= link_to("Edit", edit_group_path(@group), class: "btn btn-primary pull-right")%>
</div>
<h2><%= @group.title %></h2>
<p><%= @group.description %></p>
</div>
3-4 修改討論版與儲存已改的設定 ( 建立 action edit, update )
3-4.1 action edit
# [path] app/controllers/groups_controller.rb
+ def edit
+ @group = Group.find(params[:id])
+ end
<!-- [path] app/views/groups/edit.html.erb -->
<div class="col-md-4 col-md-offset-4">
<h1>修改討論版</h1>
<hr>
<%= simple_form_for @group do |f| %>
<div class="form-group">
<%= f.input :title %>
<%= f.input :description %>
</div>
<%= f.submit "Submit", class: "btn btn-primary", data: { disable_with: "Submitting..." } %>
<% end %>
</div>
3-4.2 action update
# [path] app/controllers/groups_controller.rb
+ def update
+ @group = Group.find(params[:id])
+ if @group.update(group_params)
+ redirect_to groups_path, notice: "修改討論版成功"
+ else
+ render :edit
+ end
+ end
<!-- [path] app/views/groups/edit.html.erb -->
<div class="col-md-4 col-md-offset-4">
<h1>修改討論版</h1>
<hr>
<%= simple_form_for @group do |f| %>
<div class="form-group">
<%= f.input :title %>
<%= f.input :description %>
</div>
<%= f.submit "Submit", class: "btn btn-primary", data: { disable_with: "Submitting..." } %>
<% end %>
</div>
3-5 將討論版刪除 ( action destroy )
3-5.1 建立 action destroy
# [path] app/controllers/groups_controller.rb
+ def destroy
+ @group = Group.find(params[:id])
+ @group.destroy
+ redirect_to groups_path, alert: "討論版已刪除"
+ end
3-6 資料驗證: title 不能空白
# [path] app/models/group.rb
+ validates :title, presence: true
[ Chapter 4. 可以在討論版裡發表文章 ]
4-1 建立 post 相關的 controller, model 關聯 與 routing 設定
4-1.1 建立 Controller: posts (要加s)
rails g controller posts
4-1.2 建立 Model: post (不加s)
rails g model post content:text group_id:integer
4-1.3 將 post 的資料庫建立起來
rake db:migrate
4-2 建立 group 與 post 之間 model 的關聯性 (relationship)
# [path] app/models/group.rb
+ has_many :posts
# [path] app/models/post.rb
+ belongs_to :group
4-3 routing 設定
# [path] config/routes.rb
- resources :groups
+ resources :groups do
+ resources :posts
+ end
4-4 可以在 group 的 show 頁面顯示所擁有的 post
# [path] app/controllers/groups_controller.rb
def show
@group = Group.find(params[:id])
+ @posts = @group.posts
end
<!-- [path] app/views/groups/show.html.erb -->
<div class="col-md-12">
<div class="group">
+ <%= link_to("New Post", new_group_post_path(@group), class: "btn btn-warning pull-right") %>
<%= link_to("Edit", edit_group_path(@group), class: "btn btn-primary pull-right")%>
</div>
<h2><%= @group.title %></h2>
<p><%= @group.description %></p>
+ <table class="table">
+ <thead>
+ <tr>
+ <th>文章</th>
+ <th colspan="2"></th>
+ </tr>
+ </thead>
+ <tbody>
+ <% @posts.each do |post| %>
+ <tr>
+ <td><%= post.content %></td>
+ <td>
+ <%= link_to("Edit", edit_group_post_path(post.group, post),
+ class: "btn btn-default btn-xs")%>
+ <%= link_to("Delete", group_post_path(post.group, post),
+ class: "btn btn-default btn-xs ", method: :delete,
+ data: { confirm: "Are you sure?" } )%>
+ </td>
+ </tr>
+ <% end %>
+ </tbody>
+ </table>
</div>
4-5 可以在討論版裡新增 post ( action new, create )
4-5.1 action ‘new’
# [path] app/controllers/posts_controller.rb
+ def new
+ @group = Group.find(params[:group_id])
+ @post = @group.posts.new
+ end
# [path] app/views/posts/new.html.erb
<h1 class="text-center">新增文章</h1>
<div class="col-md-4 col-md-offset-4">
<%= simple_form_for [@group,@post] do |f| %>
<div class="form-group">
<%= f.input :content, input_html: { class: "form-control"} %>
</div>
<div class="form-actions">
<%= f.submit "Submit", disable_with: "Submiting...", class: "btn btn-primary"%>
</div>
<% end %>
</div>
4-5.2 action ‘create’
# [path] app/controllers/posts_controller.rb
+ def create
+ @group = Group.find(params[:group_id])
+ @post = @group.posts.build(post_params)
+ if @post.save
+ redirect_to group_path(@group), notice: "新增文章成功!"
+ else
+ render :new
+ end
+ end
+ private
+ def post_params
+ params.require(:post).permit(:content)
+ end
4-6 可以修改並更新 post ( action edit, update )
4-6.1 設定 action ‘edit’ 與 action ‘update’
# [path] app/controllers/posts_controller.rb
+ def edit
+ @group = Group.find(params[:group_id])
+ @post = @group.posts.find(params[:id])
+ end
+ def update
+ @group = Group.find(params[:group_id])
+ @post = @group.posts.find(params[:id])
+ if @post.update(post_params)
+ redirect_to group_path(@group), notice: "文章修改成功!"
+ else
+ render :edit
+ end
+ end
<!-- [path] app/views/posts/edit.html.erb -->
<h1 class="text-center">修改文章</h1>
<div class="col-md-4 col-md-offset-4">
<%= simple_form_for [@group,@post] do |f| %>
<div class="form-group">
<%= f.input :content, input_html: { class: "form-control"} %>
</div>
<div class="form-actions">
<%= f.submit "Submit", disable_with: "Submiting...", class: "btn btn-primary"%>
</div>
<% end %>
</div>
4-7 可以刪除 post ( action destroy )
4-7.1 action ‘destroy’
# [path] app/controllers/posts_controller.rb
+ def destroy
+ @group = Group.find(params[:group_id])
+ @post = @group.posts.find(params[:id])
+
+ @post.destroy
+ redirect_to group_path(@group), alert: "文章已刪除"
+ end
4-8 資料驗證: post 必須要有內容才能儲存 / 新增
# [path] app/models/post.rb
+ validates :content, presence: true
4-9 用 before_action 來整理重複的程式碼
# [path] app/controllers/posts_controller.rb
+ before_action :find_group
private
+ def find_group
+ @group = Group.find(params[:group_id])
+ end
將所有@group = Group.find(params[:group_id])
刪掉(new edit create update destory)
before_action 可以用 only,指定某些 action 執行:
before_action :find_group, only: [:edit, :update]
或者使用 except,排除某些 action 不執行:
[ Chapter 5. 第五章:(1) 建立基本使用者功能 ]
5-1 安裝 gem “devise”
https://github.com/plataformatec/devise
# [path] gemfile
gem "devise", "~> 3.4.1"
執行bundle install
5-2 設定 Devise
5-2.1 devise 安裝
rails g devise:install
5-2.2 建立 user 功能
rails g devise user
rake db:migrate
5-2.3 叫出(原本是隱藏的) devise views,以便未來可以客製化修改
rails g devise:views
5-2.4 重開rails server
rails s
[ Chapter 5. 第五章:(2) 客製化 devise => 新增一個 “name” 的欄位 ]
5-3 客製化欄位:name
5-3.1 客製化 devise => 新增一個 “name” 的欄位
rails g migration add_name_to_user
# [path] db/migrate/(一堆數字)_add_name_to_user.rb
def change
+ add_column :users, :name, :string
end
rake db:migrate
5-4 客製化 devise 的 views => 註冊頁面新增 name 欄位
# [path] app/views/devise/registrations/new.html.erb
<div class="form-inputs">
<%= f.input :email, required: true, autofocus: true %>
+ <%= f.input :name, required: true %>
<%= f.input :password, required: true, hint: ("#{@minimum_password_length} characters minimum" if @validatable) %>
<%= f.input :password_confirmation, required: true %>
</div>
5-5 加入 strong_parameters 與 devise 整合的 hack
# [path] app/controller/application_controller.rb
+ before_filter :configure_permitted_parameters, if: :devise_controller?
+ protected
+ def configure_permitted_parameters
+ devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:name, :email, :password, :password_confirmation) }
+ end
5-6 navbar 上的 hi! email 改成 hi! name
# [path] app/views/common/_navbar.html.erb
- Hi!, <%= current_user.email %>
+ Hi!, <%= current_user.name %>
5-7 新增 “帳號設定” 功能,並能修改自己帳號的 name
<!-- [path] app/views/common/_navbar.html.erb -->
<ul class="dropdown-menu">
+ <li> <%= link_to("帳號設定", edit_user_registration_path )%></li>
<li> <%= link_to("登出", destroy_user_session_path, method: :delete) %> </li>
</ul>
# [path] app/controller/application_controller
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:name, :email, :password, :password_confirmation) }
+ devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:name, :email, :password, :password_confirmation, :current_password) }
end
<!-- [path] app/views/devise/registrations/edit.html.erb -->
+ <%= f.input :name %>
留言