upgrow 0.0.1 → 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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +45 -12
  3. data/Rakefile +8 -4
  4. data/lib/upgrow.rb +13 -2
  5. data/lib/upgrow/action.rb +54 -0
  6. data/lib/upgrow/active_record_adapter.rb +73 -0
  7. data/lib/upgrow/basic_repository.rb +45 -0
  8. data/lib/upgrow/immutable_object.rb +57 -0
  9. data/lib/upgrow/immutable_struct.rb +40 -0
  10. data/lib/upgrow/input.rb +47 -0
  11. data/lib/upgrow/model.rb +35 -0
  12. data/lib/upgrow/repository.rb +12 -0
  13. data/lib/upgrow/result.rb +94 -0
  14. data/test/application_system_test_case.rb +13 -0
  15. data/test/dummy/app/actions/create_article_action.rb +13 -0
  16. data/test/dummy/app/actions/delete_article_action.rb +7 -0
  17. data/test/dummy/app/actions/edit_article_action.rb +10 -0
  18. data/test/dummy/app/actions/list_articles_action.rb +8 -0
  19. data/test/dummy/app/actions/show_article_action.rb +10 -0
  20. data/test/dummy/app/actions/update_article_action.rb +13 -0
  21. data/test/dummy/app/channels/application_cable/channel.rb +5 -0
  22. data/test/dummy/app/channels/application_cable/connection.rb +5 -0
  23. data/test/dummy/app/controllers/application_controller.rb +3 -0
  24. data/test/dummy/app/controllers/articles_controller.rb +64 -0
  25. data/test/dummy/app/helpers/application_helper.rb +102 -0
  26. data/test/dummy/app/inputs/article_input.rb +8 -0
  27. data/test/dummy/app/jobs/application_job.rb +9 -0
  28. data/test/dummy/app/mailers/application_mailer.rb +5 -0
  29. data/test/dummy/app/models/article.rb +6 -0
  30. data/test/dummy/app/records/application_record.rb +5 -0
  31. data/test/dummy/app/records/article_record.rb +5 -0
  32. data/test/dummy/app/repositories/article_repository.rb +4 -0
  33. data/test/dummy/config/application.rb +23 -0
  34. data/test/dummy/config/boot.rb +6 -0
  35. data/test/dummy/config/environment.rb +6 -0
  36. data/test/dummy/config/environments/development.rb +79 -0
  37. data/test/dummy/config/environments/production.rb +133 -0
  38. data/test/dummy/config/environments/test.rb +61 -0
  39. data/test/dummy/config/initializers/application_controller_renderer.rb +9 -0
  40. data/test/dummy/config/initializers/assets.rb +13 -0
  41. data/test/dummy/config/initializers/backtrace_silencers.rb +12 -0
  42. data/test/dummy/config/initializers/content_security_policy.rb +31 -0
  43. data/test/dummy/config/initializers/cookies_serializer.rb +6 -0
  44. data/test/dummy/config/initializers/filter_parameter_logging.rb +7 -0
  45. data/test/dummy/config/initializers/inflections.rb +17 -0
  46. data/test/dummy/config/initializers/mime_types.rb +5 -0
  47. data/test/dummy/config/initializers/permissions_policy.rb +12 -0
  48. data/test/dummy/config/initializers/wrap_parameters.rb +16 -0
  49. data/test/dummy/config/puma.rb +44 -0
  50. data/test/dummy/config/routes.rb +7 -0
  51. data/test/dummy/db/migrate/20210219211631_create_articles.rb +11 -0
  52. data/test/dummy/db/schema.rb +22 -0
  53. data/test/rails_helper.rb +21 -0
  54. data/test/system/articles_test.rb +109 -0
  55. data/test/test_helper.rb +3 -3
  56. data/test/upgrow/action_test.rb +25 -0
  57. data/test/upgrow/active_record_adapter_test.rb +94 -0
  58. data/test/upgrow/basic_repository_test.rb +73 -0
  59. data/test/upgrow/documentation_test.rb +12 -0
  60. data/test/upgrow/immutable_object_test.rb +60 -0
  61. data/test/upgrow/immutable_struct_test.rb +49 -0
  62. data/test/upgrow/input_test.rb +65 -0
  63. data/test/upgrow/model_test.rb +27 -0
  64. data/test/upgrow/result_test.rb +95 -0
  65. metadata +128 -7
  66. data/test/documentation_test.rb +0 -10
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+ # Be sure to restart your server when you modify this file.
3
+
4
+ # Add new mime types for use in respond_to blocks:
5
+ # Mime::Type.register "text/richtext", :rtf
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ # Define an application-wide HTTP permissions policy. For further
3
+ # information see https://developers.google.com/web/updates/2018/06/feature-policy
4
+ #
5
+ # Rails.application.config.permissions_policy do |f|
6
+ # f.camera :none
7
+ # f.gyroscope :none
8
+ # f.microphone :none
9
+ # f.usb :none
10
+ # f.fullscreen :self
11
+ # f.payment :self, "https://secure.example.com"
12
+ # end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+ # Be sure to restart your server when you modify this file.
3
+
4
+ # This file contains settings for ActionController::ParamsWrapper which
5
+ # is enabled by default.
6
+
7
+ # Enable parameter wrapping for JSON. You can disable this by setting :format to
8
+ # an empty array.
9
+ ActiveSupport.on_load(:action_controller) do
10
+ wrap_parameters format: [:json]
11
+ end
12
+
13
+ # To enable root element in JSON for ActiveRecord objects.
14
+ # ActiveSupport.on_load(:active_record) do
15
+ # self.include_root_in_json = true
16
+ # end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+ # Puma can serve each request in a thread from an internal thread pool.
3
+ # The `threads` method setting takes two numbers: a minimum and maximum.
4
+ # Any libraries that use thread pools should be configured to match
5
+ # the maximum value specified for Puma. Default is set to 5 threads for minimum
6
+ # and maximum; this matches the default thread size of Active Record.
7
+ #
8
+ max_threads_count = ENV.fetch('RAILS_MAX_THREADS') { 5 }
9
+ min_threads_count = ENV.fetch('RAILS_MIN_THREADS') { max_threads_count }
10
+ threads min_threads_count, max_threads_count
11
+
12
+ # Specifies the `worker_timeout` threshold that Puma will use to wait before
13
+ # terminating a worker in development environments.
14
+ #
15
+ worker_timeout 3600 if ENV.fetch('RAILS_ENV', 'development') == 'development'
16
+
17
+ # Specifies the `port` that Puma will listen on to receive requests.
18
+ #
19
+ port ENV.fetch('PORT') { 3000 }
20
+
21
+ # Specifies the `environment` that Puma will run in.
22
+ #
23
+ environment ENV.fetch('RAILS_ENV') { 'development' }
24
+
25
+ # Specifies the `pidfile` that Puma will use.
26
+ pidfile ENV.fetch('PIDFILE') { 'tmp/pids/server.pid' }
27
+
28
+ # Specifies the number of `workers` to boot in clustered mode.
29
+ # Workers are forked web server processes. If using threads and workers together
30
+ # the concurrency of the application would be max `threads` * `workers`.
31
+ # Workers do not work on JRuby or Windows (both of which do not support
32
+ # processes).
33
+ #
34
+ # workers ENV.fetch("WEB_CONCURRENCY") { 2 }
35
+
36
+ # Use the `preload_app!` method when specifying a `workers` number.
37
+ # This directive tells Puma to first boot the application and load code
38
+ # before forking the application. This takes advantage of Copy On Write
39
+ # process behavior so workers use less memory.
40
+ #
41
+ # preload_app!
42
+
43
+ # Allow puma to be restarted by `rails restart` command.
44
+ plugin :tmp_restart
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rails.application.routes.draw do
4
+ resources :articles
5
+
6
+ root 'articles#index'
7
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ class CreateArticles < ActiveRecord::Migration[6.1]
3
+ def change
4
+ create_table(:articles) do |t|
5
+ t.string(:title, null: false)
6
+ t.text(:body, null: false)
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,22 @@
1
+ # This file is auto-generated from the current state of the database. Instead
2
+ # of editing this file, please use the migrations feature of Active Record to
3
+ # incrementally modify your database, and then regenerate this schema definition.
4
+ #
5
+ # This file is the source Rails uses to define your schema when running `bin/rails
6
+ # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
7
+ # be faster and is potentially less error prone than running all of your
8
+ # migrations from scratch. Old migrations may fail to apply correctly if those
9
+ # migrations use external dependencies or application code.
10
+ #
11
+ # It's strongly recommended that you check this file into your version control system.
12
+
13
+ ActiveRecord::Schema.define(version: 2021_02_19_211631) do
14
+
15
+ create_table "articles", force: :cascade do |t|
16
+ t.string "title", null: false
17
+ t.text "body", null: false
18
+ t.datetime "created_at", precision: 6, null: false
19
+ t.datetime "updated_at", precision: 6, null: false
20
+ end
21
+
22
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ ENV['RAILS_ENV'] = 'test'
4
+
5
+ require_relative '../test/dummy/config/environment'
6
+ ActiveRecord::Migrator.migrations_paths = [File.expand_path(
7
+ '../test/dummy/db/migrate', __dir__
8
+ )]
9
+ require 'rails/test_help'
10
+
11
+ # Load fixtures from the engine
12
+ if ActiveSupport::TestCase.respond_to?(:fixture_path=)
13
+ ActiveSupport::TestCase.fixture_path = File.expand_path('fixtures', __dir__)
14
+ ActionDispatch::IntegrationTest.fixture_path =
15
+ ActiveSupport::TestCase.fixture_path
16
+ ActiveSupport::TestCase.file_fixture_path =
17
+ ActiveSupport::TestCase.fixture_path + '/files'
18
+ ActiveSupport::TestCase.fixtures(:all)
19
+ end
20
+
21
+ Warning[:deprecated] = true
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'application_system_test_case'
4
+
5
+ class ArticlesTest < ApplicationSystemTestCase
6
+ test 'a message is shown when there are no Articles' do
7
+ visit root_path
8
+ assert_title 'Articles'
9
+ assert_text 'There are no Articles just yet.'
10
+ end
11
+
12
+ test 'Article can be created' do
13
+ visit root_path
14
+ click_on 'New Article'
15
+ assert_title 'New Article'
16
+
17
+ fill_in 'Title', with: 'My title'
18
+ fill_in 'Body', with: 'My long body'
19
+ click_on 'Create'
20
+
21
+ assert_text 'Article was successfully created.'
22
+ assert_title 'My title'
23
+ assert_text 'My long body'
24
+ end
25
+
26
+ test 'validation errors are shown' do
27
+ visit root_path
28
+ click_on 'New Article'
29
+ click_on 'Create'
30
+
31
+ assert_text "Title can't be blank"
32
+ assert_text "Body can't be blank"
33
+ assert_text 'Body is too short (minimum is 10 characters)'
34
+ end
35
+
36
+ test 'previously entered data is shown' do
37
+ visit root_path
38
+ click_on 'New Article'
39
+ fill_in 'Body', with: 'Short'
40
+ click_on 'Create'
41
+
42
+ assert_text 'Body is too short (minimum is 10 characters)'
43
+ assert_field 'Body', with: 'Short'
44
+ end
45
+
46
+ test 'new Article is listed in the index page' do
47
+ visit root_path
48
+ click_on 'New Article'
49
+ fill_in 'Title', with: 'My title'
50
+ fill_in 'Body', with: 'My long body'
51
+ click_on 'Create'
52
+ click_on 'Back'
53
+
54
+ assert_link 'My title'
55
+ assert_text 'My long body'
56
+ end
57
+
58
+ test 'Article can be edited' do
59
+ visit root_path
60
+ click_on 'New Article'
61
+ fill_in 'Title', with: 'My title'
62
+ fill_in 'Body', with: 'My long body'
63
+ click_on 'Create'
64
+ click_on 'Edit'
65
+
66
+ assert_title 'Edit Article'
67
+
68
+ assert_field 'Title', with: 'My title'
69
+ assert_field 'Body', with: 'My long body'
70
+
71
+ fill_in 'Title', with: 'Edited title'
72
+ fill_in 'Body', with: 'Edited body'
73
+ click_on 'Update'
74
+
75
+ assert_text 'Article was successfully updated.'
76
+ assert_title 'Edited title'
77
+ assert_text 'Edited body'
78
+ end
79
+
80
+ test 'validation errors are shown when editing Article' do
81
+ visit root_path
82
+ click_on 'New Article'
83
+ fill_in 'Title', with: 'My title'
84
+ fill_in 'Body', with: 'My long body'
85
+ click_on 'Create'
86
+ click_on 'Edit'
87
+
88
+ fill_in 'Title', with: ''
89
+ fill_in 'Body', with: 'Short'
90
+ click_on 'Update'
91
+
92
+ assert_text "Title can't be blank"
93
+ assert_text 'Body is too short (minimum is 10 characters)'
94
+ assert_field 'Title', with: ''
95
+ assert_field 'Body', with: 'Short'
96
+ end
97
+
98
+ test 'Article can be deleted' do
99
+ visit root_path
100
+ click_on 'New Article'
101
+ fill_in 'Title', with: 'My title'
102
+ fill_in 'Body', with: 'My long body'
103
+ click_on 'Create'
104
+ click_on 'Destroy'
105
+
106
+ assert_text 'Article was successfully destroyed'
107
+ assert_text 'There are no Articles just yet.'
108
+ end
109
+ end
data/test/test_helper.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'minitest/autorun'
4
- require 'active_support'
5
- require 'active_support/test_case'
6
-
4
+ require 'pry-byebug'
7
5
  require 'upgrow'
