joinfix 0.1.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +157 -85
- data/Rakefile +38 -0
- data/TEST_README +45 -44
- data/lib/joinfix/error.rb +220 -0
- data/lib/joinfix/fixture.rb +3 -4
- data/lib/joinfix/fixtures.rb +107 -145
- data/lib/joinfix/fixtures_class.rb +51 -97
- data/lib/joinfix.rb +118 -84
- data/rails/app/models/group.rb +3 -3
- data/rails/db/migrate/004_create_users.rb +1 -1
- data/rails/db/schema.rb +1 -1
- data/rails/log/development.log +409 -57
- data/rails/log/test.log +350 -23
- data/rails/test/fixtures/groups.yml +2 -1
- data/rails/test/fixtures/users.yml +27 -19
- data/rails/test/unit/user_test.rb +25 -4
- data/test/has_many_test.rb +16 -0
- data/test/joinfix_test.rb +6 -69
- data/test/joinfix_test_suite.rb +1 -1
- metadata +9 -5
- data/test/todo +0 -15
data/lib/joinfix/fixtures.rb
CHANGED
@@ -1,27 +1,67 @@
|
|
1
|
+
# Fixtures objects are essentially nested hashes:
|
2
|
+
#
|
3
|
+
# # A Fixtures is a hash of entry name keys and Fixture values
|
4
|
+
# entry_name:
|
5
|
+
# # A Fixture is a hash of entry fields and values
|
6
|
+
# field: value
|
7
|
+
#
|
8
|
+
# Fixtures also tracks data required for loading entries into the database,
|
9
|
+
# such as table_name and the connection to use. See 'active_record/fixtures.rb'
|
10
|
+
# for more details.
|
11
|
+
#
|
12
|
+
# JoinFix extends Fixtures to track additional information like the ActiveRecord
|
13
|
+
# class modeling the entry data. Using reflection, Fixtures can figure out which fields
|
14
|
+
# in an entry correspond to an association. Entries with association fields are
|
15
|
+
# extracted and turned into join entries. Consider and ActiveRecord class User, with
|
16
|
+
# 'name' as an attribute and a 'groups' association...
|
17
|
+
#
|
18
|
+
# [users.yml]
|
19
|
+
# # This entry will not be extracted as a template because it defines no 'groups'
|
20
|
+
# john:
|
21
|
+
# name: John
|
22
|
+
#
|
23
|
+
# # This entry will be extracted because it defines the 'groups' association
|
24
|
+
# jane:
|
25
|
+
# name: Jane
|
26
|
+
# groups:
|
27
|
+
# - admin_group
|
28
|
+
# - workers
|
29
|
+
#
|
30
|
+
# If you loaded users.yml into a Fixtures...
|
31
|
+
# users = Fixtures.new( ...arguments to load users.yml...)
|
32
|
+
# users.to_hash # => {'john' => ..., 'jane' => ...}
|
33
|
+
# users.templates # => nil
|
34
|
+
#
|
35
|
+
# users.extract_templates
|
36
|
+
# users.to_hash # => {'john' => ...}
|
37
|
+
# users.templates # => {'jane' => ...}
|
38
|
+
#
|
39
|
+
# The entry templates are extended with JoinFix and used to create the join entries.
|
1
40
|
class Fixtures
|
2
|
-
attr_reader :klass, :
|
41
|
+
attr_reader :klass, :association_names, :templates, :fixture_path
|
3
42
|
|
4
43
|
alias join_fix_original_initialize initialize
|
5
|
-
def initialize(*args)
|
44
|
+
def initialize(*args) # :nodoc:
|
6
45
|
join_fix_original_initialize(*args)
|
7
46
|
@klass = Object.const_get(@class_name)
|
8
|
-
|
9
|
-
# default attributes, constructed from reflecting on the active record table
|
10
|
-
@attributes = {}
|
11
|
-
@klass.columns.each do |column|
|
12
|
-
@attributes[column.name] = column.default
|
13
|
-
end
|
14
|
-
|
47
|
+
@association_names = klass.reflect_on_all_associations.collect {|assoc| assoc.name.to_s}
|
15
48
|
@join_configs = {}
|
16
49
|
end
|
17
50
|
|
18
51
|
alias join_fix_original_insert_fixtures insert_fixtures
|
52
|
+
|
53
|
+
# Extends the default method to provide a hook for making join fixtures.
|
54
|
+
# Now insert_fixtures calls Fixtures.make_join_fixtures before calling
|
55
|
+
# the original insert_fixtures method.
|
19
56
|
def insert_fixtures
|
20
|
-
Fixtures.
|
57
|
+
Fixtures.make_join_fixtures if templates.nil?
|
21
58
|
join_fix_original_insert_fixtures
|
22
59
|
end
|
23
60
|
|
24
|
-
|
61
|
+
# Extracts the child entry templates then makes the entries specified
|
62
|
+
# by each template. Does not execute if templates have already been
|
63
|
+
# extracted.
|
64
|
+
def make_child_entries
|
25
65
|
return unless templates.nil?
|
26
66
|
|
27
67
|
extract_templates
|
@@ -30,83 +70,88 @@ class Fixtures
|
|
30
70
|
end
|
31
71
|
end
|
32
72
|
|
33
|
-
|
34
|
-
0
|
35
|
-
# FUTURE!: is this even needed? I don't think so given that all rows are
|
36
|
-
# deleted by delete_existing_fixtures... not sure.
|
37
|
-
# @connection. QUERY FOR NEXT ID
|
38
|
-
end
|
39
|
-
|
73
|
+
# Returns the join configuration (as per JoinFix.configure) for the given association.
|
40
74
|
def join_config(assoc_name)
|
41
75
|
@join_configs[assoc_name] ||= JoinFix.send("configure", klass, assoc_name)
|
42
76
|
end
|
43
77
|
|
44
|
-
|
78
|
+
# Iterates through each entry
|
79
|
+
def each_pair(&block)
|
45
80
|
map { |entry_name, fixture| yield(entry_name, fixture) }
|
46
81
|
end
|
47
82
|
|
83
|
+
# Returns all entries as a hash of {entry_name => entry} pairs
|
48
84
|
def to_hash
|
49
85
|
hash = {}
|
50
|
-
each_pair do |
|
51
|
-
hash[
|
86
|
+
each_pair do |entry_name, entry|
|
87
|
+
hash[entry_name] = entry.to_hash
|
52
88
|
end
|
53
89
|
hash
|
54
90
|
end
|
91
|
+
|
92
|
+
# The initial offset for indexing (ie 0 so that indexing starts at 1).
|
93
|
+
# This method is provided as a hook for overrides if necessary.
|
94
|
+
def primary_key_offset
|
95
|
+
0
|
96
|
+
end
|
55
97
|
|
56
98
|
protected
|
57
99
|
|
58
|
-
|
59
|
-
|
100
|
+
# Extracts template entries. Entries are Fixture objects, essentially a hash of {attribute => value} pairs.
|
101
|
+
# An entry is considered a template if it contains an association attribute. If this is true, then the entry
|
102
|
+
# is removed from self and stored as a template.
|
103
|
+
def extract_templates # :nodoc:
|
60
104
|
@templates = {}
|
61
|
-
|
62
|
-
|
105
|
+
|
106
|
+
# iterate over all entries looking for templates
|
107
|
+
each do |entry_name, fixture|
|
63
108
|
entry = fixture.to_hash
|
64
|
-
|
109
|
+
|
110
|
+
# fixture is a template if it contains an association
|
111
|
+
next if (entry.keys & association_names).empty?
|
65
112
|
@templates[entry_name] = entry
|
66
113
|
end
|
114
|
+
|
115
|
+
# remove template entries
|
67
116
|
delete_if do |entry_name, fixture|
|
68
117
|
@templates.has_key?(entry_name)
|
69
118
|
end
|
70
119
|
end
|
71
120
|
|
72
|
-
|
73
|
-
|
121
|
+
# Makes the specified entry and adds the entry to self if add_entry_on_complete is true.
|
122
|
+
def make_entry(entry_name, entry, add_entry_on_complete) # :nodoc:
|
123
|
+
|
124
|
+
# If the entry is not a hash, then no entry name was specified in the fixture file
|
125
|
+
unless entry.kind_of?(Hash)
|
126
|
+
raise NoEntryNameError.new(self, entry_name, entry)
|
127
|
+
end
|
74
128
|
|
75
|
-
entry = attributes.merge(entry_template)
|
76
129
|
entry.extend JoinFix
|
77
130
|
entry.entry_name = entry_name
|
78
131
|
|
79
|
-
# extract
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
key == "id" || key.kind_of?(Array)
|
85
|
-
end
|
86
|
-
|
87
|
-
# also extract templates for entries that have an array value. These entries indicate a set of
|
88
|
-
# associated entries that should each be joined to the current entry
|
89
|
-
assoc_entries.merge( entry.extract_if { |key, value| value.kind_of?(Array) } )
|
90
|
-
assoc_entries.each_pair do |assoc_name, assoc_array|
|
91
|
-
# ensure that assoc_array is an array of template
|
92
|
-
assoc_array = [assoc_array] unless assoc_array.kind_of?(Array)
|
132
|
+
# extract and construct associated entries
|
133
|
+
associated_entries = entry.extract_if(association_names)
|
134
|
+
associated_entries.each_pair do |assoc_name, associations|
|
135
|
+
# ensure that associations is an array
|
136
|
+
associations = [associations] unless associations.kind_of?(Array)
|
93
137
|
|
94
|
-
#
|
138
|
+
# get the join configuration for the association
|
95
139
|
join_config = join_config(assoc_name)
|
96
140
|
join_table = join_config[:join_table]
|
97
141
|
macro = join_config[:macro]
|
98
142
|
|
99
|
-
# pull the polymorphic
|
100
|
-
# beforehand what table they will join to
|
143
|
+
# pull the polymorphic join information out of the entry -- polymorphic joins cannot determine
|
144
|
+
# beforehand what table they will join to; the associable_type MUST be specified in the entry.
|
101
145
|
if join_config[:polymorphic] == true
|
102
|
-
|
146
|
+
# be sure to preserve the base configuration...
|
147
|
+
join_config = join_config.dup
|
103
148
|
|
104
149
|
associable_type = join_config[:associable_type]
|
105
150
|
associable_class = entry[associable_type]
|
106
151
|
|
107
152
|
unless associable_class
|
108
|
-
raise MissingPolymorphicTypeError.new(self, entry_name,
|
109
|
-
|
153
|
+
raise MissingPolymorphicTypeError.new(self, entry_name, entry.merge(associated_entries),
|
154
|
+
"No <#{associable_type}> was specified.")
|
110
155
|
end
|
111
156
|
|
112
157
|
join_config[:child_class] = associable_class
|
@@ -114,16 +159,16 @@ class Fixtures
|
|
114
159
|
end
|
115
160
|
|
116
161
|
# raise an error if the macro doesn't allow for multiple joins, but multiple associated entries are specified
|
117
|
-
unless
|
118
|
-
raise MultipleChildrenError.new(self, entry_name,
|
162
|
+
unless associations.length == 1 || JoinFix.macro_allows_multiple(macro)
|
163
|
+
raise MultipleChildrenError.new(self, entry_name, entry.merge(associated_entries),
|
119
164
|
"Multiple joined entries specified for the single-join macro '#{macro}'.")
|
120
165
|
end
|
121
166
|
|
122
|
-
|
123
|
-
#
|
167
|
+
associations.each do |template|
|
168
|
+
# String templates are references to another entry. Make a dummy template with a dummy JoinFix.
|
124
169
|
template = {template => JoinFix.new(template)} if template.kind_of?(String)
|
125
170
|
|
126
|
-
#
|
171
|
+
# Make the entries specified in the template
|
127
172
|
template.each_pair do |child_name, child|
|
128
173
|
# generate the child entry
|
129
174
|
child_fixture = Fixtures.fixture(join_config[:child_table])
|
@@ -131,12 +176,10 @@ class Fixtures
|
|
131
176
|
|
132
177
|
# generate the join entry
|
133
178
|
join = entry.send("join_#{macro}", child, join_config)
|
134
|
-
|
135
|
-
|
136
|
-
#
|
137
|
-
# join entry will be processed according to the wizard modules specified for the join table.
|
179
|
+
Fixtures.fixture(join_table).make_entry(join.entry_name, join, true) if join
|
180
|
+
|
181
|
+
# add the child entry
|
138
182
|
child_fixture.add_entry(child_name, child)
|
139
|
-
Fixtures.fixture(join_table).make_entry(join.entry_name, join, true) if join
|
140
183
|
end
|
141
184
|
end
|
142
185
|
end
|
@@ -145,17 +188,11 @@ class Fixtures
|
|
145
188
|
add_entry(entry_name, entry) if add_entry_on_complete
|
146
189
|
entry
|
147
190
|
end
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
# remove any attributes that are equal to their default
|
154
|
-
entry.delete_if do |attribute, value|
|
155
|
-
default = attributes[attribute]
|
156
|
-
value == default
|
157
|
-
end
|
158
|
-
|
191
|
+
|
192
|
+
# Adds the specified entry to self, or merges entry attributes into the
|
193
|
+
# existing entry. Raises an error in the case of an entry attribute collision
|
194
|
+
# (ie an existing attribute does not equal the new attribute).
|
195
|
+
def add_entry(entry_name, entry) # :nodoc:
|
159
196
|
# create a new fixture if one by the entry_name doesn't exist
|
160
197
|
existing = self[entry_name] ||= Fixture.new({}, klass.class_name)
|
161
198
|
|
@@ -169,78 +206,3 @@ class Fixtures
|
|
169
206
|
end
|
170
207
|
end
|
171
208
|
end
|
172
|
-
|
173
|
-
class MakeEntryError < RuntimeError # :nodoc:
|
174
|
-
attr_reader :fixtures, :entry_name, :entry, :msg
|
175
|
-
attr_accessor :advice
|
176
|
-
|
177
|
-
def initialize(fixtures, entry_name, entry, msg=nil)
|
178
|
-
@fixtures = fixtures
|
179
|
-
@entry_name = entry_name
|
180
|
-
@entry = entry
|
181
|
-
@msg =msg
|
182
|
-
end
|
183
|
-
|
184
|
-
def message
|
185
|
-
"Error making <#{fixtures.klass.table_name}(:#{entry_name})> in <#{fixtures.fixture_path}>.\n" +
|
186
|
-
{entry_name => entry}.to_yaml +
|
187
|
-
(msg.nil? ? '' : "\n#{msg}\n") +
|
188
|
-
(advice.nil? ? '' : "#{advice}\n")
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
class EntryCollisionError < MakeEntryError # :nodoc:
|
193
|
-
end
|
194
|
-
|
195
|
-
class NoEntryNameError < MakeEntryError # :nodoc:
|
196
|
-
def advice
|
197
|
-
%Q{
|
198
|
-
This error occurs when an entry is not named as in:
|
199
|
-
---
|
200
|
-
dog:
|
201
|
-
title: Dog
|
202
|
-
author:
|
203
|
-
# <an entry name like 'ferlinghetti' is missing here>
|
204
|
-
full_name: Lawrence Ferlinghetti
|
205
|
-
...}
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
class MultipleChildrenError < MakeEntryError # :nodoc:
|
210
|
-
def advice
|
211
|
-
%Q{
|
212
|
-
Single entry joins should specify a single entry, not an array of entries.
|
213
|
-
Use a different association if you need multiple joined entries.
|
214
|
-
---
|
215
|
-
poem:
|
216
|
-
title: Slave's Dream
|
217
|
-
author:
|
218
|
-
longfellow:
|
219
|
-
full_name: Henry Wadsworth Longfellow}
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
class MissingPolymorphicTypeError < MakeEntryError # :nodoc:
|
224
|
-
def advice
|
225
|
-
%Q{
|
226
|
-
When specifying a belongs_to :polymorphic join, the type
|
227
|
-
of the joined entry must be specified because it cannot be
|
228
|
-
inferred from association itself. Use something like:
|
229
|
-
--
|
230
|
-
book_I_read:
|
231
|
-
opinion: Great!
|
232
|
-
readable_type: Book
|
233
|
-
readable:
|
234
|
-
the_jungle_books:
|
235
|
-
author: Rudyard Kipling
|
236
|
-
title: The Jungle Books
|
237
|
-
|
238
|
-
poem_I_read:
|
239
|
-
opinion: Essential!
|
240
|
-
readable_type: Poem
|
241
|
-
readable:
|
242
|
-
sea_fever:
|
243
|
-
poet: John Masefield
|
244
|
-
title: Sea-Fever}
|
245
|
-
end
|
246
|
-
end
|
@@ -1,26 +1,45 @@
|
|
1
1
|
class Fixtures
|
2
|
-
# Class methods to tie fixture joining into the standard process for generating fixtures.
|
3
2
|
class << self
|
4
3
|
|
5
|
-
#
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
# Makes join fixtures for all loaded fixtures. Called just prior to inserting
|
5
|
+
# fixtures, after all fixtures have been loaded.
|
6
|
+
#
|
7
|
+
# After make_join_fixtures completes, entries for tables matching ENV['joinfix_dump']
|
8
|
+
# are printed to STDOUT. You can print entries for each loaded fixture by setting
|
9
|
+
# ENV['joinfix_dump'] = 'true'. By default, no entries are printed.
|
10
|
+
#
|
11
|
+
# Note: printing does not affect the creation or loading of fixtures.
|
12
|
+
def make_join_fixtures
|
10
13
|
all_loaded_fixtures.each_pair do |table_name, fixtures|
|
11
|
-
fixtures.
|
14
|
+
fixtures.make_child_entries
|
12
15
|
end
|
16
|
+
|
13
17
|
# note indexing and reference resolution must execute after all
|
14
18
|
# fixtures have been templated because you never know which fixture(s)
|
15
19
|
# will recieve new entries. Additionally, indexing and resolution must
|
16
|
-
# run separately, because reference resolution requires the
|
17
|
-
|
20
|
+
# run separately, because reference resolution requires the primary key
|
21
|
+
# be set for the referenced entry.
|
18
22
|
all_loaded_fixtures.values.each {|fixtures| index_fixtures(fixtures) }
|
19
23
|
all_loaded_fixtures.values.each {|fixtures| resolve_references(fixtures)}
|
24
|
+
|
25
|
+
# Print entries to STDOUT for review, if applicable
|
26
|
+
joinfix_dump = ENV['joinfix_dump']
|
27
|
+
if joinfix_dump
|
28
|
+
print_all = (joinfix_dump.to_s =~ /^true$/i)
|
29
|
+
regexp = Regexp.new(joinfix_dump.to_s)
|
30
|
+
|
31
|
+
all_loaded_fixtures.values.each do |fixtures|
|
32
|
+
table_name = fixtures.klass.table_name
|
33
|
+
next unless print_all || table_name =~ regexp
|
34
|
+
|
35
|
+
puts "------- #{fixtures.klass.table_name} --------"
|
36
|
+
puts fixtures.to_hash.to_yaml.gsub(/^---/, '') + "\n"
|
37
|
+
end
|
38
|
+
end
|
20
39
|
end
|
21
40
|
|
22
|
-
# Retreives the
|
23
|
-
# not yet been loaded.
|
41
|
+
# Retreives the Fixtures for the given table name. Raises an error if this Fixtures
|
42
|
+
# has not yet been loaded.
|
24
43
|
def fixture(table_name)
|
25
44
|
fixture = all_loaded_fixtures[table_name.to_s]
|
26
45
|
raise MissingFixtureError.new(table_name) unless fixture
|
@@ -29,26 +48,25 @@ class Fixtures
|
|
29
48
|
|
30
49
|
protected
|
31
50
|
|
32
|
-
# Sets the primary key in each of the input
|
33
|
-
|
34
|
-
|
51
|
+
# Sets the primary key for entries in each of the input Fixtures, beginning
|
52
|
+
# one past the Fixtures primary key offset (ie 1). Skips entries that already
|
53
|
+
# have a primary key assigned.
|
54
|
+
def index_fixtures(fixtures) # :nodoc:
|
35
55
|
id = fixtures.klass.primary_key
|
36
56
|
|
37
|
-
#
|
57
|
+
# find entries with the primary key and record these so that they will be skipped
|
38
58
|
skip_indicies = []
|
39
59
|
fixtures.each_pair do |name, fixture|
|
40
60
|
skip_indicies << fixture[id].to_i if fixture.has_key?(id)
|
41
61
|
end
|
42
62
|
|
43
|
-
#
|
44
|
-
index = fixtures.
|
63
|
+
# find and index entries that do not have a primary key defined
|
64
|
+
index = fixtures.primary_key_offset
|
45
65
|
fixtures.each_pair do |name, fixture|
|
46
|
-
# skip entries that already have an id defined
|
47
66
|
next if fixture.has_key?(id)
|
48
67
|
|
49
|
-
# find the next available index
|
50
|
-
|
51
|
-
# in case index 1 is marked for skipping
|
68
|
+
# find the next available index. Note this must happen before
|
69
|
+
# the assignment, in case '1' is marked for skipping
|
52
70
|
while true
|
53
71
|
index += 1
|
54
72
|
break unless skip_indicies.include?(index)
|
@@ -58,24 +76,17 @@ class Fixtures
|
|
58
76
|
end
|
59
77
|
end
|
60
78
|
|
61
|
-
# Resolves
|
62
|
-
def resolve_references(fixtures)
|
63
|
-
fixtures.each_pair do |entry_name,
|
64
|
-
|
65
|
-
fixture.each_pair do |join_ref, join_name|
|
79
|
+
# Resolves join references in the input Fixtures.
|
80
|
+
def resolve_references(fixtures) # :nodoc:
|
81
|
+
fixtures.each_pair do |entry_name, entry|
|
82
|
+
entry.each_pair do |join_ref, join_name|
|
66
83
|
# next if the key isn't a join reference
|
67
84
|
next unless join_ref.kind_of?(Array)
|
68
85
|
|
69
86
|
foreign_key = join_ref.first
|
70
87
|
join_table_name = join_ref.last
|
71
|
-
|
72
|
-
|
73
|
-
unless Fixtures.all_loaded_fixtures.has_key?(join_table_name)
|
74
|
-
raise ResolveJoinReferenceError.new(fixtures, entry_name, join_table_name, join_name,
|
75
|
-
"The join table '#{join_table_name}' has not been loaded.")
|
76
|
-
end
|
77
|
-
|
78
|
-
join_fixtures = Fixtures.all_loaded_fixtures[join_table_name]
|
88
|
+
|
89
|
+
join_fixtures = Fixtures.fixture(join_table_name)
|
79
90
|
id = join_fixtures.klass.primary_key
|
80
91
|
|
81
92
|
# raise an error if the join entry isn't in the join table; the reference cannot be resolved
|
@@ -86,82 +97,25 @@ class Fixtures
|
|
86
97
|
|
87
98
|
join_entry = join_fixtures[join_name]
|
88
99
|
|
89
|
-
# raise an exception if
|
100
|
+
# raise an exception if the primary key for the join entry is not set
|
90
101
|
unless join_entry.has_key?(id)
|
91
102
|
raise ResolveJoinReferenceError.new(fixtures, entry_name, join_table_name, join_name,
|
92
103
|
"No #{id} present in join entry '#{join_name}'.")
|
93
104
|
end
|
94
105
|
|
95
106
|
# raise an exception if the foreign key is already set
|
96
|
-
unless
|
107
|
+
unless entry[foreign_key].nil?
|
97
108
|
raise ForeignKeySetError.new(fixtures, entry_name, join_table_name, join_name,
|
98
109
|
"Foreign key <#{foreign_key}> is already set!")
|
99
110
|
end
|
100
111
|
|
101
|
-
# set the
|
102
|
-
|
112
|
+
# set the foreign key to the joined entry primary key
|
113
|
+
entry[foreign_key] = join_entry[id]
|
103
114
|
end
|
104
115
|
|
105
116
|
# delete the join references
|
106
|
-
|
117
|
+
entry.delete_if {|key,value| key.kind_of?(Array) }
|
107
118
|
end
|
108
119
|
end
|
109
120
|
end
|
110
|
-
end
|
111
|
-
|
112
|
-
class MissingFixtureError < RuntimeError # :nodoc:
|
113
|
-
attr_reader :table_name
|
114
|
-
def initialize(table_name)
|
115
|
-
@table_name = table_name
|
116
|
-
end
|
117
|
-
|
118
|
-
def message
|
119
|
-
"No fixture loaded for <#{table_name}>\n" +
|
120
|
-
(advice.nil? ? '' : "#{advice}\n")
|
121
|
-
end
|
122
|
-
|
123
|
-
def advice
|
124
|
-
%Q{}
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
class ResolveJoinReferenceError < RuntimeError # :nodoc:
|
129
|
-
attr_reader :fixtures, :entry_name, :join_table_name, :join_name, :msg
|
130
|
-
attr_accessor :advice
|
131
|
-
|
132
|
-
def initialize(fixtures, entry_name, join_table_name, join_name, msg=nil)
|
133
|
-
@fixtures = fixtures
|
134
|
-
@entry_name = entry_name
|
135
|
-
@join_table_name = join_table_name
|
136
|
-
@join_name = join_name
|
137
|
-
@msg =msg
|
138
|
-
end
|
139
|
-
|
140
|
-
def message
|
141
|
-
"Cannot resolve reference to <#{join_table_name}(:#{join_name})> " +
|
142
|
-
"for <#{fixtures.klass.table_name}(:#{entry_name})> " +
|
143
|
-
"in <#{fixtures.fixture_path}>.\n" +
|
144
|
-
(msg.nil? ? '' : "\n#{msg}\n") +
|
145
|
-
(advice.nil? ? '' : "#{advice}\n")
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
class ForeignKeySetError < ResolveJoinReferenceError # :nodoc:
|
150
|
-
def advice
|
151
|
-
%Q{
|
152
|
-
This error occurs when you specifiy the foreign key, as well as a join entry.
|
153
|
-
---
|
154
|
-
poem:
|
155
|
-
title: Poetry of Departures
|
156
|
-
author_id: 8
|
157
|
-
author: larkin
|
158
|
-
|
159
|
-
If you need to specify the foreign key, do so within the entry.
|
160
|
-
---
|
161
|
-
poem:
|
162
|
-
title: Poetry of Departures
|
163
|
-
author:
|
164
|
-
larkin:
|
165
|
-
id: 8}
|
166
|
-
end
|
167
|
-
end
|
121
|
+
end
|