zoukankan      html  css  js  c++  java
  • Polymorphic form--多态表单

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

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

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

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

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

    01 class Company< ActiveRecord::Base
    02   has_one :address, :as =>; :addressable, :dependent => :destroy
    03 end
    04  
    05 class User < ActiveRecord::Base
    06   has_one :address, :as => :addressable, :dependent => :destroy
    07 end
    08  
    09 class Address < ActiveRecord::Base
    10   belongs_to :addressable, :polymorphic => true
    11 end

    接下来是创建一个Address表来保存地址:

    01 class CreateAddresses < ActiveRecord::Migration
    02   def self.up
    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
    11  
    12       t.timestamps
    13     end
    14   end
    15  
    16   def self.down
    17     drop_table :addresses
    18   end
    19 end

    接下来是controller,你只需要修改controller中的"new","create","edit","update"四个action,好让需要的时候可以访问和修改address。

    01 class CompaniesController < ApplicationController
    02  
    03   def new
    04     @company = Company.new
    05     @company.address = Address.new
    06   end
    07  
    08   def edit
    09     @company = Company.find(params[:id])
    10     @company.address = Address.new unless @company.address != nil
    11   end
    12  
    13   def create
    14     @company = Company.new(params[:company])
    15     @company.address = Address.new(params[:address])
    16  
    17     if @company.save
    18       @company.address.save
    19       flash[:notice] = 'Company was successfully created.'
    20       redirect_to(@company)
    21     else
    22       render :action => 'new'
    23     end
    24   end
    25  
    26   def update
    27     @company = Company.find(params[:id])
    28  
    29     if @company.update_attributes(params[:company])
    30       @company.address.update_attributes(params[:address])
    31       flash[:notice] = 'Company was successfully updated.'
    32       redirect_to(@company)
    33     else
    34       render :action => 'edit'
    35     end
    36   end
    37 end

    最后一件事是让address在表单中可以正常工作,我们这里使用field_for方法:

    01 <% form_for(@company) do |f| %>
    02     <%= f.error_messages %>
    03 <dl>
    04         <%= f.text_field :name %>
    05         <%= f.text_field :telephone %>
    06         <%= f.text_field :fax %>
    07         <%= f.text_field :website_url %>
    08     </dl>
    09  
    10     <% fields_for(@company.address) do |address_fields| %>
    11         <%= address_fields.hidden_field :addressable_id %>
    12         <%= address_fields.hidden_field :addressable_type %>
    13 <dl>
    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 %>
    19         </dl>
    20  
    21     <% end %>
    22 <% end %>

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

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

    1 @address = Address.find(params[:id])
    2 @address.addressable
    3 这样就可以访问了。
  • 相关阅读:
    VB.NET中lambda的写法
    C#中DllImport用法和路径问题
    SQL*Loader 和 Data Pump
    批处理-函数定义及应用01
    Office 2010 KMS激活原理和案例分享
    Hyper-V架构与VMware ESXi的差异
    Tomcat免安装配置2
    Tomcat免安装配置
    域名解析过程
    内部类访问的局部变量必须加final
  • 原文地址:https://www.cnblogs.com/wangyuyu/p/3312332.html
Copyright © 2011-2022 走看看