gris 0.0.2

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.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +1 -0
  5. data/.rubocop_todo.yml +67 -0
  6. data/.ruby-gemset +1 -0
  7. data/.ruby-version +1 -0
  8. data/Gemfile +12 -0
  9. data/Gemfile.lock +203 -0
  10. data/Guardfile +82 -0
  11. data/MIT-LICENSE +20 -0
  12. data/README.md +7 -0
  13. data/Rakefile +11 -0
  14. data/bin/gris +5 -0
  15. data/gris.gemspec +40 -0
  16. data/lib/gris.rb +37 -0
  17. data/lib/gris/cli.rb +71 -0
  18. data/lib/gris/deprecations.rb +9 -0
  19. data/lib/gris/deprecations/gris_setup.rb +14 -0
  20. data/lib/gris/generators.rb +3 -0
  21. data/lib/gris/generators/api_generator.rb +31 -0
  22. data/lib/gris/generators/migration_generator.rb +228 -0
  23. data/lib/gris/generators/scaffold_generator.rb +21 -0
  24. data/lib/gris/generators/templates/api/app/apis/%name_tableize%_endpoint.rb.tt +65 -0
  25. data/lib/gris/generators/templates/api/app/models/%name_underscore%.rb.tt +2 -0
  26. data/lib/gris/generators/templates/api/app/presenters/%name_tableize%_presenter.rb.tt +5 -0
  27. data/lib/gris/generators/templates/api/app/presenters/%name_underscore%_presenter.rb.tt +10 -0
  28. data/lib/gris/generators/templates/api/spec/apis/%name_tableize%_endpoint_spec.rb.tt +70 -0
  29. data/lib/gris/generators/templates/api/spec/fabricators/%name_tableize%_fabricator.rb.tt +2 -0
  30. data/lib/gris/generators/templates/api/spec/models/%name_underscore%_spec.rb.tt +7 -0
  31. data/lib/gris/generators/templates/create_table_migration/%migration_filename%.rb.tt +19 -0
  32. data/lib/gris/generators/templates/migration/%migration_filename%.rb.tt +39 -0
  33. data/lib/gris/generators/templates/scaffold/.Procfile.tt +1 -0
  34. data/lib/gris/generators/templates/scaffold/.env.test.tt +11 -0
  35. data/lib/gris/generators/templates/scaffold/.env.tt +10 -0
  36. data/lib/gris/generators/templates/scaffold/.gitignore.tt +11 -0
  37. data/lib/gris/generators/templates/scaffold/.rspec.tt +3 -0
  38. data/lib/gris/generators/templates/scaffold/.rubocop.yml +18 -0
  39. data/lib/gris/generators/templates/scaffold/.ruby-gemset.tt +1 -0
  40. data/lib/gris/generators/templates/scaffold/.ruby-version.tt +1 -0
  41. data/lib/gris/generators/templates/scaffold/Gemfile.tt +33 -0
  42. data/lib/gris/generators/templates/scaffold/README.md.tt +3 -0
  43. data/lib/gris/generators/templates/scaffold/Rakefile +9 -0
  44. data/lib/gris/generators/templates/scaffold/app.rb +57 -0
  45. data/lib/gris/generators/templates/scaffold/app/apis/application_endpoint.rb +9 -0
  46. data/lib/gris/generators/templates/scaffold/app/presenters/root_presenter.rb +20 -0
  47. data/lib/gris/generators/templates/scaffold/config.ru.tt +6 -0
  48. data/lib/gris/generators/templates/scaffold/config/database.yml.tt +19 -0
  49. data/lib/gris/generators/templates/scaffold/config/initializers/active_record.rb +4 -0
  50. data/lib/gris/generators/templates/scaffold/db/schema.rb +11 -0
  51. data/lib/gris/generators/templates/scaffold/public/errors/404.html +11 -0
  52. data/lib/gris/generators/templates/scaffold/public/errors/500.html +11 -0
  53. data/lib/gris/generators/templates/scaffold/spec/apis/cors_spec.rb +31 -0
  54. data/lib/gris/generators/templates/scaffold/spec/spec_helper.rb +26 -0
  55. data/lib/gris/generators/templates/scaffold/spec/support/app_helper.rb +3 -0
  56. data/lib/gris/grape_extensions/crud_helpers.rb +26 -0
  57. data/lib/gris/identity.rb +50 -0
  58. data/lib/gris/middleware/app_monitor.rb +17 -0
  59. data/lib/gris/output_formatters/paginated_presenter.rb +41 -0
  60. data/lib/gris/output_formatters/presenter.rb +15 -0
  61. data/lib/gris/rspec_extensions/response_helpers.rb +57 -0
  62. data/lib/gris/setup.rb +17 -0
  63. data/lib/gris/version.rb +38 -0
  64. data/lib/tasks/db.rake +81 -0
  65. data/lib/tasks/routes.rake +11 -0
  66. data/spec/generators/api_generator_spec.rb +76 -0
  67. data/spec/generators/migration_generator_spec.rb +96 -0
  68. data/spec/generators/scaffold_generator_spec.rb +119 -0
  69. data/spec/grape_extensions/crud_helpers_spec.rb +5 -0
  70. data/spec/identity_spec.rb +86 -0
  71. data/spec/spec_helper.rb +10 -0
  72. data/spec/support/spec_generators_helper.rb +11 -0
  73. data/spec/version_spec.rb +40 -0
  74. metadata +426 -0
