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
这样就能够访问了。
相关文章
相关标签/搜索