foobara 0.4.1 → 0.4.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 +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +3 -1
- data/projects/command/src/command_pattern_implementation/concerns/transactions.rb +1 -0
- data/projects/command_connectors/Guardfile +1 -1
- data/projects/command_connectors/spec/auth_mappers_spec.rb +201 -0
- data/projects/command_connectors/spec/command_connector_spec.rb +2 -1
- data/projects/command_connectors/spec/pre_commit_transformers/load_atoms_pre_commit_transformer_spec.rb +5 -2
- data/projects/command_connectors/spec/request_spec.rb +23 -0
- data/projects/command_connectors/spec/spec_helper.rb +8 -3
- data/projects/command_connectors/src/authenticator.rb +27 -16
- data/projects/command_connectors/src/command_connector/request.rb +40 -5
- data/projects/command_connectors/src/command_connector.rb +98 -4
- data/projects/command_connectors/src/transformed_command.rb +12 -2
- data/projects/entities/spec/spec_helper.rb +4 -2
- data/projects/entities_plumbing/Guardfile +6 -0
- data/projects/entities_plumbing/lib/foobara/entities_plumbing.rb +12 -0
- data/projects/entities_plumbing/spec/auth_mappers_spec.rb +159 -0
- data/projects/entities_plumbing/spec/spec_helper.rb +54 -0
- data/projects/entities_plumbing/spec/support/rubyprof.rb +32 -0
- data/projects/entities_plumbing/spec/support/term_trap.rb +6 -0
- data/projects/entities_plumbing/src/command_connectors_extension.rb +17 -0
- data/projects/entities_plumbing/src/extensions/authenticator.rb +13 -0
- data/projects/manifest/spec/spec_helper.rb +6 -3
- data/projects/typesystem/projects/builtin_types/src/builtin_types.rb +6 -6
- data/projects/typesystem/projects/domain/src/domain.rb +0 -15
- data/projects/typesystem/projects/domain/src/domain_module_extension.rb +0 -153
- data/projects/typesystem/projects/domain/src/module_extension.rb +0 -58
- data/projects/typesystem/projects/namespace/src/is_namespace.rb +8 -0
- data/projects/typesystem/projects/type_declarations/lib/foobara/type_declarations.rb +0 -15
- data/projects/typesystem/projects/type_declarations/src/type_declaration.rb +15 -12
- data/projects/typesystem/projects/type_declarations/src/typed_transformer.rb +20 -2
- data/projects/typesystem/spec/common/data_path_spec.rb +6 -8
- data/projects/typesystem/spec/spec_helper.rb +5 -3
- data/version.rb +1 -1
- metadata +11 -2
- data/projects/entities/projects/model/src/extensions/domain/module_extension.rb +0 -20
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
guard :rspec, all_after_pass: false, all_on_start: true, cmd: "bundle exec rspec", failed_mode: :focus do
|
|
2
|
+
watch(%r{^spec/(.+)_spec\.rb$})
|
|
3
|
+
watch(%r{^src/(.+)\.rb$}) { "spec/" }
|
|
4
|
+
watch(%r{^lib/(.+)\.rb$}) { "spec/" }
|
|
5
|
+
watch(%r{^spec/spec_helper.rb$}) { "spec/" }
|
|
6
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require "foobara/command_connectors"
|
|
2
|
+
|
|
3
|
+
module Foobara
|
|
4
|
+
module EntitiesPlumbing
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
Foobara.project("entities_plumbing", project_path: "#{__dir__}/../..")
|
|
9
|
+
|
|
10
|
+
Foobara::CommandConnector.singleton_class.prepend(
|
|
11
|
+
Foobara::EntitiesPlumbing::CommandConnectorsExtension::ClassMethods
|
|
12
|
+
)
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
RSpec.describe Foobara::CommandConnector do
|
|
2
|
+
before do
|
|
3
|
+
Foobara::Persistence.default_crud_driver = Foobara::Persistence::CrudDrivers::InMemory.new
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
after do
|
|
7
|
+
Foobara.reset_alls
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
let(:command_class) do
|
|
11
|
+
stub_class(:ComputeExponent, Foobara::Command) do
|
|
12
|
+
inputs exponent: :integer, base: :integer
|
|
13
|
+
result :integer
|
|
14
|
+
|
|
15
|
+
def execute = base ** exponent
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
let(:command_connector) do
|
|
20
|
+
described_class.new(authenticator:, current_user: domain_user_class)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
let(:auth_user_class) do
|
|
24
|
+
stub_class "AuthUser", Foobara::Entity do
|
|
25
|
+
attributes id: :integer, name: :string
|
|
26
|
+
primary_key :id
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
let(:domain_user_class) do
|
|
30
|
+
auth_user_class
|
|
31
|
+
stub_class "User", Foobara::Entity do
|
|
32
|
+
attributes id: :integer, auth_user: AuthUser
|
|
33
|
+
primary_key :id
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
let(:auth_user) do
|
|
38
|
+
auth_user_class.transaction { AuthUser.create(name: "Fumiko") }
|
|
39
|
+
end
|
|
40
|
+
let(:domain_user) do
|
|
41
|
+
au = auth_user
|
|
42
|
+
domain_user_class.transaction do
|
|
43
|
+
User.create(auth_user: au)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
let(:authenticator) do
|
|
48
|
+
user = auth_user
|
|
49
|
+
Foobara::CommandConnector::Authenticator.subclass(to: AuthUser) { user }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
let(:base) { 2 }
|
|
53
|
+
let(:exponent) { 3 }
|
|
54
|
+
|
|
55
|
+
let(:response) { command_connector.run(full_command_name:, action:, inputs:) }
|
|
56
|
+
let(:errors_hash) { response.body.errors_hash }
|
|
57
|
+
|
|
58
|
+
let(:action) { "run" }
|
|
59
|
+
let(:full_command_name) { "ComputeExponent" }
|
|
60
|
+
let(:inputs) do
|
|
61
|
+
{ base:, exponent: }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
describe "#run_command" do
|
|
65
|
+
class << self
|
|
66
|
+
def with_current_user_allowed_rule
|
|
67
|
+
let(:allowed_rule) do
|
|
68
|
+
user = domain_user
|
|
69
|
+
-> { current_user == user }
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def with_current_user_not_allowed_rule
|
|
74
|
+
let(:allowed_rule) do
|
|
75
|
+
-> { current_user == "asfdasdf" }
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def with_authenticated_user_allowed_rule
|
|
80
|
+
let(:allowed_rule) do
|
|
81
|
+
user = auth_user
|
|
82
|
+
-> { authenticated_user == user }
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def with_authenticated_user_not_allowed_rule
|
|
87
|
+
let(:allowed_rule) do
|
|
88
|
+
-> { authenticated_user == "asfdasdf" }
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
shared_examples "a connector with auth mappers" do
|
|
94
|
+
before do
|
|
95
|
+
command_connector.connect(command_class, allowed_rule:)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
context "when using current_user in the allowed rule" do
|
|
99
|
+
context "when allowed" do
|
|
100
|
+
with_current_user_allowed_rule
|
|
101
|
+
|
|
102
|
+
it "runs the command" do
|
|
103
|
+
expect(response.status).to be(0)
|
|
104
|
+
expect(response.body).to eq(8)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
context "when not allowed" do
|
|
109
|
+
with_current_user_not_allowed_rule
|
|
110
|
+
|
|
111
|
+
it "fails with a relevant error" do
|
|
112
|
+
expect(response.status).to be(1)
|
|
113
|
+
expect(errors_hash.key?("runtime.not_allowed")).to be true
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
context "when calling current_user multiple times" do
|
|
118
|
+
let(:allowed_rule) do
|
|
119
|
+
user = domain_user
|
|
120
|
+
-> { current_user && current_user == user }
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "runs the command" do
|
|
124
|
+
expect(response.status).to be(0)
|
|
125
|
+
expect(response.body).to eq(8)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
context "when using authenticated_user in the allowed rule" do
|
|
131
|
+
context "when allowed" do
|
|
132
|
+
with_authenticated_user_allowed_rule
|
|
133
|
+
|
|
134
|
+
it "runs the command" do
|
|
135
|
+
expect(response.status).to be(0)
|
|
136
|
+
expect(response.body).to eq(8)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
context "when not allowed" do
|
|
141
|
+
with_authenticated_user_not_allowed_rule
|
|
142
|
+
|
|
143
|
+
it "fails with a relevant error" do
|
|
144
|
+
expect(response.status).to be(1)
|
|
145
|
+
expect(errors_hash.key?("runtime.not_allowed")).to be true
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
context "when auth user mapper is an entity class" do
|
|
152
|
+
before do
|
|
153
|
+
domain_user
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
it_behaves_like "a connector with auth mappers"
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
ENV["FOOBARA_ENV"] = "test"
|
|
2
|
+
|
|
3
|
+
require "bundler/setup"
|
|
4
|
+
|
|
5
|
+
if ENV["RUBY_DEBUG"] == "true"
|
|
6
|
+
require "debug"
|
|
7
|
+
elsif ENV["SKIP_PRY"] != "true" && ENV["CI"] != "true"
|
|
8
|
+
require "pry"
|
|
9
|
+
require "pry-byebug" unless ENV["SKIP_BYEBUG"] == "true"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
require "rspec/its"
|
|
13
|
+
require "simplecov"
|
|
14
|
+
|
|
15
|
+
SimpleCov.root "#{__dir__}/../../../"
|
|
16
|
+
SimpleCov.command_name "entities_plumbing"
|
|
17
|
+
SimpleCov.coverage_dir "coverage/entities_plumbing"
|
|
18
|
+
|
|
19
|
+
SimpleCov.start do
|
|
20
|
+
add_filter "spec/support/"
|
|
21
|
+
# This avoids printing out info about coverage generated by HTTPFormatter
|
|
22
|
+
formatter Class.new { def format(_result) = nil }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
require "foobara/all"
|
|
26
|
+
require "foobara/entities_plumbing"
|
|
27
|
+
|
|
28
|
+
RSpec.configure do |config|
|
|
29
|
+
# Need to do :all instead of :each because for specs that use .around,
|
|
30
|
+
# .after(:each) do |example| here is called after example.run but before any threads created in
|
|
31
|
+
# .around might have been cleaned up.
|
|
32
|
+
config.after(:suite) do
|
|
33
|
+
threads = Thread.list.reject { |t| t.name == "DEBUGGER__::SESSION@server" }
|
|
34
|
+
expect(threads.size).to eq(1)
|
|
35
|
+
end
|
|
36
|
+
config.filter_run_when_matching :focus
|
|
37
|
+
|
|
38
|
+
# Enable flags like --only-failures and --next-failure
|
|
39
|
+
config.example_status_persistence_file_path = ".rspec_status"
|
|
40
|
+
|
|
41
|
+
# Disable RSpec exposing methods globally on `Module` and `main`
|
|
42
|
+
config.disable_monkey_patching!
|
|
43
|
+
|
|
44
|
+
config.order = :defined
|
|
45
|
+
|
|
46
|
+
config.expect_with :rspec do |c|
|
|
47
|
+
c.syntax = :expect
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# config.raise_errors_for_deprecations!
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
require "foobara/spec_helpers/all"
|
|
54
|
+
Dir["#{__dir__}/support/**/*.rb"].each { |f| require f }
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
RSpec.configure do |config|
|
|
2
|
+
# TODO: move this to foobara-spec-helpers project
|
|
3
|
+
config.around(:each, :profile) do |example|
|
|
4
|
+
require "ruby-prof"
|
|
5
|
+
RubyProf.start
|
|
6
|
+
|
|
7
|
+
example.run
|
|
8
|
+
|
|
9
|
+
result = RubyProf.stop
|
|
10
|
+
printer = RubyProf::GraphHtmlPrinter.new(result)
|
|
11
|
+
File.open("tmp/profile-out.html", "w+") do |file|
|
|
12
|
+
printer.print(file)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
if ENV["RUBY_PROF"] == "true"
|
|
17
|
+
config.before(:suite) do
|
|
18
|
+
require "ruby-prof"
|
|
19
|
+
require "ruby-prof/profile"
|
|
20
|
+
RubyProf.start
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
config.after(:suite) do
|
|
24
|
+
result = RubyProf.stop
|
|
25
|
+
|
|
26
|
+
printer = RubyProf::GraphHtmlPrinter.new(result)
|
|
27
|
+
File.open("tmp/profile-out.html", "w+") do |file|
|
|
28
|
+
printer.print(file)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Foobara
|
|
2
|
+
module EntitiesPlumbing
|
|
3
|
+
module CommandConnectorsExtension
|
|
4
|
+
module ClassMethods
|
|
5
|
+
def to_auth_user_mapper(object)
|
|
6
|
+
if object.is_a?(::Class) && object < Foobara::Entity
|
|
7
|
+
TypeDeclarations::TypedTransformer.subclass(to: object) do |authenticated_user|
|
|
8
|
+
object.that_owns(authenticated_user)
|
|
9
|
+
end.instance
|
|
10
|
+
else
|
|
11
|
+
super
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Foobara
|
|
2
|
+
class CommandConnector
|
|
3
|
+
class Authenticator
|
|
4
|
+
def relevant_entity_classes(_request)
|
|
5
|
+
if to_type&.extends?(BuiltinTypes[:entity])
|
|
6
|
+
NestedTransactionable.relevant_entity_classes_for_type(to_type)
|
|
7
|
+
else
|
|
8
|
+
EMPTY_ARRAY
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -2,9 +2,11 @@ ENV["FOOBARA_ENV"] = "test"
|
|
|
2
2
|
|
|
3
3
|
require "bundler/setup"
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
if ENV["RUBY_DEBUG"] == "true"
|
|
6
|
+
require "debug"
|
|
7
|
+
elsif ENV["SKIP_PRY"] != "true" && ENV["CI"] != "true"
|
|
6
8
|
require "pry"
|
|
7
|
-
require "pry-byebug"
|
|
9
|
+
require "pry-byebug" unless ENV["SKIP_BYEBUG"] == "true"
|
|
8
10
|
end
|
|
9
11
|
|
|
10
12
|
require "rspec/its"
|
|
@@ -27,7 +29,8 @@ RSpec.configure do |config|
|
|
|
27
29
|
# .after(:each) do |example| here is called after example.run but before any threads created in
|
|
28
30
|
# .around might have been cleaned up.
|
|
29
31
|
config.after(:suite) do
|
|
30
|
-
|
|
32
|
+
threads = Thread.list.reject { |t| t.name == "DEBUGGER__::SESSION@server" }
|
|
33
|
+
expect(threads.size).to eq(1)
|
|
31
34
|
end
|
|
32
35
|
config.filter_run_when_matching :focus
|
|
33
36
|
|
|
@@ -154,12 +154,6 @@ module Foobara
|
|
|
154
154
|
type
|
|
155
155
|
end
|
|
156
156
|
|
|
157
|
-
private
|
|
158
|
-
|
|
159
|
-
def global_type_declaration_handler_registry
|
|
160
|
-
TypeDeclarations.global_type_declaration_handler_registry
|
|
161
|
-
end
|
|
162
|
-
|
|
163
157
|
def install_type_declaration_extensions_for(processor_class)
|
|
164
158
|
extension_module = Util.constant_value(processor_class, :TypeDeclarationExtension)
|
|
165
159
|
|
|
@@ -210,6 +204,12 @@ module Foobara
|
|
|
210
204
|
end
|
|
211
205
|
end
|
|
212
206
|
end
|
|
207
|
+
|
|
208
|
+
private
|
|
209
|
+
|
|
210
|
+
def global_type_declaration_handler_registry
|
|
211
|
+
TypeDeclarations.global_type_declaration_handler_registry
|
|
212
|
+
end
|
|
213
213
|
end
|
|
214
214
|
end
|
|
215
215
|
end
|
|
@@ -91,21 +91,6 @@ module Foobara
|
|
|
91
91
|
new_class.const_set(const_name, value)
|
|
92
92
|
end
|
|
93
93
|
end
|
|
94
|
-
|
|
95
|
-
lower_case_constants = old_mod.instance_variable_get(:@foobara_lowercase_constants)
|
|
96
|
-
|
|
97
|
-
if lower_case_constants && !lower_case_constants.empty?
|
|
98
|
-
lower_case_constants&.each do |lower_case_constant|
|
|
99
|
-
new_class.singleton_class.define_method lower_case_constant do
|
|
100
|
-
old_mod.send(lower_case_constant)
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
new_lowercase_constants = new_class.instance_variable_get(:@foobara_lowercase_constants) || []
|
|
105
|
-
new_lowercase_constants += lower_case_constants
|
|
106
|
-
|
|
107
|
-
new_class.instance_variable_set(:@foobara_lowercase_constants, new_lowercase_constants)
|
|
108
|
-
end
|
|
109
94
|
end
|
|
110
95
|
end
|
|
111
96
|
end
|
|
@@ -17,80 +17,6 @@ module Foobara
|
|
|
17
17
|
module ClassMethods
|
|
18
18
|
attr_writer :foobara_domain_name, :foobara_full_domain_name
|
|
19
19
|
|
|
20
|
-
def foobara_unregister(scoped)
|
|
21
|
-
scoped = to_scoped(scoped)
|
|
22
|
-
|
|
23
|
-
if scoped.is_a?(Foobara::Types::Type)
|
|
24
|
-
parent_mod = nil
|
|
25
|
-
|
|
26
|
-
if const_defined?(:Types, false)
|
|
27
|
-
parent_path = ["Foobara::GlobalDomain"]
|
|
28
|
-
unless scoped.type_symbol.to_s.start_with?("Types::")
|
|
29
|
-
parent_path << "Types"
|
|
30
|
-
end
|
|
31
|
-
parent_path += scoped.type_symbol.to_s.split("::")[..-2]
|
|
32
|
-
|
|
33
|
-
parent_name = parent_path.join("::")
|
|
34
|
-
child_name = [*parent_path, scoped.type_symbol.to_s.split("::").last].join("::")
|
|
35
|
-
removed = false
|
|
36
|
-
|
|
37
|
-
if Object.const_defined?(parent_name)
|
|
38
|
-
parent_mod = Object.const_get(parent_name)
|
|
39
|
-
|
|
40
|
-
if scoped.scoped_short_name =~ /^[a-z]/
|
|
41
|
-
lower_case_constants = parent_mod.instance_variable_get(:@foobara_lowercase_constants)
|
|
42
|
-
|
|
43
|
-
if lower_case_constants&.include?(scoped.scoped_short_name)
|
|
44
|
-
parent_mod.singleton_class.undef_method scoped.scoped_short_name
|
|
45
|
-
lower_case_constants.delete(scoped.scoped_short_name)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
removed = true
|
|
49
|
-
elsif parent_mod.const_defined?(scoped.scoped_short_name, false)
|
|
50
|
-
parent_mod.send(:remove_const, scoped.scoped_short_name)
|
|
51
|
-
removed = true
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
if removed
|
|
56
|
-
child_name = parent_name
|
|
57
|
-
|
|
58
|
-
while child_name
|
|
59
|
-
child = Object.const_get(child_name)
|
|
60
|
-
|
|
61
|
-
break if child.foobara_domain?
|
|
62
|
-
break if child.foobara_organization?
|
|
63
|
-
|
|
64
|
-
# TODO: unclear why we need this check, hmmm, figure it out and document it (or delete if not needed)
|
|
65
|
-
break if child.constants(false).any? do |constant|
|
|
66
|
-
# TODO: a clue: this stopped being entered by the test suite after deleting GlobalDomain::Types
|
|
67
|
-
# in .reset_alls hmmmmmm...
|
|
68
|
-
# :nocov:
|
|
69
|
-
value = child.const_get(constant)
|
|
70
|
-
value.is_a?(Types::Type) || (value.is_a?(::Class) && value.respond_to?(:foobara_type?))
|
|
71
|
-
# :nocov:
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
lower_case_constants = child.instance_variable_get(:@foobara_lowercase_constants)
|
|
75
|
-
break if lower_case_constants && !lower_case_constants.empty?
|
|
76
|
-
|
|
77
|
-
parent_name = Util.parent_module_name_for(child_name)
|
|
78
|
-
break unless Object.const_defined?(parent_name)
|
|
79
|
-
|
|
80
|
-
parent = Object.const_get(parent_name)
|
|
81
|
-
|
|
82
|
-
child_sym = Util.non_full_name(child).to_sym
|
|
83
|
-
parent.send(:remove_const, child_sym)
|
|
84
|
-
|
|
85
|
-
child_name = parent_name
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
super
|
|
92
|
-
end
|
|
93
|
-
|
|
94
20
|
def foobara_domain_map(*args, to: nil, strict: false, criteria: nil, should_raise: false, **opts)
|
|
95
21
|
case args.size
|
|
96
22
|
when 1
|
|
@@ -261,8 +187,6 @@ module Foobara
|
|
|
261
187
|
foobara_register(type)
|
|
262
188
|
end
|
|
263
189
|
|
|
264
|
-
_set_type_constant(type)
|
|
265
|
-
|
|
266
190
|
type
|
|
267
191
|
end
|
|
268
192
|
|
|
@@ -325,83 +249,6 @@ module Foobara
|
|
|
325
249
|
|
|
326
250
|
manifest
|
|
327
251
|
end
|
|
328
|
-
|
|
329
|
-
private
|
|
330
|
-
|
|
331
|
-
def _set_type_constant(type)
|
|
332
|
-
domain = if scoped_full_path.empty?
|
|
333
|
-
GlobalDomain
|
|
334
|
-
else
|
|
335
|
-
self
|
|
336
|
-
end
|
|
337
|
-
|
|
338
|
-
path = type.scoped_path
|
|
339
|
-
if path.first == "Types"
|
|
340
|
-
path = path[1..]
|
|
341
|
-
end
|
|
342
|
-
|
|
343
|
-
types_mod = if domain.const_defined?(:Types)
|
|
344
|
-
domain.const_get(:Types)
|
|
345
|
-
else
|
|
346
|
-
domain.const_set(:Types, Module.new)
|
|
347
|
-
end
|
|
348
|
-
|
|
349
|
-
if type.scoped_prefix
|
|
350
|
-
const_name = [types_mod.name, *path[0..-2]].join("::")
|
|
351
|
-
types_mod = Util.make_module_p(const_name, tag: true)
|
|
352
|
-
end
|
|
353
|
-
|
|
354
|
-
# TODO: dry this up
|
|
355
|
-
if type.scoped_short_name =~ /\A[a-z]/
|
|
356
|
-
unless types_mod.respond_to?(type.scoped_short_name)
|
|
357
|
-
types_mod.singleton_class.define_method type.scoped_short_name do
|
|
358
|
-
type
|
|
359
|
-
end
|
|
360
|
-
|
|
361
|
-
unless types_mod.instance_variable_defined?(:@foobara_lowercase_constants)
|
|
362
|
-
types_mod.instance_variable_set(:@foobara_lowercase_constants, [])
|
|
363
|
-
end
|
|
364
|
-
|
|
365
|
-
types_mod.instance_variable_get(:@foobara_lowercase_constants) << type.scoped_short_name
|
|
366
|
-
end
|
|
367
|
-
elsif types_mod.const_defined?(type.scoped_short_name, false)
|
|
368
|
-
existing_value = types_mod.const_get(type.scoped_short_name)
|
|
369
|
-
existing_value_type = if existing_value.is_a?(::Class) && existing_value < Foobara::Model
|
|
370
|
-
# TODO: test this code path
|
|
371
|
-
# :nocov:
|
|
372
|
-
existing_value.model_type
|
|
373
|
-
# :nocov:
|
|
374
|
-
else
|
|
375
|
-
existing_value
|
|
376
|
-
end
|
|
377
|
-
|
|
378
|
-
if existing_value_type != type
|
|
379
|
-
if existing_value.is_a?(::Module) && !existing_value.is_a?(::Class) &&
|
|
380
|
-
existing_value.instance_variable_get(:@foobara_created_via_make_class) &&
|
|
381
|
-
# not allowing lower-case "constants" to be namespaces
|
|
382
|
-
type.extends?("::model")
|
|
383
|
-
|
|
384
|
-
types_mod.send(:remove_const, type.scoped_short_name)
|
|
385
|
-
types_mod.const_set(type.scoped_short_name, type.target_class)
|
|
386
|
-
|
|
387
|
-
Domain.copy_constants(existing_value, type.target_class)
|
|
388
|
-
else
|
|
389
|
-
# :nocov:
|
|
390
|
-
raise CannotSetTypeConstantError,
|
|
391
|
-
"Already defined constant #{types_mod.name}::#{type.scoped_short_name}"
|
|
392
|
-
# :nocov:
|
|
393
|
-
end
|
|
394
|
-
end
|
|
395
|
-
else
|
|
396
|
-
symbol = type.scoped_short_name
|
|
397
|
-
|
|
398
|
-
if type.extends?("::model")
|
|
399
|
-
type = type.target_class
|
|
400
|
-
end
|
|
401
|
-
|
|
402
|
-
types_mod.const_set(symbol, type)
|
|
403
|
-
end
|
|
404
|
-
end
|
|
405
252
|
end
|
|
406
253
|
end
|
|
407
254
|
end
|
|
@@ -26,54 +26,6 @@ module Foobara
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
include(DomainModuleExtension)
|
|
29
|
-
|
|
30
|
-
children = foobara_children
|
|
31
|
-
children = children.sort_by { |child| child.scoped_path.size }
|
|
32
|
-
|
|
33
|
-
# see if we are upgrading from prefix to domain and copy over types to Types module
|
|
34
|
-
children.each do |child|
|
|
35
|
-
next unless child.is_a?(Types::Type)
|
|
36
|
-
|
|
37
|
-
types_mod_path = scoped_full_path.dup
|
|
38
|
-
unless child.scoped_path.first == "Types"
|
|
39
|
-
types_mod_path << "Types"
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
types_mod_path += child.scoped_path[..-2]
|
|
43
|
-
types_mod = Util.make_module_p(types_mod_path.join("::"))
|
|
44
|
-
|
|
45
|
-
# TODO: dry this up
|
|
46
|
-
# TODO: this doesn't handle a type nested under a lower-case type for now
|
|
47
|
-
if child.scoped_short_name =~ /^[a-z]/
|
|
48
|
-
unless types_mod.respond_to?(child.scoped_short_name)
|
|
49
|
-
types_mod.singleton_class.define_method child.scoped_short_name do
|
|
50
|
-
child
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
unless types_mod.instance_variable_defined?(:@foobara_lowercase_constants)
|
|
54
|
-
# TODO: test this path or delete it if unreachable
|
|
55
|
-
# :nocov:
|
|
56
|
-
types_mod.instance_variable_set(:@foobara_lowercase_constants, [])
|
|
57
|
-
# :nocov:
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
types_mod.instance_variable_get(:@foobara_lowercase_constants) << child.scoped_short_name
|
|
61
|
-
end
|
|
62
|
-
else
|
|
63
|
-
value = if types_mod.const_defined?(child.scoped_short_name, false)
|
|
64
|
-
# TODO: test this path or delete it if unreachable
|
|
65
|
-
# :nocov:
|
|
66
|
-
types_mod.const_get(child.scoped_short_name, false)
|
|
67
|
-
# :nocov:
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
if value != child
|
|
71
|
-
types_mod.send(:remove_const, child.scoped_short_name) if value
|
|
72
|
-
|
|
73
|
-
foobara_set_types_mod_constant(types_mod, child.scoped_short_name, child)
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
29
|
end
|
|
78
30
|
|
|
79
31
|
def foobara_organization!
|
|
@@ -101,16 +53,6 @@ module Foobara
|
|
|
101
53
|
def foobara_organization?
|
|
102
54
|
false
|
|
103
55
|
end
|
|
104
|
-
|
|
105
|
-
private
|
|
106
|
-
|
|
107
|
-
# Unclear if we actually need this but putting it here to allow entities project
|
|
108
|
-
# to override this to set the constant to the target class
|
|
109
|
-
def foobara_set_types_mod_constant(types_mod, name, value)
|
|
110
|
-
# :nocov:
|
|
111
|
-
types_mod.const_set(types_mod, name, value)
|
|
112
|
-
# :nocov:
|
|
113
|
-
end
|
|
114
56
|
end
|
|
115
57
|
end
|
|
116
58
|
end
|
|
@@ -156,6 +156,7 @@ module Foobara
|
|
|
156
156
|
|
|
157
157
|
def foobara_lookup(path, filter: nil, mode: LookupMode::GENERAL)
|
|
158
158
|
LookupMode.validate!(mode)
|
|
159
|
+
|
|
159
160
|
path = Namespace.to_registry_path(path)
|
|
160
161
|
|
|
161
162
|
lru_cache.cached([self, path, mode, *filter]) do
|
|
@@ -189,6 +190,13 @@ module Foobara
|
|
|
189
190
|
scoped = candidates.first ||
|
|
190
191
|
foobara_parent_namespace&.foobara_lookup_without_cache(path, filter:, mode:, visited:)
|
|
191
192
|
|
|
193
|
+
scoped ||= foobara_lookup_without_cache(
|
|
194
|
+
[*scoped_full_path, *path],
|
|
195
|
+
filter:,
|
|
196
|
+
mode: LookupMode::GENERAL,
|
|
197
|
+
visited:
|
|
198
|
+
)
|
|
199
|
+
|
|
192
200
|
return scoped
|
|
193
201
|
end
|
|
194
202
|
|
|
@@ -35,14 +35,6 @@ module Foobara
|
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
if GlobalDomain.const_defined?(:Types, false)
|
|
39
|
-
GlobalDomain::Types.instance_variable_set(
|
|
40
|
-
:@foobara_lowercase_constants,
|
|
41
|
-
@original_foobara_lowercase_constants || []
|
|
42
|
-
)
|
|
43
|
-
GlobalDomain.send(:remove_const, :Types)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
38
|
@original_scoped.each do |scoped|
|
|
47
39
|
Namespace.global.foobara_register(scoped)
|
|
48
40
|
end
|
|
@@ -126,13 +118,6 @@ module Foobara
|
|
|
126
118
|
# most important
|
|
127
119
|
@original_scoped = Namespace.global.foobara_registry.all_scoped.dup
|
|
128
120
|
@original_children = Namespace.global.foobara_children.dup
|
|
129
|
-
|
|
130
|
-
if GlobalDomain.const_defined?(:Types, false)
|
|
131
|
-
# :nocov:
|
|
132
|
-
@original_foobara_lowercase_constants =
|
|
133
|
-
GlobalDomain::Types.instance_variable_get(:@foobara_lowercase_constants).dup
|
|
134
|
-
# :nocov:
|
|
135
|
-
end
|
|
136
121
|
end
|
|
137
122
|
end
|
|
138
123
|
end
|