law 0.1.3 → 0.1.8

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
  SHA256:
3
- metadata.gz: e74cd15524ae8f0731bcb351779158496be3fa61a49e7e3553a53a0bfd5fdcff
4
- data.tar.gz: fa7920650d8debe57a1bbcafa2b6cabf1e9b617783a3f22edc9568a9e7eea359
3
+ metadata.gz: 2e2ac1483d7b8253bb52289a1c81727bbfc15f47a60f0f03ab7f7f9c78e38d69
4
+ data.tar.gz: ab18b48276b107552e3335cd8dfc17e98d04a764aef9655ca369d40b5c6fae10
5
5
  SHA512:
6
- metadata.gz: cb1bda1a9cfbbe9205453a318d2ef783e2adc62ce13bdea457e76c93f07194d4531265c0d3284eb866c722aed16853696d6283a7d590de5f8a90145ef441b7bd
7
- data.tar.gz: 866e1524f3d77b29d872ade4758faa389889a114a6a287b68fae0772fa5371658a4be22cc9d5c1cdb87e6f046068c864a4af3838a5ed35cf965d8aadace18de8
6
+ metadata.gz: 259728e11d27c2c78829433b4dcd6e6d6f869533c7637002b6823c498523e5bc8353a2ffcd307556d09b94095ea435cf963bf4ae6fe88234ae1e6fe90fecc437
7
+ data.tar.gz: 6383a6bd485a6ea5ad111095bc8df0e961c570ef54206f5139eb7c8ad2b742501d427656e79a26e2838b3a0ccef224401a9e8c564ceb9eadb55b14d78600f152
@@ -0,0 +1,9 @@
1
+ Description:
2
+ Stub a Law with a test.
3
+
4
+ Example:
5
+ `rails generate law foo`
6
+
7
+ Generates:
8
+ Law: app/laws/foo_law.rb
9
+ Test: spec/laws/foo_law_spec.rb
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Law
4
+ module Generators
5
+ class LawGenerator < Rails::Generators::NamedBase
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ hook_for :test_framework
9
+
10
+ def create_law
11
+ template "law.rb.erb", File.join("app/laws/", class_path, "#{file_name}_law.rb")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ Description:
2
+ Stub a Regulation with a test.
3
+
4
+ Example:
5
+ `rails generate law:regulation foo`
6
+
7
+ Generates:
8
+ Regulation: app/regulations/foo_regulation.rb
9
+ Test: spec/regulations/foo_regulation_spec.rb
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Law
4
+ module Generators
5
+ class RegulationGenerator < Rails::Generators::NamedBase
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ hook_for :test_framework
9
+
10
+ def create_regulation
11
+ template "regulation.rb.erb", File.join("app/regulations/", class_path, "#{file_name}_regulation.rb")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= class_name %>Regulation < ApplicationRegulation
4
+ end
@@ -0,0 +1,9 @@
1
+ Description:
2
+ Stub a Statute with a test.
3
+
4
+ Example:
5
+ `rails generate law:statute foo`
6
+
7
+ Generates:
8
+ Statute: app/statutes/foo_statute.rb
9
+ Test: spec/statutes/foo_statute_spec.rb
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Law
4
+ module Generators
5
+ class StatuteGenerator < Rails::Generators::NamedBase
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ hook_for :test_framework
9
+
10
+ def create_statute
11
+ template "statute.rb.erb", File.join("app/statutes/", class_path, "#{file_name}_statute.rb")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= class_name %>Statute < ApplicationStatute
4
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= class_name %>Law < ApplicationLaw
4
+ end
@@ -0,0 +1,9 @@
1
+
2
+ Description:
3
+ Stub a Law test.
4
+
5
+ Example:
6
+ `rails generate rspec:law foo`
7
+
8
+ Generates:
9
+ Test: spec/laws/foo_law_spec.rb
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rspec
4
+ module Generators
5
+ class LawGenerator < Rails::Generators::NamedBase
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ def create_spec_file
9
+ template "law_spec.rb.erb", File.join("spec/laws/", class_path, "#{file_name}_law_spec.rb")
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails_helper"
4
+
5
+ RSpec.describe <%= class_name %>Law, type: :law do
6
+ it { is_expected.to inherit_from ApplicationLaw }
7
+ end
@@ -0,0 +1,9 @@
1
+
2
+ Description:
3
+ Stub a Regulation test.
4
+
5
+ Example:
6
+ `rails generate rspec:regulation foo`
7
+
8
+ Generates:
9
+ Test: spec/regulations/foo_regulation_spec.rb
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rspec
4
+ module Generators
5
+ class RegulationGenerator < Rails::Generators::NamedBase
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ def create_spec_file
9
+ template "regulation_spec.rb.erb", File.join("spec/regulations/", class_path, "#{file_name}_regulation_spec.rb")
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails_helper"
4
+
5
+ RSpec.describe <%= class_name %>Regulation, type: :regulation do
6
+ it { is_expected.to inherit_from ApplicationRegulation }
7
+ end
@@ -0,0 +1,9 @@
1
+
2
+ Description:
3
+ Stub a Statute test.
4
+
5
+ Example:
6
+ `rails generate rspec:statute foo`
7
+
8
+ Generates:
9
+ Test: spec/statutes/foo_statute_spec.rb
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rspec
4
+ module Generators
5
+ class StatuteGenerator < Rails::Generators::NamedBase
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ def create_spec_file
9
+ template "statute_spec.rb.erb", File.join("spec/statutes/", class_path, "#{file_name}_statute_spec.rb")
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails_helper"
4
+
5
+ RSpec.describe <%= class_name %>Statute, type: :statute do
6
+ it { is_expected.to inherit_from ApplicationStatute }
7
+ end
data/lib/law.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "active_support"
4
4
  require "active_support/core_ext/enumerable"
