shaf 2.1.0 → 3.0.1
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
- checksums.yaml.gz.sig +0 -0
- data/lib/shaf/app.rb +27 -9
- data/lib/shaf/command/base.rb +4 -0
- data/lib/shaf/command/new.rb +5 -1
- data/lib/shaf/command/server.rb +5 -1
- data/lib/shaf/command/templates/config/settings.yml.erb +9 -8
- data/lib/shaf/extensions/resource_uris.rb +37 -155
- data/lib/shaf/extensions/symbolic_routes.rb +5 -18
- data/lib/shaf/formable/builder.rb +58 -19
- data/lib/shaf/formable/form.rb +13 -10
- data/lib/shaf/formable.rb +10 -23
- data/lib/shaf/generator/base.rb +82 -0
- data/lib/shaf/generator/controller.rb +19 -35
- data/lib/shaf/generator/forms.rb +10 -14
- data/lib/shaf/generator/migration/add_column.rb +0 -4
- data/lib/shaf/generator/migration/add_index.rb +0 -4
- data/lib/shaf/generator/migration/base.rb +8 -0
- data/lib/shaf/generator/migration/create_table.rb +0 -4
- data/lib/shaf/generator/migration/drop_column.rb +0 -4
- data/lib/shaf/generator/migration/rename_column.rb +0 -4
- data/lib/shaf/generator/model.rb +29 -14
- data/lib/shaf/generator/policy.rb +8 -14
- data/lib/shaf/generator/profile.rb +9 -14
- data/lib/shaf/generator/scaffold.rb +6 -9
- data/lib/shaf/generator/serializer.rb +31 -30
- data/lib/shaf/generator/templates/api/controller.rb.erb +13 -13
- data/lib/shaf/generator/templates/api/forms.rb.erb +2 -2
- data/lib/shaf/generator/templates/api/model.rb.erb +1 -1
- data/lib/shaf/generator/templates/api/profile.rb.erb +1 -1
- data/lib/shaf/generator/templates/api/serializer.rb.erb +1 -1
- data/lib/shaf/generator/templates/spec/integration_spec.rb.erb +14 -14
- data/lib/shaf/helpers/paginate.rb +1 -1
- data/lib/shaf/link_relations.rb +77 -0
- data/lib/shaf/profile.rb +8 -8
- data/lib/shaf/registrable_factory.rb +62 -32
- data/lib/shaf/responder/problem_json.rb +1 -1
- data/lib/shaf/router.rb +65 -12
- data/lib/shaf/spec/integration_spec.rb +1 -1
- data/lib/shaf/tasks.rb +0 -1
- data/lib/shaf/upgrade/package.rb +5 -7
- data/lib/shaf/utils.rb +2 -2
- data/lib/shaf/version.rb +1 -1
- data/lib/shaf/yard/link_object.rb +2 -3
- data/templates/Rakefile +0 -6
- data/templates/api/controllers/base_controller.rb +0 -2
- data/templates/api/serializers/root_serializer.rb +0 -11
- data/templates/config/initializers/middleware.rb +6 -0
- data/templates/spec/spec_helper.rb +4 -1
- data/upgrades/3.0.0.tar.gz +0 -0
- data/yard_templates/api_doc/profile_attribute/html/attribute.erb +2 -1
- data/yard_templates/api_doc/resource_attribute/html/attribute.erb +2 -1
- data/yard_templates/api_doc/sidebar/html/profile_list.erb +2 -1
- data/yard_templates/api_doc/sidebar/html/serializer_list.erb +2 -1
- data.tar.gz.sig +0 -0
- metadata +34 -36
- metadata.gz.sig +0 -0
- data/lib/shaf/api_doc/comment.rb +0 -27
- data/lib/shaf/api_doc/document.rb +0 -137
- data/lib/shaf/api_doc/link_relations.rb +0 -77
- data/lib/shaf/middleware.rb +0 -1
- data/lib/shaf/tasks/api_doc_task.rb +0 -146
@@ -11,19 +11,8 @@ module Shaf
|
|
11
11
|
create_profile
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
|
16
|
-
return n unless n.empty?
|
17
|
-
raise Command::ArgumentError,
|
18
|
-
"Please provide a model name when using the serializer generator!"
|
19
|
-
end
|
20
|
-
|
21
|
-
def plural_name
|
22
|
-
Utils.pluralize(name)
|
23
|
-
end
|
24
|
-
|
25
|
-
def model_class_name
|
26
|
-
Utils.model_name(name)
|
14
|
+
def serializer_class_name
|
15
|
+
"#{model_class_name}Serializer"
|
27
16
|
end
|
28
17
|
|
29
18
|
def policy_class_name
|
@@ -38,21 +27,31 @@ module Shaf
|
|
38
27
|
'spec/serializer_spec.rb'
|
39
28
|
end
|
40
29
|
|
41
|
-
def
|
42
|
-
|
30
|
+
def target_dir
|
31
|
+
'api/serializers'
|
32
|
+
end
|
33
|
+
|
34
|
+
def target_name
|
35
|
+
"#{name}_serializer.rb"
|
43
36
|
end
|
44
37
|
|
45
38
|
def spec_target
|
46
|
-
|
39
|
+
target(directory: 'spec/serializers', name: "#{name}_serializer_spec.rb")
|
40
|
+
end
|
41
|
+
|
42
|
+
def policy_file
|
43
|
+
File.join(['policies', namespace, "#{name}_policy"].compact)
|
47
44
|
end
|
48
45
|
|
49
46
|
def create_serializer
|
50
47
|
content = render(template, opts)
|
48
|
+
content = wrap_in_module(content, module_name)
|
51
49
|
write_output(target, content)
|
52
50
|
end
|
53
51
|
|
54
52
|
def create_serializer_spec
|
55
53
|
content = render(spec_template, opts)
|
54
|
+
content = wrap_in_module(content, module_name, search: "describe #{serializer_class_name}")
|
56
55
|
write_output(spec_target, content)
|
57
56
|
end
|
58
57
|
|
@@ -74,16 +73,16 @@ module Shaf
|
|
74
73
|
|
75
74
|
def profile_with_doc
|
76
75
|
doc = <<~DOC
|
77
|
-
# Adds a link to the '#{
|
76
|
+
# Adds a link to the '#{resource_name}' profile and a curie. By default the
|
78
77
|
# curie prefix is 'doc', use the `curie_prefix` keyword argument to
|
79
78
|
# change this.
|
80
79
|
# Note: the target of the profile link and the curie will be set to
|
81
|
-
# `profile_uri('#{
|
80
|
+
# `profile_uri('#{resource_name}')` resp. `doc_curie_uri('#{resource_name}')`. To
|
82
81
|
# create links for external profiles or curies, delete the next line
|
83
82
|
# and use `::link` and/or `::curie` instead.
|
84
83
|
DOC
|
85
84
|
|
86
|
-
doc.split("\n") << %Q(profile #{Utils.symbol_string(
|
85
|
+
doc.split("\n") << %Q(profile #{Utils.symbol_string(resource_name)})
|
87
86
|
end
|
88
87
|
|
89
88
|
def links_with_doc
|
@@ -98,7 +97,7 @@ module Shaf
|
|
98
97
|
def collection_link
|
99
98
|
link(
|
100
99
|
rel: "collection",
|
101
|
-
uri_helper: "#{
|
100
|
+
uri_helper: "#{collection_name}_uri",
|
102
101
|
kwargs: {embed_depth: 0}
|
103
102
|
)
|
104
103
|
end
|
@@ -106,21 +105,21 @@ module Shaf
|
|
106
105
|
def self_link
|
107
106
|
link(
|
108
107
|
rel: "self",
|
109
|
-
uri_helper: "#{
|
108
|
+
uri_helper: "#{resource_name}_uri(resource)"
|
110
109
|
)
|
111
110
|
end
|
112
111
|
|
113
112
|
def edit_link
|
114
113
|
link(
|
115
114
|
rel: "edit-form",
|
116
|
-
uri_helper: "edit_#{
|
115
|
+
uri_helper: "edit_#{resource_name}_uri(resource)"
|
117
116
|
)
|
118
117
|
end
|
119
118
|
|
120
119
|
def delete_link
|
121
120
|
link(
|
122
121
|
rel: "delete",
|
123
|
-
uri_helper: "#{
|
122
|
+
uri_helper: "#{resource_name}_uri(resource)",
|
124
123
|
kwargs: {curie: :doc}
|
125
124
|
)
|
126
125
|
end
|
@@ -128,7 +127,7 @@ module Shaf
|
|
128
127
|
def create_link
|
129
128
|
link(
|
130
129
|
rel: "create-form",
|
131
|
-
uri_helper: "new_#{
|
130
|
+
uri_helper: "new_#{resource_name}_uri"
|
132
131
|
)
|
133
132
|
end
|
134
133
|
|
@@ -147,9 +146,9 @@ module Shaf
|
|
147
146
|
def collection_with_doc
|
148
147
|
<<~EOS.split("\n")
|
149
148
|
collection of: '#{plural_name}' do
|
150
|
-
curie(:doc) { doc_curie_uri('#{
|
149
|
+
curie(:doc) { doc_curie_uri('#{resource_name}') }
|
151
150
|
|
152
|
-
link :self, #{
|
151
|
+
link :self, #{collection_name}_uri
|
153
152
|
link :up, root_uri
|
154
153
|
|
155
154
|
#{create_link.join("\n ")}
|
@@ -160,10 +159,12 @@ module Shaf
|
|
160
159
|
def opts
|
161
160
|
{
|
162
161
|
name: name,
|
163
|
-
|
162
|
+
resource_name: resource_name,
|
163
|
+
collection_name: collection_name,
|
164
|
+
class_name: serializer_class_name,
|
164
165
|
model_class_name: model_class_name,
|
165
166
|
policy_class_name: policy_class_name,
|
166
|
-
|
167
|
+
policy_file: policy_file,
|
167
168
|
attribute_names: attribute_names,
|
168
169
|
link_relations: link_relations,
|
169
170
|
profile_with_doc: profile_with_doc,
|
@@ -174,12 +175,12 @@ module Shaf
|
|
174
175
|
end
|
175
176
|
|
176
177
|
def create_policy
|
177
|
-
policy_args = ["policy",
|
178
|
+
policy_args = ["policy", name_arg, *attribute_names]
|
178
179
|
Generator::Factory.create(*policy_args, **options).call
|
179
180
|
end
|
180
181
|
|
181
182
|
def create_profile
|
182
|
-
profile_args = ["profile",
|
183
|
+
profile_args = ["profile", name_arg, *attributes]
|
183
184
|
Generator::Factory.create(*profile_args, **options).call
|
184
185
|
end
|
185
186
|
end
|
@@ -4,45 +4,45 @@ class <%= controller_class_name %> < BaseController
|
|
4
4
|
|
5
5
|
authorize_with <%= policy_class_name %>
|
6
6
|
|
7
|
-
resource_uris_for :<%= name %>
|
7
|
+
resource_uris_for :<%= name %><%= namespace ? ", namespace: '#{namespace}'" : "" %>
|
8
8
|
|
9
|
-
get :<%=
|
9
|
+
get :<%= collection_name %>_path do
|
10
10
|
authorize! :read
|
11
11
|
collection = paginate(<%= model_class_name %>.order(:created_at).reverse)
|
12
12
|
respond_with_collection collection, serializer: <%= serializer_class_name %>
|
13
13
|
end
|
14
14
|
|
15
|
-
get :new_<%=
|
15
|
+
get :new_<%= resource_name %>_path do
|
16
16
|
authorize! :read
|
17
17
|
cache_control(:private, http_cache_max_age: :short)
|
18
18
|
respond_with create_form
|
19
19
|
end
|
20
20
|
|
21
|
-
post :<%=
|
21
|
+
post :<%= collection_name %>_path do
|
22
22
|
authorize! :write
|
23
23
|
<%= name %> = <%= model_class_name %>.create(<%= name %>_params)
|
24
|
-
headers('Location' => <%=
|
24
|
+
headers('Location' => <%= resource_name %>_uri(<%= name %>))
|
25
25
|
respond_with <%= name %>, status: 201
|
26
26
|
end
|
27
27
|
|
28
|
-
get :<%=
|
28
|
+
get :<%= resource_name %>_path do
|
29
29
|
authorize! :read
|
30
30
|
respond_with <%= name %>
|
31
31
|
end
|
32
32
|
|
33
|
-
get :edit_<%=
|
33
|
+
get :edit_<%= resource_name %>_path do
|
34
34
|
authorize! :write
|
35
35
|
cache_control(:private, http_cache_max_age: :short)
|
36
36
|
respond_with edit_form
|
37
37
|
end
|
38
38
|
|
39
|
-
put :<%=
|
39
|
+
put :<%= resource_name %>_path do
|
40
40
|
authorize! :write
|
41
41
|
<%= name %>.update(<%= name %>_params)
|
42
42
|
respond_with <%= name %>
|
43
43
|
end
|
44
44
|
|
45
|
-
delete :<%=
|
45
|
+
delete :<%= resource_name %>_path do
|
46
46
|
authorize! :write
|
47
47
|
<%= name %>.destroy
|
48
48
|
status 204
|
@@ -62,15 +62,15 @@ class <%= controller_class_name %> < BaseController
|
|
62
62
|
|
63
63
|
def create_form
|
64
64
|
<%= model_class_name %>.create_form.tap do |form|
|
65
|
-
form.self_link = new_<%=
|
66
|
-
form.href = <%=
|
65
|
+
form.self_link = new_<%= resource_name %>_uri
|
66
|
+
form.href = <%= collection_name %>_uri
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
70
|
def edit_form
|
71
71
|
<%= name %>.edit_form.tap do |form|
|
72
|
-
form.self_link = edit_<%=
|
73
|
-
form.href = <%=
|
72
|
+
form.self_link = edit_<%= resource_name %>_uri(<%= name %>)
|
73
|
+
form.href = <%= resource_name %>_uri(<%= name %>)
|
74
74
|
end
|
75
75
|
end
|
76
76
|
end
|
@@ -4,12 +4,12 @@ class <%= class_name %>
|
|
4
4
|
forms_for(<%= model_class_name %>) do
|
5
5
|
<%= fields.join("\n ") %>
|
6
6
|
|
7
|
-
|
7
|
+
create_form do
|
8
8
|
title 'Create <%= model_class_name %>'
|
9
9
|
name 'create-<%= model_name %>'
|
10
10
|
end
|
11
11
|
|
12
|
-
|
12
|
+
edit_form do
|
13
13
|
instance_accessor
|
14
14
|
title 'Update <%= model_class_name %>'
|
15
15
|
name 'update-<%= model_name %>'
|
@@ -4,10 +4,10 @@ describe <%= model_class_name %>, type: :integration do
|
|
4
4
|
|
5
5
|
it "returns a <%= name %>" do
|
6
6
|
<%= name %> = <%= model_class_name %>.create
|
7
|
-
get <%=
|
7
|
+
get <%= resource_name %>_uri(<%= name %>)
|
8
8
|
_(status).must_equal 200
|
9
9
|
_(link_rels).must_include(:self)
|
10
|
-
_(links[:self][:href]).must_equal <%=
|
10
|
+
_(links[:self][:href]).must_equal <%= resource_name %>_uri(<%= name %>)
|
11
11
|
<% params.each do |param| -%>
|
12
12
|
_(attributes).must_include(:'<%= param[0] %>')
|
13
13
|
<% end -%>
|
@@ -16,10 +16,10 @@ describe <%= model_class_name %>, type: :integration do
|
|
16
16
|
it "lists all <%= plural_name %>" do
|
17
17
|
2.times { <%= model_class_name %>.create }
|
18
18
|
|
19
|
-
get <%=
|
19
|
+
get <%= collection_name %>_uri
|
20
20
|
_(status).must_equal 200
|
21
21
|
_(link_rels).must_include(:self)
|
22
|
-
_(links[:self][:href]).must_include <%=
|
22
|
+
_(links[:self][:href]).must_include <%= collection_name %>_uri
|
23
23
|
_(embedded(:'<%= plural_name %>').size).must_equal 2
|
24
24
|
|
25
25
|
each_embedded :'<%= plural_name %>' do
|
@@ -31,12 +31,12 @@ describe <%= model_class_name %>, type: :integration do
|
|
31
31
|
end
|
32
32
|
<% if params.size > 0 %>
|
33
33
|
it "can create <%= plural_name %>" do
|
34
|
-
get <%=
|
34
|
+
get <%= collection_name %>_uri
|
35
35
|
|
36
36
|
_(link_rels).must_include(:'create-form')
|
37
37
|
follow_rel :'create-form'
|
38
|
-
_(links[:self][:href]).must_equal new_<%=
|
39
|
-
_(attributes[:href]).must_equal <%=
|
38
|
+
_(links[:self][:href]).must_equal new_<%= resource_name %>_uri
|
39
|
+
_(attributes[:href]).must_equal <%= collection_name %>_uri
|
40
40
|
_(attributes[:method]).must_equal "POST"
|
41
41
|
_(attributes[:name]).must_equal "create-<%= name %>"
|
42
42
|
_(attributes[:title]).must_equal "Create <%= model_class_name %>"
|
@@ -49,9 +49,9 @@ describe <%= model_class_name %>, type: :integration do
|
|
49
49
|
_(link_rels).must_include(:self)
|
50
50
|
_(headers["Location"]).must_equal links[:self][:href]
|
51
51
|
|
52
|
-
get <%=
|
52
|
+
get <%= collection_name %>_uri
|
53
53
|
_(status).must_equal 200
|
54
|
-
_(links[:self][:href]).must_include <%=
|
54
|
+
_(links[:self][:href]).must_include <%= collection_name %>_uri
|
55
55
|
_(embedded(:'<%= plural_name %>').size).must_equal 1
|
56
56
|
|
57
57
|
embedded :'<%= plural_name %>' do
|
@@ -68,14 +68,14 @@ describe <%= model_class_name %>, type: :integration do
|
|
68
68
|
|
69
69
|
it "<%= plural_name %> can be updated" do
|
70
70
|
<%= name %> = <%= model_class_name %>.create
|
71
|
-
get <%=
|
71
|
+
get <%= resource_name %>_uri(<%= name %>)
|
72
72
|
_(status).must_equal 200
|
73
73
|
|
74
74
|
_(link_rels).must_include(:'edit-form')
|
75
75
|
follow_rel :'edit-form'
|
76
76
|
|
77
|
-
_(links[:self][:href]).must_equal edit_<%=
|
78
|
-
_(attributes[:href]).must_equal <%=
|
77
|
+
_(links[:self][:href]).must_equal edit_<%= resource_name %>_uri(<%= name %>)
|
78
|
+
_(attributes[:href]).must_equal <%= resource_name %>_uri(<%= name %>)
|
79
79
|
_(attributes[:method]).must_equal "PUT"
|
80
80
|
_(attributes[:name]).must_equal "update-<%= name %>"
|
81
81
|
_(attributes[:title]).must_equal "Update <%= model_class_name %>"
|
@@ -91,14 +91,14 @@ describe <%= model_class_name %>, type: :integration do
|
|
91
91
|
|
92
92
|
it "<%= plural_name %> can be deleted" do
|
93
93
|
<%= name %> = <%= model_class_name %>.create
|
94
|
-
get <%=
|
94
|
+
get <%= resource_name %>_uri(<%= name %>)
|
95
95
|
_(status).must_equal 200
|
96
96
|
_(link_rels).must_include(:'doc:delete')
|
97
97
|
|
98
98
|
follow_rel(:'doc:delete', method: :delete)
|
99
99
|
_(status).must_equal 204
|
100
100
|
|
101
|
-
get <%=
|
101
|
+
get <%= resource_name %>_uri(<%= name %>)
|
102
102
|
_(status).must_equal 404
|
103
103
|
end
|
104
104
|
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'tempfile'
|
5
|
+
require 'uri'
|
6
|
+
require 'csv'
|
7
|
+
|
8
|
+
module Shaf
|
9
|
+
class LinkRelations
|
10
|
+
class LinkRelation
|
11
|
+
attr_reader :name, :description, :reference, :notes
|
12
|
+
|
13
|
+
def initialize(name, description, reference, notes)
|
14
|
+
@name = name.to_sym
|
15
|
+
@description = description.freeze
|
16
|
+
@reference = reference.freeze
|
17
|
+
@notes = notes.freeze
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class << self
|
22
|
+
IANA_URL = URI('https://www.iana.org/assignments/link-relations/link-relations-1.csv')
|
23
|
+
|
24
|
+
def all
|
25
|
+
relations.values
|
26
|
+
end
|
27
|
+
|
28
|
+
def get(key)
|
29
|
+
load_iana
|
30
|
+
relations[key.to_sym]
|
31
|
+
end
|
32
|
+
|
33
|
+
def add(link_relation)
|
34
|
+
relations[link_relation.name.to_sym] = link_relation
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def load_iana
|
40
|
+
return if @loaded
|
41
|
+
|
42
|
+
iana_csv.each do |name, desc, ref, notes|
|
43
|
+
next if name == 'Relation Name'
|
44
|
+
add LinkRelation.new(name, desc, ref, notes)
|
45
|
+
end
|
46
|
+
|
47
|
+
@loaded = true
|
48
|
+
end
|
49
|
+
|
50
|
+
def relations
|
51
|
+
@relations ||= {}
|
52
|
+
end
|
53
|
+
|
54
|
+
def tmp_file_name
|
55
|
+
File.join(Dir.tmpdir, 'shaf_iana_link_relations')
|
56
|
+
end
|
57
|
+
|
58
|
+
def iana_csv
|
59
|
+
CSV.new(iana_links)
|
60
|
+
end
|
61
|
+
|
62
|
+
def iana_links
|
63
|
+
return File.read(tmp_file_name) if File.readable? tmp_file_name
|
64
|
+
|
65
|
+
response = Net::HTTP.get_response(IANA_URL)
|
66
|
+
|
67
|
+
if response.code.to_i == 200
|
68
|
+
response.body.tap do |content|
|
69
|
+
File.open(tmp_file_name, 'w') { |file| file.write(content) }
|
70
|
+
end
|
71
|
+
else
|
72
|
+
Utils.iana_link_relations
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/lib/shaf/profile.rb
CHANGED
@@ -5,6 +5,14 @@ require 'shaf/extensions/resource_uris'
|
|
5
5
|
|
6
6
|
module Shaf
|
7
7
|
class Profile
|
8
|
+
module NormalizeName
|
9
|
+
private def normalize(name)
|
10
|
+
name.to_s.downcase.tr('-', '_')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
extend NormalizeName
|
15
|
+
include NormalizeName
|
8
16
|
include Shaf::UriHelper
|
9
17
|
|
10
18
|
class << self
|
@@ -98,18 +106,10 @@ module Shaf
|
|
98
106
|
def evaluator
|
99
107
|
Evaluator.new(parent: self)
|
100
108
|
end
|
101
|
-
|
102
|
-
def normalize(name)
|
103
|
-
name.to_s.downcase.tr('-', '_')
|
104
|
-
end
|
105
109
|
end
|
106
110
|
|
107
111
|
def name
|
108
112
|
normalize(self.class.name)
|
109
113
|
end
|
110
|
-
|
111
|
-
def normalize(str)
|
112
|
-
self.class.normalize(str)
|
113
|
-
end
|
114
114
|
end
|
115
115
|
end
|
@@ -1,15 +1,58 @@
|
|
1
1
|
module Shaf
|
2
2
|
module RegistrableFactory
|
3
|
-
|
4
3
|
class NotFoundError < StandardError; end
|
4
|
+
class NoIdentifiersError < StandardError
|
5
|
+
|
6
|
+
def initialize(clazz)
|
7
|
+
super <<~ERR
|
8
|
+
#{clazz} does not have an @identifiers ivar.
|
9
|
+
Did you perhaps forget to call `#{clazz}.identifier`?
|
10
|
+
ERR
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Entry
|
15
|
+
attr_reader :clazz
|
16
|
+
|
17
|
+
def initialize(clazz)
|
18
|
+
@clazz = clazz
|
19
|
+
end
|
20
|
+
|
21
|
+
def match?(strings)
|
22
|
+
raise NoIdentifiersError, clazz unless identifiers
|
23
|
+
return false if strings.size < identifiers.size
|
24
|
+
identifiers.zip(strings).all? { |pattern, str| matching_identifier? str, pattern }
|
25
|
+
end
|
26
|
+
|
27
|
+
def identifier_count
|
28
|
+
identifiers&.size || 0
|
29
|
+
end
|
30
|
+
|
31
|
+
def usage
|
32
|
+
clazz.instance_variable_get(:@usage)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def identifiers
|
38
|
+
clazz.identified_by
|
39
|
+
end
|
40
|
+
|
41
|
+
def matching_identifier?(str, pattern)
|
42
|
+
return false if pattern.nil? || str.nil? || str.empty?
|
43
|
+
pattern = pattern.to_s if pattern.is_a? Symbol
|
44
|
+
return str == pattern if pattern.is_a? String
|
45
|
+
!!str.match(pattern)
|
46
|
+
end
|
47
|
+
end
|
5
48
|
|
6
49
|
def all
|
7
|
-
reg.
|
50
|
+
reg.map(&:clazz)
|
8
51
|
end
|
9
52
|
|
10
|
-
def each
|
53
|
+
def each(&block)
|
11
54
|
return all.each unless block_given?
|
12
|
-
all.each
|
55
|
+
all.each(&block)
|
13
56
|
end
|
14
57
|
|
15
58
|
def size
|
@@ -17,34 +60,31 @@ module Shaf
|
|
17
60
|
end
|
18
61
|
|
19
62
|
def register(clazz)
|
20
|
-
reg << clazz
|
63
|
+
reg << Entry.new(clazz)
|
21
64
|
end
|
22
65
|
|
23
66
|
def unregister(*str)
|
24
67
|
return if str.empty? || !str.all?
|
25
|
-
reg.delete_if { |
|
68
|
+
reg.delete_if { |entry| entry.match? str }
|
26
69
|
end
|
27
70
|
|
28
71
|
def lookup(*str)
|
29
|
-
|
30
|
-
reg.select { |clazz| matching_class? str, clazz }
|
31
|
-
.sort_by(&method(:identifier_count))
|
32
|
-
.last
|
72
|
+
lookup_entry(*str)&.clazz
|
33
73
|
end
|
34
74
|
|
35
75
|
def usage
|
36
76
|
reg.compact.map do |entry|
|
37
|
-
usage = entry.
|
77
|
+
usage = entry.usage
|
38
78
|
usage.respond_to?(:call) ? usage.call : usage
|
39
79
|
end
|
40
80
|
end
|
41
81
|
|
42
82
|
def create(*params, **options)
|
43
|
-
|
44
|
-
raise NotFoundError.new(%Q(Command '#{ARGV}' is not supported)) unless
|
83
|
+
entry = lookup_entry(*params)
|
84
|
+
raise NotFoundError.new(%Q(Command '#{ARGV}' is not supported)) unless entry
|
45
85
|
|
46
|
-
args = init_args(
|
47
|
-
clazz.new(*args, **options)
|
86
|
+
args = init_args(entry, params)
|
87
|
+
entry.clazz.new(*args, **options)
|
48
88
|
end
|
49
89
|
|
50
90
|
private
|
@@ -53,25 +93,15 @@ module Shaf
|
|
53
93
|
@reg ||= []
|
54
94
|
end
|
55
95
|
|
56
|
-
def
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
def matching_identifier?(str, pattern)
|
63
|
-
return false if pattern.nil? || str.nil? || str.empty?
|
64
|
-
pattern = pattern.to_s if pattern.is_a? Symbol
|
65
|
-
return str == pattern if pattern.is_a? String
|
66
|
-
str.match(pattern) || false
|
67
|
-
end
|
68
|
-
|
69
|
-
def identifier_count(clazz)
|
70
|
-
clazz.instance_variable_get(:@identifiers)&.size || 0
|
96
|
+
def lookup_entry(*str)
|
97
|
+
return if str.empty? || !str.all?
|
98
|
+
reg.select { |entry| entry.match? str }
|
99
|
+
.sort_by { |entry| entry.identifier_count }
|
100
|
+
.last
|
71
101
|
end
|
72
102
|
|
73
|
-
def init_args(
|
74
|
-
first_non_id = identifier_count
|
103
|
+
def init_args(entry, params)
|
104
|
+
first_non_id = entry.identifier_count
|
75
105
|
params[first_non_id..-1]
|
76
106
|
end
|
77
107
|
end
|