foreign_key_validation 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6efa881cebd85a67f4706bf7251ee36caa3cc710
4
- data.tar.gz: 52bcaf493a5508f7f519e6af787082ad82ead28e
3
+ metadata.gz: 7af20d0ad7b99c870491e939cb66a117ef0f4def
4
+ data.tar.gz: e7c83abbc241fbcfab820e58b46b00fa64632ce8
5
5
  SHA512:
6
- metadata.gz: 353a11c25d79edd2b1148118dc08989f972244f9592f5414a24826418a66789343b32cecf6959fa511237d4131101c761731a1b252fcc62d000aa7a1bb79dad8
7
- data.tar.gz: 6a9c0ed52a1e93b28435bc87dcd977304c3f15aee5b2f516c84b1683d7de7c2864514e4c7c0ab1946946efc3b04f91be6f2c29ec3a3f4b2e6bb6595971322fb8
6
+ metadata.gz: 92ec77233357a8e66e4410364439e5de674ac84d3c6a5d7f43e96193798495287e9f43426a579f56e05560ee01e24a85a7e7f134262f2ac917620743e52f4a8a
7
+ data.tar.gz: 08191da451eb213cd450d013fac17de97eb433b5a9984c3358e406df51a75bf141da22c400995a689f3c27705dfe65d604a0e74b39f062841ce8febfc4334822
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  # foreign_key_validation
2
2
 
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.
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
+
5
+ ## Requirements
6
+ rails >= 3.2
4
7
 
5
8
  ## Installation
6
9
 
