homeASCIIcasts

16: Virtual Attributes 

(view original Railscast)

Other translations: En It Es Fr

Other formats:

Written by fanhaipeng (fanhaipeng.javaeye.com)

下面是一个用户注册表单,可以输入名、姓和密码。

The new user form.

数据库中也定义了这些字段:

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,我们怎么办呢?我们可以用虚拟属性来实现。首先,我们需要修改视图代码,把名和姓的字段进行合并。

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

<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的虚拟属性来创建这个字段。

/app/models/User.rb

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_namelast_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语句中,然后写入了数据库。

虚拟属性提供了一个强大并且灵活的方法让你来定制你的用户界面。