foreign_key_validation 0.0.2 → 0.0.3

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 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