[Ruby]《Ruby on Rails Tutorial》的搬運工之一

ruby-on-rails-tutorials.jpg

背景:

  1. 最近比較閑,想學(xué)習(xí)ruby on rails
  2. 于是找到了https://www.railstutorial.org 上的首推教程《Ruby on Rails Tutorial》
    屏幕快照 2016-05-29 上午11.04.20.png

    這本書第一章和第二章講了2個基本demo,實在沒啥意思,姑且略過. 從第三章開始到第十二章是從0到1實現(xiàn)了一個類似Twitter的簡單社交網(wǎng)站(首頁,登錄注冊,發(fā)布推文,關(guān)注等功能). 怎么樣是不是很棒?
    但是這個本書實在講得過于詳細(xì),對于我這種本身沒有那么多時間(也沒那么多耐心??)去一點一點看下來的童鞋,看著實在太著急了,于是準(zhǔn)備快速整理下(把里面的干貨和代碼提取出來),方便大家可以分分鐘coding出這個demo出來.
    當(dāng)然真正學(xué)習(xí)還是要看原教程,我這個只是"扒皮版本".

<br />

原文鏈接

RUBY ON RAILS TUTORIAL
https://www.railstutorial.org/book/static_pages

他們的github:

railstutorial/sample_app_rails_4
https://github.com/railstutorial/sample_app_rails_4

<br />

ruby學(xué)習(xí)框架圖

ruby on rails is hard?

開始


前兩章略掉...
從第三章開始:

3. Mostly static pages

3.1 Sample app setup

$ rails  new sample_app
$ cd sample_app/

生成我們的APP,ruby會生成如下文件


生成的APP文件

3.2 Static pages

3.2.1 Generated static pages

生成StaticPages 這個controller

$ rails generate controller StaticPages home help

3.2.2 Custom static pages

畫UI, 剛才生成了home和help2個頁面,默認(rèn)頁面啥也沒有,我們來填東西:

a). Custom HTML for the Home page

用vim 或者自己熟悉的編輯器,修改home.html.erb和help.html.erb 2個文件

vim app/views/static_pages/home.html.erb 
<h1>Sample App</h1>
<p> This is the home page for the 
    <a >Ruby on Rails Tutorial</a> 
    sample application.
</p>

b). Custom HTML for the Help page

vim app/views/static_pages/help.html.erb
<h1>Help</h1>
<p> Get help on the Ruby on Rails Tutorial at the 
<a >Rails Tutorial help section</a>. 
To get help on this sample app, see the <a ><em>Ruby on Rails Tutorial</em> book</a>.
</p>

3.3 Getting started with testing

執(zhí)行測試,這本書的教材很重視test,這也是國內(nèi)開發(fā)人員很不重視的地方,想著都留給測試好了,其實開發(fā)測試做得好了,代碼才會漂亮,質(zhì)量高. 如果全靠測試,那代碼全是東一坨西一坨,全是補丁.
rails 中執(zhí)行 測試可以在控制臺中進(jìn)行,當(dāng)然,最簡單的步驟是

rake test

下面的我這邊執(zhí)行后的一次結(jié)果,可以看到,測試結(jié)果提示,"schema.rb doesn't exist yet",讓我執(zhí)行"Run rake db:migrate to create it"

屏幕快照 2016-05-29 下午1.18.12.png

另,原文中教程叫你如何測試一個about界面,這里不詳述了,有興趣的點鏈接:
Our first step is to write a failing test for the About page...

這里只說下如何搭建about頁面
a). 建立路由(vim config/routes.rb)

 vim config/routes.rb
//  Adding the about route.
Rails.application.routes.draw do 
  get 'static_pages/home' 
  get 'static_pages/help' 
  get 'static_pages/about' 
. . .
end

b). controller中增加about action

class StaticPagesController < ApplicationController 
  def home 
  end 
  def help 
  end 
  def about 
  end
end

c). 新建about.html.erb

touch 創(chuàng)建,vim編輯
<h1>About</h1>
<p> 
The <a ><em>Ruby on Rails Tutorial</em></a> 
is a 
<a >book</a> 
and 
<a >screencast series</a> 
to teach web development with 
<a >Ruby on Rails</a>. 
This is the sample application for the tutorial.
</p>

