一个ruby on rails项目,用户和公司的模型都有地址。
我要创建一个地址表,包含用户和公司表的引用,比直接做下去要好一点,这回让我的数据库设计保持干净。
我的第一印象是,这似乎很难实现,外面所有的讨论及教程都只说明了在model如何设置,但是并没有说明在controller和view如何使用它。我好一顿放狗,也没有得到太多的帮助。
令我感到惊喜是其实在rails设置并使用多态表单是很简单的。
首先依然是先设置model结构:
01 |
class Company< ActiveRecord::Base |
02 |
has_one :address , :as =>; :addressable , :dependent => :destroy |
05 |
class User < ActiveRecord::Base |
06 |
has_one :address , :as => :addressable , :dependent => :destroy |
09 |
class Address < ActiveRecord::Base |
10 |
belongs_to :addressable , :polymorphic => true |
接下来是创建一个Address表来保存地址:
01 |
class CreateAddresses < ActiveRecord::Migration |
03 |
create_table :addresses do |t| |
04 |
t.string :street_address1 , :null => false |
05 |
t.string :street_address2 |
06 |
t.string :city , :null => false |
07 |
t.string :region , :null => false |
08 |
t.string :postcode , :null => false , :limit => 55 |
09 |
t.integer :addressable_id , :null => false |
10 |
t.string :addressable_type , :null => false |
接下来是controller,你只需要修改controller中的"new","create","edit","update"四个action,好让需要的时候可以访问和修改address。
01 |
class CompaniesController < ApplicationController |
04 |
@company = Company. new |
05 |
@company .address = Address. new |
09 |
@company = Company.find(params[ :id ]) |
10 |
@company .address = Address. new unless @company .address != nil |
14 |
@company = Company. new (params[ :company ]) |
15 |
@company .address = Address. new (params[ :address ]) |
19 |
flash[ :notice ] = 'Company was successfully created.' |
22 |
render :action => 'new' |
27 |
@company = Company.find(params[ :id ]) |
29 |
if @company .update_attributes(params[ :company ]) |
30 |
@company .address.update_attributes(params[ :address ]) |
31 |
flash[ :notice ] = 'Company was successfully updated.' |
34 |
render :action => 'edit' |
最后一件事是让address在表单中可以正常工作,我们这里使用field_for方法:
01 |
<% form_for( @company ) do |f| %> |
02 |
<%= f.error_messages %> |
04 |
<%= f.text_field :name %> |
05 |
<%= f.text_field :telephone %> |
06 |
<%= f.text_field :fax %> |
07 |
<%= f.text_field :website_url %> |
10 |
<% fields_for( @company .address) do |address_fields| %> |
11 |
<%= address_fields.hidden_field :addressable_id %> |
12 |
<%= address_fields.hidden_field :addressable_type %> |
14 |
<%= address_fields.text_field :street_address1 %> |
15 |
<%= address_fields.text_field :street_address2 %> |
16 |
<%= address_fields.text_field :city %> |
17 |
<%= address_fields.text_field :region %> |
18 |
<%= address_fields.text_field :postcode %> |
到这就应该可以正常工作了。
有人要问了,如果我去的了address对象,能否反向取得Company或者User对象呢?答案当然是肯定的。
1 |
@address = Address.find(params[ :id ]) |