问题是这样:原来代码.html.erb页面中有一个select元素,其每个item对应的是model中的类常量:

<%= f.select :pay_type,Order::PAYMENT_TYPES,prompt:'Select a payment method' %>

类中的常量定义如下:

class Order < ActiveRecord::Base
  PAYMENT_TYPES = ["Check","Credit card","Purchase order"]
end

现在想把PAYMENT_TYPES重构至数据库中的表里去,于是有了尝试性的第一步,首先创建一个model如下:

rails g model payment_types type:string

rake db:migrate

第二步是写一个脚本将常量导入至表中:

PaymentType.transaction do
  Order::PAYMENT_TYPES.each do |type|
    PaymentType.create(type:type)
  end
end

但是运行rails runner script/load_payment_types.rb时出错了,提示如下:

/var/lib/gems/2.1.0/gems/activerecord-4.2.0/lib/active_record/inheritance.rb:215:in `subclass_from_attributes': Invalid single-table inheritance type: Check is not a subclass of PaymentType (ActiveRecord::SubclassNotFound)

确认没有语法上的错误后推测,可能type名称和框架中某个方法或属性冲突了,这样只有更改该名称了:

rails g migration rename_type_to_payment_types

在migrate目录中生成的.rb文件中修改type的名称:

class RenameTypeToPaymentTypes < ActiveRecord::Migration
  def change
    rename_column :payment_types,:type,:pay_type
  end
end

然后rake db:migrate,接下来再修改load_payment_types.rb中的代码以顺应更改:

PaymentType.transaction do
  PaymentType.delete_all
  Order::PAYMENT_TYPES.each do |type|
    PaymentType.create(pay_type:type)
  end
end

接着再执行rails runner script/load_payment_types.rb,这时没有问题了:) ,第三步是修改控制器中的new方法,添加以下一行:

    @payment_types = PaymentType.all.map {|type|type.pay_type}

第四步是修改.html.erb中的代码如下:

<%= f.select :pay_type,@payment_types,prompt:'Select a payment method' %>

第五步别忘了修改model的验证代码:

class Order < ActiveRecord::Base
  validates :name,:address,:email,:pay_type,presence:true
  #validates :pay_type,inclusion:PAYMENT_TYPES
  validates :pay_type,inclusion:PaymentType.all.map {|type|type.pay_type}
end

运行一下貌似没有问题.可是等等!如果new.html.erb全部留空提交订单,则会报错,提示nil对象没有empty?方法!稍微想一下可知,提交订单会转至Order#create方法,在order.save时会调用Order类的验证方法,因为前面留空,所以验证失败,save方法会出错;这时会重新render到new.html.erb中去,但这时@payment_types不存在其值当然为空喽!于是乎在create方法中也加上new方法中的那一句吧!

还有神马呢?代码中有这么多@payment_types的重复,违反了DRY原则哦!我们可以考虑将其放到Order控制器的类变量中去,不过这还要考虑如果数据库中的pay_types有修改怎么及时反应到类变量中去的问题.我们简单起见,payment_types表中的pay_type很少修改,如果修改可以重启rails服务器来应用变更;于是可以进一步重构:

首先在Order控制器中加入类变量以及类变量属性:

class OrdersController < ApplicationController
  @@payment_types = PaymentType.all.map {|type|type.pay_type}

  def self.payment_types
    @@payment_types
  end
end

然后在new.html.erb和Order model中做如下修改

#in new.html.erb
<%= f.select :pay_type,OrdersController.payment_types,prompt:'Select a payment method' %>

#in Order.rb
validates :pay_type,inclusion:OrdersController.payment_types

这时原先new和create中的变量@payment_types都可以删掉鸟.至此重构告一段落! :

rails将类常量重构到数据库对应的表中之一的更多相关文章

  1. rails将类常量重构到数据库对应的表中之二

    在博文之一中我们将Order中的常量重构到了数据库的表中,也做了一些测试,貌似一切都很完美.可是...梦魔还未开始啊!我们少做了一步测试,就是rake test! 结果惨不忍睹,所有测试都是E,全部出 ...

  2. rails将类常量重构到数据库对应的表中之三

    经过博文之一和之二的重构,貌似代码表现的还不错,正常运行和test都通过鸟,但是,感觉告诉我们还是有什么地方不对劲啊!究竟是哪里不对劲呢?我们再来好好看一下. 我们把数据库表中的支付方式集合直接放在实 ...

  3. rails将类常量重构到数据库对应的表之后记

    怎么还有啊!别急,有强迫症的人伤不起!有点小事没说完感觉痒痒的:就是如果表payment_types经常变动该怎么办?每次都要关闭rails网页服务器,然后重启吗?那也太麻烦鸟,最终的解决方案是,在O ...

  4. 【Java/JDBC】利用ResultSetMetaData从数据库的某表中获取字段信息并存到csv文件

    代码下载:https://files.cnblogs.com/files/xiandedanteng/FindNotnullColumns20191102-2.rar 这篇还不够完善,请看更完善的续篇 ...

  5. iOS-查询数据库-->指定数据表中的当前数据行的总数量

    很多时候,我们在查询一个表的时候,不想得到里面的记录内容,只是想简单的得到符合查询条件的记录条数. FMDB中有一个很简单的方法就可以实现,见下面的代码实例: #import "FMdata ...

  6. Mysql 导出数据库和指定表中的数据

    参考地址:http://jingyan.baidu.com/article/b7001fe14240ab0e7282dde9.html [root@youo zw]# mysqldump -u roo ...

  7. 4.mysql数据库创建,表中创建模具模板脚本,mysql_SQL99标准连接查询(恩,外部连接,全外连接,交叉连接)

     mysql数据库创建,表创建模等模板脚本 -- 用root用户登录系统,运行脚本 -- 创建数据库 create database mydb61 character set utf8 ; -- ...

  8. 用SQL语句将远程SQL Server数据库中表数据导入到本地数据库相应的表中

    一.方法一 访问不同电脑上的数据库(远程访问,只好联好网就一样),如果经常访问或数据量较大,建议用链接服务器方法. 1.创建链接服务器 exec sp_addlinkedserver ‘srv_lnk ...

  9. 修改MySQL数据库中表和表中字段的编码方式的方法

    今天向MySQL数据库中的一张表添加含有中文的数据,可是老是出异常,检查程序并没有发现错误,无奈呀,后来重新检查这张表发现表的编码方式为latin1并且原想可以插入中文的字段的编码方式也是latin1 ...

随机推荐

  1. Android View的绘制过程

    首先是view的绘制过程~最主要的分三部分 measure layout draw 看字面意思,计算,布局,画~ android中控件相当于是画在一个无限大的画布上的,那就产生了几个问题 画布无限大, ...

  2. 18 UI美化自定义形状shape

    自定义某个控件的形状 如 圆角 巨型 环形 : 在工程文件的新建 res/drawable/shape文件(以下键一个圆角) <?xml version="1.0" enco ...

  3. H3C数据中心虚拟化解决方案技术白皮书

    缩略语清单: 缩略语 英文全名 中文解释 IDC Internet Data Center 互联网数据中心 VRF Virtual Router Forwarding 虚拟路由器转发 SMP Symm ...

  4. Android软件设置自动检查更新

    如果让我推荐功能强大的第三方集成开发包,我一定会推荐友盟,有着强大的软件统计,分析功能(原谅我,我不是打广告). 这一篇介绍友盟的自动更新功能,但是首先你得拥有友盟. 友盟的集成步骤 1.1 导入SD ...

  5. 1gitolite构建git服务器

     软件环境:在有网络条件下(主要是为了安装软件),UbuntuKylin 14.04 1 安装openssh-serveropenssh-client,如果用的是VPS之类的一般都默认安装好了,不 ...

  6. javascript之cookie对象

    属性 name          唯一必须设置的属性,表示cookie的名称 expires       指定cookie的存活周期,如不设置,浏览器关闭自动失效 path           决定c ...

  7. 《java入门第一季》之TreeSet存储自定义对象并保证排序和唯一

    上一篇用一个简单的例子,介绍了treeset集合存储的内部过程,这里再完善其存储自定义对象保证唯一. 需求:A:  * 自然排序,按照年龄从小到大排序  *         B:  * 成员变量值都相 ...

  8. 如何在Cocos2D游戏中实现A*寻路算法(一)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...

  9. 使用HTML5拍照

    原文连接地址: Camera and Video Control with HTML5 演示地址: HTML5拍照演示 翻译日期: 2013年8月6日 首先,我们看看HTML代码结构,当然,这部分的D ...

  10. ROS_Kinetic_01 在ubuntu 16.04安装ROS Kinetic 2017.01更新

    ROS_Kinetic系列学习(一),在ubuntu 16.04安装ROS Kinetic. Celebrating 9 Years of ROS! ubuntu16.04已经发布半年多了,ROS的K ...