6
+
7
+ Warning[:deprecated] = true
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ module Upgrow
6
+ class ActionTest < ActiveSupport::TestCase
7
+ test '.result_class is an empty Result by default' do
8
+ assert_equal([:errors], Action.result_class.members)
9
+ end
10
+
11
+ test '.result sets the members in the Action Result class' do
12
+ result_class = Action.result_class
13
+
14
+ Action.result(:user, :data)
15
+
16
+ assert_equal([:user, :data, :errors], Action.result_class.members)
17
+
18
+ Action.result_class = result_class
19
+ end
20
+
21
+ test '#result returns the Result class from the Action class' do
22
+ assert_equal Action.result_class, Action.new.result
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ module Upgrow
6
+ class ActiveRecordAdapterTest < ActiveSupport::TestCase
7
+ class User < Model
8
+ attribute :name
9
+ end
10
+
11
+ class UserInput < Input
12
+ attribute :name
13
+ end
14
+
15
+ class UserRepository < BasicRepository
16
+ include ActiveRecordAdapter
17
+ end
18
+
19
+ class UserRecord; end
20
+
21
+ setup do
22
+ freeze_time
23
+ @base = Minitest::Mock.new
24
+ @repository = UserRepository.new(base: @base)
25
+ @record = Minitest::Mock.new
26
+ @record_attributes = {
27
+ name: 'volmer', id: 1, created_at: Time.now, updated_at: Time.now
28
+ }
29
+ @record.expect(:attributes, @record_attributes)
30
+ end
31
+
32
+ test '.new sets base to the Active Record Base class according to the Repository name by default' do
33
+ repository = UserRepository.new
34
+ assert_equal UserRecord, repository.base
35
+ end
36
+
37
+ test '#all returns all Records as Models' do
38
+ @base.expect(:all, [@record])
39
+
40
+ all = @repository.all
41
+
42
+ assert all.one?
43
+
44
+ assert_equal 1, all.first.id
45
+ assert_equal 'volmer', all.first.name
46
+ assert_equal Time.now, all.first.created_at
47
+ assert_equal Time.now, all.first.updated_at
48
+ end
49
+
50
+ test '#find retrieves the Model for the given ID' do
51
+ @base.expect(:find, @record, [1])
52
+
53
+ model = @repository.find(1)
54
+
55
+ assert_equal 1, model.id
56
+ assert_equal 'volmer', model.name
57
+ assert_equal Time.now, model.created_at
58
+ assert_equal Time.now, model.updated_at
59
+ end
60
+
61
+ test '#create creates a new Record with the given attributes' do
62
+ input = UserInput.new(name: 'volmer')
63
+
64
+ @base.expect(:create!, @record, [{ name: 'volmer' }])
65
+
66
+ model = @repository.create(input)
67
+
68
+ assert_equal 1, model.id
69
+ assert_equal 'volmer', model.name
70
+ assert_equal Time.now, model.created_at
71
+ assert_equal Time.now, model.updated_at
72
+ end
73
+
74
+ test '#update changes the existing Record attributes' do
75
+ input = UserInput.new(name: 'rafael')
76
+
77
+ @base.expect(:update, @record, [1, { name: 'rafael' }])
78
+ @record_attributes[:name] = 'rafael'
79
+
80
+ model = @repository.update(1, input)
81
+
82
+ assert_equal 1, model.id
83
+ assert_equal 'rafael', model.name
84
+ assert_equal Time.now, model.created_at
85
+ assert_equal Time.now, model.updated_at
86
+ end
87
+
88
+ test '#delete deletes the Record with the given ID' do
89
+ @base.expect(:destroy, true, [1])
90
+
91
+ @repository.delete(1)
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ module Upgrow
6
+ class BasicRepositoryTest < ActiveSupport::TestCase
7
+ class User < Model; end
8
+
9
+ class UserRepository < BasicRepository; end
10
+
11
+ class NoModelRepository < BasicRepository; end
12
+
13
+ setup do
14
+ freeze_time
15
+
16
+ @repository = UserRepository.new
17
+ end
18
+
19
+ test '.new instantiates a new Repository with a base and a Model class' do
20
+ repository = UserRepository.new(base: :my_base, model_class: User)
21
+
22
+ assert_equal :my_base, repository.base
23
+ assert_equal User, repository.model_class
24
+ end
25
+
26
+ test '.new sets the base to nil by default' do
27
+ assert_nil @repository.base
28
+ end
29
+
30
+ test '.new sets the Model class by default to a constant derived from the Repository name' do
31
+ assert_equal User, @repository.model_class
32
+ end
33
+
34
+ test '.new raises a Name Error if the Model class is undefined' do
35
+ error = assert_raises(NameError) do
36
+ NoModelRepository.new(base: :my_base)
37
+ end
38
+
39
+ assert_includes(
40
+ error.message,
41
+ 'uninitialized constant Upgrow::BasicRepositoryTest::NoModel'
42
+ )
43
+ end
44
+
45
+ test '.to_model returns a new Model with the given attributes as keyword arguments' do
46
+ model = @repository.to_model(
47
+ id: 1, created_at: Time.now, updated_at: Time.now
48
+ )
49
+
50
+ assert_equal 1, model.id
51
+ assert_equal Time.now, model.created_at
52
+ assert_equal Time.now, model.updated_at
53
+ end
54
+
55
+ test '.to_model accepts a Hash of Symbols' do
56
+ args = { id: 1, created_at: Time.now, updated_at: Time.now }
57
+ model = @repository.to_model(args)
58
+
59
+ assert_equal 1, model.id
60
+ assert_equal Time.now, model.created_at
61
+ assert_equal Time.now, model.updated_at
62
+ end
63
+
64
+ test '.to_model accepts a Hash of Strings' do
65
+ args = { 'id' => 1, 'created_at' => Time.now, 'updated_at' => Time.now }
66
+ model = @repository.to_model(args)
67
+
68
+ assert_equal 1, model.id
69
+ assert_equal Time.now, model.created_at
70
+ assert_equal Time.now, model.updated_at
71
+ end
72
+ end
73
+ end