gold-record 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. data/HISTORY.rdoc +7 -0
  2. data/LICENSE.txt +7 -0
  3. data/README.rdoc +93 -0
  4. data/Rakefile +138 -0
  5. data/lib/gold-record.rb +1 -0
  6. data/lib/gold_record.rb +26 -0
  7. data/lib/gold_record/base.rb +57 -0
  8. data/lib/gold_record/connection_adapters/mysql_adapter.rb +65 -0
  9. data/lib/gold_record/fixtures.rb +15 -0
  10. data/lib/gold_record/version.rb +9 -0
  11. data/test/cases/aaa_create_tables_test.rb +11 -0
  12. data/test/cases/acts_as_gold_record_test.rb +32 -0
  13. data/test/cases/associations/belongs_to_integer_association_test.rb +13 -0
  14. data/test/cases/associations/belongs_to_uuid_association_test.rb +13 -0
  15. data/test/cases/associations/habtm_integer_to_integer_association_test.rb +23 -0
  16. data/test/cases/associations/habtm_integer_to_uuid_association_test.rb +23 -0
  17. data/test/cases/associations/habtm_uuid_to_uuid_association_test.rb +23 -0
  18. data/test/cases/associations/has_many_integer_assocation_test.rb +16 -0
  19. data/test/cases/associations/has_many_uuid_association_test.rb +16 -0
  20. data/test/cases/coerce_id_test.rb +20 -0
  21. data/test/cases/find_test.rb +67 -0
  22. data/test/cases/generate_id_test.rb +25 -0
  23. data/test/cases/helper.rb +85 -0
  24. data/test/cases/to_param_test.rb +20 -0
  25. data/test/cases/to_uuid_test.rb +25 -0
  26. data/test/cases/zzz_migration_test.rb +97 -0
  27. data/test/config.rb +5 -0
  28. data/test/connection.rb +15 -0
  29. data/test/fixtures/albums.yml +19 -0
  30. data/test/fixtures/artists.yml +28 -0
  31. data/test/fixtures/fans.yml +23 -0
  32. data/test/fixtures/labels.yml +11 -0
  33. data/test/fixtures/record_stores.yml +12 -0
  34. data/test/fixtures/songs.yml +11 -0
  35. data/test/models/album.rb +5 -0
  36. data/test/models/artist.rb +8 -0
  37. data/test/models/fan.rb +4 -0
  38. data/test/models/label.rb +6 -0
  39. data/test/models/record_store.rb +5 -0
  40. data/test/models/song.rb +5 -0
  41. data/test/schema/schema.rb +56 -0
  42. metadata +127 -0
