下面是一个用户注册表单,可以输入名、姓和密码。
数据库中也定义了这些字段:
create_table "users", :force => true do |t|
t.string "first_name"
t.string "last_name"
t.string "password"
end
但是,如果我们想改变用户界面,在上面只显示全名full_name
字段,而不是名first_name
和姓last_name
,我们怎么办呢?我们可以用虚拟属性来实现。首先,我们需要修改视图代码,把名和姓的字段进行合并。
<h1>Register</h1>
<% form_for @user do |form| %>
<ol class="formList">
<li>
<%= form.label :full_name, 'Full Name' %>
<%= form.text_field :full_name %>
</li>
<li>
<%= form.label :password, 'Password' %>
<%= form.password_field :password %>
</li>
</ol>
<% end %>
直接定义了full_name字段的new.html.erb.
现在,如果我们提交表单,就会查找User
模型中现在并不存在的full_name
字段。我们可以通过定义一个叫full_name
的虚拟属性来创建这个字段。
class User < ActiveRecord::Base
# Getter
def full_name
[first_name, last_name].join(' ')
end
# Setter
def full_name=(name)
split = name.split(' ', 2)
self.first_name = split.first
self.last_name = split.last
end
end
User模型中定义的读取和赋值方法.
读方法读取first_name
和last_name
的值,用一个空格把他们组合起来,然后返回给用户。赋值方法则把传入的值在第一个空格处分割,把分割后的第一部分赋值给first_name
,第二部分赋值给last_name
。
使用虚拟属性意味着用户界面上的字段不一定要对应到数据库表中的每一个字段。当用Rails连接到遗留系统的数据库、并且不能修改表中的字段时,这将非常有用。
看看实际效果
让我们试试我们新的表单,看看是不是好用。我们输入全名“Jonh Smith”和密码“secret”。
Processing UsersController#create (for 127.0.0.1 at 2009-01-10 21:55:44) [POST]
Parameters: {"user"=>{"password"=>"secret", "full_name"=>" John Smith"}, "commit"=>"Add user", "authenticity_token"=>"6990f4ad21cb4f9c812a6f10ceef51faa4f46ce7"}
User Create (0.4ms) INSERT INTO "users" ("first_name", "last_name", "password") VALUES('John', 'Smith', 'secret')
开发日志中显示新用户被写入到数据库中。
从上面的开发日志中我们看到,全名被传入create
动作(然后被传入User
模型),不过名和姓是被分隔后才被传入到INSERT
语句中,然后写入了数据库。
虚拟属性提供了一个强大并且灵活的方法让你来定制你的用户界面。