foreign_key_validation 0.0.3 → 0.0.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.
- checksums.yaml +13 -5
- data/.ruby-version +1 -1
- data/README.md +6 -5
- data/lib/foreign_key_validation/model_extension.rb +14 -25
- data/lib/foreign_key_validation/version.rb +1 -1
- data/spec/models/model_spec.rb +55 -11
- metadata +19 -19
checksums.yaml
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
|
|
2
|
+
!binary "U0hBMQ==":
|
|
3
|
+
metadata.gz: !binary |-
|
|
4
|
+
ZjczM2MxZDBjMGMyNzYxZDNiZTM1YTliYTZjOTg2MDk4MjcyY2UyNA==
|
|
5
|
+
data.tar.gz: !binary |-
|
|
6
|
+
MTljYzJiY2IwOWM5NzY5OTU0M2FkMzNhODRmNWM3NDYyYTY4MDEzYQ==
|
|
5
7
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
|
|
8
|
+
metadata.gz: !binary |-
|
|
9
|
+
Mjc0OTVlOGUyZWFkOTQ3ODE0OGFkNjJjZTMxMDdjYjc5ODhhMDA0NTFkZTE5
|
|
10
|
+
OGUxODgwNTRlYTAxM2ViNDRkZDMyZmYzNzMzMGVkZWFlMGZmOTY5OGQyM2Ji
|
|
11
|
+
ZWY4ZDU2NWM2MWNmMDJmY2MzMGQ2OWMzYjE0OGE5NDE0YjU2N2Q=
|
|
12
|
+
data.tar.gz: !binary |-
|
|
13
|
+
NmE5NzEyODJlNGMzNmVkYWI2ZDAwMTFiYTRkODMyZWExYzc2YWE0ZDVlYzEw
|
|
14
|
+
MzRiZGFkMzY3MzQxN2Y3ODg4ZDg5MmM5OWI3OGM0MjAwMDM3ZWEyZGM3N2Qw
|
|
15
|
+
M2IzM2E0ZDg0NmZhMDQyMGIwZWUxYjdkOTIwYjI0MmQwODVkYzA=
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
1.9.3
|
data/README.md
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
Protect your models by specifying a collection of foreign keys that should be tested for consistency with the `belongs_to` relations. For example, when the `user_id` is used in all models we can check if the `user_id` of `model a` matches `user_id` of `model b` before saving the records.
|
|
4
4
|
|
|
5
5
|
## Requirements
|
|
6
|
-
|
|
6
|
+
ruby >= 1.9
|
|
7
|
+
rails
|
|
8
|
+
active_record
|
|
7
9
|
|
|
8
10
|
## Installation
|
|
9
11
|
|
|
@@ -21,22 +23,21 @@ Or install it yourself as:
|
|
|
21
23
|
|
|
22
24
|
## Usage
|
|
23
25
|
|
|
24
|
-
Call `validate_foreign_keys` in your model. By default it assumes that it should check all foreign keys against the `user_id` column. So any relation
|
|
26
|
+
Call `validate_foreign_keys` in your model. By default it assumes that it should check all foreign keys against the `user_id` column. So any relation (except `user`) will be checked for a matching `user_id` if the column exists.
|
|
25
27
|
|
|
26
28
|
Change behaviour by calling `validate_foreign_keys` with arguments hash.
|
|
27
29
|
|
|
28
|
-
|
|
30
|
+
validate_foreign_keys on: :admin_user, with: [:project]
|
|
29
31
|
|
|
30
32
|
This would only check `model.project.admin_user_id` to match `model.admin_user_id`.
|
|
31
33
|
|
|
32
34
|
## Note
|
|
33
35
|
|
|
34
|
-
Only tested with
|
|
36
|
+
Only tested with ActiveRecord
|
|
35
37
|
|
|
36
38
|
## TODO
|
|
37
39
|
|
|
38
40
|
- Tests!
|
|
39
|
-
- Support Ruby 1.9 (remove keyword arguments)
|
|
40
41
|
|
|
41
42
|
## Contributing
|
|
42
43
|
|
|
@@ -4,41 +4,30 @@ module ForeignKeyValidation
|
|
|
4
4
|
|
|
5
5
|
included do
|
|
6
6
|
private
|
|
7
|
-
def validate_foreign_key(
|
|
8
|
-
relation
|
|
9
|
-
|
|
10
|
-
# do not try to validate if self does not respond to relation or one of the keys is nil
|
|
11
|
-
return if !respond_to?(relation) or send(relation).try(key_to_validate_against).nil? or send(key_to_validate_against).nil?
|
|
12
|
-
|
|
13
|
-
# add error if keys does not match
|
|
14
|
-
if send(relation).send(key_to_validate_against) != send(key_to_validate_against)
|
|
15
|
-
errors.add(key_to_validate_against, "#{key_to_validate_against} of #{relation} does not match #{self.class.name.tableize} #{key_to_validate_against}")
|
|
7
|
+
def validate_foreign_key(validate_against, relation)
|
|
8
|
+
if send(relation).send("#{validate_against}_id") != send("#{validate_against}_id")
|
|
9
|
+
errors.add(validate_against, "#{validate_against} of #{relation} does not match #{self.class.name.tableize} #{validate_against}")
|
|
16
10
|
end
|
|
17
11
|
end
|
|
18
12
|
end
|
|
19
13
|
|
|
20
14
|
module ClassMethods
|
|
21
|
-
def validate_foreign_keys(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
raise ArgumentError, "No foreign key #{key_to_validate_against} on #{self.table_name} table!" unless self.column_names.include?(key_to_validate_against)
|
|
26
|
-
|
|
27
|
-
# use provided 'with' array or column_names from self to get all foreign keys
|
|
28
|
-
keys_to_validate_with = (Array(with).map(&:to_s) if with) || self.column_names.select {|n| n.match(/\w_id/)}
|
|
15
|
+
def validate_foreign_keys(opt={})
|
|
16
|
+
validate_against = (opt[:on] || :user).to_s
|
|
17
|
+
reflections = self.reflect_on_all_associations(:belongs_to).map(&:name).map(&:to_s)
|
|
18
|
+
validate_with = ((Array(opt[:with]).map(&:to_s) if opt[:with]) || reflections).reject {|n| n == validate_against}
|
|
29
19
|
|
|
30
|
-
|
|
31
|
-
|
|
20
|
+
raise ArgumentError, "No foreign key #{validate_against} on #{self.table_name} table!" unless reflections.include?(validate_against)
|
|
21
|
+
raise ArgumentError, "Unknown relation in #{validate_with}!" unless validate_with.all? {|k| reflections.include?(k) }
|
|
32
22
|
|
|
33
|
-
define_method "validate_foreign_keys_on_#{
|
|
34
|
-
|
|
35
|
-
validate_foreign_key(
|
|
23
|
+
define_method "validate_foreign_keys_on_#{validate_against}" do
|
|
24
|
+
validate_with.each do |relation|
|
|
25
|
+
validate_foreign_key(validate_against, relation)
|
|
36
26
|
end
|
|
37
27
|
end
|
|
38
|
-
private "validate_foreign_keys_on_#{
|
|
28
|
+
private "validate_foreign_keys_on_#{validate_against}".to_sym
|
|
39
29
|
|
|
40
|
-
#
|
|
41
|
-
before_validation "validate_foreign_keys_on_#{key_to_validate_against}"
|
|
30
|
+
before_validation "validate_foreign_keys_on_#{validate_against}"
|
|
42
31
|
end
|
|
43
32
|
end
|
|
44
33
|
end
|
data/spec/models/model_spec.rb
CHANGED
|
@@ -71,21 +71,21 @@ describe ForeignKeyValidation::ModelExtension do
|
|
|
71
71
|
it "does not allow to rewrite user id of idea" do
|
|
72
72
|
idea.user_id = 42
|
|
73
73
|
idea.save
|
|
74
|
-
expect(idea.errors.messages.values.flatten).to include("
|
|
74
|
+
expect(idea.errors.messages.values.flatten).to include("user of project does not match ideas user")
|
|
75
75
|
expect(idea.reload.user_id).to_not eq(42)
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
it "does not allow to rewrite user id of issue" do
|
|
79
79
|
issue.user_id = 42
|
|
80
80
|
issue.save
|
|
81
|
-
expect(issue.errors.messages.values.flatten).to include("
|
|
81
|
+
expect(issue.errors.messages.values.flatten).to include("user of project does not match issues user")
|
|
82
82
|
expect(issue.reload.user_id).to_not eq(42)
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
it "does not allow to rewrite user id of comment" do
|
|
86
86
|
comment.user_id = 42
|
|
87
87
|
comment.save
|
|
88
|
-
expect(comment.errors.messages.values.flatten).to include("
|
|
88
|
+
expect(comment.errors.messages.values.flatten).to include("user of issue does not match comments user")
|
|
89
89
|
expect(comment.reload.user_id).to_not eq(42)
|
|
90
90
|
end
|
|
91
91
|
|
|
@@ -101,34 +101,78 @@ describe ForeignKeyValidation::ModelExtension do
|
|
|
101
101
|
end
|
|
102
102
|
|
|
103
103
|
it "does not allow to call private validate_foreign_keys_on_* methods" do
|
|
104
|
-
expect{issue.
|
|
104
|
+
expect{issue.validate_foreign_keys_on_user}.to raise_exception(/private method `validate_foreign_keys_on_user' called/)
|
|
105
105
|
end
|
|
106
106
|
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
-
context "With calling validation with
|
|
109
|
+
context "With calling validation with attributes hash" do
|
|
110
|
+
before do
|
|
111
|
+
Idea.class_eval do
|
|
112
|
+
validate_foreign_keys on: :user, with: :project
|
|
113
|
+
end
|
|
114
|
+
end
|
|
110
115
|
|
|
111
116
|
# NOTE: it's important here to not create the object through relation (user.projects.create...)
|
|
112
117
|
# it looks like active_record is caching the classes - but we need to test different class configs
|
|
113
118
|
let(:user) { User.create }
|
|
114
119
|
let(:project) { Project.create user: user }
|
|
120
|
+
let(:idea) { Idea.create user: user, project: project }
|
|
115
121
|
let(:issue) { Issue.create user: user, project: project }
|
|
116
122
|
let(:comment) { Comment.create user: user, issue: issue }
|
|
117
123
|
|
|
118
|
-
it "
|
|
119
|
-
expect
|
|
124
|
+
it "uses same user ids by default" do
|
|
125
|
+
expect(project.user_id).to eq(user.id)
|
|
126
|
+
expect(idea.user_id).to eq(user.id)
|
|
120
127
|
end
|
|
121
128
|
|
|
122
|
-
it "does not
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
129
|
+
it "does not allow to rewrite user id of idea" do
|
|
130
|
+
idea.user_id = 42
|
|
131
|
+
idea.save
|
|
132
|
+
expect(idea.errors.messages.values.flatten).to include("user of project does not match ideas user")
|
|
133
|
+
expect(idea.reload.user_id).to_not eq(42)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it "allow to rewrite user id of project" do
|
|
137
|
+
project.user_id = 42
|
|
138
|
+
project.save
|
|
139
|
+
project.reload
|
|
140
|
+
expect(project.user_id).to eq(42)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it "allow to rewrite user id of issue" do
|
|
126
144
|
issue.user_id = 42
|
|
127
145
|
issue.save
|
|
128
146
|
issue.reload
|
|
129
147
|
expect(issue.user_id).to eq(42)
|
|
130
148
|
end
|
|
131
149
|
|
|
150
|
+
it "allow to rewrite user id of comment" do
|
|
151
|
+
comment.user_id = 42
|
|
152
|
+
comment.save
|
|
153
|
+
comment.reload
|
|
154
|
+
expect(comment.user_id).to eq(42)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
context "With calling validation with wrong attributes hash" do
|
|
160
|
+
|
|
161
|
+
# NOTE: it's important here to not create the object through relation (user.projects.create...)
|
|
162
|
+
# it looks like active_record is caching the classes - but we need to test different class configs
|
|
163
|
+
let(:user) { User.create }
|
|
164
|
+
let(:project) { Project.create user: user }
|
|
165
|
+
let(:issue) { Issue.create user: user, project: project }
|
|
166
|
+
let(:comment) { Comment.create user: user, issue: issue }
|
|
167
|
+
|
|
168
|
+
it "raises error due to wrong :on key" do
|
|
169
|
+
expect{Idea.class_eval { validate_foreign_keys on: :not_existing_id }}.to raise_error("No foreign key not_existing_id on ideas table!")
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
it "raises error due to wrong :with key" do
|
|
173
|
+
expect{Idea.class_eval { validate_foreign_keys with: :not_existing_id }}.to raise_error('Unknown relation in ["not_existing_id"]!')
|
|
174
|
+
end
|
|
175
|
+
|
|
132
176
|
end
|
|
133
177
|
|
|
134
178
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: foreign_key_validation
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Marcus Geißler
|
|
@@ -14,84 +14,84 @@ dependencies:
|
|
|
14
14
|
name: rails
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- -
|
|
17
|
+
- - ~>
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
19
|
version: 4.0.0
|
|
20
20
|
type: :development
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- -
|
|
24
|
+
- - ~>
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: 4.0.0
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: bundler
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- -
|
|
31
|
+
- - ~>
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
33
|
version: '1.6'
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
|
-
- -
|
|
38
|
+
- - ~>
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '1.6'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: rake
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
|
-
- -
|
|
45
|
+
- - ~>
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
47
|
version: '10.1'
|
|
48
48
|
type: :development
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
|
-
- -
|
|
52
|
+
- - ~>
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '10.1'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: rspec-rails
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
|
-
- -
|
|
59
|
+
- - ~>
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
61
|
version: '3.0'
|
|
62
62
|
type: :development
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
|
-
- -
|
|
66
|
+
- - ~>
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
68
|
version: '3.0'
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
70
|
name: sqlite3
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
72
72
|
requirements:
|
|
73
|
-
- -
|
|
73
|
+
- - ~>
|
|
74
74
|
- !ruby/object:Gem::Version
|
|
75
75
|
version: '1.3'
|
|
76
76
|
type: :development
|
|
77
77
|
prerelease: false
|
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
79
|
requirements:
|
|
80
|
-
- -
|
|
80
|
+
- - ~>
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
82
|
version: '1.3'
|
|
83
83
|
- !ruby/object:Gem::Dependency
|
|
84
84
|
name: pry
|
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
|
86
86
|
requirements:
|
|
87
|
-
- -
|
|
87
|
+
- - ~>
|
|
88
88
|
- !ruby/object:Gem::Version
|
|
89
89
|
version: '0.10'
|
|
90
90
|
type: :development
|
|
91
91
|
prerelease: false
|
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
93
|
requirements:
|
|
94
|
-
- -
|
|
94
|
+
- - ~>
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
96
|
version: '0.10'
|
|
97
97
|
description: Protect the foreign keys in your Rails models. Really.
|
|
@@ -101,10 +101,10 @@ executables: []
|
|
|
101
101
|
extensions: []
|
|
102
102
|
extra_rdoc_files: []
|
|
103
103
|
files:
|
|
104
|
-
-
|
|
105
|
-
-
|
|
106
|
-
-
|
|
107
|
-
-
|
|
104
|
+
- .gitignore
|
|
105
|
+
- .rspec
|
|
106
|
+
- .ruby-gemset
|
|
107
|
+
- .ruby-version
|
|
108
108
|
- Gemfile
|
|
109
109
|
- LICENSE
|
|
110
110
|
- README.md
|
|
@@ -128,12 +128,12 @@ require_paths:
|
|
|
128
128
|
- lib
|
|
129
129
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
130
130
|
requirements:
|
|
131
|
-
- -
|
|
131
|
+
- - ! '>='
|
|
132
132
|
- !ruby/object:Gem::Version
|
|
133
133
|
version: '0'
|
|
134
134
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
135
135
|
requirements:
|
|
136
|
-
- -
|
|
136
|
+
- - ! '>='
|
|
137
137
|
- !ruby/object:Gem::Version
|
|
138
138
|
version: '0'
|
|
139
139
|
requirements: []
|