katapult 0.1.0
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 +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/Guardfile +11 -0
- data/LICENSE.txt +22 -0
- data/README.md +122 -0
- data/Rakefile +14 -0
- data/bin/katapult +44 -0
- data/features/binary.feature +48 -0
- data/features/configuration.feature +24 -0
- data/features/katapult.feature +201 -0
- data/features/model.feature +203 -0
- data/features/navigation.feature +80 -0
- data/features/step_definitions/db_steps.rb +8 -0
- data/features/step_definitions/file_steps.rb +14 -0
- data/features/step_definitions/katapult_steps.rb +14 -0
- data/features/step_definitions/rails_steps.rb +44 -0
- data/features/step_definitions/test_steps.rb +7 -0
- data/features/support/env.rb +16 -0
- data/features/wui.feature +319 -0
- data/katapult.gemspec +35 -0
- data/katapult.png +0 -0
- data/lib/generators/katapult/basics/basics_generator.rb +95 -0
- data/lib/generators/katapult/basics/templates/Gemfile +76 -0
- data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application.css.sass +6 -0
- data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_all.css.sass +4 -0
- data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_items.css.sass +11 -0
- data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_layout.css.sass +26 -0
- data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_navigation.css.sass +11 -0
- data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_tools.css.sass +12 -0
- data/lib/generators/katapult/basics/templates/config/database.sample.yml +16 -0
- data/lib/generators/katapult/basics/templates/config/database.yml +13 -0
- data/lib/generators/katapult/basics/templates/config/spring.rb +3 -0
- data/lib/generators/katapult/basics/templates/features/support/env-custom.rb +3 -0
- data/lib/generators/katapult/basics/templates/features/support/paths.rb +47 -0
- data/lib/generators/katapult/cucumber_features/cucumber_features_generator.rb +23 -0
- data/lib/generators/katapult/cucumber_features/templates/feature.feature +59 -0
- data/lib/generators/katapult/haml/haml_generator.rb +90 -0
- data/lib/generators/katapult/haml/templates/_form.html.haml +38 -0
- data/lib/generators/katapult/haml/templates/app/views/layouts/application.html.haml +25 -0
- data/lib/generators/katapult/haml/templates/custom_action.html.haml +5 -0
- data/lib/generators/katapult/haml/templates/edit.html.haml +4 -0
- data/lib/generators/katapult/haml/templates/index.html.haml +29 -0
- data/lib/generators/katapult/haml/templates/new.html.haml +4 -0
- data/lib/generators/katapult/haml/templates/show.html.haml +41 -0
- data/lib/generators/katapult/install/install_generator.rb +14 -0
- data/lib/generators/katapult/install/templates/lib/katapult/application_model.rb +18 -0
- data/lib/generators/katapult/model/model_generator.rb +59 -0
- data/lib/generators/katapult/model/templates/app/models/shared/does_flag.rb +32 -0
- data/lib/generators/katapult/model/templates/model.rb +21 -0
- data/lib/generators/katapult/model_specs/model_specs_generator.rb +51 -0
- data/lib/generators/katapult/model_specs/templates/model_spec.rb +34 -0
- data/lib/generators/katapult/navigation/navigation_generator.rb +25 -0
- data/lib/generators/katapult/navigation/templates/app/models/navigation.rb +12 -0
- data/lib/generators/katapult/transform/transform_generator.rb +47 -0
- data/lib/generators/katapult/w_u_i/templates/_route.rb +13 -0
- data/lib/generators/katapult/w_u_i/templates/controller.rb +106 -0
- data/lib/generators/katapult/w_u_i/w_u_i_generator.rb +57 -0
- data/lib/katapult.rb +5 -0
- data/lib/katapult/action.rb +44 -0
- data/lib/katapult/application_model.rb +45 -0
- data/lib/katapult/attribute.rb +83 -0
- data/lib/katapult/element.rb +72 -0
- data/lib/katapult/generator.rb +28 -0
- data/lib/katapult/model.rb +33 -0
- data/lib/katapult/navigation.rb +22 -0
- data/lib/katapult/parser.rb +39 -0
- data/lib/katapult/util.rb +16 -0
- data/lib/katapult/version.rb +3 -0
- data/lib/katapult/wui.rb +77 -0
- data/script/console +16 -0
- data/spec/action_spec.rb +44 -0
- data/spec/attribute_spec.rb +48 -0
- data/spec/model_spec.rb +18 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/util_spec.rb +23 -0
- data/spec/wui_spec.rb +49 -0
- metadata +253 -0
@@ -0,0 +1,203 @@
|
|
1
|
+
Feature: Generate Models
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given a pristine Rails application
|
5
|
+
And I install katapult
|
6
|
+
And I generate katapult basics
|
7
|
+
|
8
|
+
|
9
|
+
Scenario: Generate ActiveRecord Model
|
10
|
+
When I overwrite "lib/katapult/application_model.rb" with:
|
11
|
+
"""
|
12
|
+
model 'Car'
|
13
|
+
"""
|
14
|
+
And I successfully transform the application model
|
15
|
+
Then the file "app/models/car.rb" should contain exactly:
|
16
|
+
"""
|
17
|
+
class Car < ActiveRecord::Base
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
"Car##{id}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
"""
|
25
|
+
And there should be a migration with:
|
26
|
+
"""
|
27
|
+
class CreateCars < ActiveRecord::Migration
|
28
|
+
def change
|
29
|
+
create_table :cars do |t|
|
30
|
+
|
31
|
+
t.timestamps
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
"""
|
37
|
+
And the file "spec/models/car_spec.rb" should contain exactly:
|
38
|
+
"""
|
39
|
+
require 'rails_helper'
|
40
|
+
|
41
|
+
describe Car do
|
42
|
+
|
43
|
+
describe '#to_s' do
|
44
|
+
it 'returns its class name with its id' do
|
45
|
+
subject.id = 17
|
46
|
+
expect(subject.to_s).to eql("Car#17")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
"""
|
53
|
+
|
54
|
+
|
55
|
+
Scenario: Generate ActiveRecord Model with attributes
|
56
|
+
When I overwrite "lib/katapult/application_model.rb" with:
|
57
|
+
"""
|
58
|
+
model 'Person' do |person|
|
59
|
+
|
60
|
+
# Basic types
|
61
|
+
person.attr :age, type: :integer
|
62
|
+
person.attr :nick, type: :string
|
63
|
+
person.attr :hobby # string is default
|
64
|
+
|
65
|
+
# Special types
|
66
|
+
person.attr :email # type is detected as email
|
67
|
+
person.attr :income, type: :money
|
68
|
+
person.attr :homepage, type: :url, default: 'http://www.makandra.de'
|
69
|
+
person.attr :locked, type: :flag, default: false
|
70
|
+
end
|
71
|
+
"""
|
72
|
+
And I successfully transform the application model
|
73
|
+
Then the file "app/models/person.rb" should contain exactly:
|
74
|
+
"""
|
75
|
+
class Person < ActiveRecord::Base
|
76
|
+
include DoesFlag[:locked, default: false]
|
77
|
+
has_defaults({:homepage=>"http://www.makandra.de"})
|
78
|
+
|
79
|
+
def to_s
|
80
|
+
age.to_s
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
"""
|
85
|
+
And there should be a migration with:
|
86
|
+
"""
|
87
|
+
class CreatePeople < ActiveRecord::Migration
|
88
|
+
def change
|
89
|
+
create_table :people do |t|
|
90
|
+
t.integer :age
|
91
|
+
t.string :nick
|
92
|
+
t.string :hobby
|
93
|
+
t.string :email
|
94
|
+
t.decimal :income, precision: 10, scale: 2
|
95
|
+
t.string :homepage
|
96
|
+
t.boolean :locked
|
97
|
+
|
98
|
+
t.timestamps
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
"""
|
104
|
+
And the file "spec/models/person_spec.rb" should contain exactly:
|
105
|
+
"""
|
106
|
+
require 'rails_helper'
|
107
|
+
|
108
|
+
describe Person do
|
109
|
+
|
110
|
+
describe '#to_s' do
|
111
|
+
it 'returns the #age attribute' do
|
112
|
+
subject.age = 778
|
113
|
+
expect(subject.to_s).to eql("778")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '#homepage' do
|
118
|
+
|
119
|
+
it 'has a default' do
|
120
|
+
expect( subject.homepage ).to eql("http://www.makandra.de")
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe '#locked' do
|
125
|
+
|
126
|
+
it 'has a default' do
|
127
|
+
expect( subject.locked ).to eql(false)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
"""
|
134
|
+
And the specs should pass
|
135
|
+
|
136
|
+
|
137
|
+
Scenario: Get a helpful error message when an attribute has an unknown option
|
138
|
+
When I overwrite "lib/katapult/application_model.rb" with:
|
139
|
+
"""
|
140
|
+
model 'Person' do |person|
|
141
|
+
person.attr :x, invalid_option: 'here'
|
142
|
+
end
|
143
|
+
"""
|
144
|
+
And I transform the application model
|
145
|
+
Then the output should contain "Katapult::Attribute does not support option :invalid_option. (Katapult::Element::UnknownOptionError)"
|
146
|
+
|
147
|
+
|
148
|
+
Scenario: Specify assignable values
|
149
|
+
When I overwrite "lib/katapult/application_model.rb" with:
|
150
|
+
"""
|
151
|
+
model 'Person' do |person|
|
152
|
+
person.attr :age, type: :integer, assignable_values: 9..99
|
153
|
+
person.attr :hobby, assignable_values: %w[soccer baseball], default: 'soccer', allow_blank: true
|
154
|
+
end
|
155
|
+
"""
|
156
|
+
And I successfully transform the application model
|
157
|
+
Then the file "app/models/person.rb" should contain exactly:
|
158
|
+
"""
|
159
|
+
class Person < ActiveRecord::Base
|
160
|
+
assignable_values_for :age, {} do
|
161
|
+
9..99
|
162
|
+
end
|
163
|
+
assignable_values_for :hobby, {:allow_blank=>true, :default=>"soccer"} do
|
164
|
+
["soccer", "baseball"]
|
165
|
+
end
|
166
|
+
|
167
|
+
def to_s
|
168
|
+
age.to_s
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
"""
|
173
|
+
And the file "spec/models/person_spec.rb" should contain exactly:
|
174
|
+
"""
|
175
|
+
require 'rails_helper'
|
176
|
+
|
177
|
+
describe Person do
|
178
|
+
|
179
|
+
describe '#to_s' do
|
180
|
+
it 'returns the #age attribute' do
|
181
|
+
subject.age = 9
|
182
|
+
expect(subject.to_s).to eql("9")
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe '#age' do
|
187
|
+
it { is_expected.to allow_value(99).for(:age) }
|
188
|
+
it { is_expected.to_not allow_value(100).for(:age) }
|
189
|
+
end
|
190
|
+
|
191
|
+
describe '#hobby' do
|
192
|
+
it { is_expected.to allow_value("baseball").for(:hobby) }
|
193
|
+
it { is_expected.to_not allow_value("baseball-unassignable").for(:hobby) }
|
194
|
+
|
195
|
+
it 'has a default' do
|
196
|
+
expect( subject.hobby ).to eql("soccer")
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
"""
|
203
|
+
And the specs should pass
|
@@ -0,0 +1,80 @@
|
|
1
|
+
Feature: Navigation
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given a pristine Rails application
|
5
|
+
And I install katapult
|
6
|
+
And I generate katapult basics
|
7
|
+
|
8
|
+
|
9
|
+
Scenario: Generate navigation
|
10
|
+
|
11
|
+
The navigation is rendered from all WUIs in the application model. It
|
12
|
+
consists of links to their index pages.
|
13
|
+
|
14
|
+
When I overwrite "lib/katapult/application_model.rb" with:
|
15
|
+
"""
|
16
|
+
model 'Customer' do |customer|
|
17
|
+
customer.attr :name
|
18
|
+
end
|
19
|
+
|
20
|
+
wui 'Customer', model: 'Customer' do |wui|
|
21
|
+
wui.action :index
|
22
|
+
wui.action :show
|
23
|
+
wui.action :create
|
24
|
+
wui.action :update
|
25
|
+
wui.action :destroy
|
26
|
+
end
|
27
|
+
|
28
|
+
navigation 'main'
|
29
|
+
"""
|
30
|
+
And I successfully transform the application model
|
31
|
+
Then the file "app/models/navigation.rb" should contain exactly:
|
32
|
+
"""
|
33
|
+
class Navigation
|
34
|
+
include Navy::Description
|
35
|
+
|
36
|
+
navigation :main do
|
37
|
+
section :customers, "Customers", customers_path
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
"""
|
43
|
+
And the file "app/views/layouts/application.html.haml" should contain:
|
44
|
+
"""
|
45
|
+
= render_navigation Navigation.main
|
46
|
+
"""
|
47
|
+
And the file "app/controllers/customers_controller.rb" should contain:
|
48
|
+
"""
|
49
|
+
before_filter :set_section
|
50
|
+
"""
|
51
|
+
And the file "app/controllers/customers_controller.rb" should contain:
|
52
|
+
"""
|
53
|
+
def set_section
|
54
|
+
in_sections :customers
|
55
|
+
end
|
56
|
+
"""
|
57
|
+
|
58
|
+
|
59
|
+
Scenario: Homepage (aka root route) is set automatically
|
60
|
+
|
61
|
+
The first WUI with an index action is set as home page
|
62
|
+
|
63
|
+
When I overwrite "lib/katapult/application_model.rb" with:
|
64
|
+
"""
|
65
|
+
model 'Customer'
|
66
|
+
model 'Elephant'
|
67
|
+
|
68
|
+
wui 'Elephant' do |wui|
|
69
|
+
wui.action :trumpet, scope: :member, method: :post
|
70
|
+
end
|
71
|
+
|
72
|
+
wui 'Customer' do |wui|
|
73
|
+
wui.crud
|
74
|
+
end
|
75
|
+
"""
|
76
|
+
And I successfully transform the application model
|
77
|
+
Then the file "config/routes.rb" should contain:
|
78
|
+
"""
|
79
|
+
root 'customers#index'
|
80
|
+
"""
|
@@ -0,0 +1,14 @@
|
|
1
|
+
When /^I replace "(.*?)" with "(.*?)" inside "(.*?)"$/ do |a, b, path|
|
2
|
+
in_current_dir do
|
3
|
+
content = File.read(path)
|
4
|
+
content.gsub! a, b
|
5
|
+
File.open(path, 'w') { |file| file.puts(content) }
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
Then /^there should be a migration with:$/ do |migration|
|
10
|
+
migrations_path = File.join(current_dir, 'db', 'migrate', '*.rb')
|
11
|
+
|
12
|
+
all_migrations = Dir.glob(migrations_path).map(&File.method(:read)).join
|
13
|
+
all_migrations.should include(migration)
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
When /^I install katapult$/ do
|
2
|
+
append_to_file 'Gemfile', "gem 'katapult', path: '../../..'"
|
3
|
+
run_simple('bin/rails generate katapult:install')
|
4
|
+
end
|
5
|
+
|
6
|
+
# This step is required for any feature because it generates config/database.yml
|
7
|
+
When /^I generate katapult basics$/ do
|
8
|
+
run_simple('bin/rails generate katapult:basics')
|
9
|
+
end
|
10
|
+
|
11
|
+
When /^I( successfully)? transform the application model$/ do |require_success|
|
12
|
+
# the second parameter would be true when not specified
|
13
|
+
run_simple('bin/rails generate katapult:transform lib/katapult/application_model.rb', !!require_success)
|
14
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module KatapultRailsHelper
|
2
|
+
|
3
|
+
def with_aruba_timeout(timeout, &block)
|
4
|
+
original_aruba_timeout = @aruba_timeout_seconds
|
5
|
+
@aruba_timeout_seconds = timeout
|
6
|
+
|
7
|
+
block.call
|
8
|
+
ensure
|
9
|
+
@aruba_timeout_seconds = original_aruba_timeout
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_cached_app(name)
|
13
|
+
job = 'Cached Rails app generation'
|
14
|
+
rails_new_command = "bundle exec rails new #{name} --skip-test-unit --skip-bundle --database mysql"
|
15
|
+
|
16
|
+
puts "#{job} started (in #{Dir.pwd})"
|
17
|
+
system(rails_new_command) or raise "#{job} failed"
|
18
|
+
puts "#{job} done."
|
19
|
+
end
|
20
|
+
|
21
|
+
def ensure_bundled(path)
|
22
|
+
Dir.chdir(path) do
|
23
|
+
Bundler.with_clean_env do
|
24
|
+
system('bundle check &> /dev/null') or system('bundle install')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
World(KatapultRailsHelper)
|
31
|
+
|
32
|
+
|
33
|
+
Given /^a pristine Rails application$/ do
|
34
|
+
with_aruba_timeout(120) do
|
35
|
+
Dir.chdir('tmp') do
|
36
|
+
create_cached_app('cached_test_app') unless File.directory?('cached_test_app')
|
37
|
+
ensure_bundled('cached_test_app')
|
38
|
+
end
|
39
|
+
|
40
|
+
# copy cached app to aruba directory
|
41
|
+
FileUtils.cp_r('tmp/cached_test_app', File.join(current_dir, 'katapult_test_app'))
|
42
|
+
cd 'katapult_test_app' # Aruba::Api method
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'aruba/cucumber'
|
2
|
+
require 'pry'
|
3
|
+
|
4
|
+
# Make sure tests use the correct katapult gem
|
5
|
+
ENV['KATAPULT_GEMFILE_OPTIONS'] = ", path: '../../..'"
|
6
|
+
|
7
|
+
Before do
|
8
|
+
@aruba_timeout_seconds = 30
|
9
|
+
|
10
|
+
unset_bundler_env_vars
|
11
|
+
run_simple 'spring stop # Clean up in case the After hook did not run'
|
12
|
+
end
|
13
|
+
|
14
|
+
After do
|
15
|
+
run_simple 'spring stop'
|
16
|
+
end
|
@@ -0,0 +1,319 @@
|
|
1
|
+
Feature: Web User Interface
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given a pristine Rails application
|
5
|
+
And I install katapult
|
6
|
+
And I generate katapult basics
|
7
|
+
|
8
|
+
|
9
|
+
Scenario: Generate a Web User Interface
|
10
|
+
When I overwrite "lib/katapult/application_model.rb" with:
|
11
|
+
"""
|
12
|
+
model 'Customer' do |customer|
|
13
|
+
customer.attr :name
|
14
|
+
customer.attr :age, type: :integer
|
15
|
+
|
16
|
+
customer.attr :email
|
17
|
+
customer.attr :revenue, type: :money
|
18
|
+
customer.attr :homepage, type: :url, default: 'http://www.makandra.de'
|
19
|
+
customer.attr :locked, type: :flag, default: false
|
20
|
+
end
|
21
|
+
|
22
|
+
wui 'Customer', model: 'Customer' do |wui|
|
23
|
+
wui.crud
|
24
|
+
wui.action :get_member, method: :get, scope: :member
|
25
|
+
wui.action :post_member, method: :post, scope: :member
|
26
|
+
wui.action :get_collection, method: :get, scope: :collection
|
27
|
+
wui.action :put_collection, method: :put, scope: :collection
|
28
|
+
end
|
29
|
+
"""
|
30
|
+
And I successfully transform the application model
|
31
|
+
Then the file "app/controllers/customers_controller.rb" should contain exactly:
|
32
|
+
"""
|
33
|
+
class CustomersController < ApplicationController
|
34
|
+
|
35
|
+
def index
|
36
|
+
load_customers
|
37
|
+
end
|
38
|
+
|
39
|
+
def show
|
40
|
+
load_customer
|
41
|
+
end
|
42
|
+
|
43
|
+
def new
|
44
|
+
build_customer
|
45
|
+
end
|
46
|
+
|
47
|
+
def create
|
48
|
+
build_customer
|
49
|
+
save_customer or render :new
|
50
|
+
end
|
51
|
+
|
52
|
+
def edit
|
53
|
+
load_customer
|
54
|
+
build_customer
|
55
|
+
end
|
56
|
+
|
57
|
+
def update
|
58
|
+
load_customer
|
59
|
+
build_customer
|
60
|
+
save_customer or render :edit
|
61
|
+
end
|
62
|
+
|
63
|
+
def destroy
|
64
|
+
load_customer
|
65
|
+
@customer.destroy
|
66
|
+
redirect_to customers_path
|
67
|
+
end
|
68
|
+
|
69
|
+
def get_member
|
70
|
+
load_customer
|
71
|
+
end
|
72
|
+
|
73
|
+
def post_member
|
74
|
+
load_customer
|
75
|
+
redirect_to @customer
|
76
|
+
end
|
77
|
+
|
78
|
+
def get_collection
|
79
|
+
load_customers
|
80
|
+
end
|
81
|
+
|
82
|
+
def put_collection
|
83
|
+
load_customers
|
84
|
+
redirect_to customers_path
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def load_customers
|
90
|
+
@customers ||= customer_scope.to_a
|
91
|
+
end
|
92
|
+
|
93
|
+
def load_customer
|
94
|
+
@customer ||= customer_scope.find(params[:id])
|
95
|
+
end
|
96
|
+
|
97
|
+
def build_customer
|
98
|
+
@customer ||= customer_scope.build
|
99
|
+
@customer.attributes = customer_params
|
100
|
+
end
|
101
|
+
|
102
|
+
def save_customer
|
103
|
+
if @customer.save
|
104
|
+
redirect_to @customer
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def customer_params
|
109
|
+
customer_params = params[:customer]
|
110
|
+
customer_params ? customer_params.permit([:name, :age, :email, :revenue, :homepage, :locked]) : {}
|
111
|
+
end
|
112
|
+
|
113
|
+
def customer_scope
|
114
|
+
Customer.scoped
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
"""
|
120
|
+
And the file "config/routes.rb" should contain:
|
121
|
+
"""
|
122
|
+
resources :customers, only: [:index, :show, :new, :create, :edit, :update, :destroy] do
|
123
|
+
member do
|
124
|
+
get 'get_member'
|
125
|
+
post 'post_member'
|
126
|
+
end
|
127
|
+
collection do
|
128
|
+
get 'get_collection'
|
129
|
+
put 'put_collection'
|
130
|
+
end
|
131
|
+
end
|
132
|
+
"""
|
133
|
+
And the file "app/views/customers/index.html.haml" should contain exactly:
|
134
|
+
"""
|
135
|
+
%h1
|
136
|
+
Customers
|
137
|
+
|
138
|
+
.tools
|
139
|
+
= link_to 'Add customer', new_customer_path, class: 'tools__button is_primary'
|
140
|
+
= link_to 'Get Collection', get_collection_customers_path, class: 'tools__button'
|
141
|
+
= link_to 'Put Collection', put_collection_customers_path, class: 'tools__button'
|
142
|
+
|
143
|
+
- if @customers.any?
|
144
|
+
%table.items
|
145
|
+
- @customers.each do |customer|
|
146
|
+
%tr
|
147
|
+
%td
|
148
|
+
= link_to customer.to_s, customer, class: 'hyperlink'
|
149
|
+
%td
|
150
|
+
.items__actions
|
151
|
+
= link_to 'Edit', edit_customer_path(customer), class: 'items__action'
|
152
|
+
= link_to 'Destroy', customer_path(customer), method: :delete, class: 'items__action', confirm: 'Really destroy?'
|
153
|
+
= link_to 'Get Member', get_member_customer_path(customer), class: 'items__action'
|
154
|
+
= link_to 'Post Member', post_member_customer_path(customer), class: 'items__action', method: :post
|
155
|
+
|
156
|
+
- else
|
157
|
+
%p.help-block
|
158
|
+
There are no customers yet.
|
159
|
+
|
160
|
+
"""
|
161
|
+
And the file "app/views/customers/show.html.haml" should contain exactly:
|
162
|
+
"""
|
163
|
+
%h1
|
164
|
+
= @customer.to_s
|
165
|
+
|
166
|
+
.tools
|
167
|
+
= link_to 'All customers', customers_path, class: 'tools__button'
|
168
|
+
= link_to 'Edit', edit_customer_path(@customer), class: 'tools__button is_primary'
|
169
|
+
= link_to 'Destroy', customer_path(@customer), method: :delete, class: 'tools__button', confirm: 'Really destroy?'
|
170
|
+
= link_to 'Get Member', get_member_customer_path(@customer), class: 'tools__button'
|
171
|
+
= link_to 'Post Member', post_member_customer_path(@customer), class: 'tools__button', method: :post
|
172
|
+
|
173
|
+
%dl.values
|
174
|
+
%dt
|
175
|
+
= Customer.human_attribute_name(:name)
|
176
|
+
%dd
|
177
|
+
= @customer.name
|
178
|
+
%dt
|
179
|
+
= Customer.human_attribute_name(:age)
|
180
|
+
%dd
|
181
|
+
= @customer.age
|
182
|
+
%dt
|
183
|
+
= Customer.human_attribute_name(:email)
|
184
|
+
%dd
|
185
|
+
= mail_to @customer.email, nil, class: 'hyperlink'
|
186
|
+
%dt
|
187
|
+
= Customer.human_attribute_name(:revenue)
|
188
|
+
%dd
|
189
|
+
= @customer.revenue
|
190
|
+
€
|
191
|
+
%dt
|
192
|
+
= Customer.human_attribute_name(:homepage)
|
193
|
+
%dd
|
194
|
+
= link_to @customer.homepage, @customer.homepage, class: 'hyperlink'
|
195
|
+
%dt
|
196
|
+
= Customer.human_attribute_name(:locked)
|
197
|
+
%dd
|
198
|
+
= @customer.locked ? 'Yes' : 'No'
|
199
|
+
|
200
|
+
"""
|
201
|
+
And the file "app/views/customers/new.html.haml" should contain exactly:
|
202
|
+
"""
|
203
|
+
%h1
|
204
|
+
Add customer
|
205
|
+
|
206
|
+
= render 'form'
|
207
|
+
|
208
|
+
"""
|
209
|
+
And the file "app/views/customers/edit.html.haml" should contain exactly:
|
210
|
+
"""
|
211
|
+
%h1
|
212
|
+
= @customer.to_s
|
213
|
+
|
214
|
+
= render 'form'
|
215
|
+
|
216
|
+
"""
|
217
|
+
And the file "app/views/customers/_form.html.haml" should contain exactly:
|
218
|
+
"""
|
219
|
+
= form_for @customer do |form|
|
220
|
+
|
221
|
+
%dl.controls
|
222
|
+
%dt
|
223
|
+
= form.label :name
|
224
|
+
%dd
|
225
|
+
= form.text_field :name
|
226
|
+
%dt
|
227
|
+
= form.label :age
|
228
|
+
%dd
|
229
|
+
= form.number_field :age
|
230
|
+
%dt
|
231
|
+
= form.label :email
|
232
|
+
%dd
|
233
|
+
= form.email_field :email
|
234
|
+
%dt
|
235
|
+
= form.label :revenue
|
236
|
+
%dd
|
237
|
+
= form.number_field :revenue
|
238
|
+
€
|
239
|
+
%dt
|
240
|
+
= form.label :homepage
|
241
|
+
%dd
|
242
|
+
= form.url_field :homepage
|
243
|
+
%dt
|
244
|
+
= form.label :locked
|
245
|
+
%dd
|
246
|
+
= form.check_box :locked
|
247
|
+
|
248
|
+
.tools
|
249
|
+
= form.submit 'Save', class: 'tools__button is_primary'
|
250
|
+
- cancel_path = @customer.new_record? ? customers_path : customer_path(@customer)
|
251
|
+
= link_to 'Cancel', cancel_path, class: 'tools__button'
|
252
|
+
|
253
|
+
"""
|
254
|
+
And the file "app/views/customers/get_member.html.haml" should contain exactly:
|
255
|
+
"""
|
256
|
+
%h1
|
257
|
+
Get Member
|
258
|
+
|
259
|
+
.tools
|
260
|
+
= link_to 'All customers', customers_path, class: 'tools__button'
|
261
|
+
|
262
|
+
"""
|
263
|
+
But a file named "app/views/customers/post_member.html.haml" should not exist
|
264
|
+
And the file "app/views/customers/get_collection.html.haml" should contain exactly:
|
265
|
+
"""
|
266
|
+
%h1
|
267
|
+
Get Collection
|
268
|
+
|
269
|
+
.tools
|
270
|
+
= link_to 'All customers', customers_path, class: 'tools__button'
|
271
|
+
|
272
|
+
"""
|
273
|
+
But a file named "app/views/customers/put_collection.html.haml" should not exist
|
274
|
+
And the file "features/customers.feature" should contain exactly:
|
275
|
+
"""
|
276
|
+
Feature: Customers
|
277
|
+
|
278
|
+
Scenario: CRUD customers
|
279
|
+
Given I am on the list of customers
|
280
|
+
|
281
|
+
# create
|
282
|
+
When I follow "Add customer"
|
283
|
+
And I fill in "Name" with "name-string"
|
284
|
+
And I fill in "Age" with "778"
|
285
|
+
And I fill in "Email" with "email@example.com"
|
286
|
+
And I fill in "Revenue" with "2.21"
|
287
|
+
And I fill in "Homepage" with "homepage.example.com"
|
288
|
+
And I check "Locked"
|
289
|
+
And I press "Save"
|
290
|
+
|
291
|
+
# read
|
292
|
+
Then I should be on the page for the customer above
|
293
|
+
And I should see "name-string"
|
294
|
+
And I should see "778"
|
295
|
+
And I should see "email@example.com"
|
296
|
+
And I should see "2.21"
|
297
|
+
And I should see "homepage.example.com"
|
298
|
+
And I should see "Locked Yes"
|
299
|
+
|
300
|
+
# update
|
301
|
+
When I follow "Edit"
|
302
|
+
Then I should be on the form for the customer above
|
303
|
+
And the "Name" field should contain "name-string"
|
304
|
+
And the "Age" field should contain "778"
|
305
|
+
And the "Email" field should contain "email@example.com"
|
306
|
+
And the "Revenue" field should contain "2.21"
|
307
|
+
And the "Homepage" field should contain "homepage.example.com"
|
308
|
+
And the "Locked" checkbox should be checked
|
309
|
+
|
310
|
+
# destroy
|
311
|
+
When I go to the list of customers
|
312
|
+
Then I should see "name-string"
|
313
|
+
|
314
|
+
When I follow "Destroy"
|
315
|
+
Then I should be on the list of customers
|
316
|
+
But I should not see "name-string"
|
317
|
+
|
318
|
+
"""
|
319
|
+
And the features should pass
|