`

Rails migration 和model 的validations检查冲突时

阅读更多
    今天,干活的时候,遇到这样的一个问题,我们的一个系统有很多版本,有些客户由于种种原因始终使用的是比较早期的版本,姑且说2.03版本吧。

有这样一个migration

class AddFreqAnalyzers < ActiveRecord::Migration
#055_add_freq_analyzers.rb
  def self.up
    add_column :analyzers, :start_freq, :int
    add_column :analyzers, :stop_freq, :int
    startFreq=ConfigParam.get_value(ConfigParam::StartFreq);
    stopFreq=ConfigParam.get_value(ConfigParam::StopFreq);
    puts startFreq
    puts stopFreq
    Analyzer.find(:all).each { |a|
      a.start_freq=startFreq;
      a.stop_freq = stopFreq;
      a.save
    }
    1;
  end

  def self.down
    remove_column :analyzers, :start_freq
    remove_column :analyzers, :stop_freq
  end
end

主要的作用是添加了两个字段和给这个字段赋值。

然后,我们2.06版本的时候给一个model加了一个字段,很正常的我们给这个字段加了validation的保存检查。然后,我们测试升级

class AddWebApiUrl < ActiveRecord::Migration
#085_add_web_api_url.rb
  def self.up
    add_column :analyzers, :api_url, :string,  :null => true
  end

  def self.down
    remove_column :analyzers, :api_url
  end
end

并且在model中增加检查如下:
  validates_format_of     :api_url,
                          :with =>/(^(rubyscript:|http:\/\/|https:\/\/)[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$)|^about:blank$|^$/ix  


然后,一直没有什么问题,包括正常的升级。然而,在一个用户那里他们的系统是2.02的那么系统升级的话,就会把migration从040一直运行。结果报了错,如下:

引用
== 55 AddFreqAnalyzers: migrating =============================================
-- add_column(:analyzers, :start_freq, :int)
   -> 0.0136s
-- add_column(:analyzers, :stop_freq, :int)
   -> 0.0033s
2000000.0
52000000.0
rake aborted!
undefined method `api_url' for #<Analyzer:0x2aaaae4533b8>



错误提示是没有定义api_url方法,实际上055版本的migrate根本没有api_url的字段,只有到085才有,可是代码里已经有了validation的检查,所以,升级过程就出错了。这样的错误还真奇怪了一阵子,最后,怎么解决的呢:

  validates_format_of     :api_url,
                          :with =>/(^(rubyscript:|http:\/\/|https:\/\/)[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$)|^about:blank$|^$/ix,
                          :if => Proc.new { |record| record.respond_to? :api_url}	


这就和
  validates_format_of     :email,
                          :with => /(\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z|^$)/i,
                          :if => Proc.new { |analyzer|analyzer.email.length >0 }   

一样表示只有特定条件才进行检查。


下面是同样的例子:

class CreateVendors < ActiveRecord::Migration
  def self.up
    create_table :vendors do |t|
      t.string :name
      t.string :email
    end    a = Vendor.new(:name => “Fred Flinstone”, :email => “fred@example.com”)
    a.save!
    b = Vendor.new(:name => “Barney Ruble”, :email => “barney@example.com”)
    b.save
  end
  def self.down
    drop_table :vendors
  end
end


model:

validates_presence_of :rating, :on => :create, :message => "can't be blank"



出错提示:

引用
$ rake db:migrate
(in .... )
== 2 CreateVendors: migrating =======================================
rake aborted!
Validation failed: Rating can't be blank(See full trace by running task with --trace)


解决如下:


  validates_presence_of :rating, :on => :create, :message => "can't be blank",
    :if => Proc.new { |record| record.respond_to? :rating }


原文作者的解释关于respond_to?
引用
responds_to asks the Rails model: “Do you have a method named ‘rating’?”. Because Rails magically creates methods for every column an entity has in the database, Rails will either have that method (because it has been defined in the database), or not (because no such column exists). So we only run the validation if we have the column, avoiding the mess with trying to validate data that doesn’t make sense (yet).

0
0
分享到:
评论

相关推荐

    rails-practice-validations:一个 repo 设置,以便您可以练习验证

    Rails 实践:验证练习添加验证和部分。

    张文钿 Rails Best Practices 幻灯片

    rails_best_practices的安装和使用都非常方便,只需简单两条命令就能知道代码中何处需要修改: sudo gem install rails_best_practices --source http://gemcutter.org rails_best_practices . 最新的0.3.3版本中...

    Ruby on Rails Tutorial

    在这个全球互联的世界中,计算机编程和 Web 应用程序开发都在迅猛发展,我很期待能为中国的开发者提供 Ruby on Rails 培训。学习英语这门世界语言是很重要的,但先通过母语学习往往会更有效果。正因为这样,当看到 ...

    Rails之道,完整扫描版

    《Rails之道》按照Rails的各个子系统进行组织编排,分别介绍了Rails的环境、初始过程、配置和日志记录,Rails的分配器、控制器、页面生成和路由,REST、资源和Rails,ActiveRecord的基础、关联、验证和高级技巧,...

    提升Ruby on Rails性能的几个解决方案

    ActiveRecord 的灵活让你再也不用配置繁琐的 Hibernate 即可实现非常易用的持久化,Github 和 Rubygems 上丰富多样的 Rails 插件是 Rails 开发高效率的又一有力保障。Rails 是一个真正彻底的 MVC(Model-View-...

    rails 2.3.2离线安装rails 2.3.2离线安装

    rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails ...

    Learning Rails 5(高清文字pdf版)

    Rather than toss you into the middle of the framework’s Model-View-Controller architecture, as many books do, Learning Rails 5 begins with the foundations of the Web you already know. You’ll learn ...

    rails本地安装包part2

    rails本地安装包 需要你在安装了ruby一键安装包后安装,内有安装命令步骤。 第一部分在: http://download.csdn.net/source/498734

    [Rails] Crafting Rails Applications (英文版)

    [Pragmatic Bookshelf] Crafting Rails Applications Expert Practices for Everyday Rails Development (E-Book) ☆ 图书概要:☆ Rails 3 is a huge step forward. You can now easily extend the framework, ...

    Rails3常用命令行命令

    rails常用命令,例如新建rails项目,新建controller、model 等等

    Ruby on Rails Guides v2 - Ruby on Rails 4.2.5

    Ruby on Rails Guides v2 - Ruby on Rails 4.2.5

    Rails项目源代码

    一个用Ruby on Rails搭建的图片分享的网站项目.完整源代码

    Rails预加载程序Spring-Rails.zip

    Spring是Rails的预加载器。Spring 能够通过保持应用运行在后台,来提升开发模式下的速度。使得不需要在执行test,rake task以及migration时每次都加载。 标签:Spring

    Bootstrap for Rails (2015)

    Bootstrap 3 和 Rails 4(样例用的是Ruby 2.1.1,Rails 4.1.4) Table of Contents Preface 1 Chapter 1: Introducing Web Application Development in Rails 7 Why Bootstrap with Rails? 8 Setting up a Todo ...

    rails敏捷开发的购物车系统

    本资源是参照rails敏捷开发第四版书中的例子,rails的版本是rails3.2.6

    rails, Ruby on Rails.zip

    rails, Ruby on Rails 欢迎使用 RailsRails 是一个web应用程序框架,它包括根据 Model-View-Controller ( MVC ) Pattern 创建数据库备份的web应用程序所需的所有内容。理解 MVC Pattern 是理解 Rai

    Rails.Angular.Postgres.and.Bootstrap.2nd.Edition

    Wrangle Forms and Validations with Angular Chapter 13. Dig Deeper Appendix A1. Full Listing of Customer Detail Page HTML Appendix A2. Creating Customer Address Seed Data Appendix A3. How Webpack ...

    adminlte-rails, AdminLTE Rails gem 将AdminLTE主题与 Rails 资产管道集成.zip

    adminlte-rails, AdminLTE Rails gem 将AdminLTE主题与 Rails 资产管道集成 AdminLTE Rails gem AdminLTE 是后端的高级 Bootstrap 主题。英镑 AdminLTE Rails gem 与 Rails 资产管道集成了英镑AdminLTE主题。安装将...

    rubocop-rails:RuboCop配置,具有与官方Ruby on Rails相同的代码样式检查

    RuboCop滑轨 RuboCop配置具有与官方Ruby on Rails相同的代码样式检查。 :warning: rubocop-rails重命名为 :warning: rubocop-rails被重命名为rubocop-rails_config 。 要迁移到新的gem,请安装rubocop-rails_config...

Global site tag (gtag.js) - Google Analytics