Rails Rails 遇到个 bug:scope 和 class method 在 Execute environment 阶段受到不同的待遇

sinalpha · 2016年03月28日 · 最后由 sinalpha 回复于 2016年03月29日 · 2161 次阅读

下面代码find_by部分会报SQLite3::SQLException: no such table的错误

class SomeModel < ActiveRecord::Base
  ALL_NAME = %w{ level_0 level_1 level_2 level_3}
  enum name: ALL_NAME

  class << self
    def lol_scope
      r = {}
      ALL_NAME[0..3].map do |name|
        selected = find_by(name: names[name]).first
        r[name] = selected.blank? ? 0 : selected.rate
      end
      r
    end
  end

然后不管是bundle exec rake db:rest db:schema:load db:migrate都会报错如下:

  lol git:(dota)  be rake db:migrate --trace
/Users/lol/env/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.1.0/lib/active_support/values/time_zone.rb:285: warning: circular argument reference - now.
** Invoke db:migrate (first_time)
** Invoke environment (first_time)
** Execute environment
rake aborted!
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such table: ......

但是如果写成scope的方式:

scope :lol_scope, { find_by name: 2}

运行 rails s 是可以起来的,只是访问的时候会提示pre migrate,然后在终端敲下 rake db:migrate就 OK。

环境

rails 4.1.0 ruby 2.2.2 ,activerecord 上面那个rake db:migrate --trace有写。

找到原因了

是在另外一个 model 中直接调用了这个 scope some_var = SomeModel.lol_scope,如果当时把这个调用封装在一个方法里面就不会有这个 bug 了。


.....

private
def some_var
    SomeModel.lol_scope
end

no such table 后面的补全看看。

2 楼 已删除
3 楼 已删除

还是没明白你这为啥会这样

#4 楼 @qinfanpeng 简单说是蛋和鸡的问题。

我在另外一个 class 里面用一个常量调用了这个 scope。A_CONSTANT_VAR = SomeModel.lol_scop。然后 Rails 初始化的时候,会预加载所有的常量。然后,SomeModel这个 model 的 migration 只在自己的数据库有,小伙伴的数据库里面是没有这个表的。

所有就造成了,只有当时写这个 model 的人才能正常使用。

其他人,即使代码是一模一样的,也是没有办法启动 rails 的。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号