foreign_key_validation 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZjUwMTlkNzAzZDliZTUxOGViNzJmNDA4YTVhNGY5NzEzNjdlYzJkZg==
4
+ MTRkMDgxMDUxZmJiN2ViODhiNjc2MjlkMjkwNzU3NWE1NGYyNDMxMw==
5
5
  data.tar.gz: !binary |-
6
- OWJkZjlkM2I4NWIyYmY3Y2IyZDRjZDQ2NTk3MjBjZDQ0YzkyMjFmNw==
6
+ NWRmMDQzMmRkNTM4OTE5MGIzZTRmMjk3ODllMDU1ZmYyOGZjZTkyMw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- OTBmZmRhZDZlZDI5MDc1ZWM3Y2ExOWMxODIzZmQ1YjI3YmFkZjJkYTg2OTI3
10
- NTYxNWNhZmJmOTAyYzI2NjhiNTY4ODYzYjdhNjIxM2JiZTEyNjhhNTI0ZTcx
11
- MDEwZDc5ZDc1ZWE2M2EyZDUxMmQyNDMxYTdkYzk0M2M3ZGFlMTQ=
9
+ M2NhODc1MzQ0NDEwNGMwZmU0MzRkN2E2ZWJjZDg5OTlhYzFkYzhlYWEyM2Yx
10
+ MTUwMTQ3ZWU3ZGM0OTIxNTZhZTQ1MTMyZTk5ZDUzOGI2NzhjZTA1Nzg0MTk2
11
+ NWNhNjQzYzllOTIwYWJlNGM1ODk1NjIwY2ZhZDc0YzczYjRiNmY=
12
12
  data.tar.gz: !binary |-
