Skip to content

Instantly share code, notes, and snippets.

@JayTeeSF
Created June 13, 2015 00:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JayTeeSF/0af43b8b6312b4195e89 to your computer and use it in GitHub Desktop.
Save JayTeeSF/0af43b8b6312b4195e89 to your computer and use it in GitHub Desktop.
Calling new on an AR class, from within the context of an ActiveRelation on a subclass of said class, assumes the "id" attribute defined in the relation's where clause
#!/usr/bin/env ruby
class ArWeirdnessUsage
def self.run
message = <<-EOF
Usage:
0) make this file executable and run it in order to see these instructions
1) Create a Rails Project (rails new foo) and add this file: cp %s ./foo/lib/
2) rails g scaffold TestClass name && RAILS_ENV=test rake db:create db:migrate
3) echo 'TestClass; ArWeirdness.test_suite' \\
| rails c --environment=test
4) Cleanup:
echo 'ActiveRecord::Base.connection.execute("drop table test_classes")' \\
| rails c --environment=test && rails destroy scaffold TestClass
You may also want to remove stray files like:
db/schema.rb
app/assets/stylesheets/scaffolds.scss
with either 'git checkout ...' or 'rm ...'
EOF
return(message % $PROGRAM_NAME)
end
end
if __FILE__ == $PROGRAM_NAME
puts ArWeirdnessUsage.run
else
class ArWeirdness
COMMON_ATTRS = { } # <-- put any required attributes here; sorry, can't handle attributes that must be unique.
def self.test_setup
::TestClass.create!(COMMON_ATTRS.merge(name: 'foo'))
::TestClass.create!(COMMON_ATTRS.merge(name: 'bar'))
end
def self.test_cleanup
::TestClass.delete_all
end
module ExtraFunctionality
def create_instance_of_test_class(attrs={})
ret_val = BROKEN_TEST
new_record = ::TestClass.new(attrs) # this new record shouldn't have an ID!
if new_record.id.present?
ret_val = BUG
puts " ------------> huh: generated a new instance with an ID assigned?!" # the id of the activerecord relation got in our way!
else
ret_val = BUG_FREE
puts " ------------> ok"
end
puts "\tWe have #{new_record.inspect}"
puts "\tfrom: #{attrs.inspect}"
return ret_val
end
end
class SubsetOfTestClass < ::TestClass
extend ExtraFunctionality
end
def self.test_suite
test_ok
test_huh
end
BUG = -1; BROKEN_TEST = 0; BUG_FREE = 1
def self.test_ok # this WORKS ...it creates a new object without picking-up the "id" of the collection
test_setup
ids = ::TestClass.pluck(:id)
@id = ids.first
@filtered_collection = ::TestClass.where(id: [@id]) #<-- the use-case: to present a filtered_version of TestClass with only the current user's entries
@filtered_collection.send(:extend, ExtraFunctionality)
result = @filtered_collection.create_instance_of_test_class(COMMON_ATTRS.merge(name: 'foo-bar-baz-OK'))
test_cleanup
return result
end
def self.test_huh # this FAILS ...it creates a new object, that ?magically? picks-up the id of the ARRelation within which it's defined
test_setup
ids = ::TestClass.pluck(:id)
@id = ids.first
@filtered_collection = SubsetOfTestClass.where(id: [@id]) #<-- the use-case: to present a filtered_version of TestClass with only the current user's entries
result = @filtered_collection.create_instance_of_test_class(COMMON_ATTRS.merge(name: 'foo-bar-baz-HUH'))
test_cleanup
return result
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment