activeuuid 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +1 -0
- data/.travis.yml +27 -0
- data/Gemfile +2 -0
- data/README.mkd +12 -34
- data/Rakefile +2 -0
- data/activeuuid.gemspec +2 -2
- data/gemfiles/Gemfile.rails-3-1 +5 -0
- data/gemfiles/Gemfile.rails-3-2 +5 -0
- data/gemfiles/Gemfile.rails-head +5 -0
- data/lib/activeuuid/patches.rb +65 -8
- data/lib/activeuuid/uuid.rb +56 -64
- data/lib/activeuuid/version.rb +1 -1
- data/spec/lib/activerecord_spec.rb +148 -24
- data/spec/lib/uuid_mokeypatch_spec.rb +20 -28
- data/spec/spec_helper.rb +7 -0
- data/spec/support/database.yml +3 -6
- data/spec/support/migrate/20120817081813_create_uuid_articles.rb +1 -0
- data/spec/support/models/uuid_article.rb +0 -1
- data/spec/support/spec_for_adapter.rb +20 -0
- metadata +13 -9
- data/spec/lib/serializer_spec.rb +0 -76
data/.rspec
CHANGED
data/.travis.yml
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
before_script:
|
2
|
+
- mysql -e 'create database activeuuid_test;'
|
3
|
+
- psql -c 'create database activeuuid_test;' -U postgres
|
4
|
+
|
5
|
+
rvm:
|
6
|
+
- 1.9.2
|
7
|
+
- 1.9.3
|
8
|
+
- 2.0.0
|
9
|
+
- rbx-19mode
|
10
|
+
|
11
|
+
gemfile:
|
12
|
+
- Gemfile
|
13
|
+
- gemfiles/Gemfile.rails-3-1
|
14
|
+
- gemfiles/Gemfile.rails-3-2
|
15
|
+
- gemfiles/Gemfile.rails-head
|
16
|
+
|
17
|
+
env:
|
18
|
+
- DB=sqlite3
|
19
|
+
- DB=mysql
|
20
|
+
- DB=postgresql
|
21
|
+
|
22
|
+
matrix:
|
23
|
+
allow_failures:
|
24
|
+
- gemfile: gemfiles/Gemfile.rails-head
|
25
|
+
exclude:
|
26
|
+
- rvm: 1.9.2
|
27
|
+
gemfile: gemfiles/Gemfile.rails-head
|
data/Gemfile
CHANGED
data/README.mkd
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/jashmenn/activeuuid.png)](http://travis-ci.org/jashmenn/activeuuid)
|
2
|
+
|
1
3
|
# activeuuid
|
2
4
|
|
3
|
-
Add `binary(16)` UUIDs to ActiveRecord.
|
5
|
+
Add `binary(16)` UUIDs to ActiveRecord.
|
4
6
|
|
5
7
|
## Example
|
6
8
|
|
@@ -48,20 +50,15 @@ require 'spec_helper'
|
|
48
50
|
describe Email do
|
49
51
|
|
50
52
|
context "when using uuid's as keys" do
|
51
|
-
|
52
|
-
|
53
|
-
@guid = "1dd74dd0-d116-11e0-99c7-5ac5d975667e"
|
54
|
-
@e = Email.new(:subject => "hello", :body => "world") {|e| e.id = UUIDTools::UUID.parse(@guid) }
|
55
|
-
@e.save
|
56
|
-
end
|
53
|
+
let(:guid) { "1dd74dd0-d116-11e0-99c7-5ac5d975667e" }
|
54
|
+
let(:email) { Fabricate :email }
|
57
55
|
|
58
56
|
it "the id guid should be equal to the uuid" do
|
59
|
-
|
57
|
+
email.id.to_s.should eql(guid)
|
60
58
|
end
|
61
59
|
|
62
60
|
it "should be able to find an email by the uuid" do
|
63
|
-
|
64
|
-
f.id.to_s.should eql(@guid)
|
61
|
+
Email.find(guid).id.to_s.should == guid
|
65
62
|
end
|
66
63
|
|
67
64
|
end
|
@@ -73,9 +70,9 @@ end
|
|
73
70
|
From [2]:
|
74
71
|
|
75
72
|
> [Here is a] UUID: 1e8ef774-581c-102c-bcfe-f1ab81872213
|
76
|
-
>
|
73
|
+
>
|
77
74
|
> A UUID like the one above is 36 characters long, including dashes. If you store this VARCHAR(36), you're going to decrease compare performance dramatically. This is your primary key, you don't want it to be slow.
|
78
|
-
>
|
75
|
+
>
|
79
76
|
> At its bit level, a UUID is 128 bits, which means it will fit into
|
80
77
|
> 16 bytes, note this is not very human readable, but it will keep
|
81
78
|
> storage low, and is only 4 times larger than a 32-bit int, or 2
|
@@ -98,10 +95,9 @@ application the keys are represented by a UUIDTools::UUID object.
|
|
98
95
|
* more transparent support for natural and composite keys
|
99
96
|
* support for MySQLs `INSERT ... ON DUPLICATE KEY UPDATE` syntax
|
100
97
|
* support a primary column name other than `id`
|
101
|
-
* work on other databases (Postgres, etc)
|
102
98
|
* tests
|
103
99
|
|
104
|
-
## Inspiration
|
100
|
+
## Inspiration
|
105
101
|
James Golick's `friendly` is a great gem for NoSQL on MySQL. It's
|
106
102
|
a great gateway drug to systems like Cassandra for teams that are
|
107
103
|
already familiar with the ins-and-outs of MySQL.
|
@@ -114,35 +110,17 @@ Add this to your `Gemfile`
|
|
114
110
|
|
115
111
|
Or get the code here: https://github.com/jashmenn/activeuuid
|
116
112
|
|
117
|
-
## Notes
|
118
|
-
|
119
|
-
### Fixtures
|
120
|
-
|
121
|
-
You can use `activeuuid` in fixtures by using the `!!binary` directive in YAML.
|
122
|
-
The trick is to base64 encode the raw bytes of the hexdigest.
|
123
|
-
|
124
|
-
```yaml
|
125
|
-
devin_ifttt_new_tweet:
|
126
|
-
id: !!binary "<%= Base64.encode64(UUIDTools::UUID.parse_hexdigest('2D79B402CBA811E1AA7C14DAE903E06A').raw) %>"
|
127
|
-
data:
|
128
|
-
user_id: 1
|
129
|
-
source_id: 1
|
130
|
-
recipe_id: 1
|
131
|
-
created_at: Mon, 09 Jul 2012 14:06:21 -0700
|
132
|
-
body: Nice blog entry!
|
133
|
-
```
|
134
113
|
|
135
114
|
## References
|
136
115
|
* [1] http://bret.appspot.com/entry/how-friendfeed-uses-mysql
|
137
|
-
* [2] http://kekoav.com/blog/36-computers/58-uuids-as-primary-keys-in-mysql.html
|
116
|
+
* [2] http://kekoav.com/blog/36-computers/58-uuids-as-primary-keys-in-mysql.html
|
138
117
|
* [3] https://gist.github.com/937739
|
139
118
|
* [4] http://www.codinghorror.com/blog/2007/03/primary-keys-ids-versus-guids.html
|
140
119
|
* [5] http://krow.livejournal.com/497839.html
|
141
120
|
* [6] https://github.com/jamesgolick/friendly
|
142
121
|
|
143
122
|
## Dependencies
|
144
|
-
Rails ~> 3.1.0
|
145
|
-
Patterson introduced in Rails 3.1.
|
123
|
+
Rails ~> 3.1.0
|
146
124
|
|
147
125
|
## Author
|
148
126
|
|
data/Rakefile
CHANGED
data/activeuuid.gemspec
CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
|
|
7
7
|
s.version = Activeuuid::VERSION
|
8
8
|
s.authors = ["Nate Murray"]
|
9
9
|
s.email = ["nate@natemurray.com"]
|
10
|
-
s.homepage = "
|
10
|
+
s.homepage = "https://github.com/jashmenn/activeuuid"
|
11
11
|
s.summary = %q{Add binary UUIDs to ActiveRecord in MySQL}
|
12
12
|
s.description = %q{Add binary (not string) UUIDs to ActiveRecord in MySQL}
|
13
13
|
|
@@ -27,5 +27,5 @@ Gem::Specification.new do |s|
|
|
27
27
|
s.add_development_dependency "mysql2"
|
28
28
|
|
29
29
|
s.add_runtime_dependency "uuidtools"
|
30
|
-
s.add_runtime_dependency "activerecord"
|
30
|
+
s.add_runtime_dependency "activerecord", '>= 3.1'
|
31
31
|
end
|
data/lib/activeuuid/patches.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'active_support/concern'
|
3
|
+
|
4
|
+
|
1
5
|
module ActiveUUID
|
2
6
|
module Patches
|
3
7
|
module Migrations
|
4
|
-
def uuid(*
|
5
|
-
options =
|
6
|
-
column_names = args
|
8
|
+
def uuid(*column_names)
|
9
|
+
options = column_names.extract_options!
|
7
10
|
column_names.each do |name|
|
8
11
|
type = @base.adapter_name.downcase == 'postgresql' ? 'uuid' : 'binary(16)'
|
9
12
|
column(name, "#{type}#{' PRIMARY KEY' if options.delete(:primary_key)}", options)
|
@@ -11,22 +14,65 @@ module ActiveUUID
|
|
11
14
|
end
|
12
15
|
end
|
13
16
|
|
17
|
+
module Column
|
18
|
+
extend ActiveSupport::Concern
|
19
|
+
|
20
|
+
included do
|
21
|
+
def type_cast_with_uuid(value)
|
22
|
+
return UUIDTools::UUID.serialize(value) if type == :uuid
|
23
|
+
type_cast_without_uuid(value)
|
24
|
+
end
|
25
|
+
|
26
|
+
def type_cast_code_with_uuid(var_name)
|
27
|
+
return "UUIDTools::UUID.serialize(#{var_name})" if type == :uuid
|
28
|
+
type_cast_code_without_uuid(var_name)
|
29
|
+
end
|
30
|
+
|
31
|
+
def simplified_type_with_uuid(field_type)
|
32
|
+
return :uuid if field_type == 'binary(16)'
|
33
|
+
simplified_type_without_uuid(field_type)
|
34
|
+
end
|
35
|
+
|
36
|
+
alias_method_chain :type_cast, :uuid
|
37
|
+
alias_method_chain :type_cast_code, :uuid
|
38
|
+
alias_method_chain :simplified_type, :uuid
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
module PostgreSQLColumn
|
43
|
+
extend ActiveSupport::Concern
|
44
|
+
|
45
|
+
included do
|
46
|
+
def simplified_type_with_pguuid(field_type)
|
47
|
+
return :uuid if field_type == 'uuid'
|
48
|
+
simplified_type_without_pguuid(field_type)
|
49
|
+
end
|
50
|
+
|
51
|
+
alias_method_chain :simplified_type, :pguuid
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
14
55
|
module Quoting
|
15
56
|
extend ActiveSupport::Concern
|
16
57
|
|
17
58
|
included do
|
18
59
|
def quote_with_visiting(value, column = nil)
|
19
|
-
value =
|
60
|
+
value = UUIDTools::UUID.serialize(value) if column && column.type == :uuid
|
20
61
|
quote_without_visiting(value, column)
|
21
62
|
end
|
22
63
|
|
23
64
|
def type_cast_with_visiting(value, column = nil)
|
24
|
-
value =
|
65
|
+
value = UUIDTools::UUID.serialize(value) if column && column.type == :uuid
|
25
66
|
type_cast_without_visiting(value, column)
|
26
67
|
end
|
27
68
|
|
69
|
+
def native_database_types_with_uuid
|
70
|
+
@native_database_types ||= native_database_types_without_uuid.merge(uuid: { name: 'binary', limit: 16 })
|
71
|
+
end
|
72
|
+
|
28
73
|
alias_method_chain :quote, :visiting
|
29
74
|
alias_method_chain :type_cast, :visiting
|
75
|
+
alias_method_chain :native_database_types, :uuid
|
30
76
|
end
|
31
77
|
end
|
32
78
|
|
@@ -35,24 +81,35 @@ module ActiveUUID
|
|
35
81
|
|
36
82
|
included do
|
37
83
|
def quote_with_visiting(value, column = nil)
|
38
|
-
value =
|
84
|
+
value = UUIDTools::UUID.serialize(value) if column && column.type == :uuid
|
85
|
+
value = value.to_s if value.is_a? UUIDTools::UUID
|
39
86
|
quote_without_visiting(value, column)
|
40
87
|
end
|
41
88
|
|
42
89
|
def type_cast_with_visiting(value, column = nil)
|
43
|
-
value =
|
90
|
+
value = UUIDTools::UUID.serialize(value) if column && column.type == :uuid
|
91
|
+
value = value.to_s if value.is_a? UUIDTools::UUID
|
44
92
|
type_cast_without_visiting(value, column)
|
45
93
|
end
|
46
94
|
|
95
|
+
def native_database_types_with_pguuid
|
96
|
+
@native_database_types ||= native_database_types_without_pguuid.merge(uuid: { name: 'uuid' })
|
97
|
+
end
|
98
|
+
|
47
99
|
alias_method_chain :quote, :visiting
|
48
100
|
alias_method_chain :type_cast, :visiting
|
101
|
+
alias_method_chain :native_database_types, :pguuid
|
49
102
|
end
|
50
103
|
end
|
51
104
|
|
52
105
|
def self.apply!
|
53
106
|
ActiveRecord::ConnectionAdapters::Table.send :include, Migrations if defined? ActiveRecord::ConnectionAdapters::Table
|
54
107
|
ActiveRecord::ConnectionAdapters::TableDefinition.send :include, Migrations if defined? ActiveRecord::ConnectionAdapters::TableDefinition
|
55
|
-
|
108
|
+
|
109
|
+
ActiveRecord::ConnectionAdapters::Column.send :include, Column
|
110
|
+
ActiveRecord::ConnectionAdapters::PostgreSQLColumn.send :include, PostgreSQLColumn if defined? ActiveRecord::ConnectionAdapters::PostgreSQLColumn
|
111
|
+
|
112
|
+
ActiveRecord::ConnectionAdapters::Mysql2Adapter.send :include, Quoting if defined? ActiveRecord::ConnectionAdapters::Mysql2Adapter
|
56
113
|
ActiveRecord::ConnectionAdapters::SQLite3Adapter.send :include, Quoting if defined? ActiveRecord::ConnectionAdapters::SQLite3Adapter
|
57
114
|
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.send :include, PostgreSQLQuoting if defined? ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
|
58
115
|
end
|
data/lib/activeuuid/uuid.rb
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
require 'uuidtools'
|
2
2
|
|
3
|
+
# monkey-patch Friendly::UUID to serialize UUIDs
|
3
4
|
module UUIDTools
|
4
5
|
class UUID
|
5
|
-
# monkey-patch Friendly::UUID to serialize UUIDs to MySQL
|
6
6
|
alias_method :id, :raw
|
7
7
|
|
8
|
+
# duck typing activerecord 3.1 dirty hack )
|
9
|
+
def gsub *; self; end
|
10
|
+
|
8
11
|
def quoted_id
|
9
12
|
s = raw.unpack("H*")[0]
|
10
13
|
"x'#{s}'"
|
@@ -17,6 +20,30 @@ module UUIDTools
|
|
17
20
|
def to_param
|
18
21
|
hexdigest.upcase
|
19
22
|
end
|
23
|
+
|
24
|
+
def self.serialize(value)
|
25
|
+
case value
|
26
|
+
when self
|
27
|
+
value
|
28
|
+
when String
|
29
|
+
parse_string value
|
30
|
+
else
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def self.parse_string(str)
|
38
|
+
return nil if str.length == 0
|
39
|
+
if str.length == 36
|
40
|
+
parse str
|
41
|
+
elsif str.length == 32
|
42
|
+
parse_hexdigest str
|
43
|
+
else
|
44
|
+
parse_raw str
|
45
|
+
end
|
46
|
+
end
|
20
47
|
end
|
21
48
|
end
|
22
49
|
|
@@ -49,89 +76,53 @@ module Arel
|
|
49
76
|
end
|
50
77
|
|
51
78
|
module ActiveUUID
|
52
|
-
class UUIDSerializer
|
53
|
-
def load(binary)
|
54
|
-
case binary
|
55
|
-
when UUIDTools::UUID
|
56
|
-
binary
|
57
|
-
when String
|
58
|
-
parse_string(binary)
|
59
|
-
else
|
60
|
-
nil
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def dump(uuid)
|
65
|
-
case uuid
|
66
|
-
when UUIDTools::UUID
|
67
|
-
uuid.raw
|
68
|
-
when String
|
69
|
-
parse_string(uuid).try(:raw)
|
70
|
-
else
|
71
|
-
nil
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
private
|
76
|
-
|
77
|
-
def parse_string str
|
78
|
-
return nil if str.blank?
|
79
|
-
if str.length == 36
|
80
|
-
UUIDTools::UUID.parse str
|
81
|
-
elsif str.length == 32
|
82
|
-
UUIDTools::UUID.parse_hexdigest str
|
83
|
-
else
|
84
|
-
UUIDTools::UUID.parse_raw str
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
79
|
module UUID
|
90
80
|
extend ActiveSupport::Concern
|
91
81
|
|
92
82
|
included do
|
93
|
-
class_attribute :
|
94
|
-
|
83
|
+
class_attribute :_natural_key, instance_writer: false
|
84
|
+
class_attribute :_uuid_generator, instance_writer: false
|
85
|
+
self._uuid_generator = :random
|
86
|
+
|
87
|
+
singleton_class.alias_method_chain :instantiate, :uuid
|
95
88
|
before_create :generate_uuids_if_needed
|
96
89
|
end
|
97
90
|
|
98
91
|
module ClassMethods
|
99
|
-
def natural_key_attributes
|
100
|
-
@_activeuuid_natural_key_attributes
|
101
|
-
end
|
102
|
-
|
103
92
|
def natural_key(*attributes)
|
104
|
-
|
93
|
+
self._natural_key = attributes
|
105
94
|
end
|
106
95
|
|
107
|
-
def uuid_generator(generator_name
|
108
|
-
|
109
|
-
@_activeuuid_kind || :random
|
96
|
+
def uuid_generator(generator_name)
|
97
|
+
self._uuid_generator = generator_name
|
110
98
|
end
|
111
99
|
|
112
100
|
def uuids(*attributes)
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
101
|
+
ActiveSupport::Deprecation.warn <<-EOS
|
102
|
+
ActiveUUID detects uuid columns independently.
|
103
|
+
There is no more need to use uuid method.
|
104
|
+
EOS
|
105
|
+
end
|
106
|
+
|
107
|
+
def instantiate_with_uuid(record)
|
108
|
+
uuid_columns.each do |uuid_column|
|
109
|
+
record[uuid_column] = UUIDTools::UUID.serialize(record[uuid_column]).to_s if record[uuid_column]
|
119
110
|
end
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
111
|
+
instantiate_without_uuid(record)
|
112
|
+
end
|
113
|
+
|
114
|
+
def uuid_columns
|
115
|
+
@uuid_columns ||= columns.select { |c| c.type == :uuid }.map(&:name)
|
125
116
|
end
|
126
117
|
end
|
127
118
|
|
128
119
|
def create_uuid
|
129
|
-
if
|
120
|
+
if _natural_key
|
130
121
|
# TODO if all the attributes return nil you might want to warn about this
|
131
|
-
chained =
|
122
|
+
chained = _natural_key.map { |attribute| self.send(attribute) }.join('-')
|
132
123
|
UUIDTools::UUID.sha1_create(UUIDTools::UUID_OID_NAMESPACE, chained)
|
133
124
|
else
|
134
|
-
case
|
125
|
+
case _uuid_generator
|
135
126
|
when :random
|
136
127
|
UUIDTools::UUID.random_create
|
137
128
|
when :time
|
@@ -141,8 +132,9 @@ module ActiveUUID
|
|
141
132
|
end
|
142
133
|
|
143
134
|
def generate_uuids_if_needed
|
144
|
-
|
145
|
-
|
135
|
+
primary_key = self.class.primary_key
|
136
|
+
if self.class.columns_hash[primary_key].type == :uuid
|
137
|
+
send("#{primary_key}=", create_uuid) unless send("#{primary_key}?")
|
146
138
|
end
|
147
139
|
end
|
148
140
|
|
data/lib/activeuuid/version.rb
CHANGED
@@ -1,16 +1,78 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
describe ActiveRecord::Base do
|
4
|
+
context '.connection' do
|
5
|
+
let!(:connection) { ActiveRecord::Base.connection }
|
6
|
+
let(:table_name) { :test_uuid_field_creation }
|
7
|
+
|
8
|
+
before do
|
9
|
+
connection.drop_table(table_name) if connection.table_exists?(table_name)
|
10
|
+
connection.create_table(table_name)
|
11
|
+
end
|
12
|
+
|
13
|
+
after do
|
14
|
+
connection.drop_table table_name
|
15
|
+
end
|
16
|
+
|
17
|
+
specify { connection.table_exists?(table_name).should be_true }
|
18
|
+
|
19
|
+
context '#add_column' do
|
20
|
+
let(:column_name) { :uuid_column }
|
21
|
+
let(:column) { connection.columns(table_name).detect { |c| c.name.to_sym == column_name } }
|
22
|
+
|
23
|
+
before { connection.add_column table_name, column_name, :uuid }
|
24
|
+
|
25
|
+
specify { connection.column_exists?(table_name, column_name).should be_true }
|
26
|
+
specify { column.should_not be_nil }
|
27
|
+
|
28
|
+
it 'should have proper sql type' do
|
29
|
+
spec_for_adapter do |adapters|
|
30
|
+
adapters.sqlite3 { column.sql_type.should == 'binary(16)' }
|
31
|
+
adapters.mysql2 { column.sql_type.should == 'binary(16)' }
|
32
|
+
adapters.postgresql { column.sql_type.should == 'uuid' }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context '#change_column' do
|
38
|
+
let(:column_name) { :string_col }
|
39
|
+
let(:column) { connection.columns(table_name).detect { |c| c.name.to_sym == column_name } }
|
40
|
+
|
41
|
+
before do
|
42
|
+
connection.add_column table_name, column_name, :string
|
43
|
+
spec_for_adapter do |adapters|
|
44
|
+
adapters.sqlite3 { connection.change_column table_name, column_name, :uuid }
|
45
|
+
adapters.mysql2 { connection.change_column table_name, column_name, :uuid }
|
46
|
+
# adapters.postgresql { connection.change_column table_name, column_name, :uuid }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'support changing type from string to uuid' do
|
51
|
+
spec_for_adapter do |adapters|
|
52
|
+
adapters.sqlite3 { column.sql_type.should == 'binary(16)' }
|
53
|
+
adapters.mysql2 { column.sql_type.should == 'binary(16)' }
|
54
|
+
adapters.postgresql { pending('postgresql can`t change column type to uuid') }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
3
62
|
describe Article do
|
4
63
|
let!(:article) { Fabricate :article }
|
5
64
|
let(:id) { article.id }
|
6
65
|
let(:model) { Article }
|
66
|
+
subject { model }
|
67
|
+
|
68
|
+
context 'model' do
|
69
|
+
its(:all) { should == [article] }
|
70
|
+
its(:first) { should == article }
|
71
|
+
end
|
7
72
|
|
8
73
|
context 'existance' do
|
9
|
-
|
10
|
-
|
11
|
-
model.all.should == [article]
|
12
|
-
model.first.should == article
|
13
|
-
end
|
74
|
+
subject { article }
|
75
|
+
its(:id) { should be_a Integer }
|
14
76
|
end
|
15
77
|
|
16
78
|
context '.find' do
|
@@ -18,28 +80,40 @@ describe Article do
|
|
18
80
|
end
|
19
81
|
|
20
82
|
context '.where' do
|
21
|
-
specify { model.where(:
|
83
|
+
specify { model.where(id: id).first.should == article }
|
22
84
|
end
|
23
85
|
|
24
|
-
context '
|
25
|
-
|
26
|
-
|
86
|
+
context '#destroy' do
|
87
|
+
subject { article }
|
88
|
+
its(:delete) { should be_true }
|
89
|
+
its(:destroy) { should be_true }
|
27
90
|
end
|
28
91
|
end
|
29
92
|
|
30
93
|
describe UuidArticle do
|
31
94
|
let!(:article) { Fabricate :uuid_article }
|
32
|
-
let(:id) { article.id }
|
33
|
-
let(:model) {
|
95
|
+
let!(:id) { article.id }
|
96
|
+
let(:model) { described_class }
|
97
|
+
subject { model }
|
34
98
|
|
35
|
-
|
99
|
+
context 'model' do
|
100
|
+
its(:primary_key) { should == 'id' }
|
101
|
+
its(:all) { should == [article] }
|
102
|
+
its(:first) { should == article }
|
103
|
+
end
|
36
104
|
|
37
105
|
context 'existance' do
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
106
|
+
subject { article }
|
107
|
+
its(:id) { should be_a UUIDTools::UUID }
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'interpolation' do
|
111
|
+
specify { model.where("id = :id", id: article.id) }
|
112
|
+
end
|
113
|
+
|
114
|
+
context 'batch interpolation' do
|
115
|
+
before { model.update_all(["title = CASE WHEN id = :id THEN 'Passed' ELSE 'Nothing' END", id: article.id]) }
|
116
|
+
specify { article.reload.title.should == 'Passed' }
|
43
117
|
end
|
44
118
|
|
45
119
|
context '.find' do
|
@@ -50,14 +124,64 @@ describe UuidArticle do
|
|
50
124
|
end
|
51
125
|
|
52
126
|
context '.where' do
|
53
|
-
specify { model.where(:
|
54
|
-
specify { model.where(:
|
55
|
-
specify { model.where(:
|
56
|
-
specify { model.where(:
|
127
|
+
specify { model.where(id: article).first.should == article }
|
128
|
+
specify { model.where(id: id).first.should == article }
|
129
|
+
specify { model.where(id: id.to_s).first.should == article }
|
130
|
+
specify { model.where(id: id.raw).first.should == article }
|
57
131
|
end
|
58
132
|
|
59
|
-
context '
|
60
|
-
|
61
|
-
|
133
|
+
context '#destroy' do
|
134
|
+
subject { article }
|
135
|
+
its(:delete) { should be_true }
|
136
|
+
its(:destroy) { should be_true }
|
137
|
+
end
|
138
|
+
|
139
|
+
context '#reload' do
|
140
|
+
subject { article }
|
141
|
+
its(:'reload.id') { should == id }
|
142
|
+
specify { subject.reload(:select => :another_uuid).id.should == id }
|
143
|
+
end
|
144
|
+
|
145
|
+
context 'columns' do
|
146
|
+
[:id, :another_uuid].each do |column|
|
147
|
+
context column do
|
148
|
+
subject { model.columns_hash[column.to_s] }
|
149
|
+
its(:type) { should == :uuid }
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context 'typecasting' do
|
155
|
+
let(:uuid) { UUIDTools::UUID.random_create }
|
156
|
+
let(:string) { uuid.to_s }
|
157
|
+
context 'primary' do
|
158
|
+
before { article.id = string }
|
159
|
+
specify do
|
160
|
+
article.id.should == uuid
|
161
|
+
article.id_before_type_cast.should == string
|
162
|
+
end
|
163
|
+
specify do
|
164
|
+
article.id_before_type_cast.should == string
|
165
|
+
article.id.should == uuid
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context 'non-primary' do
|
170
|
+
before { article.another_uuid = string }
|
171
|
+
specify do
|
172
|
+
article.another_uuid.should == uuid
|
173
|
+
article.another_uuid_before_type_cast.should == string
|
174
|
+
end
|
175
|
+
specify do
|
176
|
+
article.another_uuid_before_type_cast.should == string
|
177
|
+
article.another_uuid.should == uuid
|
178
|
+
end
|
179
|
+
specify do
|
180
|
+
article.save
|
181
|
+
article.reload
|
182
|
+
article.another_uuid_before_type_cast.should == string
|
183
|
+
article.another_uuid.should == uuid
|
184
|
+
end
|
185
|
+
end
|
62
186
|
end
|
63
187
|
end
|
@@ -1,37 +1,29 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe UUIDTools::UUID do
|
4
|
+
let(:input) { "e4618518-cb9f-11e1-aa7c-14dae903e06a" }
|
5
|
+
let(:hex) { "E4618518CB9F11E1AA7C14DAE903E06A" }
|
6
|
+
let(:uuid) { described_class.parse input }
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
@param_out = "E4618518CB9F11E1AA7C14DAE903E06A"
|
8
|
+
context 'instance methods' do
|
9
|
+
subject { uuid }
|
10
|
+
let(:sql_out) { "x'e4618518cb9f11e1aa7c14dae903e06a'" }
|
9
11
|
|
10
|
-
|
12
|
+
its(:quoted_id) {should == sql_out}
|
13
|
+
its(:as_json) {should == hex}
|
14
|
+
its(:to_param) {should == hex}
|
11
15
|
end
|
12
16
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
+
describe '.serialize' do
|
18
|
+
subject { described_class }
|
19
|
+
let(:raw) { uuid.raw }
|
20
|
+
|
21
|
+
specify { subject.serialize(uuid).should == uuid }
|
22
|
+
specify { subject.serialize(input).should == uuid }
|
23
|
+
specify { subject.serialize(hex).should == uuid }
|
24
|
+
specify { subject.serialize(raw).should == uuid }
|
25
|
+
specify { subject.serialize(nil).should be_nil }
|
26
|
+
specify { subject.serialize('').should be_nil }
|
27
|
+
specify { subject.serialize(5).should be_nil }
|
17
28
|
end
|
18
|
-
|
19
|
-
describe '#quoted_id' do
|
20
|
-
it 'returns the SQL binary representation for the uuid' do
|
21
|
-
@uuid.quoted_id.should eql(@sql_out)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
describe '#as_json' do
|
26
|
-
it 'returns the uppercase hexdigest' do
|
27
|
-
@uuid.as_json.should eql(@param_out)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
describe '#to_param' do
|
32
|
-
it 'also returns the uppercase hexdigest' do
|
33
|
-
@uuid.to_param.should eql(@param_out)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
29
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -13,6 +13,7 @@ ActiveRecord::Base.establish_connection(ENV["DB"] || "sqlite3")
|
|
13
13
|
require 'activeuuid'
|
14
14
|
|
15
15
|
ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + "/support/migrate")
|
16
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, STDOUT)
|
16
17
|
|
17
18
|
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
18
19
|
Dir["#{File.dirname(__FILE__)}/fabricators/**/*.rb"].each { |f| require f }
|
@@ -38,4 +39,10 @@ RSpec.configure do |config|
|
|
38
39
|
config.after(:each) do
|
39
40
|
DatabaseCleaner.clean
|
40
41
|
end
|
42
|
+
|
43
|
+
def spec_for_adapter(&block)
|
44
|
+
switcher = ActiveUUID::SpecSupport::SpecForAdapter.new()
|
45
|
+
yield switcher
|
46
|
+
switcher.run(connection)
|
47
|
+
end
|
41
48
|
end
|
data/spec/support/database.yml
CHANGED
@@ -3,13 +3,10 @@ sqlite3:
|
|
3
3
|
database: ":memory:"
|
4
4
|
postgresql:
|
5
5
|
adapter: postgresql
|
6
|
-
|
7
|
-
password:
|
6
|
+
host: localhost
|
8
7
|
database: activeuuid_test
|
9
|
-
min_messages: ERROR
|
10
8
|
mysql:
|
11
9
|
adapter: mysql2
|
12
|
-
host: localhost
|
13
10
|
username: root
|
14
|
-
|
15
|
-
|
11
|
+
database: activeuuid_test
|
12
|
+
encoding: utf8
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'activeuuid'
|
2
|
+
|
3
|
+
module ActiveUUID::SpecSupport
|
4
|
+
class SpecForAdapter
|
5
|
+
def initialize
|
6
|
+
@specs = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
[:sqlite3, :mysql2, :postgresql].each do |name|
|
10
|
+
send :define_method, name do |&block|
|
11
|
+
@specs[name] = block
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def run(connection)
|
16
|
+
name = connection.adapter_name.downcase.to_sym
|
17
|
+
@specs[name].call() if(@specs.include? name)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activeuuid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-02-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -178,7 +178,7 @@ dependencies:
|
|
178
178
|
requirements:
|
179
179
|
- - ! '>='
|
180
180
|
- !ruby/object:Gem::Version
|
181
|
-
version: '
|
181
|
+
version: '3.1'
|
182
182
|
type: :runtime
|
183
183
|
prerelease: false
|
184
184
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -186,7 +186,7 @@ dependencies:
|
|
186
186
|
requirements:
|
187
187
|
- - ! '>='
|
188
188
|
- !ruby/object:Gem::Version
|
189
|
-
version: '
|
189
|
+
version: '3.1'
|
190
190
|
description: Add binary (not string) UUIDs to ActiveRecord in MySQL
|
191
191
|
email:
|
192
192
|
- nate@natemurray.com
|
@@ -197,10 +197,14 @@ files:
|
|
197
197
|
- .gitignore
|
198
198
|
- .rspec
|
199
199
|
- .rvmrc
|
200
|
+
- .travis.yml
|
200
201
|
- Gemfile
|
201
202
|
- README.mkd
|
202
203
|
- Rakefile
|
203
204
|
- activeuuid.gemspec
|
205
|
+
- gemfiles/Gemfile.rails-3-1
|
206
|
+
- gemfiles/Gemfile.rails-3-2
|
207
|
+
- gemfiles/Gemfile.rails-head
|
204
208
|
- lib/activeuuid.rb
|
205
209
|
- lib/activeuuid/patches.rb
|
206
210
|
- lib/activeuuid/railtie.rb
|
@@ -209,7 +213,6 @@ files:
|
|
209
213
|
- spec/fabricators/article_fabricator.rb
|
210
214
|
- spec/fabricators/uuid_article_fabricator.rb
|
211
215
|
- spec/lib/activerecord_spec.rb
|
212
|
-
- spec/lib/serializer_spec.rb
|
213
216
|
- spec/lib/uuid_mokeypatch_spec.rb
|
214
217
|
- spec/spec_helper.rb
|
215
218
|
- spec/support/database.yml
|
@@ -217,7 +220,8 @@ files:
|
|
217
220
|
- spec/support/migrate/20120817081813_create_uuid_articles.rb
|
218
221
|
- spec/support/models/article.rb
|
219
222
|
- spec/support/models/uuid_article.rb
|
220
|
-
|
223
|
+
- spec/support/spec_for_adapter.rb
|
224
|
+
homepage: https://github.com/jashmenn/activeuuid
|
221
225
|
licenses: []
|
222
226
|
post_install_message:
|
223
227
|
rdoc_options: []
|
@@ -231,7 +235,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
231
235
|
version: '0'
|
232
236
|
segments:
|
233
237
|
- 0
|
234
|
-
hash:
|
238
|
+
hash: 852897539311025223
|
235
239
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
236
240
|
none: false
|
237
241
|
requirements:
|
@@ -240,7 +244,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
240
244
|
version: '0'
|
241
245
|
segments:
|
242
246
|
- 0
|
243
|
-
hash:
|
247
|
+
hash: 852897539311025223
|
244
248
|
requirements: []
|
245
249
|
rubyforge_project:
|
246
250
|
rubygems_version: 1.8.24
|
@@ -251,7 +255,6 @@ test_files:
|
|
251
255
|
- spec/fabricators/article_fabricator.rb
|
252
256
|
- spec/fabricators/uuid_article_fabricator.rb
|
253
257
|
- spec/lib/activerecord_spec.rb
|
254
|
-
- spec/lib/serializer_spec.rb
|
255
258
|
- spec/lib/uuid_mokeypatch_spec.rb
|
256
259
|
- spec/spec_helper.rb
|
257
260
|
- spec/support/database.yml
|
@@ -259,3 +262,4 @@ test_files:
|
|
259
262
|
- spec/support/migrate/20120817081813_create_uuid_articles.rb
|
260
263
|
- spec/support/models/article.rb
|
261
264
|
- spec/support/models/uuid_article.rb
|
265
|
+
- spec/support/spec_for_adapter.rb
|
data/spec/lib/serializer_spec.rb
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ActiveUUID::UUIDSerializer do
|
4
|
-
|
5
|
-
before do
|
6
|
-
@input = "2d79b402-cba8-11e1-aa7c-14dae903e06a"
|
7
|
-
@hex = "2D79B402CBA811E1AA7C14DAE903E06A"
|
8
|
-
@uuid = UUIDTools::UUID.parse @input
|
9
|
-
@raw = @uuid.raw
|
10
|
-
@serializer = ActiveUUID::UUIDSerializer.new
|
11
|
-
end
|
12
|
-
|
13
|
-
describe '#load' do
|
14
|
-
it 'returns a UUID type verbatim' do
|
15
|
-
@serializer.load(@uuid).should eql(@uuid)
|
16
|
-
end
|
17
|
-
|
18
|
-
describe 'loads a given uuid' do
|
19
|
-
it 'handles uuid string' do
|
20
|
-
@serializer.load(@input).should eql(@uuid)
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'handles uuid hexdigest string' do
|
24
|
-
@serializer.load(@hex).should eql(@uuid)
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'handles raw uuid data' do
|
28
|
-
@serializer.load(@raw).should eql(@uuid)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'returns nil for nil' do
|
33
|
-
@serializer.load(nil).should be_nil
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'returns nil for ""' do
|
37
|
-
@serializer.load('').should be_nil
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'returns nil for other types' do
|
41
|
-
@serializer.load(5).should be_nil
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
describe '#dump' do
|
46
|
-
it 'returns the raw value of a passed uuid' do
|
47
|
-
@serializer.dump(@uuid).should eql(@raw)
|
48
|
-
end
|
49
|
-
|
50
|
-
describe 'loads a given uuid' do
|
51
|
-
it 'handles uuid string' do
|
52
|
-
@serializer.dump(@input).should eql(@raw)
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'handles uuid hexdigest string' do
|
56
|
-
@serializer.dump(@hex).should eql(@raw)
|
57
|
-
end
|
58
|
-
|
59
|
-
it 'handles raw uuid data' do
|
60
|
-
@serializer.dump(@raw).should eql(@raw)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'returns nil for nil' do
|
65
|
-
@serializer.dump(nil).should be_nil
|
66
|
-
end
|
67
|
-
|
68
|
-
it 'returns nil for ""' do
|
69
|
-
@serializer.dump('').should be_nil
|
70
|
-
end
|
71
|
-
|
72
|
-
it 'returns nil for other types' do
|
73
|
-
@serializer.dump(5).should be_nil
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|