13
- MmVhODBlOWU0MzQxNTRhYjIyN2U4MGJhNjViZDUwNzc3MTIyNDljY2M2MGE3
14
- NjJjZjUwODEzNTJiMjM4ZGYwMTI2MTNmNWMwZmQ0YjhiY2FlMDVjOWM5OTFj
15
- YmMwM2ZkN2NkZjMxOTc1Y2VlZDBhOThjNmI1YzZkZTMzMDJjNTk=
13
+ ODBhMWQ2MmZiMmE2N2NkZDc3YmJmYjU2MGQwYjQzYTliNjg3NzBlMGJjMGIw
14
+ OGVjYjQ2YTk2ZDA1MzdmNzFkNDdiMTU0ODE1MWUwYzlkNmJiMGY4ZDI0YTUy
15
+ ZjFiMjRhNWNmMjc0N2Y0NDNiYjhhMjljYTkyM2ZkZDM1NzI4Yzg=
data/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  [![Coverage Status](https://coveralls.io/repos/marcusg/foreign_key_validation/badge.png?branch=master)](https://coveralls.io/r/marcusg/foreign_key_validation?branch=master)
4
4
  [![Code Climate](https://codeclimate.com/github/marcusg/foreign_key_validation/badges/gpa.svg)](https://codeclimate.com/github/marcusg/foreign_key_validation)
5
5
  [![Build Status](https://travis-ci.org/marcusg/foreign_key_validation.svg?branch=master)](https://travis-ci.org/marcusg/foreign_key_validation)
6
+ [![Gem Version](https://badge.fury.io/rb/foreign_key_validation.svg)](http://badge.fury.io/rb/foreign_key_validation)
6
7
 
7
8
  Protect your models by specifying a collection of relations that should be tested for consistency with a predefined column (e.g. `user_id`).This is useful when the column `user_id` is used in multiple models. We can check if the `user_id` of *model A* matches `user_id` of *model B* before saving the records - if the IDs are different, an error will be attached to the errors hash of checked model.
8
9
 
@@ -0,0 +1,40 @@
1
+ module ForeignKeyValidation
2
+
3
+ class Collector
4
+ attr_accessor :klass, :validate_against, :reflections, :reflection_names, :validate_against_key, :validate_with
5
+
6
+ DEFAULT_VALIDATE_AGAINST = :user
7
+
8
+ def initialize(opt={})
9
+ self.klass = opt[:klass]
10
+ self.validate_against = find_validate_against(opt[:on])
11
+ self.reflections = klass.reflect_on_all_associations(:belongs_to)
12
+ self.reflection_names = reflections.map(&:name).map(&:to_s)
13
+ self.validate_against_key = find_validate_against_key
14
+ self.validate_with = find_validate_with(opt[:with])
15
+ end
16
+
17
+ def check!
18
+ raise Errors::NoReleationFoundError.new(klass.name) if reflection_names.empty?
19
+ raise Errors::NoForeignKeyFoundError.new(validate_against, klass.table_name) unless reflection_names.include?(validate_against)
20
+ raise Errors::UnknownRelationError.new(validate_with) unless validate_with.all? {|k| reflection_names.include?(k)}
21
+ true
22
+ end
23
+
24
+ private
25
+
26
+ def find_validate_against(on)
27
+ (on || DEFAULT_VALIDATE_AGAINST).to_s
28
+ end
29
+
30
+ def find_validate_with(with)
31
+ ((Array(with).map(&:to_s) if with) || reflection_names).reject {|n| n == validate_against}
32
+ end
33
+
34
+ def find_validate_against_key
35
+ reflections.select {|r| r.name.to_s == validate_against}.first.try(:foreign_key)
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,26 @@
1
+ module ForeignKeyValidation
2
+
3
+ class Filter
4
+ attr_accessor :collector
5
+
6
+ def initialize(collector)
7
+ self.collector = collector
8
+ end
9
+
10
+ def before_filter(&block)
11
+ collector.klass.send :define_method, filter_name do
12
+ self.instance_eval &block
13
+ end
14
+ collector.klass.send :private, filter_name.to_sym
15
+ collector.klass.send :before_validation, filter_name
16
+ end
17
+
18
+ private
19
+
20
+ def filter_name
21
+ "validate_foreign_keys_on_#{collector.validate_against}"
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -2,35 +2,19 @@ module ForeignKeyValidation
2
2
  module ModelExtension
3
3
  extend ActiveSupport::Concern
4
4
 
5
- included do
6
- private
7
- def validate_foreign_key(validate_against_key, reflection_name)
8
- return if send(reflection_name).try(validate_against_key).nil? or try(validate_against_key).nil?
9
-
10
- if send(reflection_name).send(validate_against_key) != send(validate_against_key)
11
- errors.add(validate_against_key, "#{validate_against_key} of #{reflection_name} does not match #{self.class.name.tableize} #{validate_against_key}.")
12
- end
13
- end
14
- end
15
-
16
5
  module ClassMethods
6
+
17
7
  def validate_foreign_keys(opt={})
18
8
  subclasses.map {|klass| klass.send(:validate_foreign_keys, opt)}
19
9
 
20
- validator = Validator.new(self, opt)
21
- validator.check
10
+ collector = Collector.new(opt.merge(klass: self))
11
+ collector.check!
22
12
 
23
- define_method validator.filter_method_name do
24
- validator.validate_with.each do |reflection_name|
25
- validate_foreign_key(validator.validate_against_key, reflection_name)
26
- end
13
+ Filter.new(collector).before_filter do
14
+ Validator.validate(validate_against_key: collector.validate_against_key, reflection_names: collector.validate_with, object: self)
27
15
  end
28
- private validator.filter_method_name.to_sym
29
-
30
- before_validation validator.filter_method_name
31
16
  end
17
+
32
18
  end
33
19
  end
34
20
  end
35
-
36
- ActiveRecord::Base.send :include, ForeignKeyValidation::ModelExtension
@@ -1,41 +1,17 @@
1
1
  module ForeignKeyValidation
2
2
 
3
3
  class Validator
4
- attr_accessor :klass, :validate_against, :reflections, :reflection_names, :validate_against_key, :validate_with
5
4
 
6
- DEFAULT_VALIDATE_AGAINST = :user
5
+ def self.validate(opt={})
6
+ validate_against_key, reflection_names, object = opt[:validate_against_key], opt[:reflection_names], opt[:object]
7
7
 
8
- def initialize(klass, opt={})
9
- self.klass = klass
10
- self.validate_against = find_validate_against(opt[:on])
11
- self.reflections = klass.reflect_on_all_associations(:belongs_to)
12
- self.reflection_names = reflections.map(&:name).map(&:to_s)
13
- self.validate_against_key = find_validate_against_key
14
- self.validate_with = find_validate_with(opt[:with])
15
- end
16
-
17
- def check
18
- raise Errors::NoReleationFoundError.new(klass.name) if reflection_names.empty?
19
- raise Errors::NoForeignKeyFoundError.new(validate_against, klass.table_name) unless reflection_names.include?(validate_against)
20
- raise Errors::UnknownRelationError.new(validate_with) unless validate_with.all? {|k| reflection_names.include?(k)}
21
- end
22
-
23
- def filter_method_name
24
- "validate_foreign_keys_on_#{validate_against}"
25
- end
26
-
27
- private
28
-
29
- def find_validate_against(opt_on)
30
- (opt_on || DEFAULT_VALIDATE_AGAINST).to_s
31
- end
32
-
33
- def find_validate_with(opt_with)
34
- ((Array(opt_with).map(&:to_s) if opt_with) || reflection_names).reject {|n| n == validate_against}
35
- end
8
+ reflection_names.each do |reflection_name|
9
+ next if object.send(reflection_name).try(validate_against_key).nil? or object.try(validate_against_key).nil?
36
10
 
37
- def find_validate_against_key
38
- reflections.select {|r| r.name.to_s == validate_against}.first.try(:foreign_key)
11
+ if object.send(reflection_name).send(validate_against_key) != object.send(validate_against_key)
12
+ object.errors.add(validate_against_key, "#{validate_against_key} of #{reflection_name} does not match #{object.class.name.tableize} #{validate_against_key}.")
13
+ end
14
+ end
39
15
  end
40
16
 
41
17
  end
@@ -1,3 +1,3 @@
1
1
  module ForeignKeyValidation
2
- VERSION = "1.0.0"
2
+ VERSION = "1.0.1"
3
3
  end
@@ -1,4 +1,8 @@
1
1
  require "foreign_key_validation/version"
2
2
  require "foreign_key_validation/errors"
3
+ require "foreign_key_validation/collector"
4
+ require "foreign_key_validation/filter"
3
5
  require "foreign_key_validation/validator"
4
6
  require "foreign_key_validation/model_extension"
7
+
8
+ ActiveRecord::Base.send :include, ForeignKeyValidation::ModelExtension
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ describe ForeignKeyValidation::ModelExtension do
4
+
5
+ let(:user) { User.create }
6
+ let(:other_user) { User.create }
7
+
8
+ context "with calling validation with custom attributes hash" do
9
+ before do
10
+ Comment.class_eval do
11
+ validate_foreign_keys on: :user, with: :issue # member is not in list - should be editable
12
+ end
13
+ end
14
+
15
+ let(:project) { Project.create user: user }
16
+ let(:other_project) { Project.create user: other_user }
17
+ let(:issue) { Issue.create user: user, project: project }
18
+ let(:other_issue) { Issue.create user: other_user, project: other_project }
19
+ let(:comment) { Comment.create user: user, issue: issue }
20
+ let(:manager) { Manager.create user: user }
21
+ let(:other_manager) { Manager.create user: User.create }
22
+
23
+ it "uses same user ids by default" do
24
+ expect(project.user_id).to eq(user.id)
25
+ expect(issue.user_id).to eq(user.id)
26
+ expect(comment.user_id).to eq(user.id)
27
+ expect(manager.user_id).to eq(user.id)
28
+ end
29
+
30
+ it "does not allow to rewrite issue id of comment" do
31
+ comment.issue_id = other_issue.id
32
+ comment.save
33
+ expect(comment.errors.messages.values.flatten).to include("user_id of issue does not match comments user_id.")
34
+ expect(comment.reload.issue_id).to_not eq(other_issue.id)
35
+ end
36
+
37
+ # NOTE: this is possible here because Issue model is not configured to check ids
38
+ # comment model can only check id against issue model if it is present
39
+ it "does allow to rewrite issue id of comment with random id" do
40
+ comment.issue_id = 42
41
+ comment.save
42
+ comment.reload
43
+ expect(comment.issue_id).to eq(42)
44
+ end
45
+
46
+ it "allow to rewrite member id of comment" do
47
+ comment.member_id = other_manager.id
48
+ comment.save
49
+ comment.reload
50
+ expect(comment.member_id).to eq(other_manager.id)
51
+ end
52
+
53
+ it "allow to rewrite user id of issue" do
54
+ issue.user_id = other_user.id
55
+ issue.save
56
+ issue.reload
57
+ expect(issue.user_id).to eq(other_user.id)
58
+ end
59
+
60
+ it "allow to rewrite user id of manager" do
61
+ manager.user_id = other_user.id
62
+ manager.save
63
+ manager.reload
64
+ expect(manager.user_id).to eq(other_user.id)
65
+ end
66
+
67
+ end
68
+
69
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe ForeignKeyValidation::ModelExtension do
4
+
5
+ let(:user) { User.create }
6
+ let(:other_user) { User.create }
7
+
8
+ context "with calling private methods from model" do
9
+ before { Issue.send :validate_foreign_keys }
10
+
11
+ let(:issue) { Issue.create }
12
+
13
+ it "does not allow to call private validate_foreign_keys_on_* methods" do
14
+ expect{issue.validate_foreign_keys_on_user}.to raise_exception(/private method `validate_foreign_keys_on_user' called/)
15
+ end
16
+ end
17
+
18
+ context "with calling validation and wrong attributes hash" do
19
+
20
+ it "raises error due to wrong :on key" do
21
+ expect{Idea.class_eval { validate_foreign_keys on: :not_existing }}.to raise_error("No foreign key for relation not_existing on ideas table!")
22
+ end
23
+
24
+ it "raises error due to not related :on key" do
25
+ expect{Project.class_eval { validate_foreign_keys on: :comment }}.to raise_error("No foreign key for relation comment on projects table!")
26
+ end
27
+
28
+ it "raises error due to wrong :with key" do
29
+ expect{Idea.class_eval { validate_foreign_keys with: :not_existing }}.to raise_error('Unknown relation in ["not_existing"]!')
30
+ end
31
+
32
+ end
33
+
34
+ context "with calling validation and missing relations" do
35
+
36
+ it "raises error due to no existing relations" do
37
+ expect{Dummy.class_eval { validate_foreign_keys }}.to raise_error("Can't find any belongs_to relations for Dummy class. Put validation call below association definitions!")
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+
3
+ describe ForeignKeyValidation::ModelExtension do
4
+
5
+ let(:user) { User.create }
6
+ let(:other_user) { User.create }
7
+
8
+ context "with calling validation and missing foreign key on relation" do
9
+
10
+ before do
11
+ Issue.class_eval do
12
+ validate_foreign_keys
13
+ end
14
+ end
15
+
16
+ let(:project) { Project.create }
17
+ let(:other_project) { Project.create }
18
+ let(:issue) { Issue.create project: project, user: user }
19
+
20
+ it "allow to rewrite user id of issue" do
21
+ issue.user_id = other_user.id
22
+ issue.save
23
+ issue.reload
24
+ expect(issue.user_id).to eq(other_user.id)
25
+ end
26
+
27
+ it "allow to rewrite project id of issue" do
28
+ issue.project_id = other_project.id
29
+ issue.save
30
+ issue.reload
31
+ expect(issue.project_id).to eq(other_project.id)
32
+ end
33
+
34
+ end
35
+
36
+ context "with calling validation and missing foreign key on self" do
37
+
38
+ before do
39
+ Issue.class_eval do
40
+ validate_foreign_keys
41
+ end
42
+ end
43
+
44
+ let(:project) { Project.create user: user }
45
+ let(:issue) { Issue.create project: project }
46
+
47
+ it "does not allow to rewrite user id of issue" do
48
+ issue.user_id = other_user.id
49
+ issue.save
50
+ expect(issue.errors.messages.values.flatten).to include("user_id of project does not match issues user_id.")
51
+ expect(issue.reload.user_id).to_not eq(other_user.id)
52
+ end
53
+
54
+ it "does not allow to rewrite user id of issue with random id" do
55
+ issue.user_id = 42
56
+ issue.save
57
+ expect(issue.errors.messages.values.flatten).to include("user_id of project does not match issues user_id.")
58
+ expect(issue.reload.user_id).to_not eq(42)
59
+ end
60
+
61
+ end
62
+
63
+ end
@@ -0,0 +1,107 @@
1
+ require 'spec_helper'
2
+
3
+ describe ForeignKeyValidation::ModelExtension do
4
+
5
+ let(:user) { User.create }
6
+ let(:other_user) { User.create }
7
+
8
+ context "with calling validation" do
9
+ before do
10
+ Idea.send :validate_foreign_keys
11
+ Project.send :validate_foreign_keys
12
+ Issue.send :validate_foreign_keys
13
+ Comment.send :validate_foreign_keys
14
+ Member.send :validate_foreign_keys
15
+ end
16
+
17
+ let(:project) { Project.create user: user }
18
+ let(:other_project) { Project.create user: other_user }
19
+ let(:idea) { Idea.create user: user, project: project }
20
+ let(:issue) { Issue.create user: user, project: project }
21
+ let(:other_issue) { Issue.create user: other_user, project: other_project }
22
+ let(:comment) { Comment.create user: user, issue: issue }
23
+ let(:manager) { Manager.create user: user }
24
+ let(:other_manager) { Manager.create user: User.create }
25
+ let(:developer) { Developer.create user: user, boss: manager }
26
+
27
+ it "uses same user ids by default" do
28
+ expect(project.user_id).to eq(user.id)
29
+ expect(idea.user_id).to eq(user.id)
30
+ expect(issue.user_id).to eq(user.id)
31
+ expect(comment.user_id).to eq(user.id)
32
+ expect(manager.user_id).to eq(user.id)
33
+ expect(developer.user_id).to eq(user.id)
34
+ end
35
+
36
+ it "does not allow to rewrite user id of idea" do
37
+ idea.user_id = other_user.id
38
+ idea.save
39
+ expect(idea.errors.messages.values.flatten).to include("user_id of project does not match ideas user_id.")
40
+ expect(idea.reload.user_id).to_not eq(other_user.id)
41
+ end
42
+
43
+ it "does not allow to rewrite user id of idea with random id" do
44
+ idea.user_id = 42
45
+ idea.save
46
+ expect(idea.errors.messages.values.flatten).to include("user_id of project does not match ideas user_id.")
47
+ expect(idea.reload.user_id).to_not eq(42)
48
+ end
49
+
50
+ it "does not allow to rewrite project id of idea" do
51
+ idea.project_id = other_project.id
52
+ idea.save
53
+ expect(idea.errors.messages.values.flatten).to include("user_id of project does not match ideas user_id.")
54
+ expect(idea.reload.user_id).to_not eq(other_project.id)
55
+ end
56
+
57
+ it "does not allow to rewrite user id of issue" do
58
+ issue.user_id = other_user.id
59
+ issue.save
60
+ expect(issue.errors.messages.values.flatten).to include("user_id of project does not match issues user_id.")
61
+ expect(issue.reload.user_id).to_not eq(other_user.id)
62
+ end
63
+
64
+ it "does not allow to rewrite project id of issue" do
65
+ issue.project_id = other_project.id
66
+ issue.save
67
+ expect(issue.errors.messages.values.flatten).to include("user_id of project does not match issues user_id.")
68
+ expect(issue.reload.user_id).to_not eq(other_project.id)
69
+ end
70
+
71
+ it "does not allow to rewrite user id of comment" do
72
+ comment.user_id = other_user.id
73
+ comment.save
74
+ expect(comment.errors.messages.values.flatten).to include("user_id of issue does not match comments user_id.")
75
+ expect(comment.reload.user_id).to_not eq(other_user.id)
76
+ end
77
+
78
+ it "does not allow to rewrite issue id of comment" do
79
+ comment.issue_id = other_issue.id
80
+ comment.save
81
+ expect(comment.errors.messages.values.flatten).to include("user_id of issue does not match comments user_id.")
82
+ expect(comment.reload.user_id).to_not eq(other_issue.id)
83
+ end
84
+
85
+ it "does allow to rewrite user id of project" do
86
+ project.user_id = other_user.id
87
+ project.save
88
+ expect(project.errors).to be_empty
89
+ expect(project.reload.user_id).to eq(other_user.id)
90
+ end
91
+
92
+ it "does not allow to rewrite user id of developer" do
93
+ developer.user_id = other_user.id
94
+ developer.save
95
+ expect(developer.errors.messages.values.flatten).to include("user_id of boss does not match developers user_id.")
96
+ expect(developer.reload.user_id).to_not eq(other_user.id)
97
+ end
98
+
99
+ it "does not allow to rewrite boss id of developer" do
100
+ developer.custom_boss_id = other_manager.id
101
+ developer.save
102
+ expect(developer.errors.messages.values.flatten).to include("user_id of boss does not match developers user_id.")
103
+ expect(developer.reload.custom_boss_id).to_not eq(other_manager.id)
104
+ end
105
+
106
+ end
107
+ end
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ describe ForeignKeyValidation::ModelExtension do
4
+
5
+ # NOTE: it's important to not create the objects through relation (user.projects.create...)
6
+ # it looks like active_record is caching the classes - but we need to test different class configs
7
+
8
+ let(:user) { User.create }
9
+ let(:other_user) { User.create }
10
+
11
+ context "without calling validation" do
12
+
13
+ let(:project) { Project.create user: user }
14
+ let(:idea) { Idea.create user: user, project: project }
15
+ let(:issue) { Issue.create user: user, project: project }
16
+ let(:comment) { Comment.create user: user, issue: issue }
17
+ let(:manager) { Manager.create user: user }
18
+ let(:other_manager) { Manager.create user: User.create }
19
+ let(:developer) { Developer.create user: user, boss: manager }
20
+
21
+ it "uses same user ids by default" do
22
+ expect(project.user_id).to eq(user.id)
23
+ expect(idea.user_id).to eq(user.id)
24
+ expect(issue.user_id).to eq(user.id)
25
+ expect(comment.user_id).to eq(user.id)
26
+ expect(manager.user_id).to eq(user.id)
27
+ expect(developer.user_id).to eq(user.id)
28
+ end
29
+
30
+ it "allow to rewrite user id of idea with random id" do
31
+ idea.user_id = 42
32
+ idea.save
33
+ idea.reload
34
+ expect(idea.user_id).to eq(42)
35
+ end
36
+
37
+ it "allow to rewrite user id of idea" do
38
+ idea.user_id = other_user.id
39
+ idea.save
40
+ idea.reload
41
+ expect(idea.user_id).to eq(other_user.id)
42
+ end
43
+
44
+ it "allow to rewrite user id of project" do
45
+ project.user_id = other_user.id
46
+ project.save
47
+ project.reload
48
+ expect(project.user_id).to eq(other_user.id)
49
+ end
50
+
51
+ it "allow to rewrite user id of issue" do
52
+ issue.user_id = other_user.id
53
+ issue.save
54
+ issue.reload
55
+ expect(issue.user_id).to eq(other_user.id)
56
+ end
57
+
58
+ it "allow to rewrite user id of comment" do
59
+ comment.user_id = other_user.id
60
+ comment.save
61
+ comment.reload
62
+ expect(comment.user_id).to eq(other_user.id)
63
+ end
64
+
65
+ it "allow to rewrite user id of developer" do
66
+ developer.user_id = other_user.id
67
+ developer.save
68
+ developer.reload
69
+ expect(developer.user_id).to eq(other_user.id)
70
+ end
71
+
72
+ it "allow to rewrite boss id of developer" do
73
+ developer.custom_boss_id = other_user.id
74
+ developer.save
75
+ developer.reload
76
+ expect(developer.custom_boss_id).to eq(other_user.id)
77
+ end
78
+
79
+ end
80
+
81
+
82
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreign_key_validation
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
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-09-30 00:00:00.000000000 Z
11
+ date: 2014-10-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -161,11 +161,17 @@ files:
161
161
  - gemfiles/4.1.gemfile
162
162
  - gemfiles/4.2.gemfile
163
163
  - lib/foreign_key_validation.rb
164
+ - lib/foreign_key_validation/collector.rb
164
165
  - lib/foreign_key_validation/errors.rb
166
+ - lib/foreign_key_validation/filter.rb
165
167
  - lib/foreign_key_validation/model_extension.rb
166
168
  - lib/foreign_key_validation/validator.rb
167
169
  - lib/foreign_key_validation/version.rb
168
- - spec/models/model_spec.rb
170
+ - spec/models/validation_with_custom_attrs_spec.rb
171
+ - spec/models/validation_with_exceptions_spec.rb
172
+ - spec/models/validation_with_missing_foreign_key_spec.rb
173
+ - spec/models/validation_without_attrs_spec.rb
174
+ - spec/models/without_validation_spec.rb
169
175
  - spec/spec_helper.rb
170
176
  - spec/support/load_models.rb
171
177
  - spec/support/reset_models.rb
@@ -195,7 +201,11 @@ signing_key:
195
201
  specification_version: 4
196
202
  summary: Protect the foreign keys in your Rails models.
197
203
  test_files:
198
- - spec/models/model_spec.rb
204
+ - spec/models/validation_with_custom_attrs_spec.rb
205
+ - spec/models/validation_with_exceptions_spec.rb
206
+ - spec/models/validation_with_missing_foreign_key_spec.rb
207
+ - spec/models/validation_without_attrs_spec.rb
208
+ - spec/models/without_validation_spec.rb
199
209
  - spec/spec_helper.rb
200
210
  - spec/support/load_models.rb
201
211
  - spec/support/reset_models.rb
@@ -1,337 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ForeignKeyValidation::ModelExtension do
4
-
5
- # NOTE: it's important to not create the objects through relation (user.projects.create...)
6
- # it looks like active_record is caching the classes - but we need to test different class configs
7
-
8
- let(:user) { User.create }
9
- let(:other_user) { User.create }
10
-
11
- context "without calling validation" do
12
-
13
- let(:project) { Project.create user: user }
14
- let(:idea) { Idea.create user: user, project: project }
15
- let(:issue) { Issue.create user: user, project: project }
16
- let(:comment) { Comment.create user: user, issue: issue }
17
- let(:manager) { Manager.create user: user }
18
- let(:other_manager) { Manager.create user: User.create }
19
- let(:developer) { Developer.create user: user, boss: manager }
20
-
21
- it "uses same user ids by default" do
22
- expect(project.user_id).to eq(user.id)
23
- expect(idea.user_id).to eq(user.id)
24
- expect(issue.user_id).to eq(user.id)
25
- expect(comment.user_id).to eq(user.id)
26
- expect(manager.user_id).to eq(user.id)
27
- expect(developer.user_id).to eq(user.id)
28
- end
29
-
30
- it "allow to rewrite user id of idea with random id" do
31
- idea.user_id = 42
32
- idea.save
33
- idea.reload
34
- expect(idea.user_id).to eq(42)
35
- end
36
-
37
- it "allow to rewrite user id of idea" do
38
- idea.user_id = other_user.id
39
- idea.save
40
- idea.reload
41
- expect(idea.user_id).to eq(other_user.id)
42
- end
43
-
44
- it "allow to rewrite user id of project" do
45
- project.user_id = other_user.id
46
- project.save
47
- project.reload
48
- expect(project.user_id).to eq(other_user.id)
49
- end
50
-
51
- it "allow to rewrite user id of issue" do
52
- issue.user_id = other_user.id
53
- issue.save
54
- issue.reload
55
- expect(issue.user_id).to eq(other_user.id)
56
- end
57
-
58
- it "allow to rewrite user id of comment" do
59
- comment.user_id = other_user.id
60
- comment.save
61
- comment.reload
62
- expect(comment.user_id).to eq(other_user.id)
63
- end
64
-
65
- it "allow to rewrite user id of developer" do
66
- developer.user_id = other_user.id
67
- developer.save
68
- developer.reload
69
- expect(developer.user_id).to eq(other_user.id)
70
- end
71
-
72
- it "allow to rewrite boss id of developer" do
73
- developer.custom_boss_id = other_user.id
74
- developer.save
75
- developer.reload
76
- expect(developer.custom_boss_id).to eq(other_user.id)
77
- end
78
-
79
- end
80
-
81
- context "with calling validation" do
82
- before do
83
- Idea.send :validate_foreign_keys
84
- Project.send :validate_foreign_keys
85
- Issue.send :validate_foreign_keys
86
- Comment.send :validate_foreign_keys
87
- Member.send :validate_foreign_keys
88
- end
89
-
90
- let(:project) { Project.create user: user }
91
- let(:other_project) { Project.create user: other_user }
92
- let(:idea) { Idea.create user: user, project: project }
93
- let(:issue) { Issue.create user: user, project: project }
94
- let(:other_issue) { Issue.create user: other_user, project: other_project }
95
- let(:comment) { Comment.create user: user, issue: issue }
96
- let(:manager) { Manager.create user: user }
97
- let(:other_manager) { Manager.create user: User.create }
98
- let(:developer) { Developer.create user: user, boss: manager }
99
-
100
- it "uses same user ids by default" do
101
- expect(project.user_id).to eq(user.id)
102
- expect(idea.user_id).to eq(user.id)
103
- expect(issue.user_id).to eq(user.id)
104
- expect(comment.user_id).to eq(user.id)
105
- expect(manager.user_id).to eq(user.id)
106
- expect(developer.user_id).to eq(user.id)
107
- end
108
-
109
- it "does not allow to rewrite user id of idea" do
110
- idea.user_id = other_user.id
111
- idea.save
112
- expect(idea.errors.messages.values.flatten).to include("user_id of project does not match ideas user_id.")
113
- expect(idea.reload.user_id).to_not eq(other_user.id)
114
- end
115
-
116
- it "does not allow to rewrite user id of idea with random id" do
117
- idea.user_id = 42
118
- idea.save
119
- expect(idea.errors.messages.values.flatten).to include("user_id of project does not match ideas user_id.")
120
- expect(idea.reload.user_id).to_not eq(42)
121
- end
122
-
123
- it "does not allow to rewrite project id of idea" do
124
- idea.project_id = other_project.id
125
- idea.save
126
- expect(idea.errors.messages.values.flatten).to include("user_id of project does not match ideas user_id.")
127
- expect(idea.reload.user_id).to_not eq(other_project.id)
128
- end
129
-
130
- it "does not allow to rewrite user id of issue" do
131
- issue.user_id = other_user.id
132
- issue.save
133
- expect(issue.errors.messages.values.flatten).to include("user_id of project does not match issues user_id.")
134
- expect(issue.reload.user_id).to_not eq(other_user.id)
135
- end
136
-
137
- it "does not allow to rewrite project id of issue" do
138
- issue.project_id = other_project.id
139
- issue.save
140
- expect(issue.errors.messages.values.flatten).to include("user_id of project does not match issues user_id.")
141
- expect(issue.reload.user_id).to_not eq(other_project.id)
142
- end
143
-
144
- it "does not allow to rewrite user id of comment" do
145
- comment.user_id = other_user.id
146
- comment.save
147
- expect(comment.errors.messages.values.flatten).to include("user_id of issue does not match comments user_id.")
148
- expect(comment.reload.user_id).to_not eq(other_user.id)
149
- end
150
-
151
- it "does not allow to rewrite issue id of comment" do
152
- comment.issue_id = other_issue.id
153
- comment.save
154
- expect(comment.errors.messages.values.flatten).to include("user_id of issue does not match comments user_id.")
155
- expect(comment.reload.user_id).to_not eq(other_issue.id)
156
- end
157
-
158
- it "does allow to rewrite user id of project" do
159
- project.user_id = other_user.id
160
- project.save
161
- expect(project.errors).to be_empty
162
- expect(project.reload.user_id).to eq(other_user.id)
163
- end
164
-
165
- it "does not allow to rewrite user id of developer" do
166
- developer.user_id = other_user.id
167
- developer.save
168
- expect(developer.errors.messages.values.flatten).to include("user_id of boss does not match developers user_id.")
169
- expect(developer.reload.user_id).to_not eq(other_user.id)
170
- end
171
-
172
- it "does not allow to rewrite boss id of developer" do
173
- developer.custom_boss_id = other_manager.id
174
- developer.save
175
- expect(developer.errors.messages.values.flatten).to include("user_id of boss does not match developers user_id.")
176
- expect(developer.reload.custom_boss_id).to_not eq(other_manager.id)
177
- end
178
-
179
- end
180
-
181
- context "with calling private methods from model" do
182
- before { Issue.send :validate_foreign_keys }
183
-
184
- let(:issue) { Issue.create }
185
-
186
- it "does not allow to call private validate_foreign_key method" do
187
- expect{issue.validate_foreign_key("test", "unrat")}.to raise_exception(/private method `validate_foreign_key' called/)
188
- end
189
-
190
- it "does not allow to call private validate_foreign_keys_on_* methods" do
191
- expect{issue.validate_foreign_keys_on_user}.to raise_exception(/private method `validate_foreign_keys_on_user' called/)
192
- end
193
- end
194
-
195
- context "with calling validation with custom attributes hash" do
196
- before do
197
- Comment.class_eval do
198
- validate_foreign_keys on: :user, with: :issue # member is not in list - should be editable
199
- end
200
- end
201
-
202
- let(:project) { Project.create user: user }
203
- let(:other_project) { Project.create user: other_user }
204
- let(:issue) { Issue.create user: user, project: project }
205
- let(:other_issue) { Issue.create user: other_user, project: other_project }
206
- let(:comment) { Comment.create user: user, issue: issue }
207
- let(:manager) { Manager.create user: user }
208
- let(:other_manager) { Manager.create user: User.create }
209
-
210
- it "uses same user ids by default" do
211
- expect(project.user_id).to eq(user.id)
212
- expect(issue.user_id).to eq(user.id)
213
- expect(comment.user_id).to eq(user.id)
214
- expect(manager.user_id).to eq(user.id)
215
- end
216
-
217
- it "does not allow to rewrite issue id of comment" do
218
- comment.issue_id = other_issue.id
219
- comment.save
220
- expect(comment.errors.messages.values.flatten).to include("user_id of issue does not match comments user_id.")
221
- expect(comment.reload.issue_id).to_not eq(other_issue.id)
222
- end
223
-
224
- # NOTE: this is possible here because Issue model is not configured to check ids
225
- # comment model can only check id against issue model if it is present
226
- it "does allow to rewrite issue id of comment with random id" do
227
- comment.issue_id = 42
228
- comment.save
229
- comment.reload
230
- expect(comment.issue_id).to eq(42)
231
- end
232
-
233
- it "allow to rewrite member id of comment" do
234
- comment.member_id = other_manager.id
235
- comment.save
236
- comment.reload
237
- expect(comment.member_id).to eq(other_manager.id)
238
- end
239
-
240
- it "allow to rewrite user id of issue" do
241
- issue.user_id = other_user.id
242
- issue.save
243
- issue.reload
244
- expect(issue.user_id).to eq(other_user.id)
245
- end
246
-
247
- it "allow to rewrite user id of manager" do
248
- manager.user_id = other_user.id
249
- manager.save
250
- manager.reload
251
- expect(manager.user_id).to eq(other_user.id)
252
- end
253
-
254
- end
255
-
256
- context "with calling validation and wrong attributes hash" do
257
-
258
- it "raises error due to wrong :on key" do
259
- expect{Idea.class_eval { validate_foreign_keys on: :not_existing }}.to raise_error("No foreign key for relation not_existing on ideas table!")
260
- end
261
-
262
- it "raises error due to not related :on key" do
263
- expect{Project.class_eval { validate_foreign_keys on: :comment }}.to raise_error("No foreign key for relation comment on projects table!")
264
- end
265
-
266
- it "raises error due to wrong :with key" do
267
- expect{Idea.class_eval { validate_foreign_keys with: :not_existing }}.to raise_error('Unknown relation in ["not_existing"]!')
268
- end
269
-
270
- end
271
-
272
- context "with calling validation and missing relations" do
273
-
274
- it "raises error due to no existing relations" do
275
- expect{Dummy.class_eval { validate_foreign_keys }}.to raise_error("Can't find any belongs_to relations for Dummy class. Put validation call below association definitions!")
276
- end
277
-
278
- end
279
-
280
-
281
- context "with calling validation and missing foreign key on self" do
282
-
283
- before do
284
- Issue.class_eval do
285
- validate_foreign_keys
286
- end
287
- end
288
-
289
- let(:project) { Project.create user: user }
290
- let(:issue) { Issue.create project: project }
291
-
292
- it "does not allow to rewrite user id of issue" do
293
- issue.user_id = other_user.id
294
- issue.save
295
- expect(issue.errors.messages.values.flatten).to include("user_id of project does not match issues user_id.")
296
- expect(issue.reload.user_id).to_not eq(other_user.id)
297
- end
298
-
299
- it "does not allow to rewrite user id of issue with random id" do
300
- issue.user_id = 42
301
- issue.save
302
- expect(issue.errors.messages.values.flatten).to include("user_id of project does not match issues user_id.")
303
- expect(issue.reload.user_id).to_not eq(42)
304
- end
305
-
306
-
307
- end
308
-
309
- context "with calling validation and missing foreign key on relation" do
310
-
311
- before do
312
- Issue.class_eval do
313
- validate_foreign_keys
314
- end
315
- end
316
-
317
- let(:project) { Project.create }
318
- let(:other_project) { Project.create }
319
- let(:issue) { Issue.create project: project, user: user }
320
-
321
- it "allow to rewrite user id of issue" do
322
- issue.user_id = other_user.id
323
- issue.save
324
- issue.reload
325
- expect(issue.user_id).to eq(other_user.id)
326
- end
327
-
328
- it "allow to rewrite project id of issue" do
329
- issue.project_id = other_project.id
330
- issue.save
331
- issue.reload
332
- expect(issue.project_id).to eq(other_project.id)
333
- end
334
-
335
- end
336
-
337
- end