grape-starter 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 567acba57f6b5bbef50e10c04ef3ed959d1d877b
4
- data.tar.gz: 68dea7756db9323789392a89435adc899aab2c72
3
+ metadata.gz: ac704eaf32a74db38f046a62b8a949ccd89ef03c
4
+ data.tar.gz: f19c5ac175f20052670b27c09d9e9449e0f8e6c7
5
5
  SHA512:
6
- metadata.gz: 50e159bda1bd6411ca34f4ee63269fc6ae403e068e51b64926d29f50d5ba0badbc87d744d5fc1867ffd5fe46a894767d84523e3d6287f2a78a6de794dbbe26ba
7
- data.tar.gz: 1065e7cc75744049be7df78c5a2ec275a3786596e37cf6486301bdc3d94b8ff1a4736650bf407f254afc87dabe3d67920b491ed2adcf866e0510b1bf81fbc028
6
+ metadata.gz: bc576028aa7419e171a7da9ec02d36527e067a3afeae583547f795bb4fcd61cb3e2f9f27be1591c9e46c4d8b4f1b3bc71a59f43498098337b6d732ebccb52e42
7
+ data.tar.gz: '0950501ead93312c1ba389c5f33c675500b98fe3a35232b0ae8ab65d8b7efabe7dc5fcba8e233cd8a00d0e9c812262d4cb6b49d5fe5ab5762bf1441c386d3deb'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  ### NEXT
2
2
 
3
+ ### 0.5.0
4
+
5
+ - simplyfies request specs, **breaking change**: takes route from spec description
6
+ - adds option to set prefix, defaults to api
7
+ - sets prefix after project name
8
+
3
9
  ### 0.4.2
4
10
 
5
11
  - sets prefix after project name
data/README.md CHANGED
@@ -91,6 +91,3 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/LeFnor
91
91
  The gem is available as open source under the terms of the [MIT License](LICENSE).
92
92
 
93
93
  ### ToDos
94
-
95
- - [x] make scripts more configurable
96
- - [ ] add logging
data/bin/grape-starter CHANGED
@@ -22,7 +22,11 @@ switch [:f, :force], negatable: false
22
22
  desc 'Creates initial api skeleton'
23
23
  arg_name 'awesome_api'
24
24
  command :new do |c|
25
- c.action do |global_options, _, args|
25
+ c.flag [:p, :prefix],
26
+ default_value: 'api',
27
+ desc: 'sets the prefix of the API (default: api, given: takes this)'
28
+
29
+ c.action do |global_options, options, args|
26
30
  dest = args.empty? ? nil : File.join(Dir.getwd, args.first)
27
31
 
28
32
  case
@@ -34,7 +38,7 @@ command :new do |c|
34
38
  starter_gem = Gem::Specification.find_by_name('grape-starter').gem_dir
35
39
  src = File.join(starter_gem, 'template', '.')
36
40
 
37
- Starter::Builder.new!(args.first, src, dest)
41
+ Starter::Builder.new!(args.first, src, dest, options[:p])
38
42
  $stdout.puts "created: #{args.first}"
39
43
 
40
44
  # after creating tasks
@@ -63,8 +67,7 @@ command :add do |c|
63
67
 
64
68
  begin
65
69
  builder_options = global_options.merge(set: set).merge(options)
66
- Starter::Builder.add!(resource, builder_options)
67
- created_files = Starter::Builder.save
70
+ created_files = Starter::Builder.add!(resource, builder_options)
68
71
 
69
72
  `bundle exec rubocop -a #{created_files.join(' ')}`
70
73
  $stdout.puts "added resource: #{resource}"
@@ -3,30 +3,39 @@ require 'active_support/core_ext/string'
3
3
 
4
4
  module Starter
5
5
  require 'starter/builder/names'
6
+ require 'starter/builder/base_file'
7
+ require 'starter/builder/file_foo'
6
8
  require 'starter/builder/template_files'
7
9
  require 'starter/builder/template_endpoints'
8
10
 
9
11
  class Builder
10
12
  extend Starter::Names
13
+ extend Starter::BaseFile
11
14
  extend Template::Files
12
15
  extend Template::Endpoints
13
16
 
14
17
  class << self
