And*_*rtz 10 ruby activerecord development-environment ruby-on-rails sti
我有一组继承自基类的STI子User类.我发现在子类定义内的某些条件下,对子类的查询没有正确使用type条件.
class User < ActiveRecord::Base
# ...
end
class Admin < User
Rails.logger.info "#{name}: #{all.to_sql}"
# ...
end
Run Code Online (Sandbox Code Playgroud)
在开发中加载Rails控制台时,它可以实现我的期望:
Admin: SELECT `users`.* FROM `users` WHERE `users`.`type` IN ('Admin')
Run Code Online (Sandbox Code Playgroud)
但是当击中应用程序(localhost/pow)时,它缺少type条件,我得到了这个:
Admin: SELECT `users`.* FROM `users`
Run Code Online (Sandbox Code Playgroud)
但是当部署到登台服务器时,不是来自应用程序:
Admin: SELECT `users`.* FROM `users` WHERE `users`.`type` IN ('Admin')
Run Code Online (Sandbox Code Playgroud)
当然,这会导致在dev应用程序(但不是从控制台)执行的任何查询都不正确.具体来说,我试图预加载现有数据库值的(小)缓存,以便根据这些数据创建一些有用的方法.没有类型范围,缓存显然是不正确的!
从同一个位置(Admin),我们得到以下令人困惑的矛盾:
[11] pry(Admin)> Admin.finder_needs_type_condition?
=> true
[12] pry(Admin)> Admin.send(:type_condition).to_sql
=> "`users`.`type` IN ('Admin')"
[13] pry(Admin)> Admin.all.to_sql
=> "SELECT `users`.* FROM `users`"
Run Code Online (Sandbox Code Playgroud)
此外,我Q < User在user.rb文件中定义了一个一次性子类.我Q.all.to_sql从定义,定义Admin和视图中记录.按此顺序,我们得到:
From Q: Q: SELECT `users`.* FROM `users` WHERE `users`.`type` IN ('Q')
From Admin: Q: SELECT `users`.* FROM `users`
From View: Q: SELECT `users`.* FROM `users` WHERE `users`.`type` IN ('Q')
Run Code Online (Sandbox Code Playgroud)
什么可能导致Admin在admin.rb 的子类定义的第一行中,任何子类都User无法使用它type_condition?
这导致开发测试失败,因此对我的应用程序有一些影响.究竟是什么导致了这种行为上的差异?任何人都可以想到一个更通用的方法来解决在定义期间仅在开发应用环境中没有在子类上定义STI条件的问题吗?
生产和开发之间的一个区别是应用程序配置中的以下行:
# config/environments/development.rb
config.eager_load = false
Run Code Online (Sandbox Code Playgroud)
与
# config/environments/production.rb
config.eager_load = true
Run Code Online (Sandbox Code Playgroud)
因此,在您的生产环境中,所有类都会在应用程序启动时加载。当设置为 false 时,Rails 将在您第一次加载类时eager_load尝试自动加载您的类。UserAdmin
鉴于此,我假设您有另一个名为 的类或模块User。
仅供参考:ActiveRecord 有一个名为 的方法finder_needs_type_condition?。对于使用 STI 的类,它应该返回 true:
User.finder_needs_type_condition? # should be false
Admin.finder_needs_type_condition? # should be true
Run Code Online (Sandbox Code Playgroud)