@@ -0,0 +1,32 @@
1
+ require 'cases/helper'
2
+ require 'models/label'
3
+ require 'models/artist'
4
+ require 'models/album'
5
+ require 'models/song'
6
+ require 'models/fan'
7
+
8
+ class ActsAsGoldRecordTest < ActiveRecord::TestCase
9
+ def test_label_does_not_identify_as_gold_record
10
+ assert !Label.respond_to?(:gold_record?)
11
+ end
12
+
13
+ def test_artist_identifies_as_gold_record
14
+ assert Artist.respond_to?(:gold_record?)
15
+ assert Artist.gold_record?
16
+ end
17
+
18
+ def test_album_identifies_as_gold_record
19
+ assert Album.respond_to?(:gold_record?)
20
+ assert Album.gold_record?
21
+ end
22
+
23
+ def test_song_identifies_as_gold_record
24
+ assert Song.respond_to?(:gold_record?)
25
+ assert Song.gold_record?
26
+ end
27
+
28
+ def test_fan_identifies_as_gold_record
29
+ assert Fan.respond_to?(:gold_record?)
30
+ assert Fan.gold_record?
31
+ end
32
+ end
@@ -0,0 +1,13 @@
1
+ require 'cases/helper'
2
+ require 'models/artist'
3
+
4
+ class BelongsToIntegerAssociationTest < ActiveRecord::TestCase
5
+ fixtures :labels
6
+ fixtures :artists
7
+
8
+ def test_association_find
9
+ artist = artists(:beatles)
10
+ label = labels(:emi)
11
+ assert_equal label, artist.label
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require 'cases/helper'
2
+ require 'models/artist'
3
+
4
+ class BelongsToUuidAssociationTest < ActiveRecord::TestCase
5
+ fixtures :artists
6
+ fixtures :albums
7
+
8
+ def test_association_find
9
+ album = albums(:white_album)
10
+ artist = artists(:beatles)
11
+ assert_equal artist, album.artist
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ require 'cases/helper'
2
+ require 'models/record_store'
3
+ require 'models/label'
4
+
5
+ class HabtmIntegerToIntegerAssociationTest < ActiveRecord::TestCase
6
+ fixtures :record_stores
7
+ fixtures :labels
8
+
9
+ def test_association_find
10
+ record_store = record_stores(:amoeba)
11
+ labels = record_store.labels
12
+ assert_equal 4, labels.size
13
+ labels.each do |labels|
14
+ assert labels.instance_of?(Label)
15
+ end
16
+ end
17
+
18
+ def test_empty_assocation_find
19
+ record_store = record_stores(:tower)
20
+ labels = record_store.labels
21
+ assert_equal 0, labels.size
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ require 'cases/helper'
2
+ require 'models/record_store'
3
+ require 'models/artist'
4
+
5
+ class HabtmIntegerToIntegerAssociationTest < ActiveRecord::TestCase
6
+ fixtures :record_stores
7
+ fixtures :artists
8
+
9
+ def test_association_find
10
+ record_store = record_stores(:amoeba)
11
+ artists = record_store.artists
12
+ assert_equal 6, artists.size
13
+ artists.each do |artists|
14
+ assert artists.instance_of?(Artist)
15
+ end
16
+ end
17
+
18
+ def test_empty_assocation_find
19
+ record_store = record_stores(:tower)
20
+ artists = record_store.artists
21
+ assert_equal 0, artists.size
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ require 'cases/helper'
2
+ require 'models/artist'
3
+ require 'models/fan'
4
+
5
+ class HabtmUuidToUuidAssociationTest < ActiveRecord::TestCase
6
+ fixtures :artists
7
+ fixtures :fans
8
+
9
+ def test_association_find
10
+ artist = artists(:beatles)
11
+ fans = artist.fans
12
+ assert_equal 8, fans.size
13
+ fans.each do |fans|
14
+ assert fans.instance_of?(Fan)
15
+ end
16
+ end
17
+
18
+ def test_empty_assocation_find
19
+ artist = artists(:ll_cool_j)
20
+ fans = artist.fans
21
+ assert_equal 0, fans.size
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ require 'cases/helper'
2
+ require 'models/artist'
3
+
4
+ class HasManyIntegerAssociationTest < ActiveRecord::TestCase
5
+ fixtures :labels
6
+ fixtures :artists
7
+
8
+ def test_association_find
9
+ label = labels(:def_jam)
10
+ artists = label.artists
11
+ assert_equal 4, artists.size
12
+ artists.each do |artist|
13
+ assert artist.instance_of?(Artist)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ require 'cases/helper'
2
+ require 'models/artist'
3
+
4
+ class HasManyUuidAssociationTest < ActiveRecord::TestCase
5
+ fixtures :artists
6
+ fixtures :albums
7
+
8
+ def test_association_find
9
+ artist = artists(:beatles)
10
+ albums = artist.albums
11
+ assert_equal 3, albums.size
12
+ albums.each do |album|
13
+ assert album.instance_of?(Album)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,20 @@
1
+ require 'cases/helper'
2
+ require 'models/artist'
3
+
4
+ class CoerceIdTest < ActiveRecord::TestCase
5
+ def test_coerce_id_with_nil
6
+ assert_nil Artist.coerce_id(nil)
7
+ end
8
+
9
+ def test_coerce_id_with_bogus_data
10
+ assert_nil Artist.coerce_id("BOGUS")
11
+ end
12
+
13
+ def test_coerce_id_with_binary_uuid
14
+ assert_equal NULL_UUID_RAW, Artist.coerce_id(NULL_UUID_RAW)
15
+ end
16
+
17
+ def test_coerce_id_with_hex_uuid
18
+ assert_equal NULL_UUID_RAW, Artist.coerce_id(NULL_UUID.to_s)
19
+ end
20
+ end
@@ -0,0 +1,67 @@
1
+ require 'cases/helper'
2
+ require 'models/artist'
3
+
4
+ class FindTest < ActiveRecord::TestCase
5
+ fixtures :artists
6
+
7
+ def test_find_with_one_binary_uuid
8
+ artist = Artist.find identify(:michael_jackson)
9
+ assert artist.instance_of?(Artist)
10
+ end
11
+
12
+ def test_find_with_one_hex_uuid
13
+ artist = Artist.find identify_hex(:michael_jackson)
14
+ assert artist.instance_of?(Artist)
15
+ end
16
+
17
+ def test_find_with_multiple_binary_uuids
18
+ artists = Artist.find([
19
+ identify(:beatles),
20
+ identify(:ll_cool_j),
21
+ identify(:method_man),
22
+ ])
23
+ assert_equal 3, artists.size
24
+ artists.each do |artist|
25
+ assert artist.instance_of?(Artist)
26
+ end
27
+ end
28
+
29
+ def test_find_with_multiple_hex_uuids
30
+ artists = Artist.find([
31
+ identify_hex(:method_man),
32
+ identify_hex(:beatles),
33
+ identify_hex(:warren_g),
34
+ ])
35
+ assert_equal 3, artists.size
36
+ artists.each do |artist|
37
+ assert artist.instance_of?(Artist)
38
+ end
39
+ end
40
+
41
+ def test_find_with_multiple_mixed_uuids
42
+ artists = Artist.find([
43
+ identify_hex(:beatles),
44
+ identify(:michael_jackson),
45
+ identify_hex(:warren_g),
46
+ ])
47
+ assert_equal 3, artists.size
48
+ artists.each do |artist|
49
+ assert artist.instance_of?(Artist)
50
+ end
51
+ end
52
+
53
+ def test_find_with_duplicate_mixed_uuids
54
+ artists = Artist.find([
55
+ identify(:beatles),
56
+ identify(:method_man),
57
+ identify(:warren_g),
58
+ identify_hex(:beatles),
59
+ identify_hex(:method_man),
60
+ identify_hex(:warren_g),
61
+ ])
62
+ assert_equal 3, artists.size
63
+ artists.each do |artist|
64
+ assert artist.instance_of?(Artist)
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,25 @@
1
+ require 'cases/helper'
2
+ require 'models/artist'
3
+
4
+ class GenerateIdTest < ActiveRecord::TestCase
5
+ fixtures :artists
6
+
7
+ def test_generate_id_for_new_record
8
+ artist = Artist.new
9
+ assert artist.new_record?
10
+ assert_nil artist.id
11
+ artist.generate_id!
12
+ assert artist.id.instance_of?(String)
13
+ assert_equal 16, artist.id.size
14
+ end
15
+
16
+ def test_generate_id_for_existing_record
17
+ artist = Artist.first
18
+ assert !artist.new_record?
19
+ assert artist.id.instance_of?(String)
20
+ assert_equal 16, artist.id.size
21
+ id = artist.id
22
+ artist.generate_id!
23
+ assert_equal artist.id, id
24
+ end
25
+ end
@@ -0,0 +1,85 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ $:.unshift(File.dirname(__FILE__) + '/../../../activesupport/lib')
3
+
4
+ require 'config'
5
+
6
+ require 'rubygems'
7
+ require 'test/unit'
8
+ require 'stringio'
9
+
10
+ require 'active_record'
11
+ require 'active_record/test_case'
12
+ require 'active_record/fixtures'
13
+ require 'connection'
14
+
15
+ require 'uuidtools'
16
+
17
+ require 'gold_record'
18
+
19
+ # Patch Fixtures
20
+ Fixtures.send :include, GoldRecord::Fixtures
21
+
22
+ # UUID composed of all null bytes
23
+ NULL_UUID_RAW = ("\000" * 16).freeze
24
+ NULL_UUID = UUIDTools::UUID.parse_raw(NULL_UUID_RAW)
25
+ NULL_UUID_HEX = NULL_UUID.to_s
26
+
27
+ # Show backtraces for deprecated behavior for quicker cleanup.
28
+ ActiveSupport::Deprecation.debug = true
29
+
30
+ # Quote "type" if it's a reserved word for the current connection.
31
+ QUOTED_TYPE = ActiveRecord::Base.connection.quote_column_name('type')
32
+
33
+ def current_adapter?(*types)
34
+ types.any? do |type|
35
+ ActiveRecord::ConnectionAdapters.const_defined?(type) &&
36
+ ActiveRecord::Base.connection.is_a?(ActiveRecord::ConnectionAdapters.const_get(type))
37
+ end
38
+ end
39
+
40
+ ActiveRecord::Base.connection.class.class_eval do
41
+ IGNORED_SQL = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /SHOW FIELDS/]
42
+
43
+ def execute_with_query_record(sql, name = nil, &block)
44
+ $queries_executed ||= []
45
+ $queries_executed << sql unless IGNORED_SQL.any? { |r| sql =~ r }
46
+ execute_without_query_record(sql, name, &block)
47
+ end
48
+
49
+ alias_method_chain :execute, :query_record
50
+ end
51
+
52
+ # Make with_scope public for tests
53
+ class << ActiveRecord::Base
54
+ public :with_scope, :with_exclusive_scope
55
+ end
56
+
57
+ unless ENV['FIXTURE_DEBUG']
58
+ module ActiveRecord::TestFixtures::ClassMethods
59
+ def try_to_load_dependency_with_silence(*args)
60
+ ActiveRecord::Base.logger.silence { try_to_load_dependency_without_silence(*args)}
61
+ end
62
+
63
+ alias_method_chain :try_to_load_dependency, :silence
64
+ end
65
+ end
66
+
67
+ class ActiveSupport::TestCase
68
+ include ActiveRecord::TestFixtures
69
+
70
+ self.fixture_path = FIXTURES_ROOT
71
+ self.use_instantiated_fixtures = false
72
+ self.use_transactional_fixtures = true
73
+
74
+ def create_fixtures(*table_names, &block)
75
+ Fixtures.create_fixtures(ActiveSupport::TestCase.fixture_path, table_names, {}, &block)
76
+ end
77
+
78
+ def identify(label)
79
+ Fixtures.identify(label)
80
+ end
81
+
82
+ def identify_hex(label)
83
+ UUIDTools::UUID.parse_raw(identify(label)).to_s
84
+ end
85
+ end
@@ -0,0 +1,20 @@
1
+ require 'cases/helper'
2
+ require 'models/artist'
3
+
4
+ class ToParamTest < ActiveRecord::TestCase
5
+ fixtures :artists
6
+
7
+ def test_to_param_returns_nil_for_new_record
8
+ artist = Artist.new
9
+ assert artist.new_record?
10
+ param = artist.to_param
11
+ assert_nil param
12
+ end
13
+
14
+ def test_to_param_returns_a_hex_string
15
+ artist = Artist.first
16
+ param = artist.to_param
17
+ assert param.instance_of?(String)
18
+ assert param.match(/\A[0-9a-f\-]{36}\z/)
19
+ end
20
+ end
@@ -0,0 +1,25 @@
1
+ require 'cases/helper'
2
+ require 'models/artist'
3
+
4
+ class ToUuidTest < ActiveRecord::TestCase
5
+ fixtures :artists
6
+
7
+ def test_to_uuid_returns_nil_for_new_record
8
+ artist = Artist.new
9
+ assert artist.new_record?
10
+ uuid = artist.to_uuid
11
+ assert_nil uuid
12
+ end
13
+
14
+ def test_to_uuid_returns_a_uuid
15
+ artist = Artist.first
16
+ uuid = artist.to_uuid
17
+ assert uuid.instance_of?(UUIDTools::UUID)
18
+ end
19
+
20
+ def test_to_uuid_returns_the_correct_uuid
21
+ artist = Artist.first
22
+ uuid = artist.to_uuid
23
+ assert_equal artist.id, uuid.raw
24
+ end
25
+ end
@@ -0,0 +1,97 @@
1
+ # The filename begins with "zzz" to ensure this is the last test.
2
+ require 'cases/helper'
3
+ require 'models/label'
4
+ require 'models/artist'
5
+ require 'models/record_store'
6
+
7
+ if ActiveRecord::Base.connection.supports_migrations?
8
+
9
+ class MigrationTest < ActiveRecord::TestCase
10
+ fixtures :labels
11
+ fixtures :artists
12
+ fixtures :record_stores
13
+
14
+ def test_migrations
15
+ migrate_up
16
+ reset
17
+ run_tests
18
+
19
+ migrate_down
20
+ reset
21
+ run_tests
22
+ end
23
+
24
+ private
25
+
26
+ def run_tests
27
+ artist = artists(:beatles)
28
+ label = labels(:emi)
29
+ assert_equal label, artist.label
30
+
31
+ label = labels(:def_jam)
32
+ artists = label.artists
33
+ assert_equal 4, artists.size
34
+ artists.each do |artist|
35
+ assert artist.instance_of?(Artist)
36
+ end
37
+
38
+ record_store = record_stores(:amoeba)
39
+ labels = record_store.labels
40
+ assert_equal 4, labels.size
41
+ labels.each do |labels|
42
+ assert labels.instance_of?(Label)
43
+ end
44
+
45
+ record_store = record_stores(:amoeba)
46
+ artists = record_store.artists
47
+ assert_equal 6, artists.size
48
+ artists.each do |artists|
49
+ assert artists.instance_of?(Artist)
50
+ end
51
+ end
52
+
53
+ def reset
54
+ [Label, Artist, RecordStore].each do |model|
55
+ model.reset_column_information
56
+ end
57
+ ActiveRecord::Base.connection.clear_query_cache
58
+ end
59
+
60
+ def migrate_up
61
+ # Change each int(11) id column to binary(16).
62
+ # This preserves the column’s original value as a right-padded 16-byte string.
63
+ [:labels, :record_stores].each do |table|
64
+ ActiveRecord::Base.connection.change_integer_primary_key_to_uuid(table)
65
+ end
66
+
67
+ # Change association columns to binary(16).
68
+ [
69
+ [:artists, :label_id, :id],
70
+ [:labels_record_stores, :label_id, false],
71
+ [:labels_record_stores, :record_store_id, false],
72
+ [:artists_record_stores, :record_store_id, false],
73
+ ].each do |table, column, primary_key|
74
+ ActiveRecord::Base.connection.change_integer_to_uuid(table, column, primary_key)
75
+ end
76
+ end
77
+
78
+ def migrate_down
79
+ # Change each binary(16) id column to int(11).
80
+ # MySQL casts the string value to an integer.
81
+ [:labels, :record_stores].each do |table|
82
+ ActiveRecord::Base.connection.change_uuid_to_integer_primary_key(table)
83
+ end
84
+
85
+ # Change association columns to int(11).
86
+ [
87
+ [:artists, :label_id, :id],
88
+ [:labels_record_stores, :label_id, false],
89
+ [:labels_record_stores, :record_store_id, false],
90
+ [:artists_record_stores, :record_store_id, false],
91
+ ].each do |table, column, primary_key|
92
+ ActiveRecord::Base.connection.change_uuid_to_integer(table, column, primary_key)
93
+ end
94
+ end
95
+ end
96
+
97
+ end