upgrow 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|