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 ...
随机推荐
- 带你深入理解STL之Stack和Queue
上一篇博客,带你深入理解STL之Deque容器中详细介绍了deque容器的源码实现方式.结合前面介绍的两个容器vector和list,在使用的过程中,我们确实要知道在什么情况下需要选择恰当的容器来满足 ...
- 1.3、Android Studio创建一个Android Library
一个Android Library结构上与Android app模块相同.它可以包含构建一个app需要的所有东西,包括圆满,资源文件和AndroidManifest.xml.然而,并非编译成运行在设备 ...
- Servlet之cookie处理
Cookies 通常设置在 HTTP 头信息中(虽然JavaScript 也可以直接在浏览器上设置一个 Cookie).设置 Cookie 的 Servlet 会发送如下的头信息: HTTP/1.1 ...
- iOS下JS与OC互相调用(三)--MessageHandler
使用WKWebView的时候,如果想要实现JS调用OC方法,除了拦截URL之外,还有一种简单的方式.那就是利用WKWebView的新特性MessageHandler来实现JS调用原生方法. Messa ...
- API创建/更新员工薪水
DECLARE lb_inv_next_sal_date_warning BOOLEAN; lb_proposed_salary_warning BOOLEAN; lb_approved_warnin ...
- 浅谈Android布局
在前面的博客中,小编介绍了Android的极光推送以及如何实现登录的一个小demo,对于xml布局页面,摆控件这块的内容,小编还不是很熟练,今天小编主要简单总结一下在Android中的布局,学习过An ...
- Nginx模块之SessionSticky
0 工作原理 Session Sticky 模块在upstream 返回响应后,向客户的浏览器写入 Cookie ,默认名为route ,保存的内容是一个 md5 码. 之后,模块接收到客户浏览器的请 ...
- Android面试题目总结
1.java 基础题,输入结果是什么? public static void main(String[] args) { String str = new String("abc" ...
- Android的TabHost组件-android的学习之旅(四十)
TabHost简介 虽然,官方建议用Fagment取代TabHost,但是我们还是大概的介绍一下.TabHost是一种非常简单的组件,TabHost可以很方便的在窗口放置多个标签页,每一个标签页相当于 ...
- 【图的DFS】图的DFS非递归算法
在DFS的递归算法中,DFS框架如下: 1访问起点v0 2依次以v0的未访问的连接点为起点,DFS搜索图,直至图中所有与v0路径相通的顶点都被访问. 3若该图为非连通图,则图中一定还存在未被访问的顶点 ...