dm-constraints 1.1.0 → 1.2.0.rc1
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/Gemfile +8 -8
- data/README.rdoc +23 -21
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/dm-constraints.gemspec +36 -39
- data/lib/data_mapper/constraints/adapters/abstract_adapter.rb +36 -0
- data/lib/{dm-constraints/adapters/dm-do-adapter.rb → data_mapper/constraints/adapters/do_adapter.rb} +48 -39
- data/lib/data_mapper/constraints/adapters/extension.rb +49 -0
- data/lib/{dm-constraints/adapters/dm-mysql-adapter.rb → data_mapper/constraints/adapters/mysql_adapter.rb} +2 -8
- data/lib/{dm-constraints/adapters/dm-oracle-adapter.rb → data_mapper/constraints/adapters/oracle_adapter.rb} +9 -2
- data/lib/{dm-constraints/adapters/dm-postgres-adapter.rb → data_mapper/constraints/adapters/postgres_adapter.rb} +1 -1
- data/lib/{dm-constraints/adapters/dm-sqlite-adapter.rb → data_mapper/constraints/adapters/sqlite_adapter.rb} +4 -0
- data/lib/{dm-constraints/adapters/dm-sqlserver-adapter.rb → data_mapper/constraints/adapters/sqlserver_adapter.rb} +1 -1
- data/lib/data_mapper/constraints/migrations/model.rb +36 -0
- data/lib/data_mapper/constraints/migrations/relationship.rb +42 -0
- data/lib/data_mapper/constraints/migrations/singleton_methods.rb +48 -0
- data/lib/data_mapper/constraints/relationship/many_to_many.rb +50 -0
- data/lib/data_mapper/constraints/relationship/one_to_many.rb +83 -0
- data/lib/data_mapper/constraints/resource.rb +34 -0
- data/lib/dm-constraints.rb +12 -88
- data/spec/integration/constraints_spec.rb +4 -2
- data/spec/isolated/require_spec.rb +7 -4
- metadata +79 -44
- data/lib/dm-constraints/adapters/dm-abstract-adapter.rb +0 -22
- data/lib/dm-constraints/delete_constraint.rb +0 -115
- data/lib/dm-constraints/migrations.rb +0 -60
- data/lib/dm-constraints/relationships.rb +0 -41
@@ -78,10 +78,12 @@ describe 'DataMapper::Constraints', "(with #{DataMapper::Spec.adapter_name})" do
|
|
78
78
|
|
79
79
|
supported_by :postgres, :mysql do
|
80
80
|
it 'should not be able to create related objects with a failing foreign key constraint' do
|
81
|
-
jruby =
|
81
|
+
jruby = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
82
82
|
pending_if 'JRuby throws a DataObjects::SQLError for integrity errors, which is wrong', jruby do
|
83
83
|
article = Article.create(:title => 'Man on the Moon')
|
84
|
-
lambda {
|
84
|
+
lambda {
|
85
|
+
Comment.create(:body => 'So true!', :article_id => article.id + 1)
|
86
|
+
}.should raise_error(DataObjects::IntegrityError)
|
85
87
|
end
|
86
88
|
end
|
87
89
|
end
|
@@ -1,11 +1,14 @@
|
|
1
1
|
shared_examples_for "require 'dm-constraints'" do
|
2
2
|
|
3
|
-
it "
|
4
|
-
DataMapper::Model.
|
5
|
-
DataMapper::Model.
|
3
|
+
it "extends Model descendants with the constraint API" do
|
4
|
+
DataMapper::Model.descendants.should_not be_empty
|
5
|
+
DataMapper::Model.descendants.all? do |model|
|
6
|
+
model.respond_to?(:auto_migrate_constraints_down, true).should be(true)
|
7
|
+
model.respond_to?(:auto_migrate_constraints_up, true).should be(true)
|
8
|
+
end
|
6
9
|
end
|
7
10
|
|
8
|
-
it "
|
11
|
+
it "includes the constraint API into the adapter" do
|
9
12
|
@adapter.respond_to?(:constraint_exists? ).should be(true)
|
10
13
|
@adapter.respond_to?(:create_relationship_constraint ).should be(true)
|
11
14
|
@adapter.respond_to?(:destroy_relationship_constraint).should be(true)
|
metadata
CHANGED
@@ -1,8 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dm-constraints
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
4
|
+
hash: 15424023
|
5
|
+
prerelease: 6
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
- rc
|
11
|
+
- 1
|
12
|
+
version: 1.2.0.rc1
|
6
13
|
platform: ruby
|
7
14
|
authors:
|
8
15
|
- Dirkjan Bussink
|
@@ -10,53 +17,74 @@ autorequire:
|
|
10
17
|
bindir: bin
|
11
18
|
cert_chain: []
|
12
19
|
|
13
|
-
date: 2011-
|
14
|
-
default_executable:
|
20
|
+
date: 2011-09-09 00:00:00 Z
|
15
21
|
dependencies:
|
16
22
|
- !ruby/object:Gem::Dependency
|
17
|
-
|
18
|
-
|
23
|
+
type: :runtime
|
24
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
19
25
|
none: false
|
20
26
|
requirements:
|
21
27
|
- - ~>
|
22
28
|
- !ruby/object:Gem::Version
|
23
|
-
|
24
|
-
|
29
|
+
hash: 15424023
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 2
|
33
|
+
- 0
|
34
|
+
- rc
|
35
|
+
- 1
|
36
|
+
version: 1.2.0.rc1
|
25
37
|
prerelease: false
|
26
|
-
|
38
|
+
requirement: *id001
|
39
|
+
name: dm-core
|
27
40
|
- !ruby/object:Gem::Dependency
|
28
|
-
|
29
|
-
|
41
|
+
type: :development
|
42
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
30
43
|
none: false
|
31
44
|
requirements:
|
32
45
|
- - ~>
|
33
46
|
- !ruby/object:Gem::Version
|
34
|
-
|
35
|
-
|
47
|
+
hash: 7
|
48
|
+
segments:
|
49
|
+
- 1
|
50
|
+
- 6
|
51
|
+
- 4
|
52
|
+
version: 1.6.4
|
36
53
|
prerelease: false
|
37
|
-
|
54
|
+
requirement: *id002
|
55
|
+
name: jeweler
|
38
56
|
- !ruby/object:Gem::Dependency
|
39
|
-
|
40
|
-
|
57
|
+
type: :development
|
58
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
41
59
|
none: false
|
42
60
|
requirements:
|
43
61
|
- - ~>
|
44
62
|
- !ruby/object:Gem::Version
|
45
|
-
|
46
|
-
|
63
|
+
hash: 63
|
64
|
+
segments:
|
65
|
+
- 0
|
66
|
+
- 9
|
67
|
+
- 2
|
68
|
+
version: 0.9.2
|
47
69
|
prerelease: false
|
48
|
-
|
70
|
+
requirement: *id003
|
71
|
+
name: rake
|
49
72
|
- !ruby/object:Gem::Dependency
|
50
|
-
|
51
|
-
|
73
|
+
type: :development
|
74
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
52
75
|
none: false
|
53
76
|
requirements:
|
54
77
|
- - ~>
|
55
78
|
- !ruby/object:Gem::Version
|
56
|
-
|
57
|
-
|
79
|
+
hash: 31
|
80
|
+
segments:
|
81
|
+
- 1
|
82
|
+
- 3
|
83
|
+
- 2
|
84
|
+
version: 1.3.2
|
58
85
|
prerelease: false
|
59
|
-
|
86
|
+
requirement: *id004
|
87
|
+
name: rspec
|
60
88
|
description: DataMapper plugin constraining relationships
|
61
89
|
email: d.bussink [a] gmail [d] com
|
62
90
|
executables: []
|
@@ -73,17 +101,21 @@ files:
|
|
73
101
|
- Rakefile
|
74
102
|
- VERSION
|
75
103
|
- dm-constraints.gemspec
|
104
|
+
- lib/data_mapper/constraints/adapters/abstract_adapter.rb
|
105
|
+
- lib/data_mapper/constraints/adapters/do_adapter.rb
|
106
|
+
- lib/data_mapper/constraints/adapters/extension.rb
|
107
|
+
- lib/data_mapper/constraints/adapters/mysql_adapter.rb
|
108
|
+
- lib/data_mapper/constraints/adapters/oracle_adapter.rb
|
109
|
+
- lib/data_mapper/constraints/adapters/postgres_adapter.rb
|
110
|
+
- lib/data_mapper/constraints/adapters/sqlite_adapter.rb
|
111
|
+
- lib/data_mapper/constraints/adapters/sqlserver_adapter.rb
|
112
|
+
- lib/data_mapper/constraints/migrations/model.rb
|
113
|
+
- lib/data_mapper/constraints/migrations/relationship.rb
|
114
|
+
- lib/data_mapper/constraints/migrations/singleton_methods.rb
|
115
|
+
- lib/data_mapper/constraints/relationship/many_to_many.rb
|
116
|
+
- lib/data_mapper/constraints/relationship/one_to_many.rb
|
117
|
+
- lib/data_mapper/constraints/resource.rb
|
76
118
|
- lib/dm-constraints.rb
|
77
|
-
- lib/dm-constraints/adapters/dm-abstract-adapter.rb
|
78
|
-
- lib/dm-constraints/adapters/dm-do-adapter.rb
|
79
|
-
- lib/dm-constraints/adapters/dm-mysql-adapter.rb
|
80
|
-
- lib/dm-constraints/adapters/dm-oracle-adapter.rb
|
81
|
-
- lib/dm-constraints/adapters/dm-postgres-adapter.rb
|
82
|
-
- lib/dm-constraints/adapters/dm-sqlite-adapter.rb
|
83
|
-
- lib/dm-constraints/adapters/dm-sqlserver-adapter.rb
|
84
|
-
- lib/dm-constraints/delete_constraint.rb
|
85
|
-
- lib/dm-constraints/migrations.rb
|
86
|
-
- lib/dm-constraints/relationships.rb
|
87
119
|
- spec/integration/constraints_spec.rb
|
88
120
|
- spec/isolated/require_after_setup_spec.rb
|
89
121
|
- spec/isolated/require_before_setup_spec.rb
|
@@ -94,7 +126,6 @@ files:
|
|
94
126
|
- tasks/spec.rake
|
95
127
|
- tasks/yard.rake
|
96
128
|
- tasks/yardstick.rake
|
97
|
-
has_rdoc: true
|
98
129
|
homepage: http://github.com/datamapper/dm-constraints
|
99
130
|
licenses: []
|
100
131
|
|
@@ -108,23 +139,27 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
108
139
|
requirements:
|
109
140
|
- - ">="
|
110
141
|
- !ruby/object:Gem::Version
|
142
|
+
hash: 3
|
143
|
+
segments:
|
144
|
+
- 0
|
111
145
|
version: "0"
|
112
146
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
113
147
|
none: false
|
114
148
|
requirements:
|
115
|
-
- - "
|
149
|
+
- - ">"
|
116
150
|
- !ruby/object:Gem::Version
|
117
|
-
|
151
|
+
hash: 25
|
152
|
+
segments:
|
153
|
+
- 1
|
154
|
+
- 3
|
155
|
+
- 1
|
156
|
+
version: 1.3.1
|
118
157
|
requirements: []
|
119
158
|
|
120
159
|
rubyforge_project: datamapper
|
121
|
-
rubygems_version: 1.
|
160
|
+
rubygems_version: 1.8.10
|
122
161
|
signing_key:
|
123
162
|
specification_version: 3
|
124
163
|
summary: DataMapper plugin constraining relationships
|
125
|
-
test_files:
|
126
|
-
|
127
|
-
- spec/isolated/require_after_setup_spec.rb
|
128
|
-
- spec/isolated/require_before_setup_spec.rb
|
129
|
-
- spec/isolated/require_spec.rb
|
130
|
-
- spec/spec_helper.rb
|
164
|
+
test_files: []
|
165
|
+
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
module Constraints
|
3
|
-
module Adapters
|
4
|
-
|
5
|
-
module AbstractAdapter
|
6
|
-
|
7
|
-
def constraint_exists?(*)
|
8
|
-
false
|
9
|
-
end
|
10
|
-
|
11
|
-
def create_relationship_constraint(*)
|
12
|
-
false
|
13
|
-
end
|
14
|
-
|
15
|
-
def destroy_relationship_constraint(*)
|
16
|
-
false
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,115 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
module Constraints
|
3
|
-
module DeleteConstraint
|
4
|
-
def self.included(base)
|
5
|
-
base.extend(ClassMethods)
|
6
|
-
end
|
7
|
-
|
8
|
-
module ClassMethods
|
9
|
-
CONSTRAINT_OPTIONS = [ :protect, :destroy, :destroy!, :set_nil, :skip ].to_set.freeze
|
10
|
-
|
11
|
-
##
|
12
|
-
# Checks that the constraint type is appropriate to the relationship
|
13
|
-
#
|
14
|
-
# @param cardinality [Fixnum] cardinality of relationship
|
15
|
-
#
|
16
|
-
# @param name [Symbol] name of relationship to evaluate constraint of
|
17
|
-
#
|
18
|
-
# @param options [Hash] options hash
|
19
|
-
#
|
20
|
-
# @raise ArgumentError
|
21
|
-
#
|
22
|
-
# @return [nil]
|
23
|
-
#
|
24
|
-
# @api semi-public
|
25
|
-
def check_delete_constraint_type(cardinality, name, *args)
|
26
|
-
options = extract_options(args)
|
27
|
-
|
28
|
-
return unless options.key?(:constraint)
|
29
|
-
|
30
|
-
constraint = options[:constraint]
|
31
|
-
|
32
|
-
unless CONSTRAINT_OPTIONS.include?(constraint)
|
33
|
-
raise ArgumentError, ":constraint option must be one of #{CONSTRAINT_OPTIONS.to_a.join(', ')}"
|
34
|
-
end
|
35
|
-
|
36
|
-
# XXX: is any constraint valid with a :through relationship?
|
37
|
-
if constraint == :set_nil && options.key?(:through)
|
38
|
-
raise ArgumentError, 'Constraint type :set_nil is not valid for relationships using :through'
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
##
|
45
|
-
# Temporarily changes the visibility of a method so a block can be evaluated against it
|
46
|
-
#
|
47
|
-
# @param method [Symobl] method to change visibility of
|
48
|
-
#
|
49
|
-
# @param from_visibility [Symbol] original visibility
|
50
|
-
#
|
51
|
-
# @param to_visibility [Symbol] temporary visibility
|
52
|
-
#
|
53
|
-
# @param block [Proc] proc to run
|
54
|
-
#
|
55
|
-
# @note TODO: this should be moved to a 'util-like' module
|
56
|
-
#
|
57
|
-
# @return [nil]
|
58
|
-
#
|
59
|
-
# @api semi-public
|
60
|
-
def with_changed_method_visibility(method, from_visibility, to_visibility, &block)
|
61
|
-
send(to_visibility, method)
|
62
|
-
yield
|
63
|
-
ensure
|
64
|
-
send(from_visibility, method)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
##
|
69
|
-
# Adds the delete constraint options to a relationship
|
70
|
-
#
|
71
|
-
# @param params [*ARGS] Arguments passed to Relationship#initialize
|
72
|
-
#
|
73
|
-
# @return [nil]
|
74
|
-
#
|
75
|
-
# @api semi-public
|
76
|
-
def add_constraint_option(name, child_model, parent_model, options = {})
|
77
|
-
@constraint = options.fetch(:constraint, :protect) || :skip
|
78
|
-
end
|
79
|
-
|
80
|
-
private
|
81
|
-
|
82
|
-
##
|
83
|
-
# Checks delete constraints prior to destroying a dm resource or collection
|
84
|
-
#
|
85
|
-
# @note
|
86
|
-
# - It only considers a relationship's constraints if this is the parent model (ie a child shouldn't delete a parent)
|
87
|
-
# - Many to Many Relationships are skipped, as they are evaluated by their underlying 1:M relationships
|
88
|
-
#
|
89
|
-
# @return [nil]
|
90
|
-
#
|
91
|
-
# @api semi-public
|
92
|
-
def check_delete_constraints
|
93
|
-
relationships.each do |relationship|
|
94
|
-
next unless relationship.respond_to?(:constraint)
|
95
|
-
next unless association = relationship.get(self)
|
96
|
-
|
97
|
-
delete_allowed = case constraint = relationship.constraint
|
98
|
-
when :protect
|
99
|
-
Array(association).empty?
|
100
|
-
when :destroy, :destroy!
|
101
|
-
association.__send__(constraint)
|
102
|
-
when :set_nil
|
103
|
-
Array(association).all? do |resource|
|
104
|
-
resource.update(relationship.inverse => nil)
|
105
|
-
end
|
106
|
-
when :skip
|
107
|
-
true # do nothing
|
108
|
-
end
|
109
|
-
|
110
|
-
throw(:halt, false) unless delete_allowed
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end # DeleteConstraint
|
114
|
-
end # Constraints
|
115
|
-
end # DataMapper
|
@@ -1,60 +0,0 @@
|
|
1
|
-
require 'dm-migrations/auto_migration'
|
2
|
-
|
3
|
-
module DataMapper
|
4
|
-
module Constraints
|
5
|
-
module Migrations
|
6
|
-
|
7
|
-
module SingletonMethods
|
8
|
-
|
9
|
-
def auto_migrate!(repository_name = nil)
|
10
|
-
repository_execute(:auto_migrate_down_constraints!, repository_name)
|
11
|
-
descendants = super
|
12
|
-
repository_execute(:auto_migrate_up_constraints!, repository_name)
|
13
|
-
descendants
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def auto_migrate_down!(repository_name = nil)
|
19
|
-
repository_execute(:auto_migrate_down_constraints!, repository_name)
|
20
|
-
super
|
21
|
-
end
|
22
|
-
|
23
|
-
def auto_migrate_up!(repository_name = nil)
|
24
|
-
descendants = super
|
25
|
-
repository_execute(:auto_migrate_up_constraints!, repository_name)
|
26
|
-
descendants
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
module Model
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def auto_migrate_down_constraints!(repository_name = self.repository_name)
|
36
|
-
return unless storage_exists?(repository_name)
|
37
|
-
return if self.respond_to?(:is_remixable?) && self.is_remixable?
|
38
|
-
execute_each_relationship(:destroy_relationship_constraint, repository_name)
|
39
|
-
end
|
40
|
-
|
41
|
-
def auto_migrate_up_constraints!(repository_name = self.repository_name)
|
42
|
-
return if self.respond_to?(:is_remixable?) && self.is_remixable?
|
43
|
-
execute_each_relationship(:create_relationship_constraint, repository_name)
|
44
|
-
end
|
45
|
-
|
46
|
-
def execute_each_relationship(method, repository_name)
|
47
|
-
adapter = DataMapper.repository(repository_name).adapter
|
48
|
-
return unless adapter.respond_to?(method)
|
49
|
-
|
50
|
-
relationships(repository_name).each do |relationship|
|
51
|
-
adapter.send(method, relationship)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
|
-
end # module Migrations
|
58
|
-
|
59
|
-
end # module Constraints
|
60
|
-
end # module DataMapper
|
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'dm-core'
|
2
|
-
require 'dm-constraints/delete_constraint'
|
3
|
-
|
4
|
-
module DataMapper
|
5
|
-
module Associations
|
6
|
-
|
7
|
-
class OneToMany::Relationship
|
8
|
-
|
9
|
-
include DataMapper::Hook
|
10
|
-
include Constraints::DeleteConstraint
|
11
|
-
|
12
|
-
OPTIONS << :constraint
|
13
|
-
|
14
|
-
attr_reader :constraint
|
15
|
-
|
16
|
-
# initialize is a private method in Relationship
|
17
|
-
# and private methods can not be "advised" (hooked into)
|
18
|
-
# in extlib.
|
19
|
-
with_changed_method_visibility(:initialize, :private, :public) do
|
20
|
-
before :initialize, :add_constraint_option
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
class ManyToMany::Relationship
|
26
|
-
|
27
|
-
OPTIONS << :constraint
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
# TODO: document
|
32
|
-
# @api semipublic
|
33
|
-
chainable do
|
34
|
-
def one_to_many_options
|
35
|
-
super.merge(:constraint => @constraint)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
end
|