3.4 Slightly dynamic pages

3.4.1 Testing titles (Red)

3.4.2 Adding page titles (Green)

這里文中告訴你,ruby真正來了,使用ruby的標(biāo)志是使用<% ... %>,這里對于初學(xué)者有個點注意下:

<% %>: 只是執(zhí)行<>中的代碼
<%= %>:代碼還是會執(zhí)行,同時會在界面顯示執(zhí)行結(jié)果

然后我們重新修改下我們的home,help,about界面:

home

help

about

3.4.3 Layouts and embedded Ruby (Refactor)

然后發(fā)現(xiàn)每個頁面都有<title></title>然后我們代碼重新改一下,統(tǒng)一放到app/views/layouts/application.html.erb里面:


application.html.erb

另外home,help,about也對應(yīng)改一下,改成類似

<h1>Help</h1>
<h1>About</h1>

3.4.4 Setting the root route

編輯config/routes.rb

Rails.application.routes.draw do 
  root 'static_pages#home' 
  get 'static_pages/help' 
  get 'static_pages/about'
end

3.7 Advanced testing setup

3.7.2 Backtrace silencer

config/initializers/backtrace_silencers.rb 中的一行代碼解注


屏幕快照 2016-05-29 下午2.15.44.png

<br />

4. Rails-flavored Ruby


4.1 Motivation

前面有provide方法提供title,這里把title再細(xì)化,針對不同的頁面有個通用的處理title的方法:

vim app/helpers/application_helper.rb

module ApplicationHelper

  # Returns the full title on a per-page basis.
  def full_title(page_title = '')
    base_title = "Ruby on Rails Tutorial Sample App"
    if page_title.empty?
      base_title
    else
      page_title + " | " + base_title
    end
  end
end

這樣

<title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>

可以簡化為

<title><%= full_title(yield:title)></title>

4.2 Strings and methods

4.2.1 Comments

ruby中的注釋用 #, ruby的print用puts,當(dāng)然也可以直接用print,但是print需要自己打印一個"\n"

>> puts "foo" # put string
foo
=> nil

>> print "foo" # print string (same as puts, but without the newline)
foo=> nil

>> print "foo\n" # Same as puts "foo"
foo
=> nil

<br />

5. Filling in the layout


本章開始做個歡迎頁面


屏幕快照 2016-05-29 下午2.43.29.png

5.1 Adding some structure

5.1.1 Site navigation
application.html.erb中增加home,help,login的菜單欄

vim app/views/layouts/application.html.erb
屏幕快照 2016-05-29 下午2.53.02.png

home 頁面增加注冊按鈕和圖片

vim app/views/static_pages/home.html.erb
屏幕快照 2016-05-29 下午2.51.48.png

5.1.2 Bootstrap and custom CSS

安裝bootstrap-sass庫:

