一个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 这样就可以访问了。

Polymorphic form--多态表单的更多相关文章

  1. 解析:使用easyui的form提交表单,在IE下出现类似附件下载时提示是否保存的现象

    之前开发时遇到的一个问题,使用easyui的form提交表单,在Chrome下时没问题的,但是在IE下出现类似附件下载时提示是否保存的现象. 这里记录一下如何解决的.其实这个现象不光是easyui的f ...

  2. 阻止form空表单提交----JavaScript

    网上看到很不错的阻止form空表单提交 第一种方法 <div class="warp"> <h2>登录到pfan空间</h2> <p> ...

  3. form注册表单圆角 demo

    form注册表单圆角 <BODY> <div class="form"> <ul class="list"> <li& ...

  4. Form提交表单页面不跳转

    1.设计源码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www. ...

  5. 使用easyui的form提交表单,在IE下出现类似附件下载时提示是否保存的现象

    之前开发时遇到的一个问题,使用easyui的form提交表单,在Chrome下时没问题的,但是在IE下出现类似附件下载时提示是否保存的现象. 这里记录一下如何解决的.其实这个现象不光是easyui的f ...

  6. WP Mail SMTP插件解决Contact Form 7表单提交失败问题

    WP Mail SMTP插件解决Contact Form 7表单提交失败问题 WP Mail SMTP是一款非常优秀的解决WordPress主机因为不支持或者是禁用了mail()函数,导致无法实现在线 ...

  7. 关于form与表单提交操作的一切

    原文链接:http://caibaojian.com/form.html 你知道,一个表单里面只要有form元素,如果没有给action加一个默认值,为空白的时候,当你刷新页面时,会弹出一个警告框提示 ...

  8. 【转】document.form.action,表单分向提交

    document.form.action,表单分向提交,javascript提交表单 同一个表单可以根据用户的选择,提交给不同的后台处理程序.即,表单的分向提交.如,在编写论坛程序时,如果我们希望实现 ...

  9. js jquery, jquery-ui 获取form各种表单input的值?

    如何获取? make up (for): 弥补, 补偿, her beaty cannot make up for her stu'pidity. five Basic laws of human s ...

随机推荐

  1. MySQL Route负载均衡与读写分离Docker环境使用

    Docker环境描述 主机名 部署服务 备注 MySQL Route MySQL Route 部署在宿主机上的MySQL Route服务 MySQL Master1 MySQL 5.7.16 Dock ...

  2. 轻松转移github项目步骤

    之前有一些项目是托管在github上的,无奈github速度太慢,而且空间有限,还不能有私有项目.后来发现开源中国的git托管(git.oschina.net)还不错,可以托管1000个项目,而且可以 ...

  3. 基于vs2012的C# winform抽奖小程序的总结

    哈希表的使用 Hashtable hashtable = new Hashtable(); hashtable.ContainsValue(tmp);//判断哈希表中有没有tmp hashtable. ...

  4. 【mysql】Windows环境搭建(适用5.7以上)

    1 下载MySQL 登录 https://dev.mysql.com/downloads/mysql/ 2 配置 下载好了zip文件,解压至任意非中文目录,在根目录下新建my.ini: 输入以下内容( ...

  5. neutron openvswitch + vxlan 通讯

  6. keepalive 原理讲解

    keepalive 我们说到keepalive的时候,需要先明确一点,这个keepalive说的是tcp的还是http的. tcp的keepalive是侧重在保持客户端和服务端的连接,一方会不定期发送 ...

  7. Android代码编译出现的错误

    一.decoupled apps failed  解耦应用程序失败 2.每次编译时候一定先扩充内存 export JACK_SERVER_VM_ARGUMENTS="-Dfile.encod ...

  8. SFML从入门到放弃(3) 视角和碰撞检测

    SFML从入门到放弃(3) 视角和碰撞检测 视角 window.draw();所画出的对象是在世界坐标的绝对位置. 视角可以选定在窗口中显示世界坐标下的的哪一个区域. sf::View init_vi ...

  9. 《Python绝技:运用Python成为顶级黑客》 用Python进行无线网络攻击

    本章大部分代码都是实现了但是缺乏相应的应用环境,想具体测试的可以直接找到对应的环境或者自行修改脚本以适应生活常用的环境. 1.搭建无线网络攻击环境: 用Scapy测试无线网卡的嗅探功能: 插入无线网卡 ...

  10. Bootstrap框架(二)

    day58 巨幕 这是一个轻量.灵活的组件,它能延伸至整个浏览器视口来展示网站上的关键内容. Hello, world! This is a simple hero unit, a simple ju ...