@@ -0,0 +1,11 @@
1
+ unless defined?(Rails)
2
+ desc 'display all routes for Grape'
3
+ task :routes do
4
+ ApplicationEndpoint.routes.each do |api|
5
+ method = api.route_method.ljust(10)
6
+ path = api.route_path.ljust(40)
7
+ description = api.route_description
8
+ puts " #{method} #{path} # #{description}"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+ require 'gris/generators/api_generator'
3
+ require 'gris/cli'
4
+
5
+ describe Gris::Generators::ApiGenerator do
6
+ include_context 'with generator'
7
+ let(:api_name) { 'foo' }
8
+
9
+ before do
10
+ Gris::CLI::Base.new.generate('api', api_name)
11
+ end
12
+
13
+ describe 'app' do
14
+ it 'creates an endpoint class' do
15
+ expected_api_file = File.join(generator_tmp_directory, 'app/apis/foos_endpoint.rb')
16
+ api_code = File.read(expected_api_file)
17
+ expect(api_code).to match(/class FoosEndpoint/)
18
+ end
19
+
20
+ it 'creates a model class' do
21
+ expected_model_file = File.join(generator_tmp_directory, 'app/models/foo.rb')
22
+ model_code = File.read(expected_model_file)
23
+ expect(model_code).to match(/class Foo/)
24
+ end
25
+
26
+ it 'creates an item presenter module' do
27
+ expected_presenter_file = File.join(generator_tmp_directory, 'app/presenters/foo_presenter.rb')
28
+ presenter_code = File.read(expected_presenter_file)
29
+ expect(presenter_code).to match(/module FooPresenter/)
30
+ end
31
+
32
+ it 'item presenter includes Gris::Presenter' do
33
+ presenter_file = File.join(generator_tmp_directory, 'app/presenters/foo_presenter.rb')
34
+ require "./#{presenter_file}"
35
+ expect(FooPresenter).to include(Gris::Presenter)
36
+ end
37
+
38
+ it 'creates a collection presenter module' do
39
+ expected_presenter_file = File.join(generator_tmp_directory, 'app/presenters/foos_presenter.rb')
40
+ presenter_code = File.read(expected_presenter_file)
41
+ expect(presenter_code).to match(/module FoosPresenter/)
42
+ end
43
+
44
+ it 'collection presenter includes Gris::Presenter' do
45
+ presenter_file = File.join(generator_tmp_directory, 'app/presenters/foos_presenter.rb')
46
+ require "./#{presenter_file}"
47
+ expect(FoosPresenter).to include(Gris::Presenter)
48
+ end
49
+
50
+ it 'collection presenter includes Gris::PaginatedPresenter' do
51
+ presenter_file = File.join(generator_tmp_directory, 'app/presenters/foos_presenter.rb')
52
+ require "./#{presenter_file}"
53
+ expect(FoosPresenter).to include(Gris::PaginatedPresenter)
54
+ end
55
+ end
56
+
57
+ describe 'spec' do
58
+ it 'creates an api spec' do
59
+ expected_api_file = File.join(generator_tmp_directory, 'spec/apis/foos_endpoint_spec.rb')
60
+ api_code = File.read(expected_api_file)
61
+ expect(api_code).to match(/describe FoosEndpoint/)
62
+ end
63
+
64
+ it 'creates a fabricator' do
65
+ expected_fabricator_file = File.join(generator_tmp_directory, 'spec/fabricators/foos_fabricator.rb')
66
+ fabricator_code = File.read(expected_fabricator_file)
67
+ expect(fabricator_code).to include 'Fabricator(:foo) do'
68
+ end
69
+
70
+ it 'creates a model spec' do
71
+ expected_model_file = File.join(generator_tmp_directory, 'spec/models/foo_spec.rb')
72
+ model_code = File.read(expected_model_file)
73
+ expect(model_code).to match(/describe Foo/)
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+ require 'gris/generators/migration_generator'
3
+ require 'gris/cli'
4
+
5
+ describe Gris::Generators::MigrationGenerator do
6
+ include_context 'with generator'
7
+ let(:migration_filename) { 'foo' }
8
+
9
+ before do
10
+ allow_any_instance_of(described_class).to receive(:migration_filename).and_return(migration_filename)
11
+ end
12
+
13
+ describe 'AddFooToBar flew:string:index brew:integer' do
14
+ before do
15
+ Gris::CLI::Base.new.generate('migration', 'AddFooToBar', 'flew:string:index', 'brew:integer')
16
+ expected_migration_file = File.join(generator_tmp_directory, 'foo.rb')
17
+ @migration_code = File.read(expected_migration_file)
18
+ end
19
+
20
+ it 'creates a camelized migration class' do
21
+ expect(@migration_code).to match(/class AddFooToBar/)
22
+ end
23
+
24
+ it 'adds the columns' do
25
+ expect(@migration_code).to match(/add_column :bars, :flew, :string/)
26
+ expect(@migration_code).to match(/add_column :bars, :brew, :integer/)
27
+ end
28
+
29
+ it 'adds the index on the correct column' do
30
+ expect(@migration_code).to match(/add_index :bars, :flew/)
31
+ end
32
+ end
33
+
34
+ describe 'RemoveFooFromBar flew:string brew:integer' do
35
+ before do
36
+ Gris::CLI::Base.new.generate('migration', 'RemoveFooFromBar', 'flew:string', 'brew:integer')
37
+ expected_migration_file = File.join(generator_tmp_directory, 'foo.rb')
38
+ @migration_code = File.read(expected_migration_file)
39
+ end
40
+
41
+ it 'creates a camelized migration class' do
42
+ expect(@migration_code).to match(/class RemoveFooFromBar/)
43
+ end
44
+
45
+ it 'removes the columns' do
46
+ expect(@migration_code).to match(/remove_column :bars, :flew, :string/)
47
+ expect(@migration_code).to match(/remove_column :bars, :brew, :integer/)
48
+ end
49
+ end
50
+
51
+ describe 'CreateJoinTableFooBar foo bar' do
52
+ before do
53
+ Gris::CLI::Base.new.generate('migration', 'CreateJoinTableFooBar', 'foo', 'bar')
54
+ expected_migration_file = File.join(generator_tmp_directory, 'foo.rb')
55
+ @migration_code = File.read(expected_migration_file)
56
+ end
57
+
58
+ it 'creates a camelized migration class' do
59
+ expect(@migration_code).to match(/class CreateJoinTableFooBar/)
60
+ end
61
+
62
+ it 'creates the join table' do
63
+ expect(@migration_code).to match(/create_join_table :foos, :bars/)
64
+ end
65
+
66
+ it 'adds placeholders for the indexing' do
67
+ expect(@migration_code).to match(/# t.index \[:foo_id, :bar_id\]/)
68
+ expect(@migration_code).to match(/# t.index \[:bar_id, :foo_id\]/)
69
+ end
70
+ end
71
+
72
+ describe 'CreateSkrillex drops:integer hair:string:index' do
73
+ before do
74
+ Gris::CLI::Base.new.generate('migration', 'CreateSkrillex', 'drops:integer', 'hair:string:index')
75
+ expected_migration_file = File.join(generator_tmp_directory, 'foo.rb')
76
+ @migration_code = File.read(expected_migration_file)
77
+ end
78
+
79
+ it 'creates a camelized migration class' do
80
+ expect(@migration_code).to match(/class CreateSkrillex/)
81
+ end
82
+
83
+ it 'creates the table' do
84
+ expect(@migration_code).to match(/create_table :skrillexes/)
85
+ end
86
+
87
+ it 'adds the columns' do
88
+ expect(@migration_code).to match(/t.integer :drops/)
89
+ expect(@migration_code).to match(/t.string :hair/)
90
+ end
91
+
92
+ it 'adds the index on the correct column' do
93
+ expect(@migration_code).to match(/add_index :skrillexes, :hair/)
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,119 @@
1
+ require 'spec_helper'
2
+ require 'gris/generators/scaffold_generator'
3
+ require 'gris/cli'
4
+
5
+ describe Gris::Generators::ScaffoldGenerator do
6
+ let(:app_name) { 'my_test_app' }
7
+ let(:app_path) { 'spec/my_different_directory' }
8
+ let(:options) { {} }
9
+
10
+ before do
11
+ scaffold = Gris::CLI::Base.new(args, options)
12
+ scaffold.invoke(:new)
13
+ end
14
+
15
+ after do
16
+ if args[1] # if app_path exists, delete dir at app_path
17
+ FileUtils.rm_rf(args[1])
18
+ else # otherwise delete dir at app_name
19
+ FileUtils.rm_rf(args[0])
20
+ end
21
+ end
22
+
23
+ context 'given only an app name' do
24
+ let(:args) { [app_name] }
25
+
26
+ it 'creates a scaffold app in a directory that mirrors the app name' do
27
+ expect(Dir).to exist(app_name)
28
+ end
29
+ end
30
+
31
+ context 'given an app name and a directory' do
32
+ let(:args) { [app_name, app_path] }
33
+
34
+ it 'creates a scaffold app in a directory of my choosing' do
35
+ expect(Dir).to exist(app_path)
36
+ end
37
+
38
+ it 'creates a .env file with with a development database name' do
39
+ expect(File).to exist("#{app_path}/.env")
40
+ env_file = File.read("#{app_path}/.env")
41
+ expect(env_file).to match(/#{app_name}_development/)
42
+ end
43
+
44
+ it 'creates a .Procfile file with puma ' do
45
+ expect(File).to exist("#{app_path}/.Procfile")
46
+ env_file = File.read("#{app_path}/.Procfile")
47
+ expect(env_file).to match(/web: bundle exec puma/)
48
+ end
49
+
50
+ it 'creates a .env.test file with a test database name' do
51
+ expect(File).to exist("#{app_path}/.env.test")
52
+ env_test_file = File.read("#{app_path}/.env.test")
53
+ expect(env_test_file).to match(/#{app_name}_test/)
54
+ end
55
+
56
+ it 'selects postgresql as the default database adapter' do
57
+ database_config_file = File.read("#{app_path}/config/database.yml")
58
+ expect(database_config_file).to match(/adapter: postgresql/)
59
+ end
60
+
61
+ it 'adds the pg gem in the Gemfile' do
62
+ gemfile = File.read("#{app_path}/Gemfile")
63
+ expect(gemfile).to match(/gem 'pg'/)
64
+ end
65
+
66
+ it 'adds the puma gem in the Gemfile' do
67
+ gemfile = File.read("#{app_path}/Gemfile")
68
+ expect(gemfile).to match(/gem 'puma'/)
69
+ end
70
+
71
+ it 'generates an application endpoint' do
72
+ expect(File).to exist("#{app_path}/app/apis/application_endpoint.rb")
73
+ end
74
+
75
+ context 'application_endpoint' do
76
+ let(:application_api_file) { File.read("#{app_path}/app/apis/application_endpoint.rb") }
77
+
78
+ it 'the application endpoint inherits from Grape::API' do
79
+ expect(application_api_file).to match(/class ApplicationEndpoint < Grape::API/)
80
+ end
81
+
82
+ it 'mounts the RootPresenter' do
83
+ expect(application_api_file).to match(/present self, with: RootPresenter/)
84
+ end
85
+
86
+ it 'uses Grape::Formatter::Roar json formatter' do
87
+ expect(application_api_file).to match(/formatter :json, Grape::Formatter::Roar/)
88
+ end
89
+ end
90
+
91
+ it 'generates a root presenter' do
92
+ expect(File).to exist("#{app_path}/app/presenters/root_presenter.rb")
93
+ end
94
+
95
+ context 'root_presenter' do
96
+ let(:root_presenter_file) { File.read("#{app_path}/app/presenters/root_presenter.rb") }
97
+
98
+ before do
99
+ require "./#{app_path}/app/presenters/root_presenter.rb"
100
+ end
101
+
102
+ it 'defines RootPresenter module' do
103
+ expect(root_presenter_file).to match(/module RootPresenter/)
104
+ end
105
+
106
+ it 'includes Grape::Roar::Representer' do
107
+ expect(RootPresenter).to include(Grape::Roar::Representer)
108
+ end
109
+
110
+ it 'includes Roar::Hypermedia' do
111
+ expect(RootPresenter).to include(Roar::Hypermedia)
112
+ end
113
+
114
+ it 'includes Roar::JSON::HAL' do
115
+ expect(RootPresenter).to include(Roar::JSON::HAL)
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+ require 'gris/grape_extensions/crud_helpers'
3
+
4
+ describe Gris::CrudHelpers do
5
+ end
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+ require 'gris/identity'
3
+
4
+ describe Gris::Identity do
5
+ before do
6
+ allow(Process).to receive(:pid).and_return(123)
7
+ allow(Gris::Identity).to receive(:hostname).and_return('system-hostname')
8
+ allow(Gris::Identity).to receive(:`).with('git rev-parse HEAD').and_return('12345')
9
+ end
10
+
11
+ context '#health' do
12
+ it 'includes name' do
13
+ expect(Gris::Identity.health[:name]).to eq(Gris::Identity.name)
14
+ end
15
+ it 'includes base_url' do
16
+ expect(Gris::Identity.health[:base_url]).to eq(Gris::Identity.base_url)
17
+ end
18
+ it 'includes hostname' do
19
+ expect(Gris::Identity.health[:hostname]).to eq(Gris::Identity.hostname)
20
+ end
21
+ it 'includes revision' do
22
+ expect(Gris::Identity.health[:revision]).to eq(Gris::Identity.revision)
23
+ end
24
+ it 'includes pid' do
25
+ expect(Gris::Identity.health[:pid]).to eq(Gris::Identity.pid)
26
+ end
27
+ it 'includes parent_pid' do
28
+ expect(Gris::Identity.health[:parent_pid]).to eq(Gris::Identity.parent_pid)
29
+ end
30
+ it 'includes platform' do
31
+ expect(Gris::Identity.health[:platform]).to eq(Gris::Identity.platform)
32
+ end
33
+ end
34
+
35
+ context '#name' do
36
+ it "returns 'api-service' if no ENV['SERVICE_NAME'] is set" do
37
+ ENV['SERVICE_NAME'] = nil
38
+ expect(Gris::Identity.name).to eq('api-service')
39
+ end
40
+
41
+ it "returns the ENV['SERVICE_NAME'] when specified" do
42
+ ENV['SERVICE_NAME'] = nil
43
+ ENV['SERVICE_NAME'] = 'my-service'
44
+ expect(Gris::Identity.name).to eq('my-service')
45
+ end
46
+ end
47
+
48
+ context '#hostname' do
49
+ it 'returns the value of the hostname system call and doesn\'t make a second system call' do
50
+ expect(Gris::Identity).to_not receive(:`).with('hostname')
51
+ expect(Gris::Identity.hostname).to eq('system-hostname')
52
+ end
53
+ end
54
+
55
+ context '#revision' do
56
+ it 'returns the value of the \'git rev-parse HEAD\' system call and doesn\'t make a second system call' do
57
+ expect(Gris::Identity).to_not receive(:`).with('git rev-parse HEAD')
58
+ expect(Gris::Identity.revision).to eq('12345')
59
+ end
60
+ end
61
+
62
+ context '#pid' do
63
+ it 'returns the process ID value' do
64
+ expect(Gris::Identity.pid).to eq(123)
65
+ end
66
+ end
67
+
68
+ context '#platform_revision' do
69
+ it 'returns the current version of the platform gem' do
70
+ expect(Gris::Identity.platform_revision).to eq(Gris::VERSION)
71
+ end
72
+ end
73
+
74
+ context '#base_url' do
75
+ it 'returns http://localhost:9292 by default' do
76
+ ENV['BASE_URL'] = nil
77
+ expect(Gris::Identity.base_url).to eq('http://localhost:9292')
78
+ end
79
+
80
+ it "returns the env['BASE_URL'] when specied" do
81
+ ENV['BASE_URL'] = nil
82
+ ENV['BASE_URL'] = 'my-base-url'
83
+ expect(Gris::Identity.base_url).to eq('my-base-url')
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,10 @@
1
+ ENV['RACK_ENV'] = 'test'
2
+
3
+ require 'gris/setup'
4
+ require 'gris'
5
+
6
+ require 'byebug'
7
+
8
+ # Requires supporting ruby files with custom matchers and macros, etc,
9
+ # in spec/support/ and its subdirectories.
10
+ Dir['./spec/support/**/*.rb'].sort.each { |f| require f }
@@ -0,0 +1,11 @@
1
+ shared_context 'with generator' do
2
+ let(:generator_tmp_directory) { 'spec/tmp' }
3
+
4
+ before do
5
+ allow_any_instance_of(described_class).to receive(:output_directory).and_return(generator_tmp_directory)
6
+ end
7
+
8
+ after do
9
+ FileUtils.rm_rf(generator_tmp_directory)
10
+ end
11
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+ require 'gris/version'
3
+
4
+ describe Gris::Version do
5
+ context '#major_bump' do
6
+ it 'should set the major revision value, and the rest should be 0' do
7
+ stub_const('Gris::VERSION', '1.2.3')
8
+ expect(Gris::Version.next_major).to eq('2.0.0')
9
+ end
10
+
11
+ it 'should set the major revision value, and the rest should be 0' do
12
+ stub_const('Gris::VERSION', '5.0.0')
13
+ expect(Gris::Version.next_major).to eq('6.0.0')
14
+ end
15
+ end
16
+
17
+ context '#minor_bump' do
18
+ it 'should set the minor revision value, leaving the major value unchanged and the patch value to 0' do
19
+ stub_const('Gris::VERSION', '1.2.3')
20
+ expect(Gris::Version.next_minor).to eq('1.3.0')
21
+ end
22
+
23
+ it 'should set the minor revision value, leaving the major value unchanged and the patch value to 0' do
24
+ stub_const('Gris::VERSION', '0.5.0')
25
+ expect(Gris::Version.next_minor).to eq('0.6.0')
26
+ end
27
+ end
28
+
29
+ context 'patch_bump' do
30
+ it 'should set the patch revision value, leaving the major and minor values unchanged' do
31
+ stub_const('Gris::VERSION', '1.2.3')
32
+ expect(Gris::Version.next_patch).to eq('1.2.4')
33
+ end
34
+
35
+ it 'should set the patch revision value, leaving the major and minor values unchanged' do
36
+ stub_const('Gris::VERSION', '5.5.5')
37
+ expect(Gris::Version.next_patch).to eq('5.5.6')
38
+ end
39
+ end
40
+ end