polen:
說到這個庫,一把辛酸淚,從github上搜到了這本教程對應(yīng)的demo代碼(https://github.com/railstutorial/sample_app_rails_4)
結(jié)果下載下來各種運行fail,逼得我ruby和bundle都重新安裝了好久
因為這個代碼里rails的版本太低,里面Gemfile對應(yīng)的很多庫都是低版本的,我們前面使用rails new project_name的時候,默認(rèn)生成的Gemfile里面庫的版本都是很新的
所以你要使用這段github代碼的話,運行之前,先把gemfile替換為你本地的,然后在里面加入如下幾條即可

gem 'bootstrap-sass',       '2.2.2.0'
gem 'bcrypt',               '3.1.7'
gem 'will_paginate',        '3.0.5'

>```
bootstrap-sass 這個3.0版本和2.0都可以,但是二者是不兼容的,命名規(guī)則一個是grayLight,一個是gray-light, 如果你運行的時候報錯, 你對應(yīng)修改下就好

言歸正傳,回到項目繼續(xù):

vim Gemfile

![屏幕快照 2016-05-29 下午3.09.30.png](http://upload-images.jianshu.io/upload_images/173709-d7c3cf72011db30e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

bundle install 或者bundle update

創(chuàng)建custom.css.scss布局文件

touch app/assets/stylesheets/custom.css.scss
vim app/assets/stylesheets/custom.css.scss

@import "bootstrap-sprockets";
@import "bootstrap";

/* universal */
body {
padding-top: 60px;
}

section {
overflow: auto;
}

textarea {
resize: vertical;
}

.center {
text-align: center;
}

.center h1 {
margin-bottom: 10px;
}

/* typography */
h1, h2, h3, h4, h5, h6 {
line-height: 1;
}

h1 {
font-size: 3em;
letter-spacing: -2px;
margin-bottom: 30px;
text-align: center;
}

h2 {
font-size: 1.2em;
letter-spacing: -1px;
margin-bottom: 30px;
text-align: center;
font-weight: normal;
color: #777;
}

p {
font-size: 1.1em;
line-height: 1.7em;
}

/* header */

logo {

float: left;
margin-right: 10px;
font-size: 1.7em;
color: #fff;
text-transform: uppercase;
letter-spacing: -1px;
padding-top: 9px;
font-weight: bold;
}

logo:hover {

color: #fff;
text-decoration: none;
}

CSS布局了,大家都懂.

###5.1.3 Partials
The site layout with partials for the stylesheets and header.
ruby的局部樣板Partials,是為了實現(xiàn)頁面復(fù)用,我們通過`<%= render 'layouts/header' %>`來實現(xiàn)調(diào)用


首先對應(yīng)新建_shim.html.erb,_header.html.erb 和_footer.html.erb

touch app/views/layouts/_shim.html.erb
touch app/views/layouts/_header.html.erb
touch app/views/layouts/_footer.html.erb

![屏幕快照 2016-05-29 下午4.12.29.png](http://upload-images.jianshu.io/upload_images/173709-b1a1d85ead7b2819.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![屏幕快照 2016-05-29 下午4.12.36.png](http://upload-images.jianshu.io/upload_images/173709-e6da93b31555ae1d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![屏幕快照 2016-05-29 下午4.12.43.png](http://upload-images.jianshu.io/upload_images/173709-aee29046d086e216.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

然后customer.css 加入footer的布局

//... 前面的省略

/* footer */
footer {
margin-top: 45px;
padding-top: 5px;
border-top: 1px solid #eaeaea;
color: #777;
}

footer a {
color: #555;
}

footer a:hover {
color: #222;
}

footer small {
float: left;
}

footer ul {
float: right;
list-style: none;
}

footer ul li {
float: left;
margin-left: 15px;
}


然后修改application.html.erb:

vim app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
<head>
<title><%= full_title(yield(:title)) %></title>
<%= stylesheet_link_tag "application", media: "all",
"data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
<%= render 'layouts/shim' %>
</head>
<body>
<%= render 'layouts/header' %>
<div class="container">
<%= yield %>
<%= render 'layouts/footer' %>
</div>
</body>
</html>



##5.3 Layout links
###5.3.1 Contact page
參照之前的方法,加入contact:
** route("入口") + controller加action("動作") + 加入contact.html("UI") 
這個3個地方**
懂得童鞋,自己默默去加,不懂的看下面的截圖:

![屏幕快照 2016-05-29 下午4.33.35.png](http://upload-images.jianshu.io/upload_images/173709-04451bdd93ffc6b1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

###5.3.2 Rails routes
修改route,增加root路由,同時該寫下之前的路由代碼:

get 'static_pages/help'
??
get 'help' => 'static_pages#help'

所以我們的config/routes.rb 變成了:

Rails.application.routes.draw do

root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'

end


###5.3.3 Using named routes

<%= link_to "About", '#' %>
??
<%= link_to "About", about_path %>

修改我們的header和footer的html文件:

vim app/views/layouts/_header.html.erb
...
vim app/views/layouts/_footer.html.erb
...

結(jié)果如下:
![header](http://upload-images.jianshu.io/upload_images/173709-0c592c4961826cd2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![footer](http://upload-images.jianshu.io/upload_images/173709-a9c1368eb048d3de.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


##5.4 User signup: A first step
###5.4.1 Users controller
好,前面糾結(jié)了半天的界面,布局,其實也就是呈現(xiàn)了個小菜單而已,大概也就是正常工程師5min的工作量吧,而且沒啥成就感,接下來,我們終于要開發(fā)第一個功能了---注冊登錄模塊.
是不是有點小激動:

ruby的一小步,人類的一大步...
----??

首先,Users要玩起來,得需要一個controller:

//generate 可直接寫成 g
rails generate controller Users new

###5.4.2 Signup URL
增加路由,不過`generate controller`的時候,會自動增加`get 'users/new'`,我們現(xiàn)在改成我們統(tǒng)一的格式

vim config/routes.rb

Rails.application.routes.draw do

root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'signup' => 'users#new'
...

然后home.html 也修改,增加signup_path:

vim app/views/static_pages/home.html.erb

<div class="center jumbotron">
<h1>Welcome to the Sample App</h1>

<h2>
This is the home page for the
<a >Ruby on Rails Tutorial</a>
sample application.
</h2>

<%= link_to "Sign up now!", 'signup_path', class: "btn btn-lg btn-primary" %>
</div>

<%= link_to image_tag("rails.png", alt: "Rails logo"),
'http://rubyonrails.org/' %>

<br />
#6.  [Modeling users](https://www.railstutorial.org/book/modeling_users#cha-modeling_users)
***
ruby和iOS一樣也是MVC模式,當(dāng)然很多語言都是這個模式
我們上一篇新建了controller,這一篇來新建model

##6.1 User model
我們要做這樣一個頁面:

![sign up](http://upload-images.jianshu.io/upload_images/173709-182a8ac9e4377d48.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

###6.1.1 Database migrations
新建一個model,有2個屬性:name和email

rails generate model User name:string email:string

>polen:
注意ruby的默認(rèn)命名習(xí)慣(注意單復(fù)數(shù)):
a *Users* controller, a *User* model => *migration*: users.table
**就是model用單數(shù),對應(yīng)的controller和對應(yīng)的數(shù)據(jù)庫用復(fù)數(shù)**

然后,遷移("migrating up")數(shù)據(jù)庫:

rake db:migrate

這樣就會創(chuàng)建一個sqlite3數(shù)據(jù)庫,當(dāng)然實際中大家肯定用的是mysql,關(guān)于ruby和mysql連接,可以去看
[MySQL Ruby tutorial](http://zetcode.com/db/mysqlrubytutorial/)

>polen:
數(shù)據(jù)庫回滾用:

rake db:rollback


###6.1.2 The model file
![usermodel](http://upload-images.jianshu.io/upload_images/173709-fac189b69eeefb43.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

###6.1.3 Creating user objects
###6.1.4 Finding user objects
###6.1.5 Updating user objects
進(jìn)入控制臺,**CRUD數(shù)據(jù)(增刪改查)**,這部分和代碼沒直接關(guān)系,暫且略過

User.create(name: "A Nother", email: "another@example.org")

<User id: 2, name: "A Nother", email: "another@example.org", created_at:

"2014-07-24 01:05:24", updated_at: "2014-07-24 01:05:24">

foo = User.create(name: "Foo", email: "foo@bar.com")

<User id: 3, name: "Foo", email: "foo@bar.com", created_at: "2014-07-24

01:05:42", updated_at: "2014-07-24 01:05:42">
...
...



##6.2 User validations
###6.2.2 Validating presence
增加數(shù)據(jù)檢查的條件,先設(shè)個簡單的,檢查是否存在

vim app/models/user.rb

class User < ActiveRecord::Base
validates :name, presence: true
//或者: validates(:name, presence: true)
end

###6.2.3 Length validation

class User < ActiveRecord::Base
validates :name, presence: true, length: { maximum: 50 }
validates :email, presence: true, length: { maximum: 255 }
end


###6.2.4 Format validation

class User < ActiveRecord::Base
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+-.]+@[a-z\d-.]+.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX }
end


###6.2.5 Uniqueness validation

class User < ActiveRecord::Base
before_save { self.email = email.downcase }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+-.]+@[a-z\d-.]+.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
end


這里增加了唯一性的檢查,

**由唯一性引出索引的問題**,為保證唯一性,對應(yīng)數(shù)據(jù)庫,需要增加index:

rails generate migration add_index_to_users_email

class AddIndexToUsersEmail < ActiveRecord::Migration
def change
add_index :users, :email, unique: true
end
end

rake db:migrate


##6.3 Adding a secure password
###6.3.1 A hashed password
我們需要保證密碼的安全,比如做個md5或者其他hash之類的,那么以下是準(zhǔn)備工作:

a). 數(shù)據(jù)庫需要加入password_digest:

$ rails generate migration add_password_digest_to_users password_digest:string

這樣就可以看到生成一個add_password_digest_to_users.rb
![屏幕快照 2016-05-29 下午6.08.37.png](http://upload-images.jianshu.io/upload_images/173709-bfbd7bf292bb519d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

然后 

run db:migrate


b). Gemfile引入新庫bcrypt, 這種用于對密碼做hash處理:

add by polen

gem 'bootstrap-sass', '3.2.0.0'

Use ActiveModel has_secure_password

gem 'bcrypt', '~> 3.1.11'

然后

bundle update

>polen:
bcrypt這個庫 gem file里面默認(rèn)會有(只是被注釋掉了),我們解注就可以了,不過默認(rèn)是3.1.7,新版本已經(jīng)是3.1.11,我這邊直接用最新的了.
另外,這個執(zhí)行bundle update之后,運行rake test或者直接本地查看我們的頁面會報錯,`bcrypt LoadError: Cannot load such file`,這個其實是因為我們需要重新rails server 運行一下. 
可以參照:[stackoverflow.com/questions/26553696/](http://stackoverflow.com/questions/26553696/bcrypt-loaderror-cannot-load-such-file)

###6.3.2 User has secure password
6.3.1準(zhǔn)備妥當(dāng)之后,
User model中增加has_secure_password

class User < ActiveRecord::Base
...
...
has_secure_password
end

###6.3.3 Minimum password standards
修改usermodel,增加validates :password:

vim app/models/user.rb

class User < ActiveRecord::Base
before_save { self.email = email.downcase }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+-.]+@[a-z\d-.]+.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, presence: true, length: { minimum: 6 }
end


<br />
#7. [Sign up](https://www.railstutorial.org/book/sign_up#cha-sign_up)
***
注冊登錄結(jié)束,接下來,就是展示user的頁面了,我們要做成這個樣子:
![show user](http://upload-images.jianshu.io/upload_images/173709-ba69909f68267b74.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
##7.1 Showing users
###7.1.1 Debug and Rails environments
真的的大頭開始做起來了,也算是第一個復(fù)雜一點的頁面了,但是畢竟沒有像xcode一樣可以時時調(diào)試,那就需要我們自己加個debug信息.

vim app/views/layouts/application.html.erb

既然是全局加,自然加到application.html這個地方了,
加一句話`<%= debug(params) if Rails.env.development? %>`

<!DOCTYPE html>
<html>
<head>
<title><%= full_title(yield(:title)) %></title>
<%= stylesheet_link_tag "application", media: "all",
"data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
<%= render 'layouts/shim' %>
</head>
<body>
<%= render 'layouts/header' %>
<div class="container">
<%= yield %>
<%= render 'layouts/footer' %>
<%= debug(params) if Rails.env.development? %>
</div>
</body>
</html>

對應(yīng)debug信息的UI位置,也要調(diào)一調(diào)啦:

vim app/assets/stylesheets/custom.css.scss

@import "bootstrap-sprockets";
@import "bootstrap";

/* mixins, variables, etc. */

$gray-medium-light: #eaeaea;

@mixin box_sizing {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
...
...
...
/* miscellaneous */

.debug_dump {
clear: both;
float: left;
width: 100%;
margin-top: 45px;
@include box_sizing;
}

###7.1.2 A Users resource
a). 增加路由

vim config/routes.rb

Rails.application.routes.draw do

root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'signup' => 'users#new'
resources :users

>polen: 
resources意思是加了個套裝的url,所有users相關(guān)的都加進(jìn)去了

b). UI跟上,加個show.html.erb

touch app/views/users/show.html.erb

![屏幕快照 2016-05-29 下午6.34.55.png](http://upload-images.jianshu.io/upload_images/173709-7fc451fe878d6f49.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

c). controller 里也需要加個show方法

vim app/controllers/users_controller.rb

class UsersController < ApplicationController
def new
end

def show
@user = User.find(params[:id])
end
end


###7.1.3 Debugger
加個debug

def show
@user = User.find(params[:id])
debugger
end

###7.1.4 A Gravatar image and a sidebar

a). 修改show.html.erb:

vim app/views/users/show.html.erb

<% provide(:title, @user.name) %>
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<h1>
<%= gravatar_for @user %>
<%= @user.name %>
</h1>
</section>
</aside>
</div>

b). 在users_helper.rb增加  
def gravatar_for(user)方法

vim app/helpers/users_helper.rb

module UsersHelper

Returns the Gravatar for the given user.

def gravatar_for(user)
gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}"
image_tag(gravatar_url, alt: user.name, class: "gravatar")
end
end

c). 剛才增加了側(cè)邊位置,以及頭像,所以我們要修改布局custom.css.scss

vim app/assets/stylesheets/custom.css.scss

...
...
/* sidebar */

aside {
section.user_info {
margin-top: 20px;
}
section {
padding: 10px 0;
margin-top: 20px;
&:first-child {
border: 0;
padding-top: 0;
}
span {
display: block;
margin-bottom: 3px;
line-height: 1;
}
h1 {
font-size: 1.4em;
text-align: left;
letter-spacing: -1px;
margin-bottom: 3px;
margin-top: 0px;
}
}
}

.gravatar {
float: left;
margin-right: 10px;
}

.gravatar_edit {
margin-top: 15px;
}


##7.2 Signup form
我們再次回到注冊,完成注冊的表單頁面
![屏幕快照 2016-05-29 下午6.48.51.png](http://upload-images.jianshu.io/upload_images/173709-5e540c4a3bd25c61.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

>polen:
補充數(shù)據(jù)庫重置的方法:

rake db:migrate:reset

此方法慎用,自己開發(fā)玩玩可以,線上千萬不要亂來...

###7.2.1 Using form_for

a). controller 中完善我們的new方法:

vim app/controllers/users_controller.rb

class UsersController < ApplicationController

def show
@user = User.find(params[:id])
debugger
end

def new
@user = User.new
end
end

b). 界面畫起來new.html.erb:

vim app/views/users/new.html.erb

<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>

<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(@user) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>

  <%= f.label :email %>
  <%= f.email_field :email %>

  <%= f.label :password %>
  <%= f.password_field :password %>

  <%= f.label :password_confirmation, "Confirmation" %>
  <%= f.password_field :password_confirmation %>

  <%= f.submit "Create my account", class: "btn btn-primary" %>
<% end %>

</div>
</div>


c). 布局也是要調(diào)一調(diào)的啊,打開custom.css.scss:

vim app/assets/stylesheets/custom.css.scss

...
...
/* forms */

input, textarea, select, .uneditable-input {
border: 1px solid #bbb;
width: 100%;
margin-bottom: 15px;
@include box_sizing;
}

input {
height: auto !important;
}


###7.2.2 Signup form HTML
其實代碼已經(jīng)完成了,只是這里來對比一下,以為大家可能已經(jīng)習(xí)慣了html語法,當(dāng)然這里也是支持直接用html寫的,但是還是要慢慢習(xí)慣過來ruby的寫法:
> 不然你學(xué)他干嘛??

用ruby寫成的表單的基本框架是這樣的:

<%= form_for(@user) do |f| %>
...
...
<% end %>

對比下html寫法和ruby寫法:

//html:
<label for="user_password">Password</label>
<input id="user_password" name="user[password]" type="password" />

//ruby:
<%= f.label :password %>
<%= f.password_field :password %>


##7.3 Unsuccessful signups
###7.3.1 A working form
下面來實現(xiàn)注冊失敗的操作:

vim app/controllers/users_controller.rb

class UsersController < ApplicationController

def show
@user = User.find(params[:id])
end

def new
@user = User.new
end

def create
@user = User.new(params[:user]) # Not the final implementation!
if @user.save
# Handle a successful save.
else
render 'new'
end
end
end

###7.3.2 Strong parameters
這個講了關(guān)于多參數(shù)的問題,rails早起版本有個attr_accessible用于處理多個參數(shù)的問題;從rails4.0 開始,有個稱之為strong parameters的方法:

params.require(:user).permit(:name, :email, :password, :password_confirmation)

這里user是必須要的參數(shù),其他屬于可選參數(shù).

###7.3.3 Signup error messages
注冊時候的錯誤信息處理:

a). 首先新建個/shared/_error_messages.html.erb:

mkdir app/views/shared
touch app/views/shared/_error_messages.html.erb

b). 修改_error_messages.html.erb,展示具體錯誤信息

vim app/views/shared/_error_messages.html.erb

<% if @user.errors.any? %>
<div id="error_explanation">
<div class="alert alert-danger">
The form contains <%= pluralize(@user.errors.count, "error") %>.
</div>
<ul>
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>

c). 布局也是要設(shè)置一下的:

vim app/assets/stylesheets/custom.css.scss

...
...

error_explanation {

color: red;
ul {
color: red;
margin: 0 0 30px 0;
}
}

.field_with_errors {
@extend .has-error;
.form-control {
color: $state-danger-text;
}
}

d). 在new.html中加入` <%= render 'shared/error_messages' %>`調(diào)用:

vim app/views/users/new.html.erb

<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>

<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(@user) do |f| %>
<%= render 'shared/error_messages' %>

  <%= f.label :name %>
  <%= f.text_field :name, class: 'form-control' %>

  <%= f.label :email %>
  <%= f.email_field :email, class: 'form-control' %>

  <%= f.label :password %>
  <%= f.password_field :password, class: 'form-control' %>

  <%= f.label :password_confirmation, "Confirmation" %>
  <%= f.password_field :password_confirmation, class: 'form-control' %>

  <%= f.submit "Create my account", class: "btn btn-primary" %>
<% end %>

</div>
</div>


##7.4 Successful signups
###7.4.1 The finished signup form
前面說的`params.require(:user)...`這里就用起來了啊,我們需要定義個`user_params`:

private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end

###7.4.2 The flash
加個小動畫:

flash[:success] = "Welcome to the Sample App!"

###以上7.4.1/7.4.2的修改合起來就是:
users_controller.rb和application.html.erb

vim app/controllers/users_controller.rb


class UsersController < ApplicationController

def show
@user = User.find(params[:id])
end

def new
@user = User.new
end

def create
@user = User.new(user_params)
if @user.save
flash[:success] = "Welcome to the Sample App!"
redirect_to @user
else
render 'new'
end
end

private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
end


vim app/views/layouts/application.html.erb


<!DOCTYPE html>
<html>
<head>
<title><%= full_title(yield(:title)) %></title>
<%= stylesheet_link_tag "application", media: "all",
"data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
<%= render 'layouts/shim' %>
</head>
<body>
<%= render 'layouts/header' %>
<div class="container">
<% flash.each do |message_type, message| %>
<div class="alert alert-<%= message_type %>"><%= message %></div>
<% end %>
<%= yield %>
<%= render 'layouts/footer' %>
<%= debug(params) if Rails.env.development? %>
</div>
</body>
</html>


##7.5 Professional-grade deployment
這個是關(guān)于環(huán)境配置和發(fā)布的問題:
###7.5.1 SSL in production

vim config/environments/production.rb

...

Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.

config.force_ssl = true
...


###7.5.2 Production webserver
Gemfile增加production所需的庫

...
group :production do
gem 'pg', '0.17.1'
gem 'rails_12factor', '0.0.2'
gem 'puma', '3.1.0'
end
...

bundle install

>polen:
這個安裝的時候,有些許困難,會遇到一個`Can't find the 'libpq-fe.h header when trying to install pg gem`的問題 ,這個的解決需要

brew install postgresql

參照[stackoverflow.com/questions/6040583](http://stackoverflow.com/questions/6040583/cant-find-the-libpq-fe-h-header-when-trying-to-install-pg-gem)
然后其他的問題,按照錯誤提示安裝所需要的庫即可

<br />
#Github:
***
本文所有的代碼已上傳github:
[polegithub/rails_sample_app_polen](https://github.com/polegithub/rails_sample_app_polen)

#相關(guān):
***
[[Ruby]《Ruby on Rails Tutorial》的搬運工之二](http://www.lxweimin.com/p/25d539845cd7)
[[Ruby]《Ruby on Rails Tutorial》的搬運工之三](http://www.lxweimin.com/p/b036349adc9c)

***
by polen
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容