通过插入从其他列计算的值来轨道质量更新列

时间:2015-07-26 22:26:19

标签: ruby-on-rails postgresql activerecord rails-activerecord

我正在 rails 制作体育排行榜,并尝试使用从其他列计算的值来批量指定列。以下是列的名称::pts:games_played:pts_per_game。前两个已经分配了值,我想通过除以pts by:games_played 将值插入到最后一个值中。所以我去了rails console并尝试了

PlayerLeaderboard.update_all(pts_per_game: pts/games_played)

但是我使用NoMethodError获取此输出

NoMethodError: undefined method `pts' for main:Object
    from (irb):24
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/railties-4.2.0/lib/rails/commands/console.rb:110:in `start'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/railties-4.2.0/lib/rails/commands/console.rb:9:in `start'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/railties-4.2.0/lib/rails/commands/commands_tasks.rb:68:in `console'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/railties-4.2.0/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/railties-4.2.0/lib/rails/commands.rb:17:in `<top (required)>'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:274:in `require'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:274:in `block in require'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:240:in `load_dependency'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:274:in `require'
    from /Users/AYL/Dropbox/workspace/rails/krossover/bin/rails:8:in `<top (required)>'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `load'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `block in load'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:240:in `load_dependency'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `load'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/spring-1.3.6/lib/spring/commands/rails.rb:6:in `call'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/spring-1.3.6/lib/spring/command_wrapper.rb:38:in `call'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/spring-1.3.6/lib/spring/application.rb:183:in `block in serve'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/spring-1.3.6/lib/spring/application.rb:156:in `fork'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/spring-1.3.6/lib/spring/application.rb:156:in `serve'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/spring-1.3.6/lib/spring/application.rb:131:in `block in run'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/spring-1.3.6/lib/spring/application.rb:125:in `loop'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/spring-1.3.6/lib/spring/application.rb:125:in `run'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/gems/2.1.0/gems/spring-1.3.6/lib/spring/application/boot.rb:18:in `<top (required)>'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require'
    from /Users/AYL/.rvm/rubies/ruby-2.1.5/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require'
    from -e:1:in `<main>'irb(main):025:0>

奇怪的是我以前尝试过这种方法并且有效。我刚刚将我的开发数据库从sqlite3切换到postgres和重新种子数据。我似乎不太可能切换db是导致此错误的原因;我一定错过了什么 我也试过了update_column

提前致谢!

2 个答案:

答案 0 :(得分:0)

您可以使用ActiveRecord执行此操作:

PlayerLeaderboard.update_all("pts_per_game = pts/games_played")

答案 1 :(得分:0)

该代码将ptsgames_played视为self上的局部变量或方法。没有这样的方法,因此错误。

你想要列,所以你需要将一些SQL发送到update_all而不是Ruby哈希:

PlayerLeaderboard.update_all('pts_per_game = pts / games_played')

据推测,ptsgames_played是整数列,因此您将在这里遇到截断问题。如果这就是你想要的(即5 / 31)那么就没有什么可担心的了。如果你的pts_per_game是浮点数,那么你需要在混合中投掷一个角色:

PlayerLeaderboard.update_all('pts_per_game = cast(pts as float) / games_played')
PlayerLeaderboard.update_all('pts_per_game = pts::float / games_played')

cast是标准SQL,::语法是特定于PostgreSQL的。

如果你的pts_per_game是一个整数而你想要它是四舍五入的,那么你必须这样说:

PlayerLeaderboard.update_all('pts_per_game = round(cast(pts as float) / games_played)')

如果可能出现负值,则您需要使用ceilfloor代替round来选择负值应该舍入的方向。

如果你在games_played中有零,那么你需要做两次更新并决定当没有任何游戏时pts_per_game应该是什么,零和NULL是合理的选择我想:

PlayerLeaderboard.where(:games_played => 0).update_all(...)
PlayerLeaderboard.where.not(:games_played => 0).update_all(:pts_per_game => 0)

如果你没有任何游戏时pts_per_game为NULL,那么你只需要第一个update_all,因为默认情况下新列是NULL。