@@ -28,7 +31,7 @@ This would only check `model.project.admin_user_id` to match `model.admin_user_i
28
31
 
29
32
  ## Note
30
33
 
31
- Only testet with ruby 2.x
34
+ Only tested with ruby 2.x and ActiveRecord
32
35
 
33
36
  ## TODO
34
37
 
@@ -18,8 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "rails", ">= 3.2"
22
-
21
+ spec.add_development_dependency "rails", "~> 4.0.0"
23
22
  spec.add_development_dependency "bundler", "~> 1.6"
24
23
  spec.add_development_dependency "rake", "~> 10.1"
25
24
  spec.add_development_dependency "rspec-rails", "~> 3.0"
@@ -3,6 +3,7 @@ module ForeignKeyValidation
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
+ private
6
7
  def validate_foreign_key(key_to_validate_against, validation_key)
7
8
  relation = validation_key.gsub('_id', '')
8
9
 
@@ -17,34 +18,30 @@ module ForeignKeyValidation
17
18
  end
18
19
 
19
20
  module ClassMethods
20
-
21
21
  def validate_foreign_keys(on: :user_id, with: nil)
22
- key_to_validate_against = on
22
+ key_to_validate_against = on.to_s
23
23
 
24
24
  # check if key_to_validate_against is present as column
25
- raise ArgumentError, "No foreign key #{key_to_validate_against} on #{self.table_name} table!" unless self.column_names.include?(key_to_validate_against.to_s)
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
26
 
27
27
  # use provided 'with' array or column_names from self to get all foreign keys
28
28
  keys_to_validate_with = (Array(with).map(&:to_s) if with) || self.column_names.select {|n| n.match(/\w_id/)}
29
29
 
30
30
  # reject keys that match either the key_to_validate_against or the current class name key (needed for sti models)
31
- keys_to_validate_with.reject! {|n| n.to_s == key_to_validate_against.to_s || n.to_s == "#{self.class.name.underscore}_id" }
31
+ keys_to_validate_with.reject! {|n| n == key_to_validate_against || n == "#{self.class.name.underscore}_id" }
32
32
 
33
33
  define_method "validate_foreign_keys_on_#{key_to_validate_against}" do
34
-
35
34
  keys_to_validate_with.each do |validation_key|
36
35
  validate_foreign_key(key_to_validate_against, validation_key)
37
36
  end
38
-
39
37
  end
40
- before_validation "validate_foreign_keys_on_#{key_to_validate_against}"
38
+ private "validate_foreign_keys_on_#{key_to_validate_against}".to_sym
41
39
 
40
+ # add before filter to validate key
41
+ before_validation "validate_foreign_keys_on_#{key_to_validate_against}"
42
42
  end
43
-
44
43
  end
45
-
46
44
  end
47
-
48
45
  end
49
46
 
50
- ActiveRecord::Base.send :include, ForeignKeyValidation::ModelExtension
47
+ ActiveRecord::Base.send :include, ForeignKeyValidation::ModelExtension
@@ -1,3 +1,3 @@
1
1
  module ForeignKeyValidation
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -1,80 +1,135 @@
1
1
  require 'spec_helper'
2
2
 
3
- class User < ActiveRecord::Base
4
- has_many :projects
5
- has_many :ideas
6
- end
3
+ describe ForeignKeyValidation::ModelExtension do
7
4
 
8
- class Project < ActiveRecord::Base
9
- belongs_to :user
10
- has_many :ideas
11
- validates_presence_of :user_id, presence: true
12
- end
5
+ context "Without calling validation" do
13
6
 
14
- class Idea < ActiveRecord::Base
15
- belongs_to :project
16
- belongs_to :user
17
- validates_presence_of :user_id, :project_id, presence: true
18
- end
7
+ # NOTE: it's important here to not create the object through relation (user.projects.create...)
8
+ # it looks like active_record is caching the classes - but we need to test different class configs
9
+ let(:user) { User.create }
10
+ let(:project) { Project.create user: user }
11
+ let(:idea) { Idea.create user: user, project: project }
12
+ let(:issue) { Issue.create user: user, project: project }
13
+ let(:comment) { Comment.create user: user, issue: issue }
19
14
 
20
- describe "Behaviour without validate_foreign_keys" do
15
+ it "uses same user ids by default" do
16
+ expect(project.user_id).to eq(user.id)
17
+ expect(idea.user_id).to eq(user.id)
18
+ end
21
19
 
22
- let!(:user) { User.create }
23
- let!(:project) { user.projects.create }
24
- let!(:idea) { project.ideas.create user: user }
20
+ it "allow to rewrite user id of idea" do
21
+ idea.user_id = 42
22
+ idea.save
23
+ idea.reload
24
+ expect(idea.user_id).to eq(42)
25
+ end
25
26
 
26
- it "uses same user ids by default" do
27
- expect(project.user_id).to eq(user.id)
28
- expect(user.id).to eq(user.id)
29
- expect(idea.user_id).to eq(user.id)
30
- end
27
+ it "allow to rewrite user id of project" do
28
+ project.user_id = 42
29
+ project.save
30
+ project.reload
31
+ expect(project.user_id).to eq(42)
32
+ end
31
33
 
32
- it "allow to rewrite user id of idea" do
33
- idea.user_id = 42
34
- idea.save
35
- idea.reload
36
- expect(idea.user_id).to eq(42)
37
- end
34
+ it "allow to rewrite user id of issue" do
35
+ issue.user_id = 42
36
+ issue.save
37
+ issue.reload
38
+ expect(issue.user_id).to eq(42)
39
+ end
40
+
41
+ it "allow to rewrite user id of comment" do
42
+ comment.user_id = 42
43
+ comment.save
44
+ comment.reload
45
+ expect(comment.user_id).to eq(42)
46
+ end
38
47
 
39
- it "allow to rewrite user id of project" do
40
- project.user_id = 42
41
- project.save
42
- project.reload
43
- expect(project.user_id).to eq(42)
44
48
  end
45
49
 
46
- end
50
+ context "With calling validation" do
51
+ before do
52
+ Idea.send :validate_foreign_keys
53
+ Project.send :validate_foreign_keys
54
+ Issue.send :validate_foreign_keys
55
+ Comment.send :validate_foreign_keys
56
+ end
47
57
 
48
- describe "Behaviour with validate_foreign_keys" do
58
+ # NOTE: it's important here to not create the object through relation (user.projects.create...)
59
+ # it looks like active_record is caching the classes - but we need to test different class configs
60
+ let(:user) { User.create }
61
+ let(:project) { Project.create user: user }
62
+ let(:idea) { Idea.create user: user, project: project }
63
+ let(:issue) { Issue.create user: user, project: project }
64
+ let(:comment) { Comment.create user: user, issue: issue }
65
+
66
+ it "uses same user ids by default" do
67
+ expect(project.user_id).to eq(user.id)
68
+ expect(idea.user_id).to eq(user.id)
69
+ end
49
70
 
50
- before do
51
- Idea.class_eval do
52
- validate_foreign_keys
71
+ it "does not allow to rewrite user id of idea" do
72
+ idea.user_id = 42
73
+ idea.save
74
+ expect(idea.errors.messages.values.flatten).to include("user_id of project does not match ideas user_id")
75
+ expect(idea.reload.user_id).to_not eq(42)
76
+ end
77
+
78
+ it "does not allow to rewrite user id of issue" do
79
+ issue.user_id = 42
80
+ issue.save
81
+ expect(issue.errors.messages.values.flatten).to include("user_id of project does not match issues user_id")
82
+ expect(issue.reload.user_id).to_not eq(42)
53
83
  end
54
- end
55
84
 
56
- let!(:user) { User.create }
57
- let!(:project) { user.projects.create }
58
- let!(:idea) { project.ideas.create user: user }
85
+ it "does not allow to rewrite user id of comment" do
86
+ comment.user_id = 42
87
+ comment.save
88
+ expect(comment.errors.messages.values.flatten).to include("user_id of issue does not match comments user_id")
89
+ expect(comment.reload.user_id).to_not eq(42)
90
+ end
59
91
 
60
- it "uses same user ids by default" do
61
- expect(project.user_id).to eq(user.id)
62
- expect(user.id).to eq(user.id)
63
- expect(idea.user_id).to eq(user.id)
64
- end
92
+ it "does allow to rewrite user id of project" do
93
+ project.user_id = 42
94
+ project.save
95
+ expect(project.errors).to be_empty
96
+ expect(project.reload.user_id).to eq(42)
97
+ end
98
+
99
+ it "does not allow to call private validate_foreign_key method" do
100
+ expect{issue.validate_foreign_key("test", "unrat")}.to raise_exception(/private method `validate_foreign_key' called/)
101
+ end
102
+
103
+ it "does not allow to call private validate_foreign_keys_on_* methods" do
104
+ expect{issue.validate_foreign_keys_on_user_id}.to raise_exception(/private method `validate_foreign_keys_on_user_id' called/)
105
+ end
65
106
 
66
- it "does not allow to rewrite user id of idea" do
67
- idea.user_id = 42
68
- idea.save
69
- expect(idea.errors.messages.values.flatten).to include("user_id of project does not match ideas user_id")
70
- expect(idea.reload.user_id).to_not eq(42)
71
107
  end
72
108
 
73
- it "does allow to rewrite user id of project" do
74
- project.user_id = 42
75
- project.save
76
- expect(project.errors).to be_empty
77
- expect(project.reload.user_id).to eq(42)
109
+ context "With calling validation with wrong attributes hash" do
110
+
111
+ # NOTE: it's important here to not create the object through relation (user.projects.create...)
112
+ # it looks like active_record is caching the classes - but we need to test different class configs
113
+ let(:user) { User.create }
114
+ let(:project) { Project.create user: user }
115
+ let(:issue) { Issue.create user: user, project: project }
116
+ let(:comment) { Comment.create user: user, issue: issue }
117
+
118
+ it "raises error due to wrong :on key" do
119
+ expect{Idea.class_eval { validate_foreign_keys on: :not_existing_id }}.to raise_error("No foreign key not_existing_id on ideas table!")
120
+ end
121
+
122
+ it "does not validate due to wrong :with key" do
123
+ Issue.class_eval do
124
+ validate_foreign_keys with: :not_existing_id
125
+ end
126
+ issue.user_id = 42
127
+ issue.save
128
+ issue.reload
129
+ expect(issue.user_id).to eq(42)
130
+ end
131
+
78
132
  end
79
133
 
80
- end
134
+
135
+ end
data/spec/spec_helper.rb CHANGED
@@ -8,11 +8,17 @@ RSpec.configure do |config|
8
8
  config.filter_run :focus
9
9
  config.infer_base_class_for_anonymous_controllers = true
10
10
 
11
- # config.order = 'random'
11
+ # reset and reload model classes for each run
12
+ config.before(:each) do
13
+ load "support/reset_models.rb"
14
+ load "support/load_models.rb"
15
+ end
16
+
17
+ config.order = 'random'
12
18
  end
13
19
 
14
20
  setup_sqlite_db = lambda do
15
21
  ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
16
- load "schema.rb"
22
+ load "support/schema.rb"
17
23
  end
18
- silence_stream(STDOUT, &setup_sqlite_db)
24
+ silence_stream(STDOUT, &setup_sqlite_db)
@@ -0,0 +1,28 @@
1
+ require "active_record"
2
+
3
+ class User < ActiveRecord::Base
4
+ has_many :projects
5
+ has_many :ideas
6
+ end
7
+
8
+ class Project < ActiveRecord::Base
9
+ belongs_to :user
10
+ has_many :ideas
11
+ has_many :issues
12
+ end
13
+
14
+ class Idea < ActiveRecord::Base
15
+ belongs_to :project
16
+ belongs_to :user
17
+ end
18
+
19
+ class Issue < ActiveRecord::Base
20
+ belongs_to :project
21
+ belongs_to :user
22
+ has_many :comments
23
+ end
24
+
25
+ class Comment < ActiveRecord::Base
26
+ belongs_to :issue
27
+ belongs_to :user
28
+ end
@@ -0,0 +1,5 @@
1
+ Object.send(:remove_const, :User) if Object.constants.include?(:User)
2
+ Object.send(:remove_const, :Project) if Object.constants.include?(:Project)
3
+ Object.send(:remove_const, :Idea) if Object.constants.include?(:Idea)
4
+ Object.send(:remove_const, :Issue) if Object.constants.include?(:Issue)
5
+ Object.send(:remove_const, :Comment) if Object.constants.include?(:Comment)
@@ -0,0 +1,26 @@
1
+ ActiveRecord::Schema.define do
2
+ self.verbose = false
3
+
4
+ create_table "users", force: true do |t|
5
+ end
6
+
7
+ create_table "projects", force: true do |t|
8
+ t.integer "user_id"
9
+ end
10
+
11
+ create_table "ideas", force: true do |t|
12
+ t.integer "user_id"
13
+ t.integer "project_id"
14
+ end
15
+
16
+ create_table "issues", force: true do |t|
17
+ t.integer "user_id"
18
+ t.integer "project_id"
19
+ end
20
+
21
+ create_table "comments", force: true do |t|
22
+ t.integer "user_id"
23
+ t.integer "issue_id"
24
+ end
25
+
26
+ end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreign_key_validation
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marcus Geißler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-29 00:00:00.000000000 Z
11
+ date: 2014-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '3.2'
20
- type: :runtime
19
+ version: 4.0.0
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
- version: '3.2'
26
+ version: 4.0.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -107,7 +107,6 @@ files:
107
107
  - ".ruby-version"
108
108
  - Gemfile
109
109
  - LICENSE
110
- - LICENSE.txt
111
110
  - README.md
112
111
  - Rakefile
113
112
  - foreign_key_validation.gemspec
@@ -115,8 +114,10 @@ files:
115
114
  - lib/foreign_key_validation/model_extension.rb
116
115
  - lib/foreign_key_validation/version.rb
117
116
  - spec/models/model_spec.rb
118
- - spec/schema.rb
119
117
  - spec/spec_helper.rb
118
+ - spec/support/load_models.rb
119
+ - spec/support/reset_models.rb
120
+ - spec/support/schema.rb
120
121
  homepage: https://github.com/marcusg/foreign_key_validation
121
122
  licenses:
122
123
  - MIT
@@ -143,5 +144,7 @@ specification_version: 4
143
144
  summary: Protect the foreign keys in your Rails models.
144
145
  test_files:
145
146
  - spec/models/model_spec.rb
146
- - spec/schema.rb
147
147
  - spec/spec_helper.rb
148
+ - spec/support/load_models.rb
149
+ - spec/support/reset_models.rb
150
+ - spec/support/schema.rb
data/LICENSE.txt DELETED
@@ -1,22 +0,0 @@
1
- Copyright (c) 2014 Marcus Geißler
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/spec/schema.rb DELETED
@@ -1,15 +0,0 @@
1
- ActiveRecord::Schema.define(:version => 20130730063732) do
2
-
3
- create_table "users", :force => true do |t|
4
- end
5
-
6
- create_table "projects", :force => true do |t|
7
- t.integer "user_id"
8
- end
9
-
10
- create_table "ideas", :force => true do |t|
11
- t.integer "user_id"
12
- t.integer "project_id"
13
- end
14
-
15
- end