rpbertp13-dm-core 0.9.11.1

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 (131) hide show
  1. data/.autotest +26 -0
  2. data/.gitignore +18 -0
  3. data/CONTRIBUTING +51 -0
  4. data/FAQ +92 -0
  5. data/History.txt +52 -0
  6. data/MIT-LICENSE +22 -0
  7. data/Manifest.txt +130 -0
  8. data/QUICKLINKS +11 -0
  9. data/README.txt +143 -0
  10. data/Rakefile +32 -0
  11. data/SPECS +62 -0
  12. data/TODO +1 -0
  13. data/dm-core.gemspec +40 -0
  14. data/lib/dm-core.rb +217 -0
  15. data/lib/dm-core/adapters.rb +16 -0
  16. data/lib/dm-core/adapters/abstract_adapter.rb +209 -0
  17. data/lib/dm-core/adapters/data_objects_adapter.rb +716 -0
  18. data/lib/dm-core/adapters/in_memory_adapter.rb +87 -0
  19. data/lib/dm-core/adapters/mysql_adapter.rb +138 -0
  20. data/lib/dm-core/adapters/postgres_adapter.rb +189 -0
  21. data/lib/dm-core/adapters/sqlite3_adapter.rb +105 -0
  22. data/lib/dm-core/associations.rb +207 -0
  23. data/lib/dm-core/associations/many_to_many.rb +147 -0
  24. data/lib/dm-core/associations/many_to_one.rb +107 -0
  25. data/lib/dm-core/associations/one_to_many.rb +315 -0
  26. data/lib/dm-core/associations/one_to_one.rb +61 -0
  27. data/lib/dm-core/associations/relationship.rb +221 -0
  28. data/lib/dm-core/associations/relationship_chain.rb +81 -0
  29. data/lib/dm-core/auto_migrations.rb +105 -0
  30. data/lib/dm-core/collection.rb +670 -0
  31. data/lib/dm-core/dependency_queue.rb +32 -0
  32. data/lib/dm-core/hook.rb +11 -0
  33. data/lib/dm-core/identity_map.rb +42 -0
  34. data/lib/dm-core/is.rb +16 -0
  35. data/lib/dm-core/logger.rb +232 -0
  36. data/lib/dm-core/migrations/destructive_migrations.rb +17 -0
  37. data/lib/dm-core/migrator.rb +29 -0
  38. data/lib/dm-core/model.rb +526 -0
  39. data/lib/dm-core/naming_conventions.rb +84 -0
  40. data/lib/dm-core/property.rb +676 -0
  41. data/lib/dm-core/property_set.rb +169 -0
  42. data/lib/dm-core/query.rb +676 -0
  43. data/lib/dm-core/repository.rb +167 -0
  44. data/lib/dm-core/resource.rb +671 -0
  45. data/lib/dm-core/scope.rb +58 -0
  46. data/lib/dm-core/support.rb +7 -0
  47. data/lib/dm-core/support/array.rb +13 -0
  48. data/lib/dm-core/support/assertions.rb +8 -0
  49. data/lib/dm-core/support/errors.rb +23 -0
  50. data/lib/dm-core/support/kernel.rb +11 -0
  51. data/lib/dm-core/support/symbol.rb +41 -0
  52. data/lib/dm-core/transaction.rb +252 -0
  53. data/lib/dm-core/type.rb +160 -0
  54. data/lib/dm-core/type_map.rb +80 -0
  55. data/lib/dm-core/types.rb +19 -0
  56. data/lib/dm-core/types/boolean.rb +7 -0
  57. data/lib/dm-core/types/discriminator.rb +34 -0
  58. data/lib/dm-core/types/object.rb +24 -0
  59. data/lib/dm-core/types/paranoid_boolean.rb +34 -0
  60. data/lib/dm-core/types/paranoid_datetime.rb +33 -0
  61. data/lib/dm-core/types/serial.rb +9 -0
  62. data/lib/dm-core/types/text.rb +10 -0
  63. data/lib/dm-core/version.rb +3 -0
  64. data/script/all +4 -0
  65. data/script/performance.rb +282 -0
  66. data/script/profile.rb +87 -0
  67. data/spec/integration/association_spec.rb +1382 -0
  68. data/spec/integration/association_through_spec.rb +203 -0
  69. data/spec/integration/associations/many_to_many_spec.rb +449 -0
  70. data/spec/integration/associations/many_to_one_spec.rb +163 -0
  71. data/spec/integration/associations/one_to_many_spec.rb +188 -0
  72. data/spec/integration/auto_migrations_spec.rb +413 -0
  73. data/spec/integration/collection_spec.rb +1073 -0
  74. data/spec/integration/data_objects_adapter_spec.rb +32 -0
  75. data/spec/integration/dependency_queue_spec.rb +46 -0
  76. data/spec/integration/model_spec.rb +197 -0
  77. data/spec/integration/mysql_adapter_spec.rb +85 -0
  78. data/spec/integration/postgres_adapter_spec.rb +731 -0
  79. data/spec/integration/property_spec.rb +253 -0
  80. data/spec/integration/query_spec.rb +514 -0
  81. data/spec/integration/repository_spec.rb +61 -0
  82. data/spec/integration/resource_spec.rb +513 -0
  83. data/spec/integration/sqlite3_adapter_spec.rb +352 -0
  84. data/spec/integration/sti_spec.rb +273 -0
  85. data/spec/integration/strategic_eager_loading_spec.rb +156 -0
  86. data/spec/integration/transaction_spec.rb +60 -0
  87. data/spec/integration/type_spec.rb +275 -0
  88. data/spec/lib/logging_helper.rb +18 -0
  89. data/spec/lib/mock_adapter.rb +27 -0
  90. data/spec/lib/model_loader.rb +100 -0
  91. data/spec/lib/publicize_methods.rb +28 -0
  92. data/spec/models/content.rb +16 -0
  93. data/spec/models/vehicles.rb +34 -0
  94. data/spec/models/zoo.rb +48 -0
  95. data/spec/spec.opts +3 -0
  96. data/spec/spec_helper.rb +91 -0
  97. data/spec/unit/adapters/abstract_adapter_spec.rb +133 -0
  98. data/spec/unit/adapters/adapter_shared_spec.rb +15 -0
  99. data/spec/unit/adapters/data_objects_adapter_spec.rb +632 -0
  100. data/spec/unit/adapters/in_memory_adapter_spec.rb +98 -0
  101. data/spec/unit/adapters/postgres_adapter_spec.rb +133 -0
  102. data/spec/unit/associations/many_to_many_spec.rb +32 -0
  103. data/spec/unit/associations/many_to_one_spec.rb +159 -0
  104. data/spec/unit/associations/one_to_many_spec.rb +393 -0
  105. data/spec/unit/associations/one_to_one_spec.rb +7 -0
  106. data/spec/unit/associations/relationship_spec.rb +71 -0
  107. data/spec/unit/associations_spec.rb +242 -0
  108. data/spec/unit/auto_migrations_spec.rb +111 -0
  109. data/spec/unit/collection_spec.rb +182 -0
  110. data/spec/unit/data_mapper_spec.rb +35 -0
  111. data/spec/unit/identity_map_spec.rb +126 -0
  112. data/spec/unit/is_spec.rb +80 -0
  113. data/spec/unit/migrator_spec.rb +33 -0
  114. data/spec/unit/model_spec.rb +321 -0
  115. data/spec/unit/naming_conventions_spec.rb +36 -0
  116. data/spec/unit/property_set_spec.rb +90 -0
  117. data/spec/unit/property_spec.rb +753 -0
  118. data/spec/unit/query_spec.rb +571 -0
  119. data/spec/unit/repository_spec.rb +93 -0
  120. data/spec/unit/resource_spec.rb +649 -0
  121. data/spec/unit/scope_spec.rb +142 -0
  122. data/spec/unit/transaction_spec.rb +469 -0
  123. data/spec/unit/type_map_spec.rb +114 -0
  124. data/spec/unit/type_spec.rb +119 -0
  125. data/tasks/ci.rb +36 -0
  126. data/tasks/dm.rb +63 -0
  127. data/tasks/doc.rb +20 -0
  128. data/tasks/gemspec.rb +23 -0
  129. data/tasks/hoe.rb +46 -0
  130. data/tasks/install.rb +20 -0
  131. metadata +215 -0
