jinx 2.1.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.
- data/.gitignore +14 -0
- data/.rspec +3 -0
- data/.yardopts +1 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +27 -0
- data/History.md +6 -0
- data/LEGAL +5 -0
- data/LICENSE +22 -0
- data/README.md +44 -0
- data/Rakefile +41 -0
- data/examples/family/README.md +10 -0
- data/examples/family/ext/build.xml +35 -0
- data/examples/family/ext/src/family/Address.java +68 -0
- data/examples/family/ext/src/family/Child.java +24 -0
- data/examples/family/ext/src/family/DomainObject.java +26 -0
- data/examples/family/ext/src/family/Household.java +36 -0
- data/examples/family/ext/src/family/Parent.java +48 -0
- data/examples/family/ext/src/family/Person.java +42 -0
- data/examples/family/lib/family.rb +15 -0
- data/examples/family/lib/family/address.rb +6 -0
- data/examples/family/lib/family/domain_object.rb +6 -0
- data/examples/family/lib/family/household.rb +6 -0
- data/examples/family/lib/family/parent.rb +16 -0
- data/examples/family/lib/family/person.rb +6 -0
- data/examples/model/README.md +25 -0
- data/examples/model/ext/build.xml +35 -0
- data/examples/model/ext/src/domain/Child.java +192 -0
- data/examples/model/ext/src/domain/Dependent.java +29 -0
- data/examples/model/ext/src/domain/DomainObject.java +26 -0
- data/examples/model/ext/src/domain/Independent.java +83 -0
- data/examples/model/ext/src/domain/Parent.java +129 -0
- data/examples/model/ext/src/domain/Person.java +14 -0
- data/examples/model/lib/model.rb +13 -0
- data/examples/model/lib/model/child.rb +13 -0
- data/examples/model/lib/model/domain_object.rb +6 -0
- data/examples/model/lib/model/independent.rb +11 -0
- data/examples/model/lib/model/parent.rb +17 -0
- data/jinx.gemspec +22 -0
- data/lib/jinx.rb +3 -0
- data/lib/jinx/active_support/README.txt +2 -0
- data/lib/jinx/active_support/core_ext/string.rb +7 -0
- data/lib/jinx/active_support/core_ext/string/inflections.rb +167 -0
- data/lib/jinx/active_support/inflections.rb +55 -0
- data/lib/jinx/active_support/inflector.rb +398 -0
- data/lib/jinx/cli/application.rb +36 -0
- data/lib/jinx/cli/command.rb +214 -0
- data/lib/jinx/helpers/array.rb +108 -0
- data/lib/jinx/helpers/boolean.rb +42 -0
- data/lib/jinx/helpers/case_insensitive_hash.rb +39 -0
- data/lib/jinx/helpers/class.rb +149 -0
- data/lib/jinx/helpers/collection.rb +33 -0
- data/lib/jinx/helpers/collections.rb +11 -0
- data/lib/jinx/helpers/collector.rb +20 -0
- data/lib/jinx/helpers/conditional_enumerator.rb +21 -0
- data/lib/jinx/helpers/enumerable.rb +242 -0
- data/lib/jinx/helpers/enumerate.rb +35 -0
- data/lib/jinx/helpers/error.rb +15 -0
- data/lib/jinx/helpers/file_separator.rb +65 -0
- data/lib/jinx/helpers/filter.rb +52 -0
- data/lib/jinx/helpers/flattener.rb +38 -0
- data/lib/jinx/helpers/hash.rb +12 -0
- data/lib/jinx/helpers/hashable.rb +502 -0
- data/lib/jinx/helpers/inflector.rb +36 -0
- data/lib/jinx/helpers/key_transformer_hash.rb +43 -0
- data/lib/jinx/helpers/lazy_hash.rb +44 -0
- data/lib/jinx/helpers/log.rb +106 -0
- data/lib/jinx/helpers/math.rb +12 -0
- data/lib/jinx/helpers/merge.rb +60 -0
- data/lib/jinx/helpers/module.rb +18 -0
- data/lib/jinx/helpers/multi_enumerator.rb +31 -0
- data/lib/jinx/helpers/options.rb +92 -0
- data/lib/jinx/helpers/os.rb +19 -0
- data/lib/jinx/helpers/partial_order.rb +37 -0
- data/lib/jinx/helpers/pretty_print.rb +207 -0
- data/lib/jinx/helpers/set.rb +8 -0
- data/lib/jinx/helpers/stopwatch.rb +76 -0
- data/lib/jinx/helpers/transformer.rb +24 -0
- data/lib/jinx/helpers/transitive_closure.rb +55 -0
- data/lib/jinx/helpers/uniquifier.rb +50 -0
- data/lib/jinx/helpers/validation.rb +33 -0
- data/lib/jinx/helpers/visitor.rb +370 -0
- data/lib/jinx/import/class_path_modifier.rb +77 -0
- data/lib/jinx/import/java.rb +337 -0
- data/lib/jinx/importer.rb +240 -0
- data/lib/jinx/metadata.rb +155 -0
- data/lib/jinx/metadata/attribute_enumerator.rb +73 -0
- data/lib/jinx/metadata/dependency.rb +244 -0
- data/lib/jinx/metadata/id_alias.rb +23 -0
- data/lib/jinx/metadata/introspector.rb +179 -0
- data/lib/jinx/metadata/inverse.rb +170 -0
- data/lib/jinx/metadata/java_property.rb +169 -0
- data/lib/jinx/metadata/propertied.rb +500 -0
- data/lib/jinx/metadata/property.rb +401 -0
- data/lib/jinx/metadata/property_characteristics.rb +114 -0
- data/lib/jinx/resource.rb +862 -0
- data/lib/jinx/resource/copy_visitor.rb +36 -0
- data/lib/jinx/resource/inversible.rb +90 -0
- data/lib/jinx/resource/match_visitor.rb +180 -0
- data/lib/jinx/resource/matcher.rb +20 -0
- data/lib/jinx/resource/merge_visitor.rb +73 -0
- data/lib/jinx/resource/mergeable.rb +185 -0
- data/lib/jinx/resource/reference_enumerator.rb +49 -0
- data/lib/jinx/resource/reference_path_visitor.rb +38 -0
- data/lib/jinx/resource/reference_visitor.rb +55 -0
- data/lib/jinx/resource/unique.rb +35 -0
- data/lib/jinx/version.rb +3 -0
- data/spec/defaults_spec.rb +30 -0
- data/spec/definitions/model/alias/child.rb +5 -0
- data/spec/definitions/model/base/child.rb +5 -0
- data/spec/definitions/model/base/domain_object.rb +5 -0
- data/spec/definitions/model/base/independent.rb +5 -0
- data/spec/definitions/model/defaults/child.rb +5 -0
- data/spec/definitions/model/dependency/child.rb +5 -0
- data/spec/definitions/model/dependency/parent.rb +6 -0
- data/spec/definitions/model/inverse/child.rb +5 -0
- data/spec/definitions/model/inverse/independent.rb +5 -0
- data/spec/definitions/model/inverse/parent.rb +5 -0
- data/spec/definitions/model/mandatory/child.rb +6 -0
- data/spec/dependency_spec.rb +47 -0
- data/spec/family_spec.rb +64 -0
- data/spec/inverse_spec.rb +53 -0
- data/spec/mandatory_spec.rb +43 -0
- data/spec/metadata_spec.rb +68 -0
- data/spec/resource_spec.rb +30 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/model.rb +19 -0
- data/test/fixtures/line_separator/cr_line_sep.txt +1 -0
- data/test/fixtures/line_separator/crlf_line_sep.txt +3 -0
- data/test/fixtures/line_separator/lf_line_sep.txt +3 -0
- data/test/fixtures/mixed/ext/build.xml +35 -0
- data/test/fixtures/mixed/ext/src/mixed/Case/Example.java +5 -0
- data/test/helper.rb +7 -0
- data/test/lib/jinx/command_test.rb +41 -0
- data/test/lib/jinx/helpers/boolean_test.rb +27 -0
- data/test/lib/jinx/helpers/class_test.rb +60 -0
- data/test/lib/jinx/helpers/collections_test.rb +402 -0
- data/test/lib/jinx/helpers/file_separator_test.rb +29 -0
- data/test/lib/jinx/helpers/inflector_test.rb +11 -0
- data/test/lib/jinx/helpers/lazy_hash_test.rb +32 -0
- data/test/lib/jinx/helpers/module_test.rb +24 -0
- data/test/lib/jinx/helpers/options_test.rb +66 -0
- data/test/lib/jinx/helpers/partial_order_test.rb +41 -0
- data/test/lib/jinx/helpers/pretty_print_test.rb +83 -0
- data/test/lib/jinx/helpers/stopwatch_test.rb +16 -0
- data/test/lib/jinx/helpers/transitive_closure_test.rb +80 -0
- data/test/lib/jinx/helpers/visitor_test.rb +288 -0
- data/test/lib/jinx/import/java_test.rb +78 -0
- data/test/lib/jinx/import/mixed_case_test.rb +16 -0
- metadata +272 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'enumerator'
|
|
2
|
+
require 'generator'
|
|
3
|
+
require 'jinx/helpers/options'
|
|
4
|
+
require 'jinx/helpers/collections'
|
|
5
|
+
|
|
6
|
+
require 'jinx/helpers/validation'
|
|
7
|
+
require 'jinx/helpers/visitor'
|
|
8
|
+
require 'jinx/helpers/math'
|
|
9
|
+
|
|
10
|
+
module Jinx
|
|
11
|
+
# A ReferenceEnumerator iterates over domain property references.
|
|
12
|
+
class ReferenceEnumerator
|
|
13
|
+
include Enumerable
|
|
14
|
+
|
|
15
|
+
# @return [Resource] the domain object containing the references
|
|
16
|
+
attr_reader :subject
|
|
17
|
+
|
|
18
|
+
alias :on :subject
|
|
19
|
+
|
|
20
|
+
alias :from :subject
|
|
21
|
+
|
|
22
|
+
# @return [<Property>] the current property
|
|
23
|
+
attr_reader :property
|
|
24
|
+
|
|
25
|
+
# @param [Resource, nil] on the object containing the references
|
|
26
|
+
# @param [<Property>, Property, nil] properties the property or properties to dereference
|
|
27
|
+
def initialize(on=nil, properties=nil)
|
|
28
|
+
@subject = on
|
|
29
|
+
@properties = properties
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @param [Resource] obj the visiting domain object
|
|
33
|
+
# @return [(Resource, Resource, Property)] the (visited, visiting, property) tuples
|
|
34
|
+
# @yield [obj, from, property] operates on the visited domain object
|
|
35
|
+
# @yieldparam [Resource] obj the visited domain object
|
|
36
|
+
# @yieldparam [Resource] from the visiting domain object
|
|
37
|
+
# @yieldparam [Property] property the visiting property
|
|
38
|
+
def each
|
|
39
|
+
return if @subject.nil?
|
|
40
|
+
@properties.enumerate do |prop|
|
|
41
|
+
@property = prop
|
|
42
|
+
# the reference(s) to visit
|
|
43
|
+
refs = @subject.send(prop.attribute)
|
|
44
|
+
# associate each reference to visit with the current visited attribute
|
|
45
|
+
refs.enumerate { |ref| yield(ref) }
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'jinx/helpers/collections'
|
|
2
|
+
|
|
3
|
+
require 'jinx/helpers/validation'
|
|
4
|
+
require 'jinx/helpers/visitor'
|
|
5
|
+
require 'jinx/helpers/math'
|
|
6
|
+
|
|
7
|
+
module Jinx
|
|
8
|
+
# A ReferencePathVisitor traverses an attribute path.
|
|
9
|
+
#
|
|
10
|
+
# For example, given the attributes:
|
|
11
|
+
# favorites : Person -> Book
|
|
12
|
+
# authors : Book -> Author
|
|
13
|
+
# publications : Author -> Book
|
|
14
|
+
# then a path visitor given by:
|
|
15
|
+
# ReferencePathVisitor.new(Person, [:favorites, :authors, :publications])
|
|
16
|
+
# visits the transitive closure of books published by the authors of a person's favorite books.
|
|
17
|
+
class ReferencePathVisitor < ReferenceVisitor
|
|
18
|
+
# @return [ReferenceVisitor] a visitor which traverses the given path attributes starting at
|
|
19
|
+
# an instance of the given type
|
|
20
|
+
#
|
|
21
|
+
# @param [Class] the type of object to begin the traversal
|
|
22
|
+
# @param [<Symbol>] the attributes to traverse
|
|
23
|
+
# @param opts (see ReferenceVisitor#initialize)
|
|
24
|
+
def initialize(klass, attributes, opts=nil)
|
|
25
|
+
# augment the attributes path as a [class, attribute] path
|
|
26
|
+
path = klass.property_path(*attributes)
|
|
27
|
+
# make the visitor
|
|
28
|
+
super(opts) do |ref|
|
|
29
|
+
# Collect the path attributes whose type is the ref type up to the
|
|
30
|
+
# next position in the path.
|
|
31
|
+
max = lineage.size.min(path.size)
|
|
32
|
+
pas = (0...max).map { |i| path[i].attribute if path[i].declarer === ref }
|
|
33
|
+
pas.compact!
|
|
34
|
+
ref.class.attribute_filter(pas)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require 'enumerator'
|
|
2
|
+
require 'generator'
|
|
3
|
+
require 'jinx/helpers/options'
|
|
4
|
+
require 'jinx/helpers/collections'
|
|
5
|
+
|
|
6
|
+
require 'jinx/helpers/validation'
|
|
7
|
+
require 'jinx/helpers/visitor'
|
|
8
|
+
require 'jinx/helpers/math'
|
|
9
|
+
|
|
10
|
+
module Jinx
|
|
11
|
+
# A ReferenceVisitor traverses reference attributes.
|
|
12
|
+
class ReferenceVisitor < Visitor
|
|
13
|
+
# Creates a new ReferenceVisitor on domain reference attributes.
|
|
14
|
+
#
|
|
15
|
+
# The required selector block given to this initializer determines which attributes to
|
|
16
|
+
# visit. The references to visit next thus consist of the current domain object's selector
|
|
17
|
+
# attributes' values. If the :filter option is set, then the given filter block is applied
|
|
18
|
+
# to the selected attribute references to restrict which domain objects will be visited.
|
|
19
|
+
#
|
|
20
|
+
# @param opts (see Visitor#initialize)
|
|
21
|
+
# @option opts [Proc] :filter an optional filter on the references to visit
|
|
22
|
+
# @yield [obj] returns the {AttributeEnumerator} of attributes to visit next from the
|
|
23
|
+
# current domain object
|
|
24
|
+
# @yieldparam [Resource] obj the current domain object
|
|
25
|
+
def initialize(opts=nil, &selector)
|
|
26
|
+
Jinx.fail(ArgumentError, "Reference visitor missing domain reference selector") unless block_given?
|
|
27
|
+
# the property selector
|
|
28
|
+
@flt_sel = selector
|
|
29
|
+
# the reference filter
|
|
30
|
+
flt = Options.get(:filter, opts)
|
|
31
|
+
# Initialize the Visitor with a reference enumerator which selects the reference
|
|
32
|
+
# attributes and applies the optional filter if necessary.
|
|
33
|
+
@ref_enums = {}
|
|
34
|
+
super do |ref|
|
|
35
|
+
# the reference property filter
|
|
36
|
+
attrs = attributes_to_visit(ref)
|
|
37
|
+
if attrs then
|
|
38
|
+
logger.debug { "#{qp} visiting #{ref} attributes #{attrs.pp_s(:single_line)}..." } if @verbose
|
|
39
|
+
# an enumerator on the reference properties
|
|
40
|
+
enum = ReferenceEnumerator.new(ref, attrs.properties)
|
|
41
|
+
# If there is a reference filter, then apply it to the enum references.
|
|
42
|
+
flt ? enum.filter(&flt) : enum
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
# @param [Resource] obj the visiting object
|
|
50
|
+
# @return [Propertied::Filter] the attributes to visit
|
|
51
|
+
def attributes_to_visit(obj)
|
|
52
|
+
@flt_sel.call(obj)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'jinx/helpers/uniquifier'
|
|
2
|
+
|
|
3
|
+
module Jinx
|
|
4
|
+
# The Unique mix-in makes values unique within the scope of a Resource class.
|
|
5
|
+
module Unique
|
|
6
|
+
# Makes the given String value unique in the context of this object's class.
|
|
7
|
+
# @return nil if value is nil
|
|
8
|
+
# Raises TypeError if value is neither nil nor a String.
|
|
9
|
+
def uniquify_value(value)
|
|
10
|
+
unless String === value or value.nil? then
|
|
11
|
+
Jinx.fail(TypeError, "Cannot uniquify #{qp} non-String value #{value}")
|
|
12
|
+
end
|
|
13
|
+
Uniquifier.instance.uniquify(self, value)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Makes the secondary key unique by replacing each String key attribute value
|
|
17
|
+
# with a unique value.
|
|
18
|
+
def uniquify
|
|
19
|
+
uniquify_attributes(self.class.secondary_key_attributes)
|
|
20
|
+
uniquify_attributes(self.class.alternate_key_attributes)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Makes the given attribute values unique by replacing each String value
|
|
24
|
+
# with a unique value.
|
|
25
|
+
def uniquify_attributes(attributes)
|
|
26
|
+
attributes.each do |ka|
|
|
27
|
+
oldval = send(ka)
|
|
28
|
+
next unless String === oldval
|
|
29
|
+
newval = uniquify_value(oldval)
|
|
30
|
+
set_property_value(ka, newval)
|
|
31
|
+
logger.debug { "Reset #{qp} #{ka} from #{oldval} to unique value #{newval}." }
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
data/lib/jinx/version.rb
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
|
2
|
+
|
|
3
|
+
module Model
|
|
4
|
+
describe 'Defaults' do
|
|
5
|
+
before(:all) do
|
|
6
|
+
Model.definitions BASE, DEFAULTS
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should recognize the property default" do
|
|
10
|
+
Child.defaults[:cardinal].should be 1
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should set the default property value" do
|
|
14
|
+
c = Child.new
|
|
15
|
+
c.add_defaults
|
|
16
|
+
c.cardinal.should be 1
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "should not reset a property value to the default" do
|
|
20
|
+
c = Child.new(:cardinal => 2)
|
|
21
|
+
c.add_defaults
|
|
22
|
+
c.cardinal.should be 2
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
# The defaults fixture model definitions.
|
|
28
|
+
DEFAULTS = File.dirname(__FILE__) + '/definitions/model/defaults'
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
|
2
|
+
|
|
3
|
+
module Model
|
|
4
|
+
describe 'Dependency' do
|
|
5
|
+
before(:all) do
|
|
6
|
+
Model.definitions BASE, DEPENDENCY
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
context '1:1' do
|
|
10
|
+
it "should capture the dependents" do
|
|
11
|
+
d = Dependent.new
|
|
12
|
+
c = Child.new(:dependent => d)
|
|
13
|
+
c.dependents.should include d
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
context '1:N' do
|
|
18
|
+
it "should set the inverses" do
|
|
19
|
+
Child.property(:parent).inverse.should be :children
|
|
20
|
+
Parent.property(:children).inverse.should be :parent
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should capture the dependents" do
|
|
24
|
+
p = Parent.new
|
|
25
|
+
c = Child.new(:parent => p)
|
|
26
|
+
p.dependents.should include c
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should fail to validate a missing owner" do
|
|
30
|
+
c = Child.new
|
|
31
|
+
expect { c.validate }.to raise_error(Jinx::ValidationError)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should validate an existing owner" do
|
|
35
|
+
p = Parent.new
|
|
36
|
+
c = Child.new(:parent => p, :name => 'Sam')
|
|
37
|
+
expect { c.validate }.to_not raise_error
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
# The dependency fixture model definitions.
|
|
44
|
+
# @private
|
|
45
|
+
DEPENDENCY = File.dirname(__FILE__) + '/definitions/model/dependency'
|
|
46
|
+
end
|
|
47
|
+
end
|
data/spec/family_spec.rb
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
|
2
|
+
require File.dirname(__FILE__) + '/../examples/family/lib/family'
|
|
3
|
+
|
|
4
|
+
module Family
|
|
5
|
+
describe DomainObject do
|
|
6
|
+
it "should set the primary key attribute" do
|
|
7
|
+
DomainObject.primary_key_attributes.should == [:identifier]
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe Address do
|
|
12
|
+
it "should have an attribute => value constructor" do
|
|
13
|
+
Address.new(:state => 'OR').state.should == 'OR'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "should recognize an alias" do
|
|
17
|
+
a = Address.new(:postal_code => '95111')
|
|
18
|
+
a.zip.should == a.postal_code
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe Parent do
|
|
23
|
+
it "should inherit the primary key" do
|
|
24
|
+
Parent.primary_key_attributes.should be DomainObject.primary_key_attributes
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should have a secondary key" do
|
|
28
|
+
Parent.secondary_key_attributes.should == [:ssn]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should have a name property" do
|
|
32
|
+
Parent.property_defined?(:name).should be true
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "should have a children dependent" do
|
|
36
|
+
Parent.property(:children).dependent?.should be true
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
describe Child do
|
|
41
|
+
it "should have a parents owner" do
|
|
42
|
+
Child.property(:parents).owner?.should be true
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "should add itself to the household inverse" do
|
|
46
|
+
h = Household.new
|
|
47
|
+
c = Child.new(:household => h)
|
|
48
|
+
h.members.should include c
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should not add itself to the parents inverse" do
|
|
52
|
+
p = Parent.new
|
|
53
|
+
c = Child.new(:parents => [p])
|
|
54
|
+
p.children.should_not include c
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe Household do
|
|
59
|
+
it "should have a dependent address" do
|
|
60
|
+
a = Address.new
|
|
61
|
+
Household.new(:address => a).dependents.should include a
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
|
2
|
+
|
|
3
|
+
module Model
|
|
4
|
+
describe 'Inverse' do
|
|
5
|
+
before(:all) do
|
|
6
|
+
Model.definitions BASE, INVERSE
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
context '1:1' do
|
|
10
|
+
it "should set the inverse" do
|
|
11
|
+
Parent.property(:spouse).inverse.should == :spouse
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should set the target inverse type back to self" do
|
|
15
|
+
Parent.property(:spouse).inverse.should == :spouse
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should enforce inverse integrity" do
|
|
19
|
+
m = Parent.new
|
|
20
|
+
f = Parent.new(:spouse => m)
|
|
21
|
+
m.spouse.should be f
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context '1:N' do
|
|
26
|
+
it "should set the inverse" do
|
|
27
|
+
Child.property(:parent).inverse.should == :children
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "should set the target inverse type back to self" do
|
|
31
|
+
Parent.property(:children).inverse.should == :parent
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should enforce inverse integrity" do
|
|
35
|
+
p = Parent.new
|
|
36
|
+
c = Child.new(:parent => p)
|
|
37
|
+
p.children.should include c
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context 'M:N' do
|
|
42
|
+
it "should set the inverse" do
|
|
43
|
+
Independent.property(:others).inverse.should == :others
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
# The inverse fixture model definitions.
|
|
50
|
+
# @private
|
|
51
|
+
INVERSE = File.dirname(__FILE__) + '/definitions/model/inverse'
|
|
52
|
+
end
|
|
53
|
+
end
|