Polymorphic form--多態表單

這是一個在rails中的多態關聯的一個簡明教程。web

最近的一個ruby on rails項目,用戶和公司的模型都有地址。數據庫

我要建立一個地址表,包含用戶和公司表的引用,比直接作下去要好一點,這回讓個人數據庫設計保持乾淨。ruby

個人第一印象是,這彷佛很難實現,外面全部的討論及教程都只說明瞭在model如何設置,可是並無說明在controller和view如何使用它。我好一頓放狗,也沒有獲得太多的幫助。less

令我感到驚喜是其實在rails設置並使用多態表單是很簡單的。數據庫設計

首先依然是先設置model結構:post

class Company< ActiveRecord::Base
  has_one :address, :as =>; :addressable, :dependent => :destroy
end

class User < ActiveRecord::Base
  has_one :address, :as => :addressable, :dependent => :destroy
end

class Address < ActiveRecord::Base
  belongs_to :addressable, :polymorphic => true
end

接下來是建立一個Address表來保存地址:url

class CreateAddresses < ActiveRecord::Migration
  def self.up
    create_table :addresses do |t|
      t.string :street_address1, :null => false
      t.string :street_address2
      t.string :city, :null => false
      t.string :region, :null => false
      t.string :postcode, :null => false, :limit => 55
      t.integer :addressable_id, :null => false
      t.string :addressable_type, :null => false

      t.timestamps
    end
  end

  def self.down
    drop_table :addresses
  end
end

接下來是controller,你只須要修改controller中的"new","create","edit","update"四個action,好讓須要的時候能夠訪問和修改address。spa

class CompaniesController < ApplicationController

  def new
    @company = Company.new
    @company.address = Address.new
  end

  def edit
    @company = Company.find(params[:id])
	@company.address = Address.new unless @company.address != nil
  end

  def create
    @company = Company.new(params[:company])
	@company.address = Address.new(params[:address])

    if @company.save
	  @company.address.save
      flash[:notice] = 'Company was successfully created.'
      redirect_to(@company)
    else
      render :action => 'new'
    end
  end

  def update
    @company = Company.find(params[:id])

    if @company.update_attributes(params[:company])
	  @company.address.update_attributes(params[:address])
      flash[:notice] = 'Company was successfully updated.'
      redirect_to(@company)
    else
      render :action => 'edit'
    end
  end
end

最後一件事是讓address在表單中能夠正常工做,咱們這裏使用field_for方法:設計

<% form_for(@company) do |f| %>
	<%= f.error_messages %>
<dl>
		<%= f.text_field :name %>
		<%= f.text_field :telephone %>
		<%= f.text_field :fax %>
		<%= f.text_field :website_url %>
	</dl>

	<% fields_for(@company.address) do |address_fields| %>
		<%= address_fields.hidden_field :addressable_id %>
		<%= address_fields.hidden_field :addressable_type %>
<dl>
			<%= address_fields.text_field :street_address1 %>
			<%= address_fields.text_field :street_address2 %>
			<%= address_fields.text_field :city %>
			<%= address_fields.text_field :region %>
			<%= address_fields.text_field :postcode %>
		</dl>

	<% end %>
<% end %>

到這就應該能夠正常工做了。 code

有人要問了,若是我去的了address對象,可否反向取得Company或者User對象呢?答案固然是確定的。

@address = Address.find(params[:id])
@address.addressable
這樣就能夠訪問了。
相關文章
相關標籤/搜索