1

Currently maintaining some old Ruby server and got the following error in Log:

NoMethodError (undefined method `find_all_by_X_ID' for #<Class:0x00000005555555>):
  app/controllers/some_controller.rb:10:in `buggy_function'

When viewed the faulty line in code of the buggy function is looks like this:

Hash[S.find_all_by_X_ID(TaskRun.select(:x_id).uniq.where(y_id: @y.Y_ID).map(&:x_id)).map { |s| [s.S_IDENTIFIER, s.X_ID] }]

To be frank, I'm new to Ruby, and wondering how implementing this find_all_by_X query would be the best, and why it appears as it should be automatic (as it has to do with the model component).

We're working on Ruby version 2.

fphilipe
  • 9,739
  • 1
  • 40
  • 52
  • Why Ruby 2.0? That's woefully obsolete and risky to use. You should be on 2.5 or 2.6. There's some issues with >2.4 if you're using a really old code-base, but for anything new it should be fine. – tadman Dec 22 '19 at 20:56
  • Defiantly Ruby 2 is not the best option, yet to update the system @tadman – Sharon Kriegman Dec 23 '19 at 14:15

1 Answers1

3

It seems that find_all_by was deprecated in Rails 4 ...

Internally Rails implemented methods like find_all_by_x_id using method_missing (the method is actually defined dynamically through metaprogramming) ... but you don't have to worry about that for your use-case.

In terms of your code, if we extract the x_ids list into a variable:

x_ids = TaskRun.select(:x_id).uniq.where(y_id: @y.Y_ID).map(&:x_id)

Then you have this line that you need to rewrite:

S.find_all_by_X_ID(x_ids)

You can rewrite this as:

S.where(x_id: x_ids)

See https://stackoverflow.com/a/23921890/2981429

max pleaner
  • 26,189
  • 9
  • 66
  • 118
  • `where` is the way to go. – tadman Dec 22 '19 at 20:56
  • Thank you @max-pleaner Any idea why this would occur (although not working with Ruby 4, and in Ruby 2 should not be deprecated)? – Sharon Kriegman Dec 23 '19 at 14:14
  • `TaskRun.select(:x_id).uniq.where(y_id: @y.Y_ID).map(&:x_id)` while this line may work; if there are a significant number of x_ids then you can run into query length issues not to mention performance issues. One would be better off with `x_ids = TaskRun.select(:x_id).where(y_id: @y.Y_ID).distinct` this will return an ActiveRecord::Relation and when used later `S.where(x_id: x_ids)` will result in a subquery rather than a very large IN statement – engineersmnky Dec 23 '19 at 14:20
  • Thank you much! @engineersmnky – Sharon Kriegman Dec 23 '19 at 22:00
  • I didn't realize that either @engineersmnky interesting info, thanks – max pleaner Dec 23 '19 at 23:01
  • maxpleaner @engineersmnky Does any of you have an idea why this 'find_all_by_X_ID' would not be found? although working in Ruby 2 where it should be recognized – Sharon Kriegman Dec 24 '19 at 09:15
  • @SharonCohen it has nothing to do with your ruby version, it's the rails version that matters rails 4 deprecated `find_all_by_...` and rails 5 removed them entirely so if you are using rails 5 that method will not exist and should be replaced by `where` [Rails 4 depreciations](https://guides.rubyonrails.org/4_0_release_notes.html#active-record-deprecations) – engineersmnky Dec 24 '19 at 17:41