smulube-fixture_dependencies 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2007-2008 Jeremy Evans
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README ADDED
@@ -0,0 +1,288 @@
1
+ = fixture_dependencies
2
+
3
+ fixture_dependencies is an advanced fixture loader, allowing the loading of
4
+ models from YAML fixtures, along with their entire dependency graph. It has
5
+ the following features:
6
+
7
+ - Fixtures specify association names instead of foreign keys
8
+ - Support both Sequel and ActiveRecord
9
+ - Supports many_to_one/belongs_to, one_to_many/has_many,
10
+ many_to_many/has_and_belongs_to_many, and has_one associations
11
+ - Loads a fixture's dependency graph in such a manner that foreign key
12
+ constraints aren't violated
13
+ - Has a very simple API (FixtureDependencies.load(:model__fixture))
14
+ - Handles almost all cyclic dependencies
15
+ - Includes Rails and Sequel test helpers for Test::Unit (and a Sequel test
16
+ helper for RSpec) that load fixtures for every test inside a transaction,
17
+ so fixture data is never left in your database
18
+ - Adds dynamic fixtures (similar to ActiveRecord) with ERb.
19
+
20
+ == Installation
21
+
22
+ Original version (lacking ERb support) available here:
23
+
24
+ sudo gem install jeremyevans-fixture_dependencies \
25
+ --source http://gems.github.com
26
+
27
+ This version available here:
28
+
29
+ sudo gem install smulube-fixture_dependencies \
30
+ --source http://gems.github.com
31
+
32
+ == Source
33
+
34
+ Original source is available via github:
35
+
36
+ http://github.com/jeremyevans/fixture_dependencies
37
+
38
+ You can check it out with git:
39
+
40
+ git clone git://github.com/jeremyevans/fixture_dependencies.git
41
+
42
+ Patched version is also available via github:
43
+
44
+ http://github.com/smulube/fixture_dependencies
45
+
46
+ You can check it out with git:
47
+
48
+ git clone git://github.com/smulube/fixture_dependencies.git
49
+
50
+
51
+ == Usage
52
+
53
+ === With Rails/ActiveRecord/Test::Unit:
54
+
55
+ Add the following to test/test_helper.rb after "require 'test_help'":
56
+
57
+ require 'fixture_dependencies/test_unit/rails'
58
+
59
+ This overrides the default test helper to load the fixtures inside transactions
60
+ and to use FixtureDependencies to load the fixtures.
61
+
62
+ === With Sequel/Test::Unit:
63
+
64
+ Somewhere before the test code is loaded:
65
+
66
+ require 'fixture_dependencies/test_unit/sequel'
67
+
68
+ Make sure the test case classes use FixtureDependencies::SequelTestCase:
69
+
70
+ class ModelTest < FixtureDependencies::SequelTestCase
71
+
72
+ This runs the test cases inside a Sequel transaction.
73
+
74
+ === With Sequel/RSpec:
75
+
76
+ Somewhere before the test code is loaded:
77
+
78
+ require 'fixture_dependencies/rspec/sequel'
79
+
80
+ This runs each spec inside a separate Sequel transaction.
81
+
82
+ === With other testing libraries:
83
+
84
+ You can just use FixtureDependencies.load to handle the loading of fixtures.
85
+ The use of transactions is up to you. One thing you must do if you are
86
+ not using the rails test helper is to set the fixture path for
87
+ FixtureDependencies:
88
+
89
+ FixtureDependencies.fixture_path = '/path/to/fixtures'
90
+
91
+ == Changes to Rails default fixtures:
92
+
93
+ fixture_dependencies is designed to require the least possible changes to
94
+ the default YAML fixtures used by Rails (well, at least Rails 1.2 and earlier).
95
+ For example, see the following changes:
96
+
97
+ OLD NEW
98
+ asset1: asset1:
99
+ id: 1 id: 1
100
+ employee_id: 2 employee: jeremy
101
+ product_id: 3 product: nx7010
102
+ vendor_id: 2 vendor: lxg_computers
103
+ note: in working order note: in working order
104
+
105
+ As you can see, you just replace the foreign key attribute and value with the
106
+ name of the association and the associations name. This assumes you have an
107
+ employee fixture with a name of jeremy, and products fixture with the name of
108
+ nx7010, and a vendors fixture with the name lxg_computers.
109
+
110
+ Fixture files still use the table_name of the model.
111
+
112
+ == Changes to the fixtures Class Method:
113
+
114
+ fixture_dependencies can still use the fixtures class method in your test:
115
+
116
+ class EmployeeTest < Test::Unit::TestCase
117
+ fixtures :assets
118
+ end
119
+
120
+ In Rails default testing practices, the arguments to fixtures are table names.
121
+ fixture_dependencies changes this to underscored model names. If you are using
122
+ Rails' recommended table practices, this shouldn't make a difference.
123
+
124
+ It is recommended that you do not use the fixtures method, and instead load
125
+ individual fixtures as needed (see below). This makes your tests much more
126
+ robust, in case you want to add or remove individual fixtures at a later date.
127
+
128
+ == Loading individual fixtures with fixtures class method
129
+
130
+ There is support for loading individual fixtures (and just their dependencies),
131
+ using the following syntax:
132
+
133
+ class EmployeeTest < Test::Unit::TestCase
134
+ fixtures :employee__jeremy # Note the double underscore
135
+ end
136
+
137
+ This would load just the jeremy fixture and its dependencies. I find this is
138
+ much better than loading all fixtures in most of my test suites. Even better
139
+ is loading just the fixtures you want instead every test method (see below).
140
+ This leads to the most robust testing.
141
+
142
+ == Loading fixtures inside test methods
143
+
144
+ I find that it is often better to skip the use of the fixtures method entirely,
145
+ and load the fixtures I want manually in each test method. This provides for
146
+ the loosest coupling possible. Here's an example:
147
+
148
+ class EmployeeTest < Test::Unit::TestCase
149
+ def test_employee_name
150
+ # Load the fixture and return the Employee object
151
+ employee = load(:employee__jeremy)
152
+ # Test the employee
153
+ end
154
+
155
+ def test_employees
156
+ # Load the fixtures and return two Employee objects
157
+ employee1, employee2 = load(:employees=>[:jeremy, :karl])
158
+ # Test the employees
159
+ end
160
+
161
+ def test_award_statistics
162
+ # Load all fixtures in both tables
163
+ load(:employee_award__jeremy_first, :award__first)
164
+ # Test the award_statistics method
165
+ # (which pulls data from the tables loaded above)
166
+ end
167
+ end
168
+
169
+ Don't worry about loading the same fixture twice, if a fixture is already
170
+ loaded, it won't attempt to load it again.
171
+
172
+ == one_to_many/many_to_many/has_many/has_and_belongs_to_many assocations
173
+
174
+ Here's an example of using has_one (logon_information), has_many (assets), and
175
+ has_and_belongs_to_many (groups) associations.
176
+
177
+ jeremy:
178
+ id: 2
179
+ name: Jeremy Evans
180
+ logon_information: jeremy
181
+ assets: [asset1, asset2, asset3]
182
+ groups: [group1]
183
+
184
+ logon_information is a has_one association to another table which was split
185
+ from the employees table due to database security requirements. Assets is a
186
+ has_many association, where one employee is responsible for the asset.
187
+ Employees can be a member of multiple groups, and each group can have multiple
188
+ employees.
189
+
190
+ For has_* associations, after fixture_dependencies saves jeremy, it will load
191
+ and save logon_information (and its dependencies...), it will load each asset
192
+ in the order specified (and their dependencies...), and it will load all of the
193
+ groups in the order specified (and their dependencies...). Note that there
194
+ is only a load order inside a specific association, associations are stored
195
+ in the same hash as attributes and are loaded in an arbitrary order.
196
+
197
+ == many_to_many/has_and_belongs_to_many join table fixtures
198
+
199
+ Another change is that Rails defaults allow you to specify habtm join tables in
200
+ fixtures. That doesn't work with fixture dependencies, as there is no
201
+ associated model. Instead, you use a has_and_belongs_to_many association name
202
+ in the the appropriate model fixtures (see above).
203
+
204
+ == Cyclic dependencies
205
+
206
+ fixture_dependencies handles almost all cyclic dependencies. It handles all
207
+ has_many, has_one, and habtm cyclic dependencies. It handles all
208
+ self-referential cyclic dependencies. It handles all belongs_to cyclic
209
+ dependencies except the case where there is a NOT NULL or validates_presence of
210
+ constraint on the cyclic dependency's foreign key.
211
+
212
+ For example, a case that won't work is when employee belongs_to supervisor
213
+ (with a NOT NULL or validates_presence_of constraint on supervisor_id), and
214
+ john is karl's supervisor and karl is john's supervisor. Since you can't create
215
+ john without a valid supervisor_id, you need to create karl first, but you
216
+ can't create karl for the same reason (as john doesn't exist yet).
217
+
218
+ There isn't a generic way to handle the belongs_to cyclic dependency, as far as
219
+ I know. Deferring foreign key checks could work, but may not be enabled (and
220
+ one of the main reasons to use the plugin is that it doesn't require them).
221
+ For associations like the example above (employee's supervisor is also an
222
+ employee), setting the foreign_key to the primary key and then changing it
223
+ later is an option, but database checks may prevent it. For more complex
224
+ cyclic dependencies involving multiple model classes (employee belongs_to
225
+ division belongs_to head_of_division when the employee is a member of the
226
+ division and also the head of the division), even that approach is not
227
+ possible.
228
+
229
+ == Dynamic fixtures with ERb
230
+
231
+ Adds support for ERb in the YAML fixtures, as is currently implemented in the
232
+ standard Rails fixtures.
233
+
234
+ <% for i in 1..100 %>
235
+ fixture_<%= i%>:
236
+ id: <%= i %>
237
+ name: guy_<%= i %>
238
+ <% end %>
239
+
240
+ This will create 100 very simple YAML fixtures.
241
+
242
+ Using ERb, you can also inject dynamic values into your fixtures with inserts
243
+ like <%= Date.today.strftime("%Y-%m-%d") %>. This is however a feature to be
244
+ used with some caution.
245
+
246
+ == Known issues
247
+
248
+ Currently, the plugin only supports YAML fixtures, but other types of fixtures
249
+ would be fairly easy to add (send me a patch if you add support for another
250
+ fixture type).
251
+
252
+ The plugin is significantly slower than the default testing method, because it
253
+ loads all fixtures inside of a transaction (one per test method), where Rails
254
+ defaults to loading the fixtures once per test suite (outside of a
255
+ transaction), and only deletes fixtures from a table when overwriting it with
256
+ new fixtures.
257
+
258
+ Instantiated fixtures are not available with this plugin. Instead, you should
259
+ use load(:model__fixture_name).
260
+
261
+ == Troubleshooting
262
+
263
+ If you run into problems with loading your fixtures, it can be difficult to see
264
+ where the problems are. To aid in debugging an error, add the following to
265
+ test/test_helper.rb:
266
+
267
+ FixtureDependencies.verbose = 3
268
+
269
+ This will give a verbose description of the loading and saving of fixtures for
270
+ every test, including the recursive loading of the dependency graph.
271
+
272
+ == Similar Ideas
273
+
274
+ Rails now supports something similar by default. Honestly, I'm not sure what
275
+ the differences are.
276
+
277
+ fixture_references is a similar plugin. It uses erb inside yaml, and uses the
278
+ foreign key numbers inside of the association names, which leads me to believe
279
+ it doesn't support has_* associations.
280
+
281
+ == License
282
+
283
+ fixture_dependencies is released under the MIT License. See the LICENSE file
284
+ for details.
285
+
286
+ == Author
287
+
288
+ Jeremy Evans <code@jeremyevans.net>
@@ -0,0 +1,218 @@
1
+ require('sequel/extensions/inflector') unless [:singularize, :camelize, :underscore, :constantize].all?{|meth| "".respond_to?(meth)}
2
+
3
+ class FixtureDependencies
4
+ @fixtures = {}
5
+ @loaded = {}
6
+ @verbose = 0
7
+
8
+ # Load all record arguments into the database. If a single argument is
9
+ # given and it corresponds to a single fixture, return the the model
10
+ # instance corresponding to that fixture. If a single argument if given
11
+ # and it corresponds to a model, return all model instances corresponding
12
+ # to that model. If multiple arguments are given, return a list of
13
+ # model instances (for single fixture arguments) or list of model instances
14
+ # (for model fixture arguments). If no arguments, return the empty list.
15
+ # If any of the arguments is a hash, assume the key specifies the model
16
+ # and the values specify the fixture, and treat it as though individual
17
+ # symbols specifying both model and fixture were given.
18
+ #
19
+ # Examples:
20
+ # * load(:posts) # All post fixtures, not recommended
21
+ # * load(:posts, :comments) # All post and comment fixtures, again not recommended
22
+ # * load(:post__post1) # Just the post fixture named post1
23
+ # * load(:post__post1, :post__post2) # Post fixtures named post1 and post2
24
+ # * load(:posts=>[:post1, :post2]) # Post fixtures named post1 and post2
25
+ # * load(:post__post1, :comment__comment2) # Post fixture named post1 and comment fixture named comment2
26
+ # * load({:posts=>[:post1, :post2]}, :comment__comment2) # Post fixtures named post1 and post2 and comment fixture named comment2
27
+ #
28
+ # This will load the data from the yaml files for each argument whose model
29
+ # is not already in the fixture hash.
30
+ def self.load(*records)
31
+ ret = records.map do |record|
32
+ if record.is_a?(Hash)
33
+ record.map do |k, vals|
34
+ model = k.to_s.singularize
35
+ vals.map{|v| :"#{model}__#{v}"}
36
+ end
37
+ else
38
+ record
39
+ end
40
+ end.flatten.compact.map do |record|
41
+ model_name, name = split_name(record)
42
+ if name
43
+ use(record.to_sym)
44
+ else
45
+ model_name = model_name.singularize
46
+ unless loaded[model_name.to_sym]
47
+ puts "loading #{model_name}.yml" if verbose > 0
48
+ load_yaml(model_name)
49
+ end
50
+ fixtures[model_name.to_sym].keys.map{|name| use(:"#{model_name}__#{name}")}
51
+ end
52
+ end
53
+ ret.length == 1 ? ret[0] : ret
54
+ end
55
+ end
56
+
57
+ require 'fixture_dependencies/active_record' if defined?(ActiveRecord::Base)
58
+ require 'fixture_dependencies/sequel' if defined?(Sequel::Model)
59
+ require 'erb'
60
+
61
+ class << FixtureDependencies
62
+ attr_reader :fixtures, :loaded
63
+ attr_accessor :verbose, :fixture_path
64
+
65
+ private
66
+
67
+ # Add a fixture to the fixture hash (does not add to the database,
68
+ # just makes it available to be add to the database via use).
69
+ def add(model_name, name, attributes)
70
+ (fixtures[model_name.to_sym]||={})[name.to_sym] = attributes
71
+ end
72
+
73
+ # Get the model instance that already exists in the database using
74
+ # the fixture name.
75
+ def get(record)
76
+ model_name, name = split_name(record)
77
+ model = model_name.camelize.constantize
78
+ model_method(:model_find, model_type(model), model, fixtures[model_name.to_sym][name.to_sym][model.primary_key.to_sym])
79
+ end
80
+
81
+ # Adds all fixtures in the yaml fixture file for the model to the fixtures
82
+ # hash (does not add them to the database, see add).
83
+ def load_yaml(model_name)
84
+ raise(ArgumentError, "No fixture_path set. Use FixtureDependencies.fixture_path = ...") unless fixture_path
85
+ YAML.load(erb_render(File.read(File.join(fixture_path, "#{model_name.camelize.constantize.table_name}.yml")))).each do |name, attributes|
86
+ symbol_attrs = {}
87
+ attributes.each{|k,v| symbol_attrs[k.to_sym] = v}
88
+ add(model_name.to_sym, name, symbol_attrs)
89
+ end
90
+ loaded[model_name.to_sym] = true
91
+ end
92
+
93
+ # Delegate to the correct method based on mtype
94
+ def model_method(meth, mtype, *args, &block)
95
+ send("#{meth}_#{mtype}", *args, &block)
96
+ end
97
+
98
+ # A symbol representing the base class of the model, currently
99
+ # ActiveRecord::Base and Sequel::Model are supported.
100
+ def model_type(model)
101
+ if model.ancestors.map{|x| x.to_s}.include?('ActiveRecord::Base')
102
+ :AR
103
+ elsif model.ancestors.map{|x| x.to_s}.include?('Sequel::Model')
104
+ :S
105
+ else
106
+ raise TypeError, 'not ActiveRecord or Sequel model'
107
+ end
108
+ end
109
+
110
+ # Split the fixture name into the name of the model and the name of
111
+ # the individual fixture.
112
+ def split_name(name)
113
+ name.to_s.split('__', 2)
114
+ end
115
+
116
+ # run the loaded fixture through ERB before loading it.
117
+ def erb_render(fixture_content)
118
+ ERB.new(fixture_content).result
119
+ end
120
+
121
+ # Load the individual fixture into the database, by loading all necessary
122
+ # belongs_to dependencies before saving the model, and all has_*
123
+ # dependencies after saving the model. If the model already exists in
124
+ # the database, return it. Will check the yaml file for fixtures if no
125
+ # fixtures yet exist for the model. If the fixture isn't in the fixture
126
+ # hash, raise an error.
127
+ def use(record, loading = [], procs = {})
128
+ spaces = " " * loading.length
129
+ puts "#{spaces}using #{record}" if verbose > 0
130
+ puts "#{spaces}load stack:#{loading.inspect}" if verbose > 1
131
+ loading.push(record)
132
+ model_name, name = split_name(record)
133
+ model = model_name.camelize.constantize
134
+ unless loaded[model_name.to_sym]
135
+ puts "#{spaces}loading #{model.table_name}.yml" if verbose > 0
136
+ load_yaml(model_name)
137
+ end
138
+ mtype = model_type(model)
139
+ model_method(:raise_model_error, mtype, "Couldn't use fixture #{record.inspect}") unless attributes = fixtures[model_name.to_sym][name.to_sym]
140
+ # return if object has already been loaded into the database
141
+ if existing_obj = model_method(:model_find_by_pk, mtype, model, attributes[model.primary_key.to_sym])
142
+ puts "#{spaces}using #{record}: already in database" if verbose > 2
143
+ loading.pop
144
+ return existing_obj
145
+ end
146
+ obj = model.new
147
+ many_associations = []
148
+ attributes.each do |attr, value|
149
+ if reflection = model_method(:reflection, mtype, model, attr.to_sym)
150
+ if [:belongs_to, :many_to_one].include?(model_method(:reflection_type, mtype, reflection))
151
+ dep_name = "#{model_method(:reflection_class, mtype, reflection).name.underscore}__#{value}".to_sym
152
+ if dep_name == record
153
+ # Self referential record, use primary key
154
+ puts "#{spaces}#{record}.#{attr}: belongs_to self-referential" if verbose > 1
155
+ attr = model_method(:reflection_key, mtype, reflection)
156
+ value = attributes[model.primary_key.to_sym]
157
+ elsif loading.include?(dep_name)
158
+ # Association cycle detected, set foreign key for this model afterward using procs
159
+ # This is will fail if the column is set to not null or validates_presence_of
160
+ puts "#{spaces}#{record}.#{attr}: belongs-to cycle detected:#{dep_name}" if verbose > 1
161
+ (procs[dep_name] ||= []) << Proc.new do |assoc|
162
+ m = model_method(:model_find, mtype, model, attributes[model.primary_key.to_sym])
163
+ m.send("#{attr}=", assoc)
164
+ model_method(:model_save, mtype, m)
165
+ end
166
+ value = nil
167
+ else
168
+ # Regular assocation, load it
169
+ puts "#{spaces}#{record}.#{attr}: belongs_to:#{dep_name}" if verbose > 1
170
+ use(dep_name, loading, procs)
171
+ value = get(dep_name)
172
+ end
173
+ elsif
174
+ many_associations << [attr, reflection, model_method(:reflection_type, mtype, reflection) == :has_one ? [value] : value]
175
+ next
176
+ end
177
+ end
178
+ puts "#{spaces}#{record}.#{attr} = #{value.inspect}" if verbose > 2
179
+ obj.send("#{attr}=", value)
180
+ end
181
+
182
+ puts "#{spaces}saving #{record}" if verbose > 1
183
+
184
+ model_method(:model_save, mtype, obj)
185
+ # after saving the model, we set the primary key within the fixture hash, in case it was not explicitly specified in the fixture and was generated by an auto_increment / serial field
186
+ fixtures[model_name.to_sym][name.to_sym][model.primary_key.to_sym] ||= obj[model.primary_key.to_sym]
187
+
188
+ loading.pop
189
+ # Update the circular references
190
+ if procs[record]
191
+ procs[record].each{|p| p.call(obj)}
192
+ procs.delete(record)
193
+ end
194
+ # Update the has_many and habtm associations
195
+ many_associations.each do |attr, reflection, values|
196
+ values.each do |value|
197
+ dep_name = "#{model_method(:reflection_class, mtype, reflection).name.underscore}__#{value}".to_sym
198
+ rtype = model_method(:reflection_type, mtype, reflection) if verbose > 1
199
+ if dep_name == record
200
+ # Self referential, add association
201
+ puts "#{spaces}#{record}.#{attr}: #{rtype} self-referential" if verbose > 1
202
+ model_method(:add_associated_object, mtype, reflection, attr, obj, obj)
203
+ elsif loading.include?(dep_name)
204
+ # Cycle Detected, add association to this object after saving other object
205
+ puts "#{spaces}#{record}.#{attr}: #{rtype} cycle detected:#{dep_name}" if verbose > 1
206
+ (procs[dep_name] ||= []) << Proc.new do |assoc|
207
+ model_method(:add_associated_object, mtype, reflection, attr, obj, assoc)
208
+ end
209
+ else
210
+ # Regular association, add it
211
+ puts "#{spaces}#{record}.#{attr}: #{rtype}:#{dep_name}" if verbose > 1
212
+ model_method(:add_associated_object, mtype, reflection, attr, obj, use(dep_name, loading, procs))
213
+ end
214
+ end
215
+ end
216
+ obj
217
+ end
218
+ end
@@ -0,0 +1,43 @@
1
+ class << FixtureDependencies
2
+ private
3
+
4
+ def add_associated_object_AR(reflection, attr, object, assoc)
5
+ if reflection.macro == :has_one
6
+ object.send("#{attr}=", assoc)
7
+ elsif !object.send(attr).include?(assoc)
8
+ object.send(attr) << assoc
9
+ end
10
+ end
11
+
12
+ def model_find_AR(model, pk)
13
+ model.find(pk)
14
+ end
15
+
16
+ def model_find_by_pk_AR(model, pk)
17
+ model.send("find_by_#{model.primary_key}", pk)
18
+ end
19
+
20
+ def model_save_AR(object)
21
+ object.save || raise(ActiveRecord::ActiveRecordError)
22
+ end
23
+
24
+ def raise_model_error_AR(message)
25
+ ActiveRecord::RecordNotFound
26
+ end
27
+
28
+ def reflection_AR(model, attr)
29
+ model.reflect_on_association(attr)
30
+ end
31
+
32
+ def reflection_class_AR(reflection)
33
+ reflection.klass
34
+ end
35
+
36
+ def reflection_key_AR(reflection)
37
+ reflection.options[:foreign_key] || reflection.klass.table_name.classify.foreign_key
38
+ end
39
+
40
+ def reflection_type_AR(reflection)
41
+ reflection.macro
42
+ end
43
+ end
@@ -0,0 +1,14 @@
1
+ class Spec::Example::ExampleGroup
2
+ def execute(*args, &block)
3
+ begin
4
+ Sequel::Model.db.transaction{super(*args, &block); raise Sequel::Error::Rollback}
5
+ return true
6
+ rescue
7
+ return false
8
+ end
9
+ end
10
+
11
+ def load(*args)
12
+ FixtureDependencies.load(*args)
13
+ end
14
+ end
@@ -0,0 +1,40 @@
1
+ class << FixtureDependencies
2
+ private
3
+
4
+ def add_associated_object_S(reflection, attr, object, assoc)
5
+ object.send("add_#{attr.to_s.singularize}", assoc) unless object.send(attr).include?(assoc)
6
+ end
7
+
8
+ def model_find_S(model, pk)
9
+ model[pk] || raise(Sequel::Error)
10
+ end
11
+
12
+ def model_find_by_pk_S(model, pk)
13
+ model[pk]
14
+ end
15
+
16
+ def model_save_S(object)
17
+ object.raise_on_save_failure = true
18
+ object.save
19
+ end
20
+
21
+ def raise_model_error_S(message)
22
+ Sequel::Error
23
+ end
24
+
25
+ def reflection_S(model, attr)
26
+ model.association_reflection(attr)
27
+ end
28
+
29
+ def reflection_class_S(reflection)
30
+ reflection.associated_class
31
+ end
32
+
33
+ def reflection_key_S(reflection)
34
+ reflection[:key]
35
+ end
36
+
37
+ def reflection_type_S(reflection)
38
+ reflection[:type]
39
+ end
40
+ end
@@ -0,0 +1,14 @@
1
+ require 'fixture_dependencies'
2
+
3
+ module Test
4
+ module Unit
5
+ class TestCase
6
+ private
7
+
8
+ # Load given fixtures using FixtureDependencies
9
+ def load(*fixture)
10
+ FixtureDependencies.load(*fixture)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ require 'fixture_dependencies/test_unit'
2
+ FixtureDependencies.fixture_path = Test::Unit::TestCase.fixture_path
3
+
4
+ module Test
5
+ module Unit
6
+ class TestCase
7
+ class << self
8
+ alias_method :stupid_method_added, :method_added
9
+ end
10
+ def self.method_added(x)
11
+ end
12
+
13
+ # Load fixtures using FixtureDependencies inside a transaction
14
+ def setup_with_fixtures
15
+ ActiveRecord::Base.send :increment_open_transactions
16
+ ActiveRecord::Base.connection.begin_db_transaction
17
+ load_fixtures
18
+ end
19
+ alias_method :setup, :setup_with_fixtures
20
+
21
+ class << self
22
+ alias_method :method_added, :stupid_method_added
23
+ end
24
+
25
+ private
26
+
27
+ # Load fixtures named with the fixtures class method
28
+ def load_fixtures
29
+ load(*fixture_table_names)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,13 @@
1
+ require 'fixture_dependencies/test_unit'
2
+
3
+ class FixtureDependencies::SequelTestCase < Test::Unit::TestCase
4
+ # Work around for Rails stupidity
5
+ undef_method :default_test if method_defined?(:default_test)
6
+
7
+ def run(*args, &block)
8
+ Sequel::Model.db.transaction do
9
+ super
10
+ raise Sequel::Error::Rollback
11
+ end
12
+ end
13
+ end
@@ -0,0 +1 @@
1
+ require 'fixture_dependencies/test_unit/rails'
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: smulube-fixture_dependencies
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.4
5
+ platform: ruby
6
+ authors:
7
+ - Jeremy Evans
8
+ - Sam Mulube
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-05-16 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: "fixture_dependencies is an advanced fixture loader for ActiveRecord and Sequel, allowing the loading of models from YAML fixtures, along with their entire dependency graph. It has the following features: - Fixtures specify association names instead of foreign keys - Support both Sequel and ActiveRecord - Supports many_to_one/belongs_to, one_to_many/has_many, many_to_many/has_and_belongs_to_many, and has_one associations - Loads a fixture's dependency graph in such a manner that foreign key constraints aren't violated - Has a very simple API (FixtureDependencies.load(:model__fixture)) - Handles almost all cyclic dependencies - Includes Rails and Sequel test helpers for Test::Unit (and a Sequel test helper for RSpec) that load fixtures for every test inside a transaction, so fixture data is never left in your database - Adds dynamic fixtures (similar to ActiveRecord) with ERb."
18
+ email:
19
+ - code@jeremyevans.net
20
+ - sam@mulube.com
21
+ executables: []
22
+
23
+ extensions: []
24
+
25
+ extra_rdoc_files:
26
+ - LICENSE
27
+ files:
28
+ - README
29
+ - LICENSE
30
+ - lib/fixture_dependencies.rb
31
+ - lib/fixture_dependencies_test_help.rb
32
+ - lib/fixture_dependencies/sequel.rb
33
+ - lib/fixture_dependencies/active_record.rb
34
+ - lib/fixture_dependencies/test_unit.rb
35
+ - lib/fixture_dependencies/test_unit/rails.rb
36
+ - lib/fixture_dependencies/test_unit/sequel.rb
37
+ - lib/fixture_dependencies/rspec/sequel.rb
38
+ has_rdoc: true
39
+ homepage:
40
+ post_install_message:
41
+ rdoc_options:
42
+ - --inline-source
43
+ - --line-numbers
44
+ - README
45
+ - lib
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ requirements: []
61
+
62
+ rubyforge_project:
63
+ rubygems_version: 1.2.0
64
+ signing_key:
65
+ specification_version: 2
66
+ summary: Sequel/ActiveRecord fixture loader that handles dependency graphs. Supports dynamic ERb fixtures.
67
+ test_files: []
68
+