15
- attr_reader :resource, :set, :force, :entity, :destination
16
-
18
+ attr_reader :prefix, :resource, :set, :force, :entity, :destination
19
+ #
20
+ # public methods
21
+ #
22
+ #
17
23
  # would be called from new command
18
24
  #
19
25
  # name - A String as project name
20
26
  # source - A String which provides the template path
21
27
  # destination - A String which provides the new project path
22
- def new!(name, source, destination)
28
+ def new!(name, source, destination, prefix = 'api')
29
+ @prefix = prefix
23
30
  @resource = name
24
31
  @destination = destination
25
32
 
26
33
  FileUtils.copy_entry source, destination
27
34
 
28
35
  replace_static(File.join('script', 'server'), "API-#{resource}")
29
- replace_static(File.join('api', 'base.rb'), ":#{resource}")
36
+ replace_static(File.join('api', 'base.rb'), ":#{prefix}")
37
+ replace_static(File.join('spec', 'requests', 'root_spec.rb'), prefix)
38
+ replace_static(File.join('spec', 'requests', 'documentation_spec.rb'), prefix)
30
39
 
31
40
  self
32
41
  end
@@ -45,23 +54,10 @@ module Starter
45
54
  @force = options[:force]
46
55
  @entity = options[:entity]
47
56
 
48
- self
49
- end
50
-
51
- #
52
- # … it saves the files
53
- def save
54
- created_files = file_list.each_with_object([]) do |new_file, memo|
55
- memo << send("#{new_file}_name")
56
- save_file(new_file)
57
- end
58
-
59
- add_mount_point
60
-
61
- created_files
57
+ save_resource
62
58
  end
63
59
 
64
- # would be called on from command
60
+ # would be called on from rm command
65
61
  #
66
62
  # resource - A String, which indicates the resource to remove
67
63
  # options - A Hash to provide some optional arguments (default: {})
@@ -93,13 +89,17 @@ module Starter
93
89
 
94
90
  private
95
91
 
96
- # get content for and save new resource files
97
- def save_file(new_file)
98
- new_file_name = "#{new_file}_name"
99
- should_raise?(send(new_file_name))
100
- write_file(send(new_file_name), send(new_file.strip_heredoc))
92
+ # #new! project creation releated helper methods
93
+ #
94
+ # replace something in existend files
95
+ def replace_static(file, replacement)
96
+ server_file = File.join(destination, file)
97
+
98
+ FileFoo.call!(server_file) { |content| content.gsub!('{{{grape-starter}}}', replacement) }
101
99
  end
102
100
 
101
+ # #add! a new resource releated helper methods
102
+ #
103
103
  # provides an array of endpoints for the new resource
104
104
  def endpoint_set
105
105
  crud_set = singular? ? singular_one : crud
@@ -108,76 +108,46 @@ module Starter
108
108
  crud_set.each_with_object([]) { |x, memo| set.map { |y| memo << x if x.to_s.start_with?(y) } }
109
109
  end
110
110
 
111
- # provides a file list for the new resource
112
- def file_list
113
- standards = %w(api_file lib_file api_spec lib_spec)
111
+ #
112
+ # saves all resource related files the files
113
+ def save_resource
114
+ created_files = file_list.each_with_object([]) do |new_file, memo|
115
+ memo << send("#{new_file}_name")
116
+ save_file(new_file)
117
+ end
114
118
 
115
- entity ? standards + ['entity_file'] : standards
116
- end
119
+ add_mount_point
117
120
 
118
- # raises if resource exist and force false
119
- def should_raise?(file)
120
- raise StandardError, '… resource exists' if File.exist?(file) && !force
121
+ created_files
121
122
  end
122
123
 
123
- # replace something in exitend files
124
- #
125
- # will be called on project creation
126
124
  #
127
- # static files such as under script folder,
128
- def replace_static(file, replacement)
129
- server_file = File.join(destination, file)
130
-
131
- file_foo(server_file) { |content| content.gsub!('{{{grape-starter}}}', replacement) }
125
+ # saves new resource files
126
+ def save_file(new_file)
127
+ new_file_name = "#{new_file}_name"
128
+ should_raise?(send(new_file_name))
129
+ FileFoo.write_file(send(new_file_name), send(new_file.strip_heredoc))
132
130
  end
133
131
 
134
- # will be called an resource creation
135
132
  #
136
- # add it in api base
137
- def add_mount_point
138
- file_foo(api_base_file_name) { |content| add_to_base(content) }
139
- end
140
-
141
- # … adding
142
- def add_to_base(file)
143
- occurence = file.scan(/(\s+mount\s.*?\n)/).last.first
144
- replacement = occurence + mount_point
145
- file.sub!(occurence, replacement)
133
+ # raises if resource exist and force false
134
+ def should_raise?(file)
135
+ raise StandardError, '… resource exists' if File.exist?(file) && !force
146
136
  end
147
137
 
148
- # remove it in api base
149
- def remove_mount_point
150
- file_foo(api_base_file_name) { |content| remove_from_base(content) }
151
- end
138
+ # #add! and #remove! a new resource releated helper methods
139
+ #
140
+ # provides a file list for the new resource
141
+ def file_list
142
+ standards = %w(api_file lib_file api_spec lib_spec)
152
143
 
153
- # removing
154
- def remove_from_base(file)
155
- file.sub!(mount_point, '')
144
+ entity ? standards + ['entity_file'] : standards
156
145
  end
157
146
 
158
147
  # content of the given set of files,
159
148
  def content(set)
160
149
  set.map { |x| send(x) }
161
150
  end
162
-
163
- # general file stuff
164
- #
165
- # … reading and writing content
166
- def file_foo(file)
167
- content = read_file(file)
168
- yield content
169
- write_file(file, content)
170
- end
171
-
172
- # … read
173
- def read_file(file)
174
- File.read(file)
175
- end
176
-
177
- # … write
178
- def write_file(file, content)
179
- File.open(file, 'w') { |f| f.write(content) }
180
- end
181
151
  end
182
152
  end
183
153
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+ module Starter
3
+ module BaseFile
4
+ # add it in api base
5
+ def add_mount_point
6
+ FileFoo.call!(api_base_file_name) { |content| add_to_base(content) }
7
+ end
8
+
9
+ # adding mount point to base class
10
+ def add_to_base(file)
11
+ occurence = file.scan(/(\s+mount\s.*?\n)/).last.first
12
+ replacement = occurence + mount_point
13
+ file.sub!(occurence, replacement)
14
+ end
15
+
16
+ # removes in api base
17
+ def remove_mount_point
18
+ FileFoo.call!(api_base_file_name) { |content| remove_from_base(content) }
19
+ end
20
+
21
+ # removes mount point form base class
22
+ def remove_from_base(file)
23
+ file.sub!(mount_point, '')
24
+ end
25
+
26
+ def base_prefix
27
+ base_file
28
+
29
+ base_file.scan(/prefix\s+(:.+)\n/).first.first.delete!(':')
30
+ end
31
+
32
+ def base_version
33
+ base_file
34
+
35
+ base_file.scan(/version\s+(.+),/).first.first.delete!("'")
36
+ end
37
+
38
+ def base_file
39
+ file = File.join(Dir.getwd, 'api', 'base.rb')
40
+ FileFoo.read_file(file)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+ module Starter
3
+ class FileFoo
4
+ class << self
5
+ # general file stuff
6
+ #
7
+ # … reading and writing content
8
+ def call!(file)
9
+ content = read_file(file)
10
+ yield content
11
+ write_file(file, content)
12
+ end
13
+
14
+ # … read
15
+ def read_file(file)
16
+ File.read(file)
17
+ end
18
+
19
+ # … write
20
+ def write_file(file, content)
21
+ File.open(file, 'w') { |f| f.write(content) }
22
+ end
23
+ end
24
+ end
25
+ end
@@ -74,34 +74,34 @@ module Starter
74
74
  # request specs shared examples
75
75
  #
76
76
  def post_spec
77
- "it_behaves_like 'POST', base_path: '/api/v1', resource: '#{resource}', params: {}"
77
+ "it_behaves_like 'POST', params: {}"
78
78
  end
79
79
 
80
80
  def get_all_spec
81
- "it_behaves_like 'GET all', base_path: '/api/v1', resource: '#{resource}'"
81
+ "it_behaves_like 'GET all'"
82
82
  end
83
83
 
