command_model 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +26 -0
- data/.gitignore +1 -1
- data/.ruby-version +1 -0
- data/.tool-versions +1 -0
- data/Gemfile.lock +50 -0
- data/README.md +135 -54
- data/Rakefile +4 -7
- data/bin/rake +27 -0
- data/command_model.gemspec +4 -5
- data/examples/bank/Gemfile +4 -4
- data/examples/bank/app/controllers/accounts_controller.rb +12 -12
- data/examples/bank/app/controllers/transfers_controller.rb +3 -3
- data/examples/bank/app/views/accounts/deposit_form.html.erb +1 -5
- data/examples/bank/app/views/accounts/withdraw_form.html.erb +1 -5
- data/examples/bank/app/views/layouts/application.html.erb +1 -1
- data/examples/bank/app/views/transfers/new.html.erb +2 -6
- data/examples/bank/config/application.rb +1 -1
- data/examples/bank/config/routes.rb +6 -6
- data/examples/bank/test/performance/browsing_test.rb +2 -2
- data/gemfiles/{5.0.gemfile → 6.1.gemfile} +1 -1
- data/gemfiles/6.1.gemfile.lock +52 -0
- data/gemfiles/{5.1.gemfile → 7.0.gemfile} +1 -1
- data/gemfiles/7.0.gemfile.lock +50 -0
- data/gemfiles/7.1.gemfile +5 -0
- data/gemfiles/7.1.gemfile.lock +60 -0
- data/lib/command_model/convert.rb +1 -1
- data/lib/command_model/model.rb +61 -16
- data/lib/command_model/version.rb +1 -1
- data/spec/convert_spec.rb +5 -4
- data/spec/model_spec.rb +129 -6
- metadata +24 -17
- data/.travis.yml +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ae545ab3c7c527111971b821772770a8b050f897550fa3512c6476edd67182d1
|
4
|
+
data.tar.gz: be5789d54e5e90730445343e9d29bd789c6a3f5f42e34a5f78075996ae51d929
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 02613c5fed0d0518ac3bff0a2d7b0fc77974d323693e1f18068d767c28bc4cc7521bb7fdece9a49ef5ef8c82a4213c098edb61972a391cb6b2be90570efc349c
|
7
|
+
data.tar.gz: d683d0d3823c268784c1821c9defed0f68fb3cc7c5cda98440d2676bae7845d8b2e6aa94de6f5ce3665b9235f7bd25efe1ec51b312342441efec370feb9d2ea9
|
@@ -0,0 +1,26 @@
|
|
1
|
+
name: "Ruby CI"
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
branches: ["master"]
|
5
|
+
pull_request:
|
6
|
+
branches: ["master"]
|
7
|
+
jobs:
|
8
|
+
test:
|
9
|
+
strategy:
|
10
|
+
fail-fast: false
|
11
|
+
matrix:
|
12
|
+
ruby: ['3.2', '3.3']
|
13
|
+
gemfile: [ "6.1", "7.0", "7.1" ]
|
14
|
+
runs-on: ubuntu-latest
|
15
|
+
env:
|
16
|
+
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
|
17
|
+
steps:
|
18
|
+
- name: Checkout code
|
19
|
+
uses: actions/checkout@v4
|
20
|
+
- name: Install Ruby and gems
|
21
|
+
uses: ruby/setup-ruby@v1
|
22
|
+
with:
|
23
|
+
ruby-version: ${{ matrix.ruby }}
|
24
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
25
|
+
- name: Run tests
|
26
|
+
run: bin/rake
|
data/.gitignore
CHANGED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.2.2
|
data/.tool-versions
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby 3.2.2
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
command_model (2.1.0)
|
5
|
+
activemodel (> 6.1)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
activemodel (7.0.4.3)
|
11
|
+
activesupport (= 7.0.4.3)
|
12
|
+
activesupport (7.0.4.3)
|
13
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
14
|
+
i18n (>= 1.6, < 2)
|
15
|
+
minitest (>= 5.1)
|
16
|
+
tzinfo (~> 2.0)
|
17
|
+
concurrent-ruby (1.2.2)
|
18
|
+
diff-lcs (1.5.1)
|
19
|
+
i18n (1.12.0)
|
20
|
+
concurrent-ruby (~> 1.0)
|
21
|
+
minitest (5.18.0)
|
22
|
+
rake (13.1.0)
|
23
|
+
rspec (3.13.0)
|
24
|
+
rspec-core (~> 3.13.0)
|
25
|
+
rspec-expectations (~> 3.13.0)
|
26
|
+
rspec-mocks (~> 3.13.0)
|
27
|
+
rspec-core (3.13.0)
|
28
|
+
rspec-support (~> 3.13.0)
|
29
|
+
rspec-expectations (3.13.0)
|
30
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
31
|
+
rspec-support (~> 3.13.0)
|
32
|
+
rspec-mocks (3.13.0)
|
33
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
34
|
+
rspec-support (~> 3.13.0)
|
35
|
+
rspec-support (3.13.1)
|
36
|
+
tzinfo (2.0.6)
|
37
|
+
concurrent-ruby (~> 1.0)
|
38
|
+
|
39
|
+
PLATFORMS
|
40
|
+
arm64-darwin-22
|
41
|
+
arm64-darwin-23
|
42
|
+
x86_64-linux
|
43
|
+
|
44
|
+
DEPENDENCIES
|
45
|
+
command_model!
|
46
|
+
rake (~> 13.1.0)
|
47
|
+
rspec (~> 3.13.0)
|
48
|
+
|
49
|
+
BUNDLED WITH
|
50
|
+
2.4.3
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
[![Build Status](https://
|
1
|
+
[![Build Status](https://github.com/jackc/command_model/actions/workflows/ci.yml/badge.svg)](https://github.com/jackc/command_model/actions/workflows/ci.yml)
|
2
2
|
|
3
3
|
# CommandModel
|
4
4
|
|
@@ -14,11 +14,13 @@ to work with once your domain operations become more complex. Domain models
|
|
14
14
|
usually have richer behavior than can be represented with a typical
|
15
15
|
ActiveRecord style update_attributes.
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
```ruby
|
18
|
+
# yuck!
|
19
|
+
account.update_attributes balance: account.balance - 50
|
19
20
|
|
20
|
-
|
21
|
-
|
21
|
+
# much better
|
22
|
+
account.withdraw amount: 50
|
23
|
+
```
|
22
24
|
|
23
25
|
But there are multiple complications with the OO approach. How do we integrate
|
24
26
|
Rails style validations? How are user-supplied strings type converted? How do we
|
@@ -28,27 +30,35 @@ know if the command succeeded? CommandModel solves these problems.
|
|
28
30
|
|
29
31
|
Add this line to your application's Gemfile:
|
30
32
|
|
31
|
-
|
33
|
+
```ruby
|
34
|
+
gem 'command_model'
|
35
|
+
```
|
32
36
|
|
33
37
|
And then execute:
|
34
38
|
|
35
|
-
|
39
|
+
```console
|
40
|
+
$ bundle
|
41
|
+
```
|
36
42
|
|
37
43
|
Or install it yourself as:
|
38
44
|
|
39
|
-
|
45
|
+
```console
|
46
|
+
$ gem install command_model
|
47
|
+
```
|
40
48
|
|
41
49
|
## Usage
|
42
50
|
|
43
51
|
Create a class derived from CommandModel::Model to represent the command
|
44
52
|
request.
|
45
53
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
54
|
+
```ruby
|
55
|
+
class WithdrawCommand < CommandModel::Model
|
56
|
+
parameter :amount,
|
57
|
+
convert: :integer,
|
58
|
+
presence: true,
|
59
|
+
numericality: { greater_than: 0, less_than_or_equal_to: 500 }
|
60
|
+
end
|
61
|
+
```
|
52
62
|
|
53
63
|
Create the method to run the command. This method should instantiate and call a new command object. It must pass call
|
54
64
|
a block that actually does the work. The block will only be called if
|
@@ -57,32 +67,36 @@ any further validations that only can be done during execution. If it adds
|
|
57
67
|
any errors to the command object then the command will be considered to have
|
58
68
|
failed. Finally, the call method will return self.
|
59
69
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
def withdraw(args)
|
64
|
-
WithdrawCommand.new(args).call do |command|
|
65
|
-
if balance >= command.amount
|
66
|
-
@balance -= command.amount
|
67
|
-
else
|
68
|
-
command.errors.add :amount, "is more than account balance"
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
70
|
+
```ruby
|
71
|
+
class Account
|
72
|
+
# ...
|
72
73
|
|
73
|
-
|
74
|
+
def withdraw(args)
|
75
|
+
WithdrawCommand.new(args).call do |command|
|
76
|
+
if balance >= command.amount
|
77
|
+
@balance -= command.amount
|
78
|
+
else
|
79
|
+
command.errors.add :amount, "is more than account balance"
|
80
|
+
end
|
74
81
|
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# ...
|
85
|
+
end
|
86
|
+
```
|
75
87
|
|
76
88
|
Use example:
|
77
89
|
|
78
|
-
|
90
|
+
```ruby
|
91
|
+
response = account.withdraw amount: 50
|
79
92
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
93
|
+
if response.success?
|
94
|
+
puts "Success!"
|
95
|
+
else
|
96
|
+
puts "Errors:"
|
97
|
+
puts response.errors.full_messages
|
98
|
+
end
|
99
|
+
```
|
86
100
|
|
87
101
|
## Mixing in Domain Logic
|
88
102
|
|
@@ -93,28 +107,73 @@ method. The execute method is called by the call method if all validations
|
|
93
107
|
succeed. The following is a reimplementation of the previous example with
|
94
108
|
internal domain logic.
|
95
109
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
110
|
+
```ruby
|
111
|
+
class WithdrawCommand < CommandModel::Model
|
112
|
+
parameter :amount,
|
113
|
+
convert: :integer,
|
114
|
+
presence: true,
|
115
|
+
numericality: { greater_than: 0, less_than_or_equal_to: 500 }
|
116
|
+
parameter :account_id, presence: true
|
117
|
+
|
118
|
+
def execute
|
119
|
+
account = Account.find_by_id account_id
|
120
|
+
unless account
|
121
|
+
errors.add :account_id, "not found"
|
122
|
+
return
|
123
|
+
end
|
124
|
+
|
125
|
+
if account.balance >= amount
|
126
|
+
account.balance -= amount
|
127
|
+
else
|
128
|
+
errors.add :amount, "is more than account balance"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
```
|
133
|
+
|
134
|
+
## Dependencies
|
135
|
+
|
136
|
+
Sometimes a command has requires values that are not supplied by the user. For example, a command may require the
|
137
|
+
current user, a database connection, or a logger. These dependencies can be specified with the `dependency` method. The following example adds filtering to ensure that the current user owns the account.
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
class WithdrawCommand < CommandModel::Model
|
141
|
+
dependency :current_user
|
142
|
+
|
143
|
+
parameter :amount,
|
144
|
+
convert: :integer,
|
145
|
+
presence: true,
|
146
|
+
numericality: { greater_than: 0, less_than_or_equal_to: 500 }
|
147
|
+
parameter :account_id, presence: true
|
148
|
+
|
149
|
+
def execute
|
150
|
+
account = current_user.accounts.find_by_id account_id
|
151
|
+
unless account
|
152
|
+
errors.add :account_id, "not found"
|
153
|
+
return
|
116
154
|
end
|
117
155
|
|
156
|
+
if account.balance >= amount
|
157
|
+
account.balance -= amount
|
158
|
+
else
|
159
|
+
errors.add :amount, "is more than account balance"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
```
|
164
|
+
|
165
|
+
This command could be called as follows.
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
WithdrawCommand.execute({amount: 200}, {current_user: current_user})
|
169
|
+
```
|
170
|
+
|
171
|
+
## Inheritance
|
172
|
+
|
173
|
+
Subclasses of `CommandModel::Model` can themselves be subclassed. Parameter and dependency definitions will be copied at
|
174
|
+
the time of subclassing. If the superclass is later modified, the parameter and dependency definitions of the subclasses
|
175
|
+
will not be modified. This may be changed in the future.
|
176
|
+
|
118
177
|
## Other uses
|
119
178
|
|
120
179
|
This could be used to wrap database generated errors into normal Rails
|
@@ -128,8 +187,30 @@ be doing a uniqueness check anyway.
|
|
128
187
|
There is a simple Rails application in examples/bank that demonstrates the
|
129
188
|
integration of Rails form helpers and validations with CommandModel.
|
130
189
|
|
190
|
+
## Testing
|
191
|
+
|
192
|
+
```console
|
193
|
+
$ bundle install
|
194
|
+
$ rake
|
195
|
+
```
|
196
|
+
|
197
|
+
To test against a specific version of Rails / ActiveModel set the BUNDLE_GEMFILE environment variable. For example, to
|
198
|
+
test Rails 6.1:
|
199
|
+
|
200
|
+
```console
|
201
|
+
$ BUNDLE_GEMFILE=gemfiles/6.1.gemfile bundle install
|
202
|
+
$ BUNDLE_GEMFILE=gemfiles/6.1.gemfile rake
|
203
|
+
```
|
204
|
+
|
131
205
|
## Version History
|
132
206
|
|
207
|
+
* 2.1.0 - March 15, 2023
|
208
|
+
* Add dependencies to CommandModel::Model
|
209
|
+
* Allow inheritance of CommandModel::Model
|
210
|
+
* Require Ruby 3.2+
|
211
|
+
* Require Rails / ActiveModel 6.1+
|
212
|
+
* 2.0.1 - April 3, 2023
|
213
|
+
* Date parsing allows 5 digit years
|
133
214
|
* 2.0 - April 11, 2018
|
134
215
|
* Rename typecast parameter option to convert
|
135
216
|
* Any callable object can be used as a type converter
|
data/Rakefile
CHANGED
@@ -1,10 +1,7 @@
|
|
1
|
-
|
1
|
+
require "bundler/setup"
|
2
2
|
require "bundler/gem_tasks"
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
RSpec::Core::RakeTask.new(:spec)
|
7
|
-
rescue LoadError
|
8
|
-
end
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
9
6
|
|
10
|
-
task :
|
7
|
+
task default: :spec
|
data/bin/rake
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rake' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
12
|
+
|
13
|
+
bundle_binstub = File.expand_path("bundle", __dir__)
|
14
|
+
|
15
|
+
if File.file?(bundle_binstub)
|
16
|
+
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
|
17
|
+
load(bundle_binstub)
|
18
|
+
else
|
19
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
require "rubygems"
|
25
|
+
require "bundler/setup"
|
26
|
+
|
27
|
+
load Gem.bin_path("rake", "rake")
|
data/command_model.gemspec
CHANGED
@@ -9,16 +9,15 @@ Gem::Specification.new do |gem|
|
|
9
9
|
gem.homepage = "https://github.com/JackC/command_model"
|
10
10
|
|
11
11
|
gem.files = `git ls-files`.split($\)
|
12
|
-
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
12
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
13
|
gem.name = "command_model"
|
15
14
|
gem.require_paths = ["lib"]
|
16
15
|
gem.version = CommandModel::VERSION
|
17
16
|
|
18
|
-
gem.required_ruby_version = '>= 2.
|
17
|
+
gem.required_ruby_version = '>= 3.2.0'
|
19
18
|
|
20
|
-
gem.add_dependency 'activemodel', ">
|
19
|
+
gem.add_dependency 'activemodel', "> 6.1"
|
21
20
|
|
22
|
-
gem.add_development_dependency 'rake', "~>
|
23
|
-
gem.add_development_dependency 'rspec', "~> 3.
|
21
|
+
gem.add_development_dependency 'rake', "~> 13.1.0"
|
22
|
+
gem.add_development_dependency 'rspec', "~> 3.13.0"
|
24
23
|
end
|
data/examples/bank/Gemfile
CHANGED
@@ -3,9 +3,9 @@ source 'https://rubygems.org'
|
|
3
3
|
gem 'rails', '3.2.8'
|
4
4
|
|
5
5
|
# Bundle edge Rails instead:
|
6
|
-
# gem 'rails', :
|
6
|
+
# gem 'rails', git: 'git://github.com/rails/rails.git'
|
7
7
|
|
8
|
-
gem 'command_model', :
|
8
|
+
gem 'command_model', path: '../..'
|
9
9
|
|
10
10
|
|
11
11
|
# Gems used only for assets and not required
|
@@ -15,7 +15,7 @@ group :assets do
|
|
15
15
|
gem 'coffee-rails', '~> 3.2.1'
|
16
16
|
|
17
17
|
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
|
18
|
-
# gem 'therubyracer', :
|
18
|
+
# gem 'therubyracer', platform: :ruby
|
19
19
|
|
20
20
|
gem 'uglifier', '>= 1.0.3'
|
21
21
|
end
|
@@ -35,4 +35,4 @@ gem 'jquery-rails'
|
|
35
35
|
# gem 'capistrano'
|
36
36
|
|
37
37
|
# To use debugger
|
38
|
-
# gem 'ruby-debug19', :
|
38
|
+
# gem 'ruby-debug19', require: 'ruby-debug'
|
@@ -7,44 +7,44 @@
|
|
7
7
|
@account = Account.find_by_name params[:id]
|
8
8
|
@deposit = Account::DepositCommand.new
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
def deposit
|
12
12
|
@account = Account.find_by_name params[:id]
|
13
13
|
@deposit = @account.deposit params[:deposit]
|
14
|
-
|
14
|
+
|
15
15
|
if @deposit.success?
|
16
|
-
redirect_to root_path, :
|
16
|
+
redirect_to root_path, notice: "Deposited #{@deposit.amount} to #{@account.name}'s account."
|
17
17
|
else
|
18
18
|
render "deposit_form"
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
def withdraw_form
|
23
23
|
@account = Account.find_by_name params[:id]
|
24
24
|
@withdraw = Account::WithdrawCommand.new
|
25
|
-
end
|
26
|
-
|
25
|
+
end
|
26
|
+
|
27
27
|
def withdraw
|
28
28
|
@account = Account.find_by_name params[:id]
|
29
29
|
@withdraw = @account.withdraw params[:withdraw]
|
30
|
-
|
30
|
+
|
31
31
|
if @withdraw.success?
|
32
|
-
redirect_to root_path, :
|
32
|
+
redirect_to root_path, notice: "Withdrew #{@withdraw.amount} from #{@account.name}'s account."
|
33
33
|
else
|
34
34
|
render "withdraw_form"
|
35
|
-
end
|
35
|
+
end
|
36
36
|
end
|
37
37
|
|
38
38
|
def transfer_form
|
39
39
|
@accounts = Account.all
|
40
40
|
@transfer = Account::TransferCommand.new
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
def transfer
|
44
44
|
@transfer = Account::TransferCommand.new(params[:transfer])
|
45
|
-
|
45
|
+
|
46
46
|
if @transfer.call.success?
|
47
|
-
redirect_to root_path, :
|
47
|
+
redirect_to root_path, notice: "Transferred #{@transfer.amount} from #{@transfer.from.name}'s account to #{@transfer.to.name}'s account."
|
48
48
|
else
|
49
49
|
@accounts = Account.all
|
50
50
|
render "transfer_form"
|
@@ -3,12 +3,12 @@ class TransfersController < ApplicationController
|
|
3
3
|
@accounts = Account.all
|
4
4
|
@transfer = Account::Transfer.new
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
7
|
def create
|
8
8
|
@transfer = Account::Transfer.new(params[:transfer])
|
9
|
-
|
9
|
+
|
10
10
|
if @transfer.call.success?
|
11
|
-
redirect_to root_path, :
|
11
|
+
redirect_to root_path, notice: "Transferred #{@transfer.amount} from #{@transfer.from.name}'s account to #{@transfer.to.name}'s account."
|
12
12
|
else
|
13
13
|
@accounts = Account.all
|
14
14
|
render :new
|
@@ -12,12 +12,8 @@
|
|
12
12
|
</ul>
|
13
13
|
<% end %>
|
14
14
|
|
15
|
-
<%= form_for @deposit, :
|
15
|
+
<%= form_for @deposit, as: :deposit, url: account_deposit_path(@account) do |f| %>
|
16
16
|
<%= f.label :amount %>
|
17
17
|
<%= f.text_field :amount %>
|
18
18
|
<%= f.submit "Deposit" %>
|
19
19
|
<% end %>
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
@@ -12,12 +12,8 @@
|
|
12
12
|
</ul>
|
13
13
|
<% end %>
|
14
14
|
|
15
|
-
<%= form_for @withdraw, :
|
15
|
+
<%= form_for @withdraw, as: :withdraw, url: account_withdraw_path(@account) do |f| %>
|
16
16
|
<%= f.label :amount %>
|
17
17
|
<%= f.text_field :amount %>
|
18
18
|
<%= f.submit "Deposit" %>
|
19
19
|
<% end %>
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
@@ -14,11 +14,11 @@
|
|
14
14
|
<%= form_for @transfer do |f| %>
|
15
15
|
<div>
|
16
16
|
<%= f.label :from_name %><br />
|
17
|
-
<%= f.select :from_name, @accounts.map { |a| ["#{a.name} - #{a.balance}", a.name] }, :
|
17
|
+
<%= f.select :from_name, @accounts.map { |a| ["#{a.name} - #{a.balance}", a.name] }, selected: f.object.from_name, include_blank: true %>
|
18
18
|
</div>
|
19
19
|
<div>
|
20
20
|
<%= f.label :to_name %><br />
|
21
|
-
<%= f.select :to_name, @accounts.map { |a| ["#{a.name} - #{a.balance}", a.name] }, :
|
21
|
+
<%= f.select :to_name, @accounts.map { |a| ["#{a.name} - #{a.balance}", a.name] }, selected: f.object.to_name, include_blank: true %>
|
22
22
|
</div>
|
23
23
|
<div>
|
24
24
|
<%= f.label :amount %><br />
|
@@ -26,7 +26,3 @@
|
|
26
26
|
</div>
|
27
27
|
<%= f.submit "Transfer" %>
|
28
28
|
<% end %>
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
@@ -10,7 +10,7 @@ require "rails/test_unit/railtie"
|
|
10
10
|
|
11
11
|
if defined?(Bundler)
|
12
12
|
# If you precompile assets before deploying to production, use this line
|
13
|
-
Bundler.require(*Rails.groups(:
|
13
|
+
Bundler.require(*Rails.groups(assets: %w(development test)))
|
14
14
|
# If you want your assets lazily compiled in production, use this line
|
15
15
|
# Bundler.require(:default, :assets, Rails.env)
|
16
16
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
Bank::Application.routes.draw do
|
2
|
-
get "accounts/:id/withdraw" => "accounts#withdraw_form", :
|
3
|
-
post "accounts/:id/withdraw" => "accounts#withdraw", :
|
4
|
-
|
5
|
-
get "accounts/:id/deposit" => "accounts#deposit_form", :
|
6
|
-
post "accounts/:id/deposit" => "accounts#deposit", :
|
2
|
+
get "accounts/:id/withdraw" => "accounts#withdraw_form", as: :account_withdraw_form
|
3
|
+
post "accounts/:id/withdraw" => "accounts#withdraw", as: :account_withdraw
|
4
|
+
|
5
|
+
get "accounts/:id/deposit" => "accounts#deposit_form", as: :account_deposit_form
|
6
|
+
post "accounts/:id/deposit" => "accounts#deposit", as: :account_deposit
|
7
7
|
|
8
8
|
resources :transfers, only: %w[new create]
|
9
9
|
|
10
|
-
root :
|
10
|
+
root to: "accounts#index"
|
11
11
|
end
|
@@ -3,8 +3,8 @@ require 'rails/performance_test_help'
|
|
3
3
|
|
4
4
|
class BrowsingTest < ActionDispatch::PerformanceTest
|
5
5
|
# Refer to the documentation for all available options
|
6
|
-
# self.profile_options = { :
|
7
|
-
# :
|
6
|
+
# self.profile_options = { runs: 5, metrics: [:wall_time, :memory]
|
7
|
+
# output: 'tmp/performance', formats: [:flat] }
|
8
8
|
|
9
9
|
def test_homepage
|
10
10
|
get '/'
|