5
+ require "active_support/hash_with_indifferent_access"
5
6
 
6
7
  require "spicery"
7
8
 
@@ -27,4 +28,5 @@ module Law
27
28
 
28
29
  class NotAuthorizedError < Error; end
29
30
  class InjunctionError < NotAuthorizedError; end
31
+ class ComplianceError < NotAuthorizedError; end
30
32
  end
data/lib/law/judgement.rb CHANGED
@@ -15,7 +15,7 @@ module Law
15
15
 
16
16
  attr_reader :petition, :violations, :applied_regulations
17
17
 
18
- delegate :statute, :applicable_regulations, to: :petition
18
+ delegate :statute, :applicable_regulations, :compliant?, to: :petition, allow_nil: true
19
19
 
20
20
  def initialize(petition)
21
21
  @petition = petition
@@ -39,20 +39,30 @@ module Law
39
39
  end
40
40
 
41
41
  def judge!
42
- if statute.unregulated?
42
+ raise AlreadyJudgedError if adjudicated?
43
+
44
+ if statute&.unregulated?
43
45
  @applied_regulations = [ nil ]
44
46
  return true
45
47
  end
46
48
 
49
+ ensure_jurisdiction
50
+ reckon!
51
+
52
+ true
53
+ end
54
+
55
+ private
56
+
57
+ def ensure_jurisdiction
47
58
  raise InjunctionError if applicable_regulations.blank?
48
- raise AlreadyJudgedError if adjudicated?
59
+ raise ComplianceError unless compliant?
60
+ end
49
61
 
62
+ def reckon!
50
63
  @applied_regulations = applicable_regulations.map { |regulation| regulation.new(petition: petition) }
51
64
  @violations = applied_regulations.reject(&:valid?)
52
-
53
65
  raise NotAuthorizedError unless authorized?
54
-
55
- true
56
66
  end
57
67
  end
58
68
  end
@@ -8,22 +8,32 @@ module Law
8
8
 
9
9
  included do
10
10
  class_attribute :actions, instance_writer: false, default: HashWithIndifferentAccess.new
11
+ class_attribute :revoked_actions, instance_writer: false, default: HashWithIndifferentAccess.new
11
12
 
12
- delegate :statute_for_action?, to: :class
13
+ delegate :statute_for_action?, :revoked_action?, to: :class
13
14
  end
14
15
 
15
16
  class_methods do
16
17
  def inherited(base)
17
18
  base.actions = actions.dup
19
+ base.revoked_actions = revoked_actions.dup
18
20
  super
19
21
  end
20
22
 
23
+ def revoked_action?(action)
24
+ revoked_actions[action].present?
25
+ end
26
+
21
27
  def statute_for_action?(action)
22
28
  actions[action].present?
23
29
  end
24
30
 
25
31
  private
26
32
 
33
+ def revoke_action(*input_actions)
34
+ input_actions.each { |action| revoked_actions[action] = true }
35
+ end
36
+
27
37
  def define_action(*input_actions, enforces: nil)
28
38
  raise ArgumentError, "invalid statute: #{enforces}" unless enforceable?(enforces)
29
39
 
@@ -14,6 +14,8 @@ module Law
14
14
  end
15
15
 
16
16
  def petition_for_action(action)
