Skip to content

Instantly share code, notes, and snippets.

@metalelf0
Created March 19, 2015 08:13
Show Gist options
  • Save metalelf0/dd6e882bd49b68bd5821 to your computer and use it in GitHub Desktop.
Save metalelf0/dd6e882bd49b68bd5821 to your computer and use it in GitHub Desktop.
Array#reactiverecordize
# array_reactiverecordize_spec.rb
require 'spec_helper'
describe "Array#reactiverecordize" do
let!(:john_doe) { create(:user, first_name: "John", last_name: "Doe", birth_year: '1966')}
let!(:mike_pike) { create(:user, first_name: "Mike", last_name: "Pike", birth_year: '1996')}
let!(:carl_doe) { create(:user, first_name: "Carl", last_name: "Doe", birth_year: '1926')}
subject { User.where(last_name: 'Doe').select { |u| u.birth_year == 1926} }
specify { expect(subject).to be_an Array }
specify { expect(subject).to include(carl_doe) }
# this raises undefined method `where' for []:Array
specify { expect{subject.where(first_name: "Carl")}.to raise_error }
# but this works
specify { expect(subject.reactiverecordize.where(first_name: "Carl")).to include(carl_doe) }
end
# lib/core_ext/array.rb
class Array
def reactiverecordize
class_of_first = self[0].class
ids = self.map(&:id)
class_of_first.where(id: ids)
end
end
@metalelf0
Copy link
Author

This is a fix for a situation that arises when you try to chain active_record scopes and in-memory operations like selects, array intersection/join, and so on.

It tries to convert an array back to an ActiveRecord scope by refiltering on ids.

The code inside Array#reactiverecordize is just a proof of concept, it requires some fixes like:

  • make sure all elements of Array are of the same class (to avoid mixing pears and apples);
  • make sure the above class extends ActiveRecord::Base;
  • [].reactiverecordize should return an instance of ActiveRecord::NullRelation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment