[Ruby]《Ruby on Rails Tutorial》的搬
背景:
- 最近比较闲,想学习ruby on rails
- 于是找到了https://www.railstutorial.org 上的首推教程《Ruby on Rails Tutorial》
屏幕快照 2016-05-29 上午11.04.20.png
这本书第一章和第二章讲了2个基本demo,实在没啥意思,姑且略过. 从第三章开始到第十二章是从0到1实现了一个类似Twitter的简单社交网站(首页,登录注册,发布推文,关注等功能). 怎么样是不是很棒?
但是这个本书实在讲得过于详细,对于我这种本身没有那么多时间(也没那么多耐心😢)去一点一点看下来的童鞋,看着实在太着急了,于是准备快速整理下(把里面的干货和代码提取出来),方便大家可以分分钟coding出这个demo出来.
当然真正学习还是要看原教程,我这个只是"扒皮版本".
<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学习框架图
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个页面,默认页面啥也没有,我们来填东西:
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 href="http://www.railstutorial.org/">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 href="http://www.railstutorial.org/#help">Rails Tutorial help section</a>.
To get help on this sample app, see the <a href="http://www.railstutorial.org/book"><em>Ruby on Rails Tutorial</em> book</a>.
</p>
3.3 Getting started with testing
执行测试,这本书的教材很重视test,这也是国内开发人员很不重视的地方,想着都留给测试好了,其实开发测试做得好了,代码才会漂亮,质量高. 如果全靠测试,那代码全是东一坨西一坨,全是补丁.
rails 中执行 测试可以在控制台中进行,当然,最简单的步骤是
rake test
下面的我这边执行后的一次结果,可以看到,测试结果提示,"schema.rb doesn't exist yet",让我执行"Run rake db:migrate
to create it"
另,原文中教程叫你如何测试一个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 创建,vim编辑<h1>About</h1>
<p>
The <a href="http://www.railstutorial.org/"><em>Ruby on Rails Tutorial</em></a>
is a
<a href="http://www.railstutorial.org/book">book</a>
and
<a href="http://screencasts.railstutorial.org/">screencast series</a>
to teach web development with
<a href="http://rubyonrails.org/">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的标志是使用<% ... %>
,这里对于初学者有个点注意下:
<% %>: 只是执行<>中的代码
<%= %>:代码还是会执行,同时会在界面显示执行结果
然后我们重新修改下我们的home,help,about界面:
homehelp
about
3.4.3 Layouts and embedded Ruby (Refactor)
然后发现每个页面都有<title></title>然后我们代码重新改一下,统一放到app/views/layouts/application.html.erb里面:
application.html.erb
另外home,help,about也对应改一下,改成类似
<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再细化,针对不同的页面有个通用的处理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,当然也可以直接用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上搜到了这本教程对应的demo代码(https://github.com/railstutorial/sample_app_rails_4)
结果下载下来各种运行fail,逼得我ruby和bundle都重新安装了好久
因为这个代码里rails的版本太低,里面Gemfile对应的很多库都是低版本的,我们前面使用rails new project_name
的时候,默认生成的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都可以,但是二者是不兼容的,命名规则一个是grayLight,一个是gray-light, 如果你运行的时候报错, 你对应修改下就好
言归正传,回到项目继续:
vim Gemfile
![屏幕快照 2016-05-29 下午3.09.30.png](http:https://img.haomeiwen.com/i173709/d7c3cf72011db30e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
bundle install 或者bundle update
创建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,是为了实现页面复用,我们通过`<%= render 'layouts/header' %>`来实现调用
首先对应新建_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:https://img.haomeiwen.com/i173709/b1a1d85ead7b2819.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![屏幕快照 2016-05-29 下午4.12.36.png](http:https://img.haomeiwen.com/i173709/e6da93b31555ae1d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![屏幕快照 2016-05-29 下午4.12.43.png](http:https://img.haomeiwen.com/i173709/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:https://img.haomeiwen.com/i173709/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
...
结果如下:
![header](http:https://img.haomeiwen.com/i173709/0c592c4961826cd2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![footer](http:https://img.haomeiwen.com/i173709/a9c1368eb048d3de.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
##5.4 User signup: A first step
###5.4.1 Users controller
好,前面纠结了半天的界面,布局,其实也就是呈现了个小菜单而已,大概也就是正常工程师5min的工作量吧,而且没啥成就感,接下来,我们终于要开发第一个功能了---注册登录模块.
是不是有点小激动:
ruby的一小步,人类的一大步...
----🍺
首先,Users要玩起来,得需要一个controller:
//generate 可直接写成 g
rails generate controller Users new
###5.4.2 Signup URL
增加路由,不过`generate controller`的时候,会自动增加`get 'users/new'`,我们现在改成我们统一的格式
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 href="http://www.railstutorial.org/">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模式,当然很多语言都是这个模式
我们上一篇新建了controller,这一篇来新建model
##6.1 User model
我们要做这样一个页面:
![sign up](http:https://img.haomeiwen.com/i173709/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的默认命名习惯(注意单复数):
a *Users* controller, a *User* model => *migration*: users.table
**就是model用单数,对应的controller和对应的数据库用复数**
然后,迁移("migrating up")数据库:
rake db:migrate
这样就会创建一个sqlite3数据库,当然实际中大家肯定用的是mysql,关于ruby和mysql连接,可以去看
[MySQL Ruby tutorial](http://zetcode.com/db/mysqlrubytutorial/)
>polen:
数据库回滚用:
rake db:rollback
###6.1.2 The model file
![usermodel](http:https://img.haomeiwen.com/i173709/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
进入控制台,**CRUD数据(增删改查)**,这部分和代码没直接关系,暂且略过
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
增加数据检查的条件,先设个简单的,检查是否存在
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
这里增加了唯一性的检查,
**由唯一性引出索引的问题**,为保证唯一性,对应数据库,需要增加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之类的,那么以下是准备工作:
a). 数据库需要加入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:https://img.haomeiwen.com/i173709/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里面默认会有(只是被注释掉了),我们解注就可以了,不过默认是3.1.7,新版本已经是3.1.11,我这边直接用最新的了.
另外,这个执行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准备妥当之后,
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)
***
注册登录结束,接下来,就是展示user的页面了,我们要做成这个样子:
![show user](http:https://img.haomeiwen.com/i173709/ba69909f68267b74.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
##7.1 Showing users
###7.1.1 Debug and Rails environments
真的的大头开始做起来了,也算是第一个复杂一点的页面了,但是毕竟没有像xcode一样可以时时调试,那就需要我们自己加个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>
对应debug信息的UI位置,也要调一调啦:
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相关的都加进去了
b). UI跟上,加个show.html.erb
touch app/views/users/show.html.erb
![屏幕快照 2016-05-29 下午6.34.55.png](http:https://img.haomeiwen.com/i173709/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). 刚才增加了侧边位置,以及头像,所以我们要修改布局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:https://img.haomeiwen.com/i173709/5e540c4a3bd25c61.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
>polen:
补充数据库重置的方法:
rake db:migrate:reset
此方法慎用,自己开发玩玩可以,线上千万不要乱来...
###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). 布局也是要调一调的啊,打开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
其实代码已经完成了,只是这里来对比一下,以为大家可能已经习惯了html语法,当然这里也是支持直接用html写的,但是还是要慢慢习惯过来ruby的写法:
> 不然你学他干嘛😄
用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
下面来实现注册失败的操作:
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
这个讲了关于多参数的问题,rails早起版本有个attr_accessible用于处理多个参数的问题;从rails4.0 开始,有个称之为strong parameters的方法:
params.require(:user).permit(:name, :email, :password, :password_confirmation)
这里user是必须要的参数,其他属于可选参数.
###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). 布局也是要设置一下的:
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' %>`调用:
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
这个是关于环境配置和发布的问题:
###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)
#相关:
***
[[Ruby]《Ruby on Rails Tutorial》的搬运工之二](http://www.jianshu.com/p/25d539845cd7)
[[Ruby]《Ruby on Rails Tutorial》的搬运工之三](http://www.jianshu.com/p/b036349adc9c)
***
by polen