【Ruby on Rails实战】3.4 登录注册页面
1、在config/routes.rb文件中,添加登录和注册页面的路由
#参考代码,无需粘贴
#root 'home#index'
get 'login' => 'accounts#login'
get 'signup' => 'accounts#signup'
代码解析:
- get 'login' => 'accounts#login'
浏览器中输入http://192.168.33.10:3000/login链接,系统会通过routes文件中的这行代码匹配到accounts_controller.rb中的login方法,在login方法中处理并返回相关数据,显示到app/views/accounts/login.html.erb页面上
2、在项目目录下运行rails g controller accounts login signup
其中accounts是controller的名字,login、signup是controller中实例方法名(即action)
vagrant@vagrant-ubuntu-trusty-64:/vagrant/data_system$ rails g controller accounts login signup
#系统返回结果
Running via Spring preloader in process 2252
create app/controllers/accounts_controller.rb
route get 'accounts/signup'
route get 'accounts/login'
invoke erb
create app/views/accounts
create app/views/accounts/login.html.erb
create app/views/accounts/signup.html.erb
invoke test_unit
create test/controllers/accounts_controller_test.rb
invoke helper
create app/helpers/accounts_helper.rb
invoke test_unit
invoke assets
invoke coffee
create app/assets/javascripts/accounts.coffee
invoke scss
create app/assets/stylesheets/accounts.scss
从系统返回信息中,我们可以看出:
- 产生了accounts_controller.rb、login.html.erb、signup.html.erb、accounts.scss等文件,我们主要操作的就是列出的这几个文件。
- 在routes.rb文件中生成了两条路由,我们将这两条路由删掉即可
get 'accounts/signup’
get 'accounts/login’
3、编辑app/assets/stylesheets/accounts.scss文件,清空文件,将下面内容粘贴进去。
.signup-form-container, .login-form-container{
width: 420px;
margin: 30px auto;
border:1px solid #ddd;
padding: 2em;
.signup-form, .login-form {
width: 100%;
}
.signup-button, .login-button {
padding: 13px;
margin-top: 15px;
width: 100%;
}
}
.remember-me {
* {
width: auto;
}
#remember_me {
margin-left: 0;
}
}
.need-signup {
float: right;
}
4、编辑app/models/account.rb文件,定义一个哈希hash,里面包含用户角色序号与名称之间的关系
#参考代码
#class Account < ApplicationRecord
ROLE = {0 => "普通用户",1 => "管理员",2 => "超级管理员"}
代码解析:
- 为什么用大写的ROLE来命名哈希?
因为用户角色名称和序号的对应关系是不变的,可以看做是常量,常量一般用大写字母命名。 - 为什么在models/account.rb文件中定义哈希?
因为role字段存在于accounts数据表中,这样定义比较规范。之后通过Account::ROLE就可以调用这个哈希,其中Account::ROLE[0]的值为"普通用户"
5、编辑注册界面,清空app/views/account/signup.html.erb文件,将下面内容粘贴进去
<div class="signup-form-container clearfix">
<div class="signup-form">
<%= form_for @account,url:"#" do |f| %>
<dl class="form">
<dt><%= f.label :name, "用户名(不多于5个字)" %></dt>
<dd><%= f.text_field :name %></dd>
</dl>
<dl class="form">
<dt><%= f.label :email %></dt>
<dd><%= f.text_field :email %></dd>
</dl>
<dl class="form">
<dt><%= f.label :password, "密码" %></dt>
<dd><%= f.password_field :password %></dd>
</dl>
<dl class="form">
<dt><%= f.label :password_confirmation, "请再输入一次" %></dt>
<dd><%= f.password_field :password_confirmation %></dd>
</dl>
<dl class="form">
<dt><%= f.label :role, "角色" %></dt>
<dd>
<select name="account[role]" class="form-control" >
<% Account::ROLE.each do |ro| %>
<option value= "<%= ro[0] %>"><%= ro[1] %></option>
<% end %>
</select>
</dd>
</dl>
<p><%= f.submit "注册", :class => "signup-button btn btn-primary" %></p>
<% end %>
</div>
</div>
代码解析:
- <%= form_for @account,url:"#" do |f| %>
form_for是用法我们下面会讲,我们先看form_for后面的@account这个实例变量,@account实例变量需要先在accounts_controller中signup方法中定义才可以在views文件中直接使用。目前没有在signup方法中定义@account实例变量,下一步我们打开浏览器看一下会报啥错误
6、编辑accounts_controller的signup方法
打开注册页面http://192.168.33.10:3000/signup,出现下面错误,错误明确指出在signup.html.erb文件的第三行,form里面不可以包含空或者nil对象。综合页面提示信息,我们可以得出目前@account是空的
解决思路:
@account值应该是由AccountsControlller中的signup方法传递的,目前该方法内没有定义@account实例变量,导致传递的值为空,所以我们应该在signup方法中定义@account实例变量
解决方法:
在accounts_controller的signup方法中,定义@account实例变量
def signup
@account = Account.new
end
保存文件,重启项目,刷新页面,可以看到注册页面显示成功了
注册页面
7、form表单Helper方法介绍--form_for和form_tag
什么是Helper:
在Rails中,Helper指的是可以在Template中(views文件夹下的页面代码)使用的辅助方法,主要用途是可以将Helper方法转化成HTML字串,例如我们已经用过的link_to方法,就可以转成a标签。Rails还内建了许多Helper方法,可以让我们建构HTML更加简易。
需要注意的是,Helper方法本质作用就是生成html代码,Helper方法只是为了让我们写代码更加简单方便,可以与html代码混着写。
(1)form_for格式介绍
<%= form_for @account, url:{action: "create_account"} do |f| %>
<%= f.label :email, "邮箱" %>
<%= f.text_field :email %>
<%= f.label :password, "密码" %>
<%= f.password_field :password %>
<%= f.submit "注册", :class => "signup-button btn btn-primary" %>
<% end %>
form_for后面的@account代表处理的实例对象,其中f.label、f.text_field、f.password_field、f.submit都是Helper方法,分别会被翻译成<label></label>、<input type="text">、<input type="password">、<input type="submit">
上面的form_for代码相当于下面的html代码:
<form class="new_account" id="new_account" action="/create_account" accept-charset="UTF-8" method="post">
<label for="account_email">邮箱</label>
<input type="text" name="account[email]" id="account_email">
<label for="account_password">密码</label>
<input type="password" name="account[password]" id="account_password">
<input type="submit" name="commit" value="注册" class="signup-button btn btn-primary" data-disable-with="注册">
</form>
需要特别注意:
<%= f.text_field :email %>相当于
<input type="text" name="account[email]" id="account_email">
input标签中的name元素为"account[email]"。根据name元素的值,我们在AccountsController中想要取浏览器页面上填写的邮箱密码数据,可以如下操作:
email = params[:account][:email]
password = params[:account][:password]
params参数介绍:
在input标签中的有两个元素我们需要了解,分别是name和value,因为在controller中,浏览器提交的参数会通过哈希的方式存在params中,其中name为哈希中的键、value为哈希中的值。
- <input type="text" name="account" id="account_email" value="猫宁">
浏览器提交的参数的形式就是param = {:account => "猫宁"},我们在controller中通过params[:account]取到的值就是"猫宁"- <input type="text" name="account[name]" id="account_email" value="狗宁">
浏览器提交的参数的形式就是param = {:account => {:name => "狗宁"}},我们在controller中通过params[:account][:name]取到的值就是"狗宁"
(2)form_tag格式介绍
<%= form_tag "/create_login_session" do %>
<%= label_tag "邮箱" %>
<%= text_field_tag :email, params[:email] %>
<%= label_tag "密码" %>
<%= password_field_tag :password, params[:password] %>
<%= check_box_tag :remember_me, 1, params[:remember_me] %>
<%= submit_tag "登录", :class => "login-button btn btn-primary" %>
<% end %>
其中label_tag、text_field_tag、password_field_tag、check_box_tag、submit_tag也都是Helper方法,分别会被翻译成<label></label>、<input type="text">、<input type="password">、<input type="checkbox">、<input type="submit">
上面的form_tag代码相当于下面的html代码:
<form action="/create_login_session" accept-charset="UTF-8" method="post">
<label for="__">邮箱</label>
<input type="text" name="email" id="email">
<label for="__">密码</label>
<input type="password" name="password" id="password">
<input type="checkbox" name="remember_me" id="remember_me" value="1">
<input type="submit" name="commit" value="登录" class="login-button btn btn-primary" data-disable-with="登录">
</form>
「邮箱」input标签中生成的name元素为"email",在AccountsController中取页面上填写好的邮箱,可以如下操作:
email = params[:email]
(3)那我们什么情况用form_for,什么情况用form_tag呢?
-
新建数据(通常与form_for配合使用):
@account = Account.new(params[:account])
相当于代码
@account = Account.new(email:params[:account][:email],password:params[:account][:password]) -
查找、修改数据(通常与form_tag配合使用):
@account = Account.where(email:params[:email])
8、编辑登录界面,清空app/views/account/login.html.erb文件,将下面内容粘贴进去
<div class="login-form-container clearfix">
<div class="login-form">
<%= form_tag "#" do %>
<dl class="form">
<dt>
<%= label_tag "邮箱" %>
</dt>
<dd>
<%= text_field_tag :email, params[:email] %>
</dd>
</dl>
<dl class="form">
<dt>
<%= label_tag "密码" %>
</dt>
<dd>
<%= password_field_tag :password, params[:password] %>
</dd>
</dl>
<p><%= submit_tag "登录", :class => "login-button btn btn-primary" %></p>
<p></p>
<div class="need-signup">
<%= link_to "没有账号?注册一个吧!", "/signup" %>
</div>
<% end %>
</div>
</div>
打开登录页面http://192.168.33.10:3000/login,可以正常显示了
登录页面9、修改app/views/layouts/application.html.erb文件,将网站主页面上的登陆注册按钮,指向登陆注册页面
<!--原代码:-->
<li><%= link_to "登录","#" %></li>
<li><%= link_to "注册","#" %></li>
<!--改为:-->
<li><%= link_to "登录","/login" %></li>
<li><%= link_to "注册","/signup" %></li>
现在我们点击主页面上的登录注册按钮,会进入相应的页面了。