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
         
     |