Polymorphic form--多态表单

这是一个在rails中的多态关联的一个简明教程。

最近的一个ruby on rails项目,用户和公司的模型都有地址。

我要创建一个地址表,包含用户和公司表的引用,比直接做下去要好一点,这回让我的数据库设计保持干净。

我的第一印象是,这似乎很难实现,外面所有的讨论及教程都只说明了在model如何设置,但是并没有说明在controller和view如何使用它。我好一顿放狗,也没有得到太多的帮助。

令我感到惊喜是其实在rails设置并使用多态表单是很简单的。

首先依然是先设置model结构:

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表来保存地址:

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。

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 %>

到这就应该可以正常工作了。

有人要问了,如果我去的了address对象,能否反向取得Company或者User对象呢?答案当然是肯定的。

@address = Address.find(params[:id])
@address.addressable
这样就可以访问了。


你可能感兴趣的:(form,ror,Polymorphic)