object_id_gem 1.0.6
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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +44 -0
- data/CHANGES.md +23 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +225 -0
- data/Rakefile +6 -0
- data/lib/objectid_columns.rb +127 -0
- data/lib/objectid_columns/active_record/base.rb +33 -0
- data/lib/objectid_columns/active_record/relation.rb +40 -0
- data/lib/objectid_columns/arel/visitors/to_sql.rb +88 -0
- data/lib/objectid_columns/dynamic_methods_module.rb +127 -0
- data/lib/objectid_columns/extensions.rb +41 -0
- data/lib/objectid_columns/has_objectid_columns.rb +47 -0
- data/lib/objectid_columns/objectid_columns_manager.rb +451 -0
- data/lib/objectid_columns/version.rb +4 -0
- data/object_id_gem.gemspec +71 -0
- data/spec/objectid_columns/helpers/database_helper.rb +178 -0
- data/spec/objectid_columns/helpers/system_helpers.rb +92 -0
- data/spec/objectid_columns/system/basic_system_spec.rb +600 -0
- data/spec/objectid_columns/system/extensions_spec.rb +69 -0
- metadata +194 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'objectid_columns/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "object_id_gem"
|
8
|
+
spec.version = ObjectidColumns::VERSION
|
9
|
+
spec.authors = ["Andrew Geweke"]
|
10
|
+
spec.email = ["ageweke@swiftype.com"]
|
11
|
+
spec.summary = %q{Transparently store MongoDB ObjectId values in ActiveRecord.}
|
12
|
+
spec.homepage = "https://www.github.com/swiftype/objectid_columns"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files`.split($/)
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
|
21
|
+
ar_version = ENV['OBJECTID_COLUMNS_AR_TEST_VERSION']
|
22
|
+
ar_version = ar_version.strip if ar_version
|
23
|
+
|
24
|
+
version_spec = case ar_version
|
25
|
+
when nil then [ ">= 5.0"]
|
26
|
+
when 'master' then nil
|
27
|
+
else [ "=#{ar_version}" ]
|
28
|
+
end
|
29
|
+
|
30
|
+
if version_spec
|
31
|
+
spec.add_dependency("activerecord", *version_spec)
|
32
|
+
spec.add_dependency("activesupport", *version_spec)
|
33
|
+
end
|
34
|
+
|
35
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
36
|
+
spec.add_development_dependency "rake"
|
37
|
+
spec.add_development_dependency "rspec", "~> 2.14"
|
38
|
+
spec.add_development_dependency "moped", "~> 1.5" unless RUBY_VERSION =~ /^1\.8\./
|
39
|
+
spec.add_development_dependency "bson", "~> 1.9"
|
40
|
+
|
41
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'spec', 'objectid_columns', 'helpers', 'database_helper'))
|
42
|
+
database_gem_name = ObjectidColumns::Helpers::DatabaseHelper.maybe_database_gem_name
|
43
|
+
|
44
|
+
# Ugh. Later versions of the 'mysql2' gem are incompatible with AR 3.0.x; so, here, we explicitly trap that case
|
45
|
+
# and use an earlier version of that Gem.
|
46
|
+
if database_gem_name && database_gem_name == 'mysql2' && ar_version && ar_version =~ /^3\.0\./
|
47
|
+
spec.add_development_dependency('mysql2', '~> 0.2.0')
|
48
|
+
else
|
49
|
+
spec.add_development_dependency(database_gem_name)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Double ugh. Basically, composite_primary_keys -- as useful as it is! -- is also incredibly incompatible with so
|
53
|
+
# much stuff:
|
54
|
+
#
|
55
|
+
# * Under Ruby 1.9+ with Postgres, it causes binary strings sent to or from the database to get truncated
|
56
|
+
# at the first null byte (!), which completely breaks binary-column support;
|
57
|
+
# * Under JRuby with ActiveRecord 3.0, it's completely broken;
|
58
|
+
# * Under JRuby with ActiveRecord 3.1 and PostgreSQL, it's also broken.
|
59
|
+
#
|
60
|
+
# In these cases, we simply don't load or test against composite_primary_keys; our code is good, but the interactions
|
61
|
+
# between CPK and the rest of the system make it impossible to run those tests. There is corresponding code in our
|
62
|
+
# +basic_system_spec+ to exclude those combinations.
|
63
|
+
cpk_allowed = true
|
64
|
+
cpk_allowed = false if database_gem_name =~ /(pg|postgres)/i && RUBY_VERSION =~ /^(1\.9)|(2\.)/ && ar_version && ar_version =~ /^4\.(0|1)\./
|
65
|
+
cpk_allowed = false if defined?(RUBY_ENGINE) && (RUBY_ENGINE == 'jruby') && ar_version && ar_version =~ /^3\.0\./
|
66
|
+
cpk_allowed = false if defined?(RUBY_ENGINE) && (RUBY_ENGINE == 'jruby') && ar_version && ar_version =~ /^3\.1\./ && database_gem_name =~ /(pg|postgres)/i
|
67
|
+
|
68
|
+
if cpk_allowed
|
69
|
+
spec.add_development_dependency "composite_primary_keys"
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
module ObjectidColumns
|
2
|
+
module Helpers
|
3
|
+
class DatabaseHelper
|
4
|
+
class InvalidDatabaseConfigurationError < StandardError; end
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def maybe_database_gem_name
|
8
|
+
begin
|
9
|
+
dh = new
|
10
|
+
dh.database_gem_name
|
11
|
+
rescue InvalidDatabaseConfigurationError => idce
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
config # make sure we raise on instantiation if configuration is invalid
|
19
|
+
end
|
20
|
+
|
21
|
+
def database_type
|
22
|
+
case database_gem_name
|
23
|
+
when /mysql/i then :mysql
|
24
|
+
when /sqlite/i then :sqlite
|
25
|
+
when /pg/i, /postgres/i then :postgres
|
26
|
+
else raise "Unknown database type for Gem name: #{database_gem_name.inspect}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def setup_activerecord!
|
31
|
+
require 'active_record'
|
32
|
+
require config[:require]
|
33
|
+
::ActiveRecord::Base.establish_connection(config[:config])
|
34
|
+
|
35
|
+
require 'logger'
|
36
|
+
require 'stringio'
|
37
|
+
@logs = StringIO.new
|
38
|
+
::ActiveRecord::Base.logger = Logger.new(@logs)
|
39
|
+
|
40
|
+
if config[:config][:adapter] == 'sqlite3'
|
41
|
+
sqlite_version = ::ActiveRecord::Base.connection.send(:sqlite_version).instance_variable_get("@version").inspect rescue "unknown"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def table_name(name)
|
46
|
+
"objectidcols_spec_#{name}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def database_gem_name
|
50
|
+
config[:database_gem_name]
|
51
|
+
end
|
52
|
+
|
53
|
+
def adapter_name
|
54
|
+
config[:config][:adapter]
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
def config
|
59
|
+
config_from_config_file || travis_ci_config_from_environment || invalid_config_file!
|
60
|
+
end
|
61
|
+
|
62
|
+
def config_from_config_file
|
63
|
+
return nil unless File.exist?(config_file_path)
|
64
|
+
require config_file_path
|
65
|
+
|
66
|
+
return nil unless defined?(OBJECTID_COLUMNS_SPEC_DATABASE_CONFIG)
|
67
|
+
return nil unless OBJECTID_COLUMNS_SPEC_DATABASE_CONFIG.kind_of?(Hash)
|
68
|
+
|
69
|
+
return nil unless OBJECTID_COLUMNS_SPEC_DATABASE_CONFIG[:require]
|
70
|
+
return nil unless OBJECTID_COLUMNS_SPEC_DATABASE_CONFIG[:database_gem_name]
|
71
|
+
|
72
|
+
return nil unless OBJECTID_COLUMNS_SPEC_DATABASE_CONFIG
|
73
|
+
OBJECTID_COLUMNS_SPEC_DATABASE_CONFIG
|
74
|
+
end
|
75
|
+
|
76
|
+
def travis_ci_config_from_environment
|
77
|
+
dbtype = (ENV['OBJECTID_COLUMNS_TRAVIS_CI_DATABASE_TYPE'] || '').strip.downcase
|
78
|
+
is_jruby = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
79
|
+
|
80
|
+
if is_jruby
|
81
|
+
case dbtype
|
82
|
+
when 'mysql'
|
83
|
+
{
|
84
|
+
:require => 'activerecord-jdbcmysql-adapter',
|
85
|
+
:database_gem_name => 'activerecord-jdbcmysql-adapter',
|
86
|
+
:config => {
|
87
|
+
:adapter => 'jdbcmysql',
|
88
|
+
:database => 'myapp_test',
|
89
|
+
:username => 'travis',
|
90
|
+
:encoding => 'utf8'
|
91
|
+
}
|
92
|
+
}
|
93
|
+
when 'postgres', 'postgresql'
|
94
|
+
{
|
95
|
+
:require => 'activerecord-jdbcpostgresql-adapter',
|
96
|
+
:database_gem_name => 'activerecord-jdbcpostgresql-adapter',
|
97
|
+
:config => {
|
98
|
+
:adapter => 'jdbcpostgresql',
|
99
|
+
:database => 'myapp_test',
|
100
|
+
:username => 'postgres'
|
101
|
+
}
|
102
|
+
}
|
103
|
+
when 'sqlite'
|
104
|
+
{
|
105
|
+
:require => 'activerecord-jdbcsqlite3-adapter',
|
106
|
+
:database_gem_name => 'activerecord-jdbcsqlite3-adapter',
|
107
|
+
:config => {
|
108
|
+
:adapter => 'jdbcsqlite3',
|
109
|
+
:database => ':memory:'
|
110
|
+
}
|
111
|
+
}
|
112
|
+
when '', nil then nil
|
113
|
+
else
|
114
|
+
raise "Unknown Travis CI database type: #{dbtype.inspect}"
|
115
|
+
end
|
116
|
+
else
|
117
|
+
case dbtype
|
118
|
+
when 'postgres', 'postgresql'
|
119
|
+
{
|
120
|
+
:require => 'pg',
|
121
|
+
:database_gem_name => 'pg',
|
122
|
+
:config => {
|
123
|
+
:adapter => 'postgresql',
|
124
|
+
:database => 'myapp_test',
|
125
|
+
:username => 'postgres',
|
126
|
+
:min_messages => 'WARNING'
|
127
|
+
}
|
128
|
+
}
|
129
|
+
when 'mysql'
|
130
|
+
{
|
131
|
+
:require => 'mysql2',
|
132
|
+
:database_gem_name => 'mysql2',
|
133
|
+
:config => {
|
134
|
+
:adapter => 'mysql2',
|
135
|
+
:database => 'myapp_test',
|
136
|
+
:username => 'travis',
|
137
|
+
:encoding => 'utf8'
|
138
|
+
}
|
139
|
+
}
|
140
|
+
when 'sqlite'
|
141
|
+
{
|
142
|
+
:require => 'sqlite3',
|
143
|
+
:database_gem_name => 'sqlite3',
|
144
|
+
:config => {
|
145
|
+
:adapter => 'sqlite3',
|
146
|
+
:database => ':memory:',
|
147
|
+
:timeout => 500
|
148
|
+
}
|
149
|
+
}
|
150
|
+
when '', nil then nil
|
151
|
+
else
|
152
|
+
raise "Unknown Travis CI database type: #{dbtype.inspect}"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def config_file_path
|
158
|
+
@config_file_path ||= File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_database_config.rb'))
|
159
|
+
end
|
160
|
+
|
161
|
+
def invalid_config_file!
|
162
|
+
raise Errno::ENOENT, %{In order to run specs for ObjectIdColumns, you need to create a file at:
|
163
|
+
|
164
|
+
#{config_file_path}
|
165
|
+
|
166
|
+
...that defines a top-level OBJECTID_COLUMNS_SPEC_DATABASE_CONFIG hash, with members:
|
167
|
+
|
168
|
+
:require => 'name_of_adapter_to_require',
|
169
|
+
:database_gem_name => 'name_of_gem_for_adapter',
|
170
|
+
:config => { ...whatever ActiveRecord::Base.establish_connection should be passed... }
|
171
|
+
|
172
|
+
Alternatively, if you're running under Travis CI, you can set the environment variable
|
173
|
+
OBJECTID_COLUMNS_TRAVIS_CI_DATABASE_TYPE to 'postgres', 'mysql', or 'sqlite', and it will
|
174
|
+
use the correct configuration for testing on Travis CI.}
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'active_record/migration'
|
3
|
+
require 'objectid_columns/helpers/database_helper'
|
4
|
+
|
5
|
+
module ObjectidColumns
|
6
|
+
module Helpers
|
7
|
+
module SystemHelpers
|
8
|
+
def migrate(&block)
|
9
|
+
migration_class = Class.new(::ActiveRecord::Migration)
|
10
|
+
metaclass = migration_class.class_eval { class << self; self; end }
|
11
|
+
metaclass.instance_eval { define_method(:up, &block) }
|
12
|
+
|
13
|
+
::ActiveRecord::Migration.suppress_messages do
|
14
|
+
migration_class.migrate(:up)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def define_model_class(name, table_name, options = { }, &block)
|
19
|
+
superclass = options[:superclass] || ::ActiveRecord::Base
|
20
|
+
model_class = Class.new(superclass)
|
21
|
+
::Object.send(:remove_const, name) if ::Object.const_defined?(name)
|
22
|
+
::Object.const_set(name, model_class)
|
23
|
+
model_class.table_name = table_name if table_name
|
24
|
+
model_class.class_eval(&block) if block
|
25
|
+
model_class
|
26
|
+
end
|
27
|
+
|
28
|
+
def ensure_database_is_set_up!
|
29
|
+
::ObjectidColumns::Helpers::SystemHelpers.database_helper
|
30
|
+
end
|
31
|
+
|
32
|
+
class << self
|
33
|
+
def database_helper
|
34
|
+
@database_helper ||= begin
|
35
|
+
out = ObjectidColumns::Helpers::DatabaseHelper.new
|
36
|
+
out.setup_activerecord!
|
37
|
+
out
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def binary_column(length)
|
42
|
+
case ObjectidColumns::Helpers::SystemHelpers.database_helper.adapter_name.to_s
|
43
|
+
when /mysql/, /sqlite/ then "BINARY(#{length})"
|
44
|
+
when /postgres/ then "BYTEA"
|
45
|
+
else raise "Don't yet know how to define a binary column for database #{OBJECTID_COLUMNS_SPEC_DATABASE_CONFIG[:config][:adapter].inspect}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def supports_length_limits_on_binary_columns?
|
50
|
+
case ObjectidColumns::Helpers::SystemHelpers.database_helper.adapter_name.to_s
|
51
|
+
when /mysql/, /sqlite/ then true
|
52
|
+
when /postgres/ then false
|
53
|
+
else raise "Don't yet know whether database #{OBJECTID_COLUMNS_SPEC_DATABASE_CONFIG[:config][:adapter].inspect} supports limits on binary columns"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def create_standard_system_spec_tables!
|
59
|
+
migrate do
|
60
|
+
drop_table :objectidcols_spec_table rescue nil
|
61
|
+
create_table :objectidcols_spec_table do |t|
|
62
|
+
t.column :perfect_b_oid, ObjectidColumns::Helpers::SystemHelpers.binary_column(12)
|
63
|
+
t.column :longer_b_oid, ObjectidColumns::Helpers::SystemHelpers.binary_column(15)
|
64
|
+
|
65
|
+
t.column :too_short_b, ObjectidColumns::Helpers::SystemHelpers.binary_column(11)
|
66
|
+
t.column :perfect_b, ObjectidColumns::Helpers::SystemHelpers.binary_column(12)
|
67
|
+
t.column :longer_b, ObjectidColumns::Helpers::SystemHelpers.binary_column(15)
|
68
|
+
|
69
|
+
t.column :perfect_s_oid, 'VARCHAR(24)'
|
70
|
+
t.column :longer_s_oid, 'VARCHAR(30)'
|
71
|
+
|
72
|
+
t.column :too_short_s, 'VARCHAR(23)'
|
73
|
+
t.column :perfect_s, 'VARCHAR(24)'
|
74
|
+
t.column :longer_s, 'VARCHAR(30)'
|
75
|
+
|
76
|
+
t.integer :some_int_column
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def create_standard_system_spec_models!
|
82
|
+
define_model_class(:Spectable, 'objectidcols_spec_table') { }
|
83
|
+
end
|
84
|
+
|
85
|
+
def drop_standard_system_spec_tables!
|
86
|
+
migrate do
|
87
|
+
drop_table :objectidcols_spec_table rescue nil
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,600 @@
|
|
1
|
+
require 'objectid_columns'
|
2
|
+
require 'objectid_columns/helpers/system_helpers'
|
3
|
+
|
4
|
+
# See the gemspec for more details -- basically, we don't always load composite_primary_keys, because it's pretty
|
5
|
+
# broken and doesn't work with a fair number of combinations of Ruby versions, databases, and so on. So if it's not
|
6
|
+
# available, we skip those tests.
|
7
|
+
begin
|
8
|
+
require 'composite_primary_keys'
|
9
|
+
$composite_primary_keys_available = true
|
10
|
+
rescue LoadError => le
|
11
|
+
# nothing here
|
12
|
+
end
|
13
|
+
|
14
|
+
unless defined?(VALID_OBJECTID_CLASSES)
|
15
|
+
VALID_OBJECTID_CLASSES = [ BSON::ObjectId ]
|
16
|
+
VALID_OBJECTID_CLASSES << Moped::BSON::ObjectId if defined?(Moped::BSON::ObjectId)
|
17
|
+
end
|
18
|
+
|
19
|
+
RSpec::Matchers.define :be_an_objectid_object do
|
20
|
+
match do |actual|
|
21
|
+
VALID_OBJECTID_CLASSES.detect { |c| actual.kind_of?(c) }
|
22
|
+
end
|
23
|
+
failure_message_for_should do |actual|
|
24
|
+
"expected that #{actual} (#{actual.class}) would be an instance of BSON::ObjectId or Moped::BSON::ObjectId"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
RSpec::Matchers.define :be_the_same_objectid_as do |expected|
|
29
|
+
match do |actual|
|
30
|
+
net_expected = expected ? expected.to_bson_id.to_s : expected
|
31
|
+
net_actual = actual ? actual.to_bson_id.to_s : actual
|
32
|
+
net_expected == net_actual
|
33
|
+
end
|
34
|
+
failure_message_for_should do |actual|
|
35
|
+
"expected that #{actual} (#{actual.class}) would be the same ObjectId as #{expected} (#{expected.class})"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
RSpec::Matchers.define :be_an_objectid_object_matching do |expected|
|
40
|
+
match do |actual|
|
41
|
+
net_expected = expected ? expected.to_bson_id.to_s : expected
|
42
|
+
net_actual = actual ? actual.to_bson_id.to_s : actual
|
43
|
+
(net_expected == net_actual) && (VALID_OBJECTID_CLASSES.detect { |c| actual.kind_of?(c) })
|
44
|
+
end
|
45
|
+
failure_message_for_should do |actual|
|
46
|
+
"expected that #{actual} (#{actual.class}) would be an ObjectId object equal to #{expected} (#{expected.class})"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "ObjectidColumns basic operations" do
|
51
|
+
include ObjectidColumns::Helpers::SystemHelpers
|
52
|
+
|
53
|
+
before :each do
|
54
|
+
ensure_database_is_set_up!
|
55
|
+
|
56
|
+
create_standard_system_spec_tables!
|
57
|
+
create_standard_system_spec_models!
|
58
|
+
end
|
59
|
+
|
60
|
+
after :each do
|
61
|
+
drop_standard_system_spec_tables!
|
62
|
+
end
|
63
|
+
|
64
|
+
VALID_OBJECTID_CLASSES.each do |test_class|
|
65
|
+
context "using test class #{test_class}" do
|
66
|
+
before :each do
|
67
|
+
@tc = test_class
|
68
|
+
end
|
69
|
+
|
70
|
+
def new_oid
|
71
|
+
@tc.new
|
72
|
+
end
|
73
|
+
|
74
|
+
context "with an STI table and model" do
|
75
|
+
before :each do
|
76
|
+
migrate do
|
77
|
+
drop_table :objectidcols_spec_table_sti rescue nil
|
78
|
+
create_table :objectidcols_spec_table_sti do |t|
|
79
|
+
t.string :type
|
80
|
+
t.column :some_oid, 'VARCHAR(24)'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
after :each do
|
86
|
+
migrate do
|
87
|
+
drop_table :objectidcols_spec_table_sti rescue nil
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
let(:parent_model_class) { define_model_class(:SpectableStiParent, 'objectidcols_spec_table_sti') { has_objectid_columns } }
|
92
|
+
let(:child_model_class) { define_model_class(:SpectableStiChild, 'objectidcols_spec_table_sti', :superclass => parent_model_class) { } }
|
93
|
+
|
94
|
+
it "should work from both the parent and child class" do
|
95
|
+
id_1 = new_oid
|
96
|
+
id_2 = new_oid
|
97
|
+
|
98
|
+
parent_instance = parent_model_class.new(:some_oid => id_1)
|
99
|
+
parent_instance.save!
|
100
|
+
|
101
|
+
child_instance = child_model_class.new(:some_oid => id_2)
|
102
|
+
child_instance.save!
|
103
|
+
|
104
|
+
all_models = parent_model_class.all.to_a
|
105
|
+
expect(all_models.length).to eq(2)
|
106
|
+
parent_instance_again = all_models.detect { |m| m.id == parent_instance.id }
|
107
|
+
child_instance_again = all_models.detect { |m| m.id == child_instance.id }
|
108
|
+
|
109
|
+
expect(parent_instance_again.some_oid).to be_an_objectid_object_matching(id_1)
|
110
|
+
expect(child_instance_again.some_oid).to be_an_objectid_object_matching(id_2)
|
111
|
+
|
112
|
+
child_models = child_model_class.all.to_a
|
113
|
+
expect(child_models.length).to eq(1)
|
114
|
+
expect(child_models[0].some_oid).to be_an_objectid_object_matching(id_2)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should not allow defining a column that's too short" do
|
119
|
+
if ObjectidColumns::Helpers::SystemHelpers.supports_length_limits_on_binary_columns?
|
120
|
+
expect { ::Spectable.class_eval { has_objectid_column :too_short_b } }.to raise_error(ArgumentError)
|
121
|
+
expect { ::Spectable.class_eval { has_objectid_column :too_short_s } }.to raise_error(ArgumentError)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should not allow defining a column that's the wrong type" do
|
126
|
+
expect { ::Spectable.class_eval { has_objectid_column :some_int_column } }.to raise_error(ArgumentError)
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should not allow defining a column that doesn't exist" do
|
130
|
+
expect { ::Spectable.class_eval { has_objectid_column :unknown_column } }.to raise_error(ArgumentError)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should not fail if the table doesn't exist" do
|
134
|
+
define_model_class(:SpectableNonexistent, 'objectidcols_spec_table_nonexistent') { }
|
135
|
+
expect { ::SpectableNonexistent.class_eval { has_objectid_column :foo } }.to_not raise_error
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should not fail if declared as a primary key and the table doesn't exist" do
|
139
|
+
define_model_class(:SpectableNonexistent, 'objectidcols_spec_table_nonexistent') { }
|
140
|
+
expect { ::SpectableNonexistent.class_eval { has_objectid_primary_key } }.to_not raise_error
|
141
|
+
expect { ::SpectableNonexistent.class_eval { has_objectid_primary_key :foo } }.to_not raise_error
|
142
|
+
end
|
143
|
+
|
144
|
+
if $composite_primary_keys_available
|
145
|
+
describe "composite primary key support" do
|
146
|
+
context "with an implicit PK" do
|
147
|
+
before :each do
|
148
|
+
migrate do
|
149
|
+
drop_table :objectidcols_spec_pk_cmp rescue nil
|
150
|
+
create_table :objectidcols_spec_pk_cmp, :id => false do |t|
|
151
|
+
t.binary :some_oid, :null => false
|
152
|
+
t.string :more_pk, :null => false
|
153
|
+
t.string :value
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
define_model_class(:SpectablePkCmp, :objectidcols_spec_pk_cmp) do
|
158
|
+
if respond_to?(:primary_keys=)
|
159
|
+
self.primary_keys = [ 'some_oid', 'more_pk' ]
|
160
|
+
else
|
161
|
+
self.set_primary_keys('some_oid', 'more_pk')
|
162
|
+
end
|
163
|
+
end
|
164
|
+
::SpectablePkCmp.class_eval { has_objectid_primary_key }
|
165
|
+
@model_class = ::SpectablePkCmp
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should allow using a composite primary key in individual parts" do
|
169
|
+
pending "disabled" unless $composite_primary_keys_available
|
170
|
+
|
171
|
+
instance = @model_class.new
|
172
|
+
instance.some_oid = new_oid
|
173
|
+
instance.more_pk = "foo"
|
174
|
+
instance.value = "foo value"
|
175
|
+
instance.save!
|
176
|
+
|
177
|
+
instance_again = @model_class.find([ instance.some_oid, instance.more_pk ])
|
178
|
+
expect(instance_again.value).to eq(instance.value)
|
179
|
+
expect(instance_again.some_oid).to eq(instance.some_oid)
|
180
|
+
expect(instance_again.more_pk).to eq(instance.more_pk)
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should allow using a composite primary key as a whole" do
|
184
|
+
pending "disabled" unless $composite_primary_keys_available
|
185
|
+
|
186
|
+
oid = new_oid
|
187
|
+
instance = @model_class.new
|
188
|
+
instance.id = [ oid, "foo" ]
|
189
|
+
instance.value = "foo value"
|
190
|
+
instance.save!
|
191
|
+
|
192
|
+
expect(instance.some_oid).to be_an_objectid_object_matching(oid)
|
193
|
+
expect(instance.more_pk).to eq("foo")
|
194
|
+
expect(instance.value).to eq("foo value")
|
195
|
+
|
196
|
+
instance_again = @model_class.find(instance.id)
|
197
|
+
expect(instance_again.id).to eq(instance.id)
|
198
|
+
expect(instance_again.some_oid).to be_an_objectid_object_matching(oid)
|
199
|
+
expect(instance_again.more_pk).to eq("foo")
|
200
|
+
expect(instance_again.value).to eq("foo value")
|
201
|
+
expect(instance_again.id).to be_kind_of(Array)
|
202
|
+
expect(instance_again.id.length).to eq(2)
|
203
|
+
expect(instance_again.id[0]).to be_an_objectid_object_matching(oid)
|
204
|
+
expect(instance_again.id[1]).to eq("foo")
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
context "with an explicit PK" do
|
209
|
+
before :each do
|
210
|
+
migrate do
|
211
|
+
drop_table :objectidcols_spec_pk_cmp_2 rescue nil
|
212
|
+
create_table :objectidcols_spec_pk_cmp_2, :id => false do |t|
|
213
|
+
t.binary :one, :null => false
|
214
|
+
t.string :two, :null => false
|
215
|
+
t.string :three, :null => false
|
216
|
+
t.string :value
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
define_model_class(:SpectablePkCmp2, :objectidcols_spec_pk_cmp_2) do
|
221
|
+
if respond_to?(:primary_keys=)
|
222
|
+
self.primary_keys = [ 'one', 'two', 'three' ]
|
223
|
+
else
|
224
|
+
self.set_primary_keys('one', 'two', 'three')
|
225
|
+
end
|
226
|
+
end
|
227
|
+
::SpectablePkCmp2.class_eval { has_objectid_primary_key :one, :three }
|
228
|
+
@model_class = ::SpectablePkCmp2
|
229
|
+
end
|
230
|
+
|
231
|
+
it "should allow using a composite primary key that's partially ObjectId and partially not" do
|
232
|
+
instance = @model_class.new
|
233
|
+
instance.two = "foo"
|
234
|
+
instance.value = "foo_value"
|
235
|
+
instance.save!
|
236
|
+
|
237
|
+
expect(instance.id).to be_kind_of(Array)
|
238
|
+
expect(instance.id[0]).to be_an_objectid_object
|
239
|
+
expect(instance.id[1]).to eq("foo")
|
240
|
+
expect(instance.id[2]).to be_an_objectid_object
|
241
|
+
|
242
|
+
id = instance.id
|
243
|
+
instance_again = @model_class.find(id)
|
244
|
+
expect(instance_again.id).to eq(id)
|
245
|
+
expect(instance_again.id[0]).to be_an_objectid_object_matching(id[0])
|
246
|
+
expect(instance_again.id[1]).to eq("foo")
|
247
|
+
expect(instance_again.id[2]).to be_an_objectid_object_matching(id[2])
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
describe "primary key column support" do
|
254
|
+
before :each do
|
255
|
+
migrate do
|
256
|
+
drop_table :objectidcols_spec_pk_bin rescue nil
|
257
|
+
create_table :objectidcols_spec_pk_bin, :id => false do |t|
|
258
|
+
t.binary :id, :null => false
|
259
|
+
t.string :name
|
260
|
+
end
|
261
|
+
|
262
|
+
drop_table :objectidcols_spec_pk_str rescue nil
|
263
|
+
create_table :objectidcols_spec_pk_str, :id => false do |t|
|
264
|
+
t.string :id, :null => false
|
265
|
+
t.string :name
|
266
|
+
end
|
267
|
+
|
268
|
+
drop_table :objectidcols_spec_pk_alt rescue nil
|
269
|
+
create_table :objectidcols_spec_pk_alt, :id => false do |t|
|
270
|
+
t.binary :some_name, :null => false
|
271
|
+
t.string :name
|
272
|
+
end
|
273
|
+
|
274
|
+
drop_table :objectidcols_spec_pk_implicit rescue nil
|
275
|
+
create_table :objectidcols_spec_pk_implicit, :id => false do |t|
|
276
|
+
t.binary :some_name, :null => false
|
277
|
+
t.string :name
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
define_model_class(:SpectablePkBin, :objectidcols_spec_pk_bin) { self.primary_key = 'id' }
|
282
|
+
define_model_class(:SpectablePkStr, :objectidcols_spec_pk_str) { self.primary_key = 'id' }
|
283
|
+
define_model_class(:SpectablePkAlt, :objectidcols_spec_pk_alt) { self.primary_key = 'some_name' }
|
284
|
+
define_model_class(:SpectablePkImplicit, :objectidcols_spec_pk_implicit) { }
|
285
|
+
|
286
|
+
::SpectablePkBin.class_eval { has_objectid_primary_key }
|
287
|
+
::SpectablePkStr.class_eval { has_objectid_primary_key }
|
288
|
+
::SpectablePkAlt.class_eval { has_objectid_primary_key }
|
289
|
+
::SpectablePkImplicit.class_eval { has_objectid_primary_key :some_name }
|
290
|
+
end
|
291
|
+
|
292
|
+
after :each do
|
293
|
+
drop_table :objectidcols_spec_pk_bin rescue nil
|
294
|
+
drop_table :objectidcols_spec_pk_str rescue nil
|
295
|
+
drop_table :objectidcols_spec_pk_table_alt rescue nil
|
296
|
+
drop_table :objectidcols_spec_pk_implicit rescue nil
|
297
|
+
end
|
298
|
+
|
299
|
+
[ :SpectablePkBin, :SpectablePkStr, :SpectablePkAlt, :SpectablePkImplicit ].each do |model_class|
|
300
|
+
context "on model #{model_class}" do
|
301
|
+
before :each do
|
302
|
+
@model_class = model_class.to_s.constantize
|
303
|
+
end
|
304
|
+
|
305
|
+
it "should fail autodetection, since there are no columns ending in _oid" do
|
306
|
+
expect { @model_class.has_objectid_columns }.to raise_error(ArgumentError)
|
307
|
+
end
|
308
|
+
|
309
|
+
it "should allow using a binary ObjectId column as a primary key" do
|
310
|
+
r1 = @model_class.new
|
311
|
+
r1.name = 'row 1'
|
312
|
+
expect(r1.id).to be_nil
|
313
|
+
r1.save!
|
314
|
+
expect(r1.id).to_not be_nil
|
315
|
+
expect(r1.id).to be_an_objectid_object
|
316
|
+
r1_id = r1.id
|
317
|
+
|
318
|
+
r2 = @model_class.new
|
319
|
+
r2.name = 'row 2'
|
320
|
+
expect(r2.id).to be_nil
|
321
|
+
r2.save!
|
322
|
+
expect(r2.id).to_not be_nil
|
323
|
+
expect(r2.id).to be_an_objectid_object
|
324
|
+
r2_id = r2.id
|
325
|
+
|
326
|
+
expect(r1.send(@model_class.primary_key)).to be_an_objectid_object_matching(r1.id)
|
327
|
+
expect(r2.send(@model_class.primary_key)).to be_an_objectid_object_matching(r2.id)
|
328
|
+
|
329
|
+
r1_again = @model_class.find(r1.id)
|
330
|
+
expect(r1_again.name).to eq('row 1')
|
331
|
+
|
332
|
+
r2_again = @model_class.find(r2.id)
|
333
|
+
expect(r2_again.name).to eq('row 2')
|
334
|
+
|
335
|
+
expect(@model_class.find([ r1.id, r2. id ]).map(&:id).sort_by(&:to_s)).to eq([ r1_id, r2_id ].sort_by(&:to_s))
|
336
|
+
|
337
|
+
expect(@model_class.where(:name => 'row 1').first.id).to eq(r1_id)
|
338
|
+
expect(@model_class.where(:name => 'row 2').first.id).to eq(r2_id)
|
339
|
+
|
340
|
+
find_by_id_method = "find_by_#{@model_class.primary_key}"
|
341
|
+
expect(@model_class.send(find_by_id_method, r1.id).id).to eq(r1_id)
|
342
|
+
expect(@model_class.send(find_by_id_method, r2.id).id).to eq(r2_id)
|
343
|
+
expect(@model_class.send(find_by_id_method, new_oid)).to be_nil
|
344
|
+
end
|
345
|
+
|
346
|
+
it "should let you load and save objects properly" do
|
347
|
+
r1 = @model_class.new
|
348
|
+
r1.name = 'row 1'
|
349
|
+
r1.id = new_oid
|
350
|
+
r1.save!
|
351
|
+
|
352
|
+
r1_again = @model_class.find(@tc.from_string(r1.id.to_s))
|
353
|
+
expect(r1_again.name).to eq('row 1')
|
354
|
+
r1_again.id = @tc.from_string(r1.id.to_s)
|
355
|
+
r1_again.name = 'row 1 again'
|
356
|
+
r1_again.save!
|
357
|
+
|
358
|
+
r1_yet_again = @model_class.find(r1_again.id)
|
359
|
+
expect(r1_yet_again.name).to eq('row 1 again')
|
360
|
+
end
|
361
|
+
|
362
|
+
it "should not pick up primary-key columns automatically, even if they're named _oid" do
|
363
|
+
migrate do
|
364
|
+
drop_table :objectidcols_spec_pk_auto rescue nil
|
365
|
+
create_table :objectidcols_spec_pk_auto, :id => false do |t|
|
366
|
+
t.binary :foo_oid, :null => false
|
367
|
+
t.binary :bar_oid
|
368
|
+
t.string :name
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
define_model_class(:SpectablePkAuto, :objectidcols_spec_pk_auto) { self.primary_key = 'foo_oid' }
|
373
|
+
|
374
|
+
::SpectablePkAuto.has_objectid_columns
|
375
|
+
r = ::SpectablePkAuto.new
|
376
|
+
r.foo_oid = 'foobar' # this will only work if we do NOT think it's an ObjectId
|
377
|
+
expect { r.bar_oid = 'foobar' }.to raise_error(ArgumentError)
|
378
|
+
r.bar_oid = the_bar_oid = new_oid.to_s
|
379
|
+
|
380
|
+
expect(r.bar_oid).to be_an_objectid_object_matching(the_bar_oid)
|
381
|
+
|
382
|
+
migrate do
|
383
|
+
drop_table :objectidcols_spec_pk_auto rescue nil
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
context "with a single, manually-defined column" do
|
391
|
+
before :each do
|
392
|
+
::Spectable.class_eval { has_objectid_column :perfect_s_oid }
|
393
|
+
end
|
394
|
+
|
395
|
+
it "should allow writing and reading via an ObjectId object" do
|
396
|
+
the_oid = new_oid
|
397
|
+
|
398
|
+
r = ::Spectable.new
|
399
|
+
r.perfect_s_oid = the_oid
|
400
|
+
expect(r.perfect_s_oid).to be_the_same_objectid_as(the_oid)
|
401
|
+
expect(r.perfect_s_oid).to be_an_objectid_object
|
402
|
+
r.save!
|
403
|
+
expect(r.perfect_s_oid).to be_the_same_objectid_as(the_oid.to_s)
|
404
|
+
expect(r.perfect_s_oid).to be_an_objectid_object
|
405
|
+
|
406
|
+
r_again = ::Spectable.find(r.id)
|
407
|
+
expect(r_again.perfect_s_oid).to be_the_same_objectid_as(the_oid.to_s)
|
408
|
+
expect(r_again.perfect_s_oid).to be_an_objectid_object
|
409
|
+
end
|
410
|
+
|
411
|
+
it "should raise a good exception if you try to assign something that isn't a valid ObjectId" do
|
412
|
+
r = ::Spectable.new
|
413
|
+
|
414
|
+
expect { r.perfect_s_oid = 12345 }.to raise_error(ArgumentError, /12345/)
|
415
|
+
expect { r.perfect_s_oid = /foobar/ }.to raise_error(ArgumentError, /foobar/i)
|
416
|
+
end
|
417
|
+
|
418
|
+
if "".respond_to?(:encoding)
|
419
|
+
it "should not allow assigning binary strings unless their encoding is BINARY" do
|
420
|
+
r = ::Spectable.new
|
421
|
+
|
422
|
+
binary = new_oid.to_binary
|
423
|
+
binary = binary.force_encoding(Encoding::ISO_8859_1)
|
424
|
+
expect { r.perfect_s_oid = binary }.to raise_error(ArgumentError)
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
it "should not allow assigning strings that are the wrong format" do
|
429
|
+
r = ::Spectable.new
|
430
|
+
|
431
|
+
expect { r.perfect_s_oid = new_oid.to_binary[0..10] }.to raise_error(ArgumentError)
|
432
|
+
expect { r.perfect_s_oid = new_oid.to_binary + "\x00" }.to raise_error(ArgumentError)
|
433
|
+
end
|
434
|
+
|
435
|
+
it "should let you set columns to nil" do
|
436
|
+
r = ::Spectable.create!(:perfect_s_oid => (@oid = new_oid))
|
437
|
+
|
438
|
+
r_again = ::Spectable.find(r.id)
|
439
|
+
expect(r_again.perfect_s_oid).to be_an_objectid_object_matching(@oid)
|
440
|
+
r.perfect_s_oid = nil
|
441
|
+
r.save!
|
442
|
+
|
443
|
+
r_yet_again = ::Spectable.find(r.id)
|
444
|
+
expect(r_yet_again.perfect_s_oid).to be_nil
|
445
|
+
end
|
446
|
+
|
447
|
+
it "should accept ObjectIds for input in binary, String, or either object format" do
|
448
|
+
VALID_OBJECTID_CLASSES.each do |klass|
|
449
|
+
r = ::Spectable.create!(:perfect_s_oid => (@oid = klass.new))
|
450
|
+
expect(::Spectable.find(r.id).perfect_s_oid).to be_an_objectid_object_matching(@oid)
|
451
|
+
end
|
452
|
+
|
453
|
+
r = ::Spectable.create!(:perfect_s_oid => (@oid = new_oid.to_s))
|
454
|
+
expect(::Spectable.find(r.id).perfect_s_oid).to be_an_objectid_object_matching(@oid)
|
455
|
+
|
456
|
+
r = ::Spectable.create!(:perfect_s_oid => (@oid = new_oid.to_binary))
|
457
|
+
expect(::Spectable.find(r.id).perfect_s_oid).to be_an_objectid_object_matching(@oid)
|
458
|
+
end
|
459
|
+
|
460
|
+
it "should not do anything to the other columns" do
|
461
|
+
r = ::Spectable.new
|
462
|
+
|
463
|
+
r.perfect_b_oid = 'perfect_b_1'
|
464
|
+
r.longer_b_oid = 'longer_b_1'
|
465
|
+
|
466
|
+
r.too_short_b = 'short_b_2'
|
467
|
+
r.perfect_b = 'perfect_b_2'
|
468
|
+
r.longer_b = 'longer_b_2'
|
469
|
+
|
470
|
+
the_oid = new_oid
|
471
|
+
r.perfect_s_oid = the_oid
|
472
|
+
r.longer_s_oid = 'longer_s_1'
|
473
|
+
|
474
|
+
r.too_short_s = 'short_s_1'
|
475
|
+
r.perfect_s = 'perfect_s_2'
|
476
|
+
r.longer_s = 'longer_s'
|
477
|
+
|
478
|
+
r.save!
|
479
|
+
|
480
|
+
r_again = ::Spectable.find(r.id)
|
481
|
+
|
482
|
+
expect(r_again.perfect_b_oid.strip).to eq('perfect_b_1')
|
483
|
+
expect(r_again.longer_b_oid.strip).to eq('longer_b_1')
|
484
|
+
|
485
|
+
expect(r_again.too_short_b.strip).to eq('short_b_2')
|
486
|
+
expect(r_again.perfect_b.strip).to eq('perfect_b_2')
|
487
|
+
expect(r_again.longer_b.strip).to eq('longer_b_2')
|
488
|
+
|
489
|
+
expect(r_again.perfect_s_oid).to be_the_same_objectid_as(the_oid)
|
490
|
+
expect(r_again.perfect_s_oid).to be_an_objectid_object
|
491
|
+
expect(r_again.longer_s_oid).to eq('longer_s_1')
|
492
|
+
|
493
|
+
expect(r_again.too_short_s).to eq('short_s_1')
|
494
|
+
expect(r_again.perfect_s).to eq('perfect_s_2')
|
495
|
+
expect(r_again.longer_s).to eq('longer_s')
|
496
|
+
end
|
497
|
+
|
498
|
+
it "should allow querying on ObjectId columns via Hash, but not change other queries" do
|
499
|
+
r1 = ::Spectable.create!(:perfect_s_oid => (@oid1 = new_oid), :longer_s_oid => "foobar")
|
500
|
+
r2 = ::Spectable.create!(:perfect_s_oid => (@oid2 = new_oid), :longer_s_oid => "barfoo")
|
501
|
+
|
502
|
+
expect(::Spectable.where(:perfect_s_oid => @oid1).to_a.map(&:id)).to eq([ r1.id ])
|
503
|
+
expect(::Spectable.where(:perfect_s_oid => @oid2).to_a.map(&:id)).to eq([ r2.id ])
|
504
|
+
expect(::Spectable.where(:perfect_s_oid => [ @oid1, @oid2 ]).to_a.map(&:id).sort).to eq([ r1.id, r2.id ].sort)
|
505
|
+
|
506
|
+
expect(::Spectable.where(:perfect_s_oid => @oid1.to_s).to_a.map(&:id)).to eq([ r1.id ])
|
507
|
+
expect(::Spectable.where(:perfect_s_oid => @oid2.to_s).to_a.map(&:id)).to eq([ r2.id ])
|
508
|
+
expect(::Spectable.where(:perfect_s_oid => [ @oid1, @oid2 ].map(&:to_s)).to_a.map(&:id).sort).to eq([ r1.id, r2.id ].sort)
|
509
|
+
|
510
|
+
expect(::Spectable.where(:perfect_s_oid => @oid1.to_binary).to_a.map(&:id)).to eq([ r1.id ])
|
511
|
+
expect(::Spectable.where(:perfect_s_oid => @oid2.to_binary).to_a.map(&:id)).to eq([ r2.id ])
|
512
|
+
expect(::Spectable.where(:perfect_s_oid => [ @oid1, @oid2 ].map(&:to_binary)).to_a.map(&:id).sort).to eq([ r1.id, r2.id ].sort)
|
513
|
+
end
|
514
|
+
|
515
|
+
it "should give a good exception if you try to pass an ObjectID for a column that isn't an official ObjectID column" do
|
516
|
+
oid = new_oid
|
517
|
+
expect { ::Spectable.where(:perfect_b_oid => oid).to_a }.to raise_error(/ObjectidColumns:.*perfect_b_oid/mi)
|
518
|
+
end
|
519
|
+
|
520
|
+
it "should not blow up (and instead let ActiveRecord blow up) if you try to pass an ObjectID for a column that isn't a column at all" do
|
521
|
+
oid = new_oid
|
522
|
+
expect { ::Spectable.where(:something => oid).to_a }.to raise_error(/something/mi)
|
523
|
+
end
|
524
|
+
|
525
|
+
it "should not blow up (and instead let ActiveRecord just find no records, or blow up) if you try to pass an ObjectID for a column on a table that isn't using this gem at all" do
|
526
|
+
define_model_class(:SpectableNondeclared, 'objectidcols_spec_table') { }
|
527
|
+
expect(::SpectableNondeclared.where(:perfect_s_oid => new_oid).to_a).to eq([ ])
|
528
|
+
|
529
|
+
expect { ::SpectableNondeclared.where(:something => new_oid).to_a }.to raise_error(/something/i)
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
533
|
+
it "should allow using any column that's long enough, including binary or string columns" do
|
534
|
+
::Spectable.class_eval do
|
535
|
+
has_objectid_columns :perfect_b_oid, :longer_b_oid
|
536
|
+
has_objectid_columns :perfect_s_oid, :longer_s_oid, :perfect_s, :longer_s
|
537
|
+
end
|
538
|
+
|
539
|
+
r = ::Spectable.new
|
540
|
+
|
541
|
+
r.perfect_b_oid = @perfect_b_oid = new_oid
|
542
|
+
r.longer_b_oid = @longer_b_oid = new_oid
|
543
|
+
r.perfect_s_oid = @perfect_s_oid = new_oid
|
544
|
+
r.longer_s_oid = @longer_s_oid = new_oid
|
545
|
+
r.perfect_s = @perfect_s = new_oid
|
546
|
+
r.longer_s = @longer_s = new_oid
|
547
|
+
|
548
|
+
r.save!
|
549
|
+
|
550
|
+
r_again = ::Spectable.find(r.id)
|
551
|
+
expect(r_again.perfect_b_oid).to be_an_objectid_object_matching(@perfect_b_oid)
|
552
|
+
expect(r_again.longer_b_oid).to be_an_objectid_object_matching(@longer_b_oid)
|
553
|
+
expect(r_again.perfect_s_oid).to be_an_objectid_object_matching(@perfect_s_oid)
|
554
|
+
expect(r_again.longer_s_oid).to be_an_objectid_object_matching(@longer_s_oid)
|
555
|
+
expect(r_again.perfect_s).to be_an_objectid_object_matching(@perfect_s)
|
556
|
+
expect(r_again.longer_s).to be_an_objectid_object_matching(@longer_s)
|
557
|
+
end
|
558
|
+
|
559
|
+
it "should automatically pick up any _oid columns" do
|
560
|
+
::Spectable.class_eval do
|
561
|
+
has_objectid_columns
|
562
|
+
end
|
563
|
+
|
564
|
+
r = ::Spectable.new
|
565
|
+
|
566
|
+
r.perfect_b_oid = @perfect_b_oid = new_oid
|
567
|
+
r.longer_b_oid = @longer_b_oid = new_oid
|
568
|
+
|
569
|
+
r.too_short_b = 'short_b_2'
|
570
|
+
r.perfect_b = 'perfect_b_2'
|
571
|
+
r.longer_b = 'longer_b_2'
|
572
|
+
|
573
|
+
r.perfect_s_oid = @perfect_s_oid = new_oid
|
574
|
+
r.longer_s_oid = @longer_s_oid = new_oid
|
575
|
+
|
576
|
+
r.too_short_s = 'short_s_1'
|
577
|
+
r.perfect_s = 'perfect_s_2'
|
578
|
+
r.longer_s = 'longer_s'
|
579
|
+
|
580
|
+
r.save!
|
581
|
+
|
582
|
+
r_again = ::Spectable.find(r.id)
|
583
|
+
|
584
|
+
expect(r_again.perfect_b_oid).to be_an_objectid_object_matching(@perfect_b_oid)
|
585
|
+
expect(r_again.longer_b_oid).to be_an_objectid_object_matching(@longer_b_oid)
|
586
|
+
|
587
|
+
expect(r_again.too_short_b.strip).to eq('short_b_2')
|
588
|
+
expect(r_again.perfect_b.strip).to eq('perfect_b_2')
|
589
|
+
expect(r_again.longer_b.strip).to eq('longer_b_2')
|
590
|
+
|
591
|
+
r_again.perfect_s_oid.should be_an_objectid_object_matching(@perfect_s_oid)
|
592
|
+
r_again.longer_s_oid.should be_an_objectid_object_matching(@longer_s_oid)
|
593
|
+
|
594
|
+
expect(r_again.too_short_s).to eq('short_s_1')
|
595
|
+
expect(r_again.perfect_s).to eq('perfect_s_2')
|
596
|
+
expect(r_again.longer_s).to eq('longer_s')
|
597
|
+
end
|
598
|
+
end
|
599
|
+
end
|
600
|
+
end
|