@@ -0,0 +1,80 @@
1
+ # TODO: move to dm-more/dm-migrations
2
+
3
+ module DataMapper
4
+ class TypeMap
5
+
6
+ attr_accessor :parent, :chains
7
+
8
+ def initialize(parent = nil, &blk)
9
+ @parent, @chains = parent, {}
10
+
11
+ blk.call(self) unless blk.nil?
12
+ end
13
+
14
+ def map(type)
15
+ @chains[type] ||= TypeChain.new
16
+ end
17
+
18
+ def lookup(type)
19
+ if type_mapped?(type)
20
+ lookup_from_map(type)
21
+ else
22
+ lookup_by_type(type)
23
+ end
24
+ end
25
+
26
+ def lookup_from_map(type)
27
+ lookup_from_parent(type).merge(map(type).translate)
28
+ end
29
+
30
+ def lookup_from_parent(type)
31
+ if !@parent.nil? && @parent.type_mapped?(type)
32
+ @parent[type]
33
+ else
34
+ {}
35
+ end
36
+ end
37
+
38
+ # @raise <DataMapper::TypeMap::Error> if the type is not a default primitive or has a type map entry.
39
+ def lookup_by_type(type)
40
+ raise DataMapper::TypeMap::Error.new(type) unless type.respond_to?(:primitive) && !type.primitive.nil?
41
+
42
+ lookup(type.primitive).merge(Type::PROPERTY_OPTIONS.inject({}) {|h, k| h[k] = type.send(k); h})
43
+ end
44
+
45
+ alias [] lookup
46
+
47
+ def type_mapped?(type)
48
+ @chains.has_key?(type) || (@parent.nil? ? false : @parent.type_mapped?(type))
49
+ end
50
+
51
+ class TypeChain
52
+ attr_accessor :primitive, :attributes
53
+
54
+ def initialize
55
+ @attributes = {}
56
+ end
57
+
58
+ def to(primitive)
59
+ @primitive = primitive
60
+ self
61
+ end
62
+
63
+ def with(attributes)
64
+ raise "method 'with' expects a hash" unless attributes.kind_of?(Hash)
65
+ @attributes.merge!(attributes)
66
+ self
67
+ end
68
+
69
+ def translate
70
+ @attributes.merge((@primitive.nil? ? {} : {:primitive => @primitive}))
71
+ end
72
+ end # class TypeChain
73
+
74
+ class Error < StandardError
75
+ def initialize(type)
76
+ super("Type #{type} must have a default primitive or type map entry")
77
+ end
78
+ end
79
+ end # class TypeMap
80
+ end # module DataMapper
@@ -0,0 +1,19 @@
1
+ dir = Pathname(__FILE__).dirname.expand_path / 'types'
2
+
3
+ require dir / 'boolean'
4
+ require dir / 'discriminator'
5
+ require dir / 'text'
6
+ require dir / 'paranoid_datetime'
7
+ require dir / 'paranoid_boolean'
8
+ require dir / 'object'
9
+ require dir / 'serial'
10
+
11
+ unless defined?(DM)
12
+ DM = DataMapper::Types
13
+ end
14
+
15
+ module DataMapper
16
+ module Resource
17
+ include Types
18
+ end # module Resource
19
+ end # module DataMapper
@@ -0,0 +1,7 @@
1
+ module DataMapper
2
+ module Types
3
+ class Boolean < DataMapper::Type
4
+ primitive TrueClass
5
+ end # class Boolean
6
+ end # module Types
7
+ end # module DataMapper
@@ -0,0 +1,34 @@
1
+ module DataMapper
2
+ module Types
3
+ class Discriminator < DataMapper::Type
4
+ primitive Class
5
+ track :set
6
+ default lambda { |r,p| p.model }
7
+ nullable false
8
+
9
+ def self.bind(property)
10
+ model = property.model
11
+
12
+ model.class_eval <<-EOS, __FILE__, __LINE__
13
+ def self.descendants
14
+ (@descendants ||= []).uniq!
15
+ @descendants
16
+ end
17
+
18
+ after_class_method :inherited, :add_scope_for_discriminator
19
+
20
+ def self.add_scope_for_discriminator(retval, target)
21
+ target.descendants << target
22
+ target.default_scope.update(#{property.name.inspect} => target.descendants)
23
+ propagate_descendants(target)
24
+ end
25
+
26
+ def self.propagate_descendants(target)
27
+ descendants << target
28
+ superclass.propagate_descendants(target) if superclass.respond_to?(:propagate_descendants)
29
+ end
30
+ EOS
31
+ end
32
+ end # class Discriminator
33
+ end # module Types
34
+ end # module DataMapper
@@ -0,0 +1,24 @@
1
+ require "base64"
2
+
3
+ module DataMapper
4
+ module Types
5
+ class Object < DataMapper::Type
6
+ primitive String
7
+ size 65535
8
+ lazy true
9
+ track :hash
10
+
11
+ def self.typecast(value, property)
12
+ value
13
+ end
14
+
15
+ def self.dump(value, property)
16
+ Base64.encode64(Marshal.dump(value))
17
+ end
18
+
19
+ def self.load(value, property)
20
+ value.nil? ? nil : Marshal.load(Base64.decode64(value))
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,34 @@
1
+ module DataMapper
2
+ module Types
3
+ class ParanoidBoolean < DataMapper::Type(Boolean)
4
+ primitive TrueClass
5
+ default false
6
+ lazy true
7
+
8
+ def self.bind(property)
9
+ model = property.model
10
+ repository = property.repository
11
+
12
+ model.send(:set_paranoid_property, property.name){true}
13
+
14
+ model.class_eval <<-EOS, __FILE__, __LINE__
15
+
16
+ def self.with_deleted
17
+ with_exclusive_scope(#{property.name.inspect} => true) do
18
+ yield
19
+ end
20
+ end
21
+
22
+ def destroy
23
+ self.class.paranoid_properties.each do |name, blk|
24
+ attribute_set(name, blk.call(self))
25
+ end
26
+ save
27
+ end
28
+ EOS
29
+
30
+ model.default_scope(repository.name).update(property.name => false)
31
+ end
32
+ end # class ParanoidBoolean
33
+ end # module Types
34
+ end # module DataMapper
@@ -0,0 +1,33 @@
1
+ module DataMapper
2
+ module Types
3
+ class ParanoidDateTime < DataMapper::Type(DateTime)
4
+ primitive DateTime
5
+ lazy true
6
+
7
+ def self.bind(property)
8
+ model = property.model
9
+ repository = property.repository
10
+
11
+ model.send(:set_paranoid_property, property.name){DateTime.now}
12
+
13
+ model.class_eval <<-EOS, __FILE__, __LINE__
14
+
15
+ def self.with_deleted
16
+ with_exclusive_scope(#{property.name.inspect}.not => nil) do
17
+ yield
18
+ end
19
+ end
20
+
21
+ def destroy
22
+ self.class.paranoid_properties.each do |name, blk|
23
+ attribute_set(name, blk.call(self))
24
+ end
25
+ save
26
+ end
27
+ EOS
28
+
29
+ model.default_scope(repository.name).update(property.name => nil)
30
+ end
31
+ end # class ParanoidDateTime
32
+ end # module Types
33
+ end # module DataMapper
@@ -0,0 +1,9 @@
1
+ # FIXME: can we alias this to the class Text if it isn't already defined?
2
+ module DataMapper
3
+ module Types
4
+ class Serial < DataMapper::Type
5
+ primitive Integer
6
+ serial true
7
+ end # class Text
8
+ end # module Types
9
+ end # module DataMapper
@@ -0,0 +1,10 @@
1
+ # FIXME: can we alias this to the class Text if it isn't already defined?
2
+ module DataMapper
3
+ module Types
4
+ class Text < DataMapper::Type
5
+ primitive String
6
+ size 65535
7
+ lazy true
8
+ end # class Text
9
+ end # module Types
10
+ end # module DataMapper
@@ -0,0 +1,3 @@
1
+ module DataMapper
2
+ VERSION = '0.9.12'.freeze
3
+ end
data/script/all ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env sh
2
+ ADAPTER=sqlite3 rake spec
3
+ ADAPTER=mysql rake spec
4
+ ADAPTER=postgres rake spec
@@ -0,0 +1,282 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'dm-core')
4
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'dm-core', 'version')
5
+
6
+ require 'ftools'
7
+ require 'rubygems'
8
+
9
+ gem 'rbench', '~>0.2.3'
10
+ require 'rbench'
11
+
12
+ gem 'faker', '~>0.3.1'
13
+ require 'faker'
14
+
15
+ gem 'activerecord', '~>2.3.2'
16
+ require 'active_record'
17
+
18
+ socket_file = Pathname.glob(%w[
19
+ /opt/local/var/run/mysql5/mysqld.sock
20
+ tmp/mysqld.sock
21
+ /tmp/mysqld.sock
22
+ tmp/mysql.sock
23
+ /tmp/mysql.sock
24
+ /var/mysql/mysql.sock
25
+ /var/run/mysqld/mysqld.sock
26
+ ]).find { |path| path.socket? }
27
+
28
+ configuration_options = {
29
+ :adapter => 'mysql',
30
+ :username => 'root',
31
+ :password => '',
32
+ :database => 'data_mapper_1',
33
+ }
34
+
35
+ configuration_options[:socket] = socket_file unless socket_file.nil?
36
+
37
+ log_dir = DataMapper.root / 'log'
38
+ log_dir.mkdir unless log_dir.directory?
39
+
40
+ DataMapper::Logger.new(log_dir / 'dm.log', :off)
41
+ adapter = DataMapper.setup(:default, "mysql://root@localhost/data_mapper_1?socket=#{socket_file}")
42
+
43
+ if configuration_options[:adapter]
44
+ sqlfile = File.join(File.dirname(__FILE__),'..','tmp','performance.sql')
45
+ mysql_bin = %w[mysql mysql5].select{|bin| `which #{bin}`.length > 0 }
46
+ mysqldump_bin = %w[mysqldump mysqldump5].select{|bin| `which #{bin}`.length > 0 }
47
+ end
48
+
49
+ ActiveRecord::Base.logger = Logger.new(log_dir / 'ar.log')
50
+ ActiveRecord::Base.logger.level = 0
51
+
52
+ ActiveRecord::Base.establish_connection(configuration_options)
53
+
54
+ class ARExhibit < ActiveRecord::Base #:nodoc:
55
+ set_table_name 'exhibits'
56
+
57
+ belongs_to :user, :class_name => 'ARUser', :foreign_key => 'user_id'
58
+ end
59
+
60
+ class ARUser < ActiveRecord::Base #:nodoc:
61
+ set_table_name 'users'
62
+
63
+ has_many :exhibits, :foreign_key => 'user_id'
64
+
65
+ end
66
+
67
+ ARExhibit.find_by_sql('SELECT 1')
68
+
69
+ class Exhibit
70
+ include DataMapper::Resource
71
+
72
+ property :id, Serial
73
+ property :name, String
74
+ property :zoo_id, Integer
75
+ property :user_id, Integer
76
+ property :notes, Text, :lazy => true
77
+ property :created_on, Date
78
+
79
+ belongs_to :user
80
+ # property :updated_at, DateTime
81
+ end
82
+
83
+ class User
84
+ include DataMapper::Resource
85
+
86
+ property :id, Serial
87
+ property :name, String
88
+ property :email, String
89
+ property :about, Text, :lazy => true
90
+ property :created_on, Date
91
+
92
+ end
93
+
94
+ touch_attributes = lambda do |exhibits|
95
+ [*exhibits].each do |exhibit|
96
+ exhibit.id
97
+ exhibit.name
98
+ exhibit.created_on
99
+ end
100
+ end
101
+
102
+ touch_relationships = lambda do |exhibits|
103
+ [*exhibits].each do |exhibit|
104
+ exhibit.id
105
+ exhibit.name
106
+ exhibit.created_on
107
+ exhibit.user
108
+ end
109
+ end
110
+
111
+
112
+ c = configuration_options
113
+
114
+ if sqlfile && File.exists?(sqlfile)
115
+ puts "Found data-file. Importing from #{sqlfile}"
116
+ #adapter.execute("LOAD DATA LOCAL INFILE '#{sqlfile}' INTO TABLE exhibits")
117
+ `#{mysql_bin} -u #{c[:username]} #{"-p#{c[:password]}" unless c[:password].blank?} #{c[:database]} < #{sqlfile}`
118
+ else
119
+
120
+ puts "Generating data for benchmarking..."
121
+
122
+ User.auto_migrate!
123
+ Exhibit.auto_migrate!
124
+
125
+ users = []
126
+ exhibits = []
127
+
128
+ # pre-compute the insert statements and fake data compilation,
129
+ # so the benchmarks below show the actual runtime for the execute
130
+ # method, minus the setup steps
131
+
132
+ # Using the same paragraph for all exhibits because it is very slow
133
+ # to generate unique paragraphs for all exhibits.
134
+ paragraph = Faker::Lorem.paragraphs.join($/)
135
+
136
+ 10_000.times do |i|
137
+ users << [
138
+ 'INSERT INTO `users` (`name`,`email`,`created_on`) VALUES (?, ?, ?)',
139
+ Faker::Name.name,
140
+ Faker::Internet.email,
141
+ Date.today
142
+ ]
143
+
144
+ exhibits << [
145
+ 'INSERT INTO `exhibits` (`name`, `zoo_id`, `user_id`, `notes`, `created_on`) VALUES (?, ?, ?, ?, ?)',
146
+ Faker::Company.name,
147
+ rand(10).ceil,
148
+ i,
149
+ paragraph,#Faker::Lorem.paragraphs.join($/),
150
+ Date.today
151
+ ]
152
+ end
153
+
154
+ puts "Inserting 10,000 users..."
155
+ 10_000.times { |i| adapter.execute(*users.at(i)) }
156
+ puts "Inserting 10,000 exhibits..."
157
+ 10_000.times { |i| adapter.execute(*exhibits.at(i)) }
158
+
159
+ if sqlfile
160
+ answer = nil
161
+ until answer && answer[/^$|y|yes|n|no/]
162
+ print("Would you like to dump data into tmp/performance.sql (for faster setup)? [Yn]");
163
+ STDOUT.flush
164
+ answer = gets
165
+ end
166
+
167
+ if answer[/^$|y|yes/]
168
+ File.makedirs(File.dirname(sqlfile))
169
+ #adapter.execute("SELECT * INTO OUTFILE '#{sqlfile}' FROM exhibits;")
170
+ `#{mysqldump_bin} -u #{c[:username]} #{"-p#{c[:password]}" unless c[:password].blank?} #{c[:database]} exhibits users > #{sqlfile}`
171
+ puts "File saved\n"
172
+ end
173
+ end
174
+
175
+ end
176
+
177
+ TIMES = ENV['x'] ? ENV['x'].to_i : 10_000
178
+
179
+ puts "You can specify how many times you want to run the benchmarks with rake:perf x=(number)"
180
+ puts "Some tasks will be run 10 and 1000 times less than (number)"
181
+ puts "Benchmarks will now run #{TIMES} times"
182
+ # Inform about slow benchmark
183
+ # answer = nil
184
+ # until answer && answer[/^$|y|yes|n|no/]
185
+ # print("A slow benchmark exposing problems with SEL is newly added. It takes approx. 20s\n");
186
+ # print("you have scheduled it to run #{TIMES / 100} times.\nWould you still include the particular benchmark? [Yn]")
187
+ # STDOUT.flush
188
+ # answer = gets
189
+ # end
190
+ # run_rel_bench = answer[/^$|y|yes/] ? true : false
191
+
192
+
193
+ RBench.run(TIMES) do
194
+
195
+ column :times
196
+ column :ar, :title => "AR 2.1"
197
+ column :dm, :title => "DM #{DataMapper::VERSION}"
198
+ column :diff, :compare => [:ar,:dm]
199
+
200
+ report "Model.new (instantiation)" do
201
+ ar { ARExhibit.new }
202
+ dm { Exhibit.new }
203
+ end
204
+
205
+ report "Model.new (setting attributes)" do
206
+ attrs = {:name => 'sam', :zoo_id => 1}
207
+ ar { ARExhibit.new(attrs) }
208
+ dm { Exhibit.new(attrs) }
209
+ end
210
+
211
+ report "Model.get specific (not cached)" do
212
+ ActiveRecord::Base.uncached { ar { touch_attributes[ARExhibit.find(1)] } }
213
+ dm { touch_attributes[Exhibit.get(1)] }
214
+ end
215
+
216
+ report "Model.get specific (cached)" do
217
+ ActiveRecord::Base.cache { ar { touch_attributes[ARExhibit.find(1)] } }
218
+ Exhibit.repository(:default) { dm { touch_attributes[Exhibit.get(1)] } }
219
+ end
220
+
221
+ report "Model.first" do
222
+ ar { touch_attributes[ARExhibit.first] }
223
+ dm { touch_attributes[Exhibit.first] }
224
+ end
225
+
226
+ report "Model.all limit(100)", (TIMES / 10.0).ceil do
227
+ ar { touch_attributes[ARExhibit.find(:all, :limit => 100)] }
228
+ dm { touch_attributes[Exhibit.all(:limit => 100)] }
229
+ end
230
+
231
+ report "Model.all limit(100) with relationship", (TIMES / 10.0).ceil do
232
+ ar { touch_relationships[ARExhibit.all(:limit => 100, :include => [:user])] }
233
+ dm { touch_relationships[Exhibit.all(:limit => 100)] }
234
+ end
235
+
236
+ report "Model.all limit(10,000)", (TIMES / 1000.0).ceil do
237
+ ar { touch_attributes[ARExhibit.find(:all, :limit => 10_000)] }
238
+ dm { touch_attributes[Exhibit.all(:limit => 10_000)] }
239
+ end
240
+
241
+ create_exhibit = {
242
+ :name => Faker::Company.name,
243
+ :zoo_id => rand(10).ceil,
244
+ :notes => Faker::Lorem.paragraphs.join($/),
245
+ :created_on => Date.today
246
+ }
247
+
248
+ report "Model.create" do
249
+ ar { ARExhibit.create(create_exhibit) }
250
+ dm { Exhibit.create(create_exhibit) }
251
+ end
252
+
253
+ report "Resource#attributes" do
254
+ attrs_first = {:name => 'sam', :zoo_id => 1}
255
+ attrs_second = {:name => 'tom', :zoo_id => 1}
256
+ ar { e = ARExhibit.new(attrs_first); e.attributes = attrs_second }
257
+ dm { e = Exhibit.new(attrs_first); e.attributes = attrs_second }
258
+ end
259
+
260
+ report "Resource#update" do
261
+ ar { e = ARExhibit.find(1); e.name = 'bob'; e.save }
262
+ dm { e = Exhibit.get(1); e.name = 'bob'; e.save }
263
+ end
264
+
265
+ report "Resource#destroy" do
266
+ ar { ARExhibit.first.destroy }
267
+ dm { Exhibit.first.destroy }
268
+ end
269
+
270
+ report "Model.transaction" do
271
+ ar { ARExhibit.transaction { ARExhibit.new } }
272
+ dm { Exhibit.transaction { Exhibit.new } }
273
+ end
274
+
275
+ summary "Total"
276
+ end
277
+
278
+ connection = adapter.send(:create_connection)
279
+ command = connection.create_command("DROP TABLE exhibits")
280
+ command = connection.create_command("DROP TABLE users")
281
+ command.execute_non_query rescue nil
282
+ connection.close