rails将类常量重构到数据库对应的表中之一
问题是这样:原来代码.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将类常量重构到数据库对应的表中之一的更多相关文章
- rails将类常量重构到数据库对应的表中之二
在博文之一中我们将Order中的常量重构到了数据库的表中,也做了一些测试,貌似一切都很完美.可是...梦魔还未开始啊!我们少做了一步测试,就是rake test! 结果惨不忍睹,所有测试都是E,全部出 ...
- rails将类常量重构到数据库对应的表中之三
经过博文之一和之二的重构,貌似代码表现的还不错,正常运行和test都通过鸟,但是,感觉告诉我们还是有什么地方不对劲啊!究竟是哪里不对劲呢?我们再来好好看一下. 我们把数据库表中的支付方式集合直接放在实 ...
- rails将类常量重构到数据库对应的表之后记
怎么还有啊!别急,有强迫症的人伤不起!有点小事没说完感觉痒痒的:就是如果表payment_types经常变动该怎么办?每次都要关闭rails网页服务器,然后重启吗?那也太麻烦鸟,最终的解决方案是,在O ...
- 【Java/JDBC】利用ResultSetMetaData从数据库的某表中获取字段信息并存到csv文件
代码下载:https://files.cnblogs.com/files/xiandedanteng/FindNotnullColumns20191102-2.rar 这篇还不够完善,请看更完善的续篇 ...
- iOS-查询数据库-->指定数据表中的当前数据行的总数量
很多时候,我们在查询一个表的时候,不想得到里面的记录内容,只是想简单的得到符合查询条件的记录条数. FMDB中有一个很简单的方法就可以实现,见下面的代码实例: #import "FMdata ...
- Mysql 导出数据库和指定表中的数据
参考地址:http://jingyan.baidu.com/article/b7001fe14240ab0e7282dde9.html [root@youo zw]# mysqldump -u roo ...
- 4.mysql数据库创建,表中创建模具模板脚本,mysql_SQL99标准连接查询(恩,外部连接,全外连接,交叉连接)
mysql数据库创建,表创建模等模板脚本 -- 用root用户登录系统,运行脚本 -- 创建数据库 create database mydb61 character set utf8 ; -- ...
- 用SQL语句将远程SQL Server数据库中表数据导入到本地数据库相应的表中
一.方法一 访问不同电脑上的数据库(远程访问,只好联好网就一样),如果经常访问或数据量较大,建议用链接服务器方法. 1.创建链接服务器 exec sp_addlinkedserver ‘srv_lnk ...
- 修改MySQL数据库中表和表中字段的编码方式的方法
今天向MySQL数据库中的一张表添加含有中文的数据,可是老是出异常,检查程序并没有发现错误,无奈呀,后来重新检查这张表发现表的编码方式为latin1并且原想可以插入中文的字段的编码方式也是latin1 ...
随机推荐
- Maven 介绍、安装使用
简介 Maven是一个强大的构建工具,能够帮我们自动化构建过程,从清理.编译.测试到生成报告,再到打包和部署.只要使用Maven配置好项目,然后执行命令(如mvn clean inst ...
- (NO.00005)iOS实现炸弹人游戏(八):游戏主角(一)
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 最近一直在做另一个RPG游戏,所以本系列迟迟没有更新,上一篇博 ...
- 剑指Offer——全排列递归思路
剑指Offer--全排列递归思路 前言 全排列,full permutation, 可以利用二叉树的遍历实现.二叉树的递归遍历,前中后都简洁的难以置信,但是都有一个共同特点,那就是一个函数里包含两次自 ...
- Android实现系统ROOT, 并能赋予app root权限
1. 获取root权限 --> 修改adb源码 a. 打开 system/core/adb/adb_main.cpp,或者是 system/core/adb/daemon/main.c ...
- UNIX/LINUX程序设计教程(1)-- 获取系统信息
1.主机标识 每一台机器都有一个主机名,主机名由系统管理员指定,在网络中主机名可能是一个网络域名. 函数 gethostname() 和 sethostname() 可以用来获取和设置主机 ...
- Hessian源码分析--HessianServlet
Hessian可以通过Servlet来对外暴露服务,HessianServlet继承于HttpServlet,但这仅仅是一个外壳,使用web服务器来提供对外的Http请求,在web.xml中我们会进行 ...
- 平述factory reset ——从main system到重引导流程
关于Android或linux的引导流程,网上大都是从开机开始讲述的,或者直接跳过bootloader引导阶段,直接从init进程开始说起.这里我从手机正常运行状态开始,到重启状态以及重启之后的状态略 ...
- C语言中的内存分配
对于一个C语言程序而言,内存空间主要由以下几个部分组成: 1)程序代码区:用来存储程序的二进制代码 2)全局区/静态存储区 3)BSS段:用来存储未初始化的全局变量和静态变量. 4)栈区:存储局部变量 ...
- Accounting Flexfield Setup and Usage (Doc ID 124333.1)
APPLIES TO:Oracle General Ledger - Version 11.5.10.2 to 12.1.3 [Release 11.5.10 to 12.1] Information ...
- JAVA之旅(二十一)——泛型的概述以及使用,泛型类,泛型方法,静态泛型方法,泛型接口,泛型限定,通配符
JAVA之旅(二十一)--泛型的概述以及使用,泛型类,泛型方法,静态泛型方法,泛型接口,泛型限定,通配符 不知不觉JAVA之旅已经写到21篇了,不得不感叹当初自己坚持要重学一遍JAVA的信念,中途也算 ...