smulube-fixture_dependencies 1.2.4

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.
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
+