17
+ return if revoked_action?(action)
18
+
17
19
  Law::Petition.new(
18
20
  statute: actions[action] || _default_statute,
19
21
  source: source,
data/lib/law/legalize.rb CHANGED
@@ -23,7 +23,7 @@ module Law
23
23
  end
24
24
 
25
25
  def law(object = nil, petitioner = nil, permissions: nil, parameters: nil, law_class: nil)
26
- object ||= try(:controller_name)&.singularize&.camelize&.safe_constantize
26
+ object ||= @record || try(:controller_name)&.singularize&.camelize&.safe_constantize
27
27
  petitioner ||= try(:current_user)
28
28
  permissions ||= petitioner.try(:permissions)
29
29
  law_class ||= object.try(:conjugate, Law::LawBase)
data/lib/law/petition.rb CHANGED
@@ -18,5 +18,11 @@ module Law
18
18
  statute.regulations.select { |regulation| permission_list.include? regulation.key }
19
19
  end
20
20
  memoize :applicable_regulations
21
+
22
+ def compliant?
23
+ return applicable_regulations.any? unless statute.full_compliance_required?
24
+
25
+ statute.regulations == applicable_regulations
26
+ end
21
27
  end
22
28
  end
@@ -6,3 +6,4 @@ require_relative "custom_matchers/be_imposed_by"
6
6
  require_relative "custom_matchers/define_action"
7
7
  require_relative "custom_matchers/have_default_statute"
8
8
  require_relative "custom_matchers/impose_regulations"
9
+ require_relative "custom_matchers/revoke_action"
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ # RSpec matcher that tests revoking of statutes in laws.
4
+ #
5
+ # class ExampleStatute < ApplicationStatute
6
+ # end
7
+ #
8
+ # class CommonLaw < ApplicationStatute
9
+ # define_action :new, enforces: ExampleRegulation
10
+ # define_action :create, enforces: ExampleRegulation
11
+ # define_action :edit
12
+ # end
13
+ #
14
+ # class ExampleLaw < CommonLaw
15
+ # revoke_action :new, :edit
16
+ # end
17
+ #
18
+ # RSpec.describe ExampleLaw, type: :law do
19
+ # it { is_expected.to revoke_action :new, :edit }
20
+ # end
21
+
22
+ RSpec::Matchers.define :revoke_action do |*actions|
23
+ match do
24
+ actions.each { |action| expect(test_subject.revoked_action?(action)).to eq true }
25
+ end
26
+ description { "revoke #{"action".pluralize(actions.length)} #{actions.join(", ")}" }
27
+ failure_message { "expected #{test_subject} to revoke #{"action".pluralize(actions.length)} #{actions.join(", ")}" }
28
+ failure_message_when_negated do
29
+ "expected #{test_subject} not to revoke #{"action".pluralize(actions.length)} #{actions.join(", ")}"
30
+ end
31
+
32
+ def test_subject
33
+ subject.is_a?(Class) ? subject : subject.class
34
+ end
35
+ end
@@ -2,11 +2,13 @@
2
2
 
3
3
  require_relative "statutes/regulations"
4
4
  require_relative "statutes/laws"
5
+ require_relative "statutes/compliance"
5
6
 
6
7
  # A **Statute** restricts actions to **Actors** by enforcing a collection of **Permissions**.
7
8
  module Law
8
9
  class StatuteBase < Spicerack::RootObject
9
10
  include Law::Statutes::Regulations
10
11
  include Law::Statutes::Laws
12
+ include Law::Statutes::Compliance
11
13
  end
12
14
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A **Statute** is a collection of imposed **Regulations** with some **Compliance** rules.
4
+ module Law
5
+ module Statutes
6
+ module Compliance
7
+ extend ActiveSupport::Concern
8
+
9
+ class_methods do
10
+ def full_compliance_required?
11
+ @require_full_compliance.present?
12
+ end
13
+
14
+ def inherited(base)
15
+ base.require_full_compliance if full_compliance_required?
16
+ super
17
+ end
18
+
19
+ protected
20
+
21
+ def require_full_compliance
22
+ @require_full_compliance = true
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
data/lib/law/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Law
4
- VERSION = "0.1.3"
4
+ VERSION = "0.1.8"
5
5
  end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: law
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Garside
8
+ - Brandon Trumpold
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2020-03-04 00:00:00.000000000 Z
12
+ date: 2021-06-09 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: activesupport
@@ -16,21 +17,21 @@ dependencies:
16
17
  requirements:
17
18
  - - ">="
18
19
  - !ruby/object:Gem::Version
19
- version: 5.2.1
20
+ version: 6.0.3.7
20
21
  type: :runtime
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
25
  - - ">="
25
26
  - !ruby/object:Gem::Version
26
- version: 5.2.1
27
+ version: 6.0.3.7
27
28
  - !ruby/object:Gem::Dependency
28
29
  name: spicery
29
30
  requirement: !ruby/object:Gem::Requirement
30
31
  requirements:
31
32
  - - ">="
32
33
  - !ruby/object:Gem::Version
33
- version: 0.22.3.1
34
+ version: 0.26.0.4
34
35
  - - "<"
35
36
  - !ruby/object:Gem::Version
36
37
  version: '1.0'
@@ -40,7 +41,7 @@ dependencies:
40
41
  requirements:
41
42
  - - ">="
42
43
  - !ruby/object:Gem::Version
43
- version: 0.22.3.1
44
+ version: 0.26.0.4
44
45
  - - "<"
45
46
  - !ruby/object:Gem::Version
46
47
  version: '1.0'
@@ -134,7 +135,7 @@ dependencies:
134
135
  requirements:
135
136
  - - ">="
136
137
  - !ruby/object:Gem::Version
137
- version: 0.22.3.1
138
+ version: 0.26.0.4
138
139
  - - "<"
139
140
  - !ruby/object:Gem::Version
140
141
  version: '1.0'
@@ -144,7 +145,7 @@ dependencies:
144
145
  requirements:
145
146
  - - ">="
146
147
  - !ruby/object:Gem::Version
147
- version: 0.22.3.1
148
+ version: 0.26.0.4
148
149
  - - "<"
149
150
  - !ruby/object:Gem::Version
150
151
  version: '1.0'
@@ -154,7 +155,7 @@ dependencies:
154
155
  requirements:
155
156
  - - ">="
156
157
  - !ruby/object:Gem::Version
157
- version: 0.22.3.1
158
+ version: 0.26.0.4
158
159
  - - "<"
159
160
  - !ruby/object:Gem::Version
160
161
  version: '1.0'
@@ -164,7 +165,7 @@ dependencies:
164
165
  requirements:
165
166
  - - ">="
166
167
  - !ruby/object:Gem::Version
167
- version: 0.22.3.1
168
+ version: 0.26.0.4
168
169
  - - "<"
169
170
  - !ruby/object:Gem::Version
170
171
  version: '1.0'
@@ -172,12 +173,31 @@ description: Enforce the laws of your Rails application with highly extensible a
172
173
  policies
173
174
  email:
174
175
  - garside@gmail.com
176
+ - brandon.trumpold@gmail.com
175
177
  executables: []
176
178
  extensions: []
177
179
  extra_rdoc_files: []
178
180
  files:
179
181
  - LICENSE.txt
180
182
  - README.md
183
+ - lib/generators/law/USAGE
184
+ - lib/generators/law/law_generator.rb
185
+ - lib/generators/law/regulation/USAGE
186
+ - lib/generators/law/regulation/regulation_generator.rb
187
+ - lib/generators/law/regulation/templates/regulation.rb.erb
188
+ - lib/generators/law/statute/USAGE
189
+ - lib/generators/law/statute/statute_generator.rb
190
+ - lib/generators/law/statute/templates/statute.rb.erb
191
+ - lib/generators/law/templates/law.rb.erb
192
+ - lib/generators/rspec/law/USAGE
193
+ - lib/generators/rspec/law/law_generator.rb
194
+ - lib/generators/rspec/law/templates/law_spec.rb.erb
195
+ - lib/generators/rspec/regulation/USAGE
196
+ - lib/generators/rspec/regulation/regulation_generator.rb
197
+ - lib/generators/rspec/regulation/templates/regulation_spec.rb.erb
198
+ - lib/generators/rspec/statute/USAGE
199
+ - lib/generators/rspec/statute/statute_generator.rb
200
+ - lib/generators/rspec/statute/templates/statute_spec.rb.erb
181
201
  - lib/law.rb
182
202
  - lib/law/judgement.rb
183
203
  - lib/law/law_base.rb
@@ -198,9 +218,11 @@ files:
198
218
  - lib/law/rspec/custom_matchers/define_action.rb
199
219
  - lib/law/rspec/custom_matchers/have_default_statute.rb
200
220
  - lib/law/rspec/custom_matchers/impose_regulations.rb
221
+ - lib/law/rspec/custom_matchers/revoke_action.rb
201
222
  - lib/law/rspec/shoulda_matcher_helper.rb
202
223
  - lib/law/spec_helper.rb
203
224
  - lib/law/statute_base.rb
225
+ - lib/law/statutes/compliance.rb
204
226
  - lib/law/statutes/laws.rb
205
227
  - lib/law/statutes/regulations.rb
206
228
  - lib/law/version.rb
@@ -226,7 +248,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
226
248
  - !ruby/object:Gem::Version
227
249
  version: '0'
228
250
  requirements: []
229
- rubygems_version: 3.0.3
251
+ rubygems_version: 3.1.4
230
252
  signing_key:
231
253
  specification_version: 4
232
254
  summary: Give illegal operations a whole new meaning with this policy enforcement