84
84
  %w(get delete).each do |verb|
85
85
  define_method(:"#{verb}_one_spec") do
86
- "it_behaves_like '#{verb.upcase} one', base_path: '/api/v1', resource: '#{resource}'"
86
+ "it_behaves_like '#{verb.upcase} one'"
87
87
  end
88
88
  end
89
89
 
90
90
  %w(put patch).each do |verb|
91
91
  define_method(:"#{verb}_one_spec") do
92
- "it_behaves_like '#{verb.upcase} one', base_path: '/api/v1', resource: '#{resource}', params: {}"
92
+ "it_behaves_like '#{verb.upcase} one', params: {}"
93
93
  end
94
94
  end
95
95
 
96
96
  %w(get delete).each do |verb|
97
97
  define_method(:"#{verb}_specific_spec") do
98
- "it_behaves_like '#{verb.upcase} specific', base_path: '/api/v1', resource: '#{resource}', key: 1"
98
+ "it_behaves_like '#{verb.upcase} specific', key: 1"
99
99
  end
100
100
  end
101
101
 
102
102
  %w(put patch).each do |verb|
103
103
  define_method(:"#{verb}_specific_spec") do
104
- "it_behaves_like '#{verb.upcase} specific', base_path: '/api/v1', resource: '#{resource}', key: 1, params: {}"
104
+ "it_behaves_like '#{verb.upcase} specific', key: 1, params: {}"
105
105
  end
106
106
  end
107
107
  end
@@ -51,7 +51,7 @@ module Starter
51
51
  # frozen_string_literal: true
52
52
  require 'spec_helper'
53
53
 
54
- RSpec.describe Api::#{klass_name} do
54
+ RSpec.describe '/#{base_prefix}/#{base_version}/#{resource}' do
55
55
  #{endpoint_specs}
56
56
  end
57
57
  FILE
@@ -1,13 +1,18 @@
1
1
  # frozen_string_literal: true
2
- RSpec.shared_examples 'POST' do |base_path: '/api/v1', resource: '', params: {}|
3
- let(:route) { "#{base_path}/#{resource}" }
2
+
3
+ def route_from_description
4
+ RSpec.current_example.metadata[:example_group][:parent_example_group][:description_args].first
5
+ end
6
+
7
+ RSpec.shared_examples 'POST' do |params: {}|
8
+ let(:route) { route_from_description }
4
9
 
5
10
  subject { post route, params }
6
11
  specify { expect(subject.status).to eql 201 }
7
12
  end
8
13
 
9
- RSpec.shared_examples 'GET all' do |base_path: '/api/v1', resource: ''|
10
- let(:route) { "#{base_path}/#{resource}" }
14
+ RSpec.shared_examples 'GET all' do
15
+ let(:route) { route_from_description }
11
16
 
12
17
  subject { get route }
13
18
  specify { expect(subject.status).to eql 200 }
@@ -15,29 +20,29 @@ end
15
20
 
16
21
  # singular forms
17
22
  #
18
- RSpec.shared_examples 'GET one' do |base_path: '/api/v1', resource: ''|
19
- let(:route) { "#{base_path}/#{resource}" }
23
+ RSpec.shared_examples 'GET one' do
24
+ let(:route) { route_from_description }
20
25
 
21
26
  subject { get route }
22
27
  specify { expect(subject.status).to eql 200 }
23
28
  end
24
29
 
25
- RSpec.shared_examples 'PUT one' do |base_path: '/api/v1', resource: '', params: {}|
26
- let(:route) { "#{base_path}/#{resource}" }
30
+ RSpec.shared_examples 'PUT one' do |params: {}|
31
+ let(:route) { route_from_description }
27
32
 
28
33
  subject { put route, params }
29
34
  specify { expect(subject.status).to eql 200 }
30
35
  end
31
36
 
32
- RSpec.shared_examples 'PATCH one' do |base_path: '/api/v1', resource: '', params: {}|
33
- let(:route) { "#{base_path}/#{resource}" }
37
+ RSpec.shared_examples 'PATCH one' do |params: {}|
38
+ let(:route) { route_from_description }
34
39
 
35
40
  subject { patch route, params }
36
41
  specify { expect(subject.status).to eql 200 }
37
42
  end
