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.
- checksums.yaml +4 -4
- data/README.md +45 -12
- data/Rakefile +8 -4
- data/lib/upgrow.rb +13 -2
- data/lib/upgrow/action.rb +54 -0
- data/lib/upgrow/active_record_adapter.rb +73 -0
- data/lib/upgrow/basic_repository.rb +45 -0
- data/lib/upgrow/immutable_object.rb +57 -0
- data/lib/upgrow/immutable_struct.rb +40 -0
- data/lib/upgrow/input.rb +47 -0
- data/lib/upgrow/model.rb +35 -0
- data/lib/upgrow/repository.rb +12 -0
- data/lib/upgrow/result.rb +94 -0
- data/test/application_system_test_case.rb +13 -0
- data/test/dummy/app/actions/create_article_action.rb +13 -0
- data/test/dummy/app/actions/delete_article_action.rb +7 -0
- data/test/dummy/app/actions/edit_article_action.rb +10 -0
- data/test/dummy/app/actions/list_articles_action.rb +8 -0
- data/test/dummy/app/actions/show_article_action.rb +10 -0
- data/test/dummy/app/actions/update_article_action.rb +13 -0
- data/test/dummy/app/channels/application_cable/channel.rb +5 -0
- data/test/dummy/app/channels/application_cable/connection.rb +5 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/controllers/articles_controller.rb +64 -0
- data/test/dummy/app/helpers/application_helper.rb +102 -0
- data/test/dummy/app/inputs/article_input.rb +8 -0
- data/test/dummy/app/jobs/application_job.rb +9 -0
- data/test/dummy/app/mailers/application_mailer.rb +5 -0
- data/test/dummy/app/models/article.rb +6 -0
- data/test/dummy/app/records/application_record.rb +5 -0
- data/test/dummy/app/records/article_record.rb +5 -0
- data/test/dummy/app/repositories/article_repository.rb +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +6 -0
- data/test/dummy/config/environment.rb +6 -0
- data/test/dummy/config/environments/development.rb +79 -0
- data/test/dummy/config/environments/production.rb +133 -0
- data/test/dummy/config/environments/test.rb +61 -0
- data/test/dummy/config/initializers/application_controller_renderer.rb +9 -0
- data/test/dummy/config/initializers/assets.rb +13 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +12 -0
- data/test/dummy/config/initializers/content_security_policy.rb +31 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +6 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +17 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/permissions_policy.rb +12 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +16 -0
- data/test/dummy/config/puma.rb +44 -0
- data/test/dummy/config/routes.rb +7 -0
- data/test/dummy/db/migrate/20210219211631_create_articles.rb +11 -0
- data/test/dummy/db/schema.rb +22 -0
- data/test/rails_helper.rb +21 -0
- data/test/system/articles_test.rb +109 -0
- data/test/test_helper.rb +3 -3
- data/test/upgrow/action_test.rb +25 -0
- data/test/upgrow/active_record_adapter_test.rb +94 -0
- data/test/upgrow/basic_repository_test.rb +73 -0
- data/test/upgrow/documentation_test.rb +12 -0
- data/test/upgrow/immutable_object_test.rb +60 -0
- data/test/upgrow/immutable_struct_test.rb +49 -0
- data/test/upgrow/input_test.rb +65 -0
- data/test/upgrow/model_test.rb +27 -0
- data/test/upgrow/result_test.rb +95 -0
- metadata +128 -7
- data/test/documentation_test.rb +0 -10
@@ -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,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
@@ -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
|