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都可以删掉鸟.至此重构告一段落! :

相关文章
|
6月前
|
弹性计算 Linux 网络安全
数据库出现了网络连通性类相关问题的抓包方法
如下列举了数据库遇到连通性问题时,在三种不同的操作系统上抓包的方式。
94 2
|
7月前
|
存储 关系型数据库 数据库
Django创建应用、ORM的进阶使用及模型类数据库迁移1
Django创建应用、ORM的进阶使用及模型类数据库迁移1
74 0
|
7月前
|
存储 数据可视化 数据库
Django创建应用、ORM的进阶使用及模型类数据库迁移3
Django创建应用、ORM的进阶使用及模型类数据库迁移3
52 0
|
7月前
|
关系型数据库 MySQL 数据库
Django创建应用、ORM的进阶使用及模型类数据库迁移2
Django创建应用、ORM的进阶使用及模型类数据库迁移2
47 0
|
1月前
|
JavaScript Java 关系型数据库
基于vue的MOBA类游戏攻略分享平台23(程序+数据库+论文)可帮忙远程调试
基于vue的MOBA类游戏攻略分享平台23(程序+数据库+论文)可帮忙远程调试
|
3月前
|
关系型数据库 MySQL 数据库
认识MySQL数据库中的常量
认识MySQL数据库中的常量。
39 0
|
4月前
|
SQL 数据库连接 数据库
VB.NET 中使用SqlConnection类连接到Microsoft SQL Server数据库的详细步骤
VB.NET 中使用SqlConnection类连接到Microsoft SQL Server数据库的详细步骤
97 0
|
10月前
|
SQL 数据库 数据库管理
Qt操作Sqlite类封装,及命令行导入csv文件到Sqlite数据库
Qt操作Sqlite类封装,及命令行导入csv文件到Sqlite数据库
|
7月前
|
SQL 关系型数据库 数据库
Rails 数据库最佳实践
Rails 数据库最佳实践
|
8月前
|
XML Java 编译器
JdbcTemplate--spring 提供的一个操作数据库(表)功能强大的类
JdbcTemplate--spring 提供的一个操作数据库(表)功能强大的类
74 0

热门文章

最新文章