38
43
 
39
- RSpec.shared_examples 'DELETE one' do |base_path: '/api/v1', resource: ''|
40
- let(:route) { "#{base_path}/#{resource}" }
44
+ RSpec.shared_examples 'DELETE one' do
45
+ let(:route) { route_from_description }
41
46
 
42
47
  subject { delete route }
43
48
  specify { expect(subject.status).to eql 204 }
@@ -45,32 +50,32 @@ end
45
50
 
46
51
  # plural forms
47
52
  #
48
- RSpec.shared_examples 'GET specific' do |base_path: '/api/v1', resource: '', key: nil|
49
- let(:route) { "#{base_path}/#{resource}" }
53
+ RSpec.shared_examples 'GET specific' do |key: nil|
54
+ let(:route) { route_from_description }
50
55
  let(:specific_route) { "#{route}/#{key}" }
51
56
 
52
57
  subject { get specific_route }
53
58
  specify { expect(subject.status).to eql 200 }
54
59
  end
55
60
 
56
- RSpec.shared_examples 'PUT specific' do |base_path: '/api/v1', resource: '', key: nil, params: {}|
57
- let(:route) { "#{base_path}/#{resource}" }
61
+ RSpec.shared_examples 'PUT specific' do |key: nil, params: {}|
62
+ let(:route) { route_from_description }
58
63
  let(:specific_route) { "#{route}/#{key}" }
59
64
 
60
65
  subject { put specific_route, params }
61
66
  specify { expect(subject.status).to eql 200 }
62
67
  end
63
68
 
64
- RSpec.shared_examples 'PATCH specific' do |base_path: '/api/v1', resource: '', key: nil, params: {}|
65
- let(:route) { "#{base_path}/#{resource}" }
69
+ RSpec.shared_examples 'PATCH specific' do |key: nil, params: {}|
70
+ let(:route) { route_from_description }
66
71
  let(:specific_route) { "#{route}/#{key}" }
67
72
 
68
73
  subject { patch specific_route, params }
69
74
  specify { expect(subject.status).to eql 200 }
70
75
  end
71
76
 
72
- RSpec.shared_examples 'DELETE specific' do |base_path: '/api/v1', resource: '', key: nil|
73
- let(:route) { "#{base_path}/#{resource}" }
77
+ RSpec.shared_examples 'DELETE specific' do |key: nil|
78
+ let(:route) { route_from_description }
74
79
  let(:specific_route) { "#{route}/#{key}" }
75
80
 
76
81
  subject { delete specific_route }
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Starter
3
- VERSION = '0.4.2'
3
+ VERSION = '0.5.0'
4
4
  end
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
  require 'spec_helper'
3
3
 
4
- RSpec.describe Api::Base do
4
+ RSpec.describe '/{{{grape-starter}}}/v1/oapi' do
5
5
  subject(:swagger) do
6
- get '/api/v1/oapi'
6
+ get RSpec.current_example.metadata[:example_group][:full_description]
7
7
  last_response
8
8
  end
9
9
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  require 'spec_helper'
3
3
 
4
- RSpec.describe Api::Base do
4
+ RSpec.describe '/{{{grape-starter}}}/v1/root' do
5
5
  let(:exposed_keys) do
6
6
  [
7
7
  :verb,
@@ -10,7 +10,7 @@ RSpec.describe Api::Base do
10
10
  ]
11
11
  end
12
12
 
13
- subject { get '/api/v1/root' }
13
+ subject { get RSpec.current_example.metadata[:example_group][:full_description] }
14
14
  specify { expect(subject.status).to eql 200 }
15
15
 
16
16
  let(:response) { JSON.parse(subject.body, symbolize_names: true) }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape-starter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - LeFnord
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-28 00:00:00.000000000 Z
11
+ date: 2016-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gli
@@ -160,6 +160,8 @@ files:
160
160
  - grape-starter.gemspec
161
161
  - lib/starter.rb
162
162
  - lib/starter/builder.rb
163
+ - lib/starter/builder/base_file.rb
164
+ - lib/starter/builder/file_foo.rb
163
165
  - lib/starter/builder/names.rb
164
166
  - lib/starter/builder/template_endpoints.rb
165
167
  - lib/starter/builder/template_files.rb