一个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 ])
|