katapult 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/README.md +57 -9
  4. data/bin/katapult +7 -3
  5. data/features/application_model.feature +4 -1
  6. data/features/authenticate.feature +1 -18
  7. data/features/basics.feature +1 -0
  8. data/features/binary.feature +5 -7
  9. data/features/model.feature +42 -3
  10. data/features/step_definitions/rails_steps.rb +1 -1
  11. data/features/web_ui.feature +17 -5
  12. data/lib/generators/katapult/app_model/templates/lib/katapult/application_model.rb +3 -0
  13. data/lib/generators/katapult/basics/basics_generator.rb +3 -8
  14. data/lib/generators/katapult/basics/templates/README.md.tt +33 -0
  15. data/lib/generators/katapult/basics/templates/features/support/paths.rb +1 -1
  16. data/lib/generators/katapult/clearance/clearance_generator.rb +6 -2
  17. data/lib/generators/katapult/clearance/templates/config/initializers/clearance.rb +1 -0
  18. data/lib/generators/katapult/cucumber_features/cucumber_features_generator.rb +10 -0
  19. data/lib/generators/katapult/cucumber_features/templates/feature.feature +4 -3
  20. data/lib/generators/katapult/model/model_generator.rb +15 -0
  21. data/lib/generators/katapult/model/templates/model.rb +13 -3
  22. data/lib/generators/katapult/model_specs/model_specs_generator.rb +1 -1
  23. data/lib/generators/katapult/model_specs/templates/model_spec.rb +1 -1
  24. data/lib/generators/katapult/transform/transform_generator.rb +4 -7
  25. data/lib/generators/katapult/views/templates/_form.html.haml +16 -13
  26. data/lib/generators/katapult/views/templates/show.html.haml +2 -0
  27. data/lib/katapult/application_model.rb +68 -19
  28. data/lib/katapult/element.rb +13 -18
  29. data/lib/katapult/{action.rb → elements/action.rb} +0 -0
  30. data/lib/katapult/elements/association.rb +35 -0
  31. data/lib/katapult/{attribute.rb → elements/attribute.rb} +14 -5
  32. data/lib/katapult/{authentication.rb → elements/authentication.rb} +2 -5
  33. data/lib/katapult/elements/model.rb +76 -0
  34. data/lib/katapult/{navigation.rb → elements/navigation.rb} +0 -0
  35. data/lib/katapult/{web_ui.rb → elements/web_ui.rb} +2 -12
  36. data/lib/katapult/generator.rb +2 -2
  37. data/lib/katapult/{binary_util.rb → support/binary_util.rb} +2 -1
  38. data/lib/katapult/{generator_goodies.rb → support/generator_goodies.rb} +9 -2
  39. data/lib/katapult/version.rb +1 -1
  40. data/script/console +5 -2
  41. data/script/update +1 -1
  42. data/spec/action_spec.rb +1 -1
  43. data/spec/application_model_spec.rb +26 -0
  44. data/spec/association_spec.rb +12 -0
  45. data/spec/attribute_spec.rb +35 -1
  46. data/spec/model_spec.rb +5 -2
  47. data/spec/util_spec.rb +1 -1
  48. data/spec/web_ui_spec.rb +11 -33
  49. metadata +17 -13
  50. data/lib/katapult/model.rb +0 -45
  51. data/lib/katapult/parser.rb +0 -53
  52. data/spec/parser_spec.rb +0 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ddcf0832f9fb8d7597253465296fe0726761e1bd2d3088d741e4bedf51e05cf7
4
- data.tar.gz: 293a4ba645e9710e1392707ae59df834e9d14cbd841920e919d02d3d0db02e73
3
+ metadata.gz: f4099dfe92529880417ce7c3ac5204b70fc115b33a6b60b0027d75c6f7e001e3
4
+ data.tar.gz: 688a93e927f9240fc0d6e67caceeaae882438c9f5114618f051fda4c5063495f
5
5
  SHA512:
6
- metadata.gz: 2ead2ca1d7f9bbee69ad9bdac6e5043c513e23deffa6f73119b3b4145206d56f7cf3537067d7116b39d04b0e7c07f795eb839600dedd14f9e22d6bc501e8f33e
7
- data.tar.gz: cd2336671a2317373433ff47a3568e35073757c21ff2972d1a8d3004830c764adcc7c422e55b34966255952516760eee329a0468687159adf78c5aa2c46551f3
6
+ metadata.gz: 5a2a28034878af36af8c5251550c87b257091d4ddadc0e923a7845ea4ace323660040c50de547f7460153fac5df88520bbe10558870a6ec6de9f22153300c5e4
7
+ data.tar.gz: 405ae1ffbdd3172e78f5e2aced6bf4096e400b5ca30d86aaa6f23b8ed10e0875c6de048d5da11e333f20709644e4fb21c6941a8e68b5e7c83eb1590ff4256f41
data/CHANGELOG.md ADDED
@@ -0,0 +1,30 @@
1
+ # Changelog
2
+
3
+ ## 0.4.0 on 2018-01-15
4
+
5
+ ### Features
6
+ - Support for has_many/belongs_to associations
7
+ - Create a project README
8
+ - New CHANGELOG
9
+
10
+ ### Fixes
11
+ - Models now inherit from `ApplicationRecord`
12
+
13
+
14
+ ## 0.3.0 on 2018-01-11
15
+
16
+ ### Features
17
+ - Generating a Rails 5.1.4 app on Ruby 2.5.0
18
+ - Dropped asset pipeline in favor of Webpacker
19
+ - The generated application now has a sleek, simple design based on Bootstrap
20
+ - Employing [Unpoly](https://unpoly.com)
21
+ - New DSL command `crud` for creating Model plus WebUI
22
+ - The generated application model is now a transformable example of katapult's features
23
+
24
+ ### Development improvements
25
+ - Add katapult update script
26
+ - Speed up tests (now running in about 9 min)
27
+ - Improve development workflow (see README)
28
+ - No bundler issues in tests any more
29
+
30
+ See [all changes](https://github.com/makandra/katapult/compare/v0.2.0...v0.3.0).
data/README.md CHANGED
@@ -99,15 +99,18 @@ has the following syntax, taking a name, options, and a block:
99
99
 
100
100
 
101
101
  ### Model
102
- Takes a name and a block:
102
+ Takes a name and a block. Generates a Rails model, a migration, and a spec.
103
103
 
104
104
  model 'Customer' do |customer|
105
105
  # customer.attr :name etc, see Attribute element
106
+ # customer.belongs_to :group, see Association element
106
107
  end
107
108
 
108
109
 
109
110
  #### Attribute
110
- Defined on Model. Takes a name and options:
111
+ Defined on Model; takes a name and options. Adds a database field in the model
112
+ migration, form fields in a WebUI, and configuration code in the model as
113
+ needed.
111
114
 
112
115
  # Default type :string
113
116
  model.attr :name
@@ -136,8 +139,21 @@ Defined on Model. Takes a name and options:
136
139
  model.attr :avoid, type: :plain_json # PostgreSQL "json"
137
140
 
138
141
 
142
+ ### Association
143
+ Defined on Model; takes the name of another model just like you called it in the
144
+ model. Adds a foreign key attribute to the model and `belongs_to`/`has_many`
145
+ calls to the respective models.
146
+
147
+ model 'Customer' do |customer|
148
+ customer.belongs_to 'Group'
149
+ end
150
+
151
+ model 'Group'
152
+
153
+
139
154
  ### WebUI
140
- Takes a name, options and a block:
155
+ Takes a name, options and a block. Generates controller, routes, views, and a
156
+ passing Cucumber feature.
141
157
 
142
158
  web_ui 'Customer', model: 'User' do |web_ui|
143
159
  web_ui.crud # Create all the standard rails actions
@@ -150,7 +166,8 @@ Takes a name, options and a block:
150
166
 
151
167
 
152
168
  #### Action
153
- Defined on WebUI. Takes a name and options:
169
+ Defined on WebUI; takes a name and options. Adds an action to the controller,
170
+ and a route as needed.
154
171
 
155
172
  # Select single Rails actions
156
173
  web_ui.action :index
@@ -164,7 +181,7 @@ Defined on WebUI. Takes a name and options:
164
181
  web_ui.action :other_action, method: :get, scope: :collection
165
182
 
166
183
  ### Crud
167
- This is a shortcut for creating a model together with a WebUI with CRUD actions.
184
+ Shortcut for creating a model together with a WebUI with CRUD actions.
168
185
 
169
186
  crud 'Customer' do |customer|
170
187
  customer.attr :name
@@ -172,8 +189,7 @@ This is a shortcut for creating a model together with a WebUI with CRUD actions.
172
189
 
173
190
 
174
191
  ### Navigation
175
- No arguments, will generate a main menu with links to the index pages of all
176
- WebUIs.
192
+ Generates a main menu with links to the index pages of all WebUIs.
177
193
 
178
194
  navigation
179
195
 
@@ -184,8 +200,8 @@ email address. Generates authentication with [Clearance](https://github.com/thou
184
200
 
185
201
  authenticate 'User', system_email: 'system@example.com'
186
202
 
187
- The email address will be the sender for Clearance mails like password reset
188
- requests.
203
+ The given email address will be configured as the sender for all mails sent by
204
+ Rails, including Clearance mails like password reset requests.
189
205
 
190
206
 
191
207
  ## Development
@@ -204,6 +220,31 @@ Create a dedicated account on your local PostgreSQL server:
204
220
  Whenever you start working on `katapult`, you should run `script/update`, which
205
221
  will guide you through a quick update process.
206
222
 
223
+ ### Architecture
224
+ `katapult` is roughly split into three parts: the `katapult` binary in bin/,
225
+ the model in lib/katapult/ and the generators in lib/generators. Also, there
226
+ is a script/ directory that holds some scripts to ease development. It is not
227
+ part of the `katapult` gem, however.
228
+
229
+ The generators of `katapult` base on the `rails/generators` you probably know
230
+ from generating migration files or scaffolds; however, it lifts their usage on a
231
+ new level by invoking generators programmatically with a "model object". Instead
232
+ of plain text input, the `katapult` generators can explore the whole application
233
+ model. They are all to be run from within a Rails application.
234
+
235
+ There are three base generators that can be considered the next-lower level API
236
+ of `katapult`:
237
+
238
+ - `basics` generator: Enhances a pristine Rails app with all of the basic
239
+ configuration `katapult` brings.
240
+ - `app_model` generator: Installs a boilerplate application model that serves as
241
+ a starting point for modeling your own application.
242
+ - `transform` generator: Parses the application model into an internal
243
+ representation, which will be turned into code by all the other generators.
244
+
245
+ Note that the `katapult` binary is the only Rails-independent part of Katapult;
246
+ everything else runs in the context of the Rails appplication.
247
+
207
248
  ### Suggested workflow
208
249
  When adding a feature to `katapult`, it will usually take you some time to
209
250
  figure out how exactly the generated code should look like. You'll be switching
@@ -225,6 +266,13 @@ Here's a the suggested process:
225
266
  7) Remove the @no-clobber tag and run the scenario normally to see if it's still
226
267
  green. Remember to stop the development server first.
227
268
 
269
+ ### Guidelines
270
+ Please respect the following guidelines during development:
271
+
272
+ - The application model should be order-agnostic. There is a #prepare_render
273
+ method in `ApplicationModel` for things that need to happen between parsing
274
+ and rendering the application model.
275
+
228
276
  ### Debugging
229
277
  Add the `@announce-output` tag to `katapult` features in order to have any output
230
278
  logged to your terminal. Note that each step will print all output to date, so
data/bin/katapult CHANGED
@@ -6,7 +6,7 @@
6
6
  usage = 'Usage: katapult new APP_NAME | fire [path/to/model] | version'
7
7
 
8
8
  require_relative '../lib/katapult/version'
9
- require_relative '../lib/katapult/binary_util'
9
+ require_relative '../lib/katapult/support/binary_util'
10
10
  util = Katapult::BinaryUtil
11
11
 
12
12
  require 'optparse'
@@ -74,8 +74,12 @@ when 'new'
74
74
  util.pink <<-INSTRUCTIONS
75
75
  Application initialization done.
76
76
 
77
- Next step: Model your application in lib/katapult/application_model.rb and
78
- transform it into code by running `katapult fire`.
77
+ Next steps:
78
+
79
+ - Model your application in lib/katapult/application_model.rb and transform it
80
+ into code by running `katapult fire`
81
+ - Configure public/robots.txt
82
+ - Write a README
79
83
  INSTRUCTIONS
80
84
 
81
85
  when 'fire'
@@ -1,5 +1,5 @@
1
1
  #@announce-output
2
- Feature: The application model prepared by Katapult
2
+ Feature: The default application model prepared by Katapult
3
3
 
4
4
  Scenario: Generating the application model template
5
5
  Given a new Rails application with Katapult basics installed
@@ -19,6 +19,9 @@ Feature: The application model prepared by Katapult
19
19
  product.attr :mode, assignable_values: %w[public private]
20
20
  product.attr :provider, type: :url
21
21
  product.attr :import_data, type: :json
22
+
23
+ # Reference other models just like you called them
24
+ product.belongs_to 'user'
22
25
  end
23
26
 
24
27
  # Define a model
@@ -170,24 +170,7 @@ Feature: Add authentication to an application
170
170
  config.middleware.use Clearance::BackDoor
171
171
 
172
172
  """
173
- And the file "config/initializers/clearance.rb" should contain exactly:
174
- """
175
- Clearance.configure do |config|
176
- config.allow_sign_up = false
177
- # config.cookie_domain = '.example.com'
178
- # config.cookie_expiration = lambda { |cookies| 1.year.from_now.utc }
179
- # config.cookie_name = 'remember_token'
180
- # config.cookie_path = '/'
181
- config.routes = false
182
- # config.httponly = true
183
- config.mailer_sender = 'system@example.com'
184
- # config.password_strategy = Clearance::PasswordStrategies::BCrypt
185
- # config.redirect_url = '/'
186
- # config.secure_cookie = true
187
- # config.sign_in_guards = []
188
- # config.user_model = User
189
- end
190
- """
173
+ And the file "config/initializers/clearance.rb" should contain " config.mailer_sender = 'system@example.com'"
191
174
  And a file named "config/locales/clearance.en.yml" should exist
192
175
  And the file "config/routes.rb" should contain:
193
176
  """
@@ -10,6 +10,7 @@ Feature: Preparation of a new Rails app (basics generator)
10
10
  Then the ruby-version file should be up-to-date
11
11
 
12
12
  And the file ".gitignore" should contain "config/database.yml"
13
+ And the file "README.md" should contain "# Katapult Test App"
13
14
  And the file ".bundle/config" should match /NOKOGIRI.*--use-system-libraries/
14
15
  And the file "Guardfile" should contain:
15
16
  """
@@ -44,13 +44,11 @@ Feature: Katapult binary `katapult`
44
44
  And the output should contain "Installing katapult"
45
45
  And the output should contain "Generating katapult basics"
46
46
  And the output should contain the configured Rails version
47
- And the output should contain:
48
- """
49
- Application initialization done.
50
47
 
51
- Next step: Model your application in lib/katapult/application_model.rb and
52
- transform it into code by running `katapult fire`.
53
- """
48
+ And the output should contain "Application initialization done."
49
+ And the output should contain "Model your application in lib/katapult/application_model.rb"
50
+ And the output should contain "Configure public/robots.txt"
51
+ And the output should contain "Write a README"
54
52
 
55
53
  When I cd to "binary_test"
56
54
  Then the file "Gemfile" should contain "gem 'katapult'"
@@ -69,7 +67,7 @@ Feature: Katapult binary `katapult`
69
67
  And the output should contain "Author: katapult <katapult@makandra.com>"
70
68
 
71
69
 
72
- Scenario: Transform the application model
70
+ Scenario: Transform the default application model
73
71
  Given a new Rails application with Katapult basics installed
74
72
  And the default aruba exit timeout is 45 seconds
75
73
 
@@ -1,4 +1,5 @@
1
1
  #@announce-output
2
+ #@announce-stderr
2
3
  Feature: Generate Models
3
4
 
4
5
  Background:
@@ -13,11 +14,13 @@ Feature: Generate Models
13
14
  And I successfully transform the application model
14
15
  Then the file "app/models/car.rb" should contain exactly:
15
16
  """
16
- class Car < ActiveRecord::Base
17
+ class Car < ApplicationRecord
18
+
17
19
 
18
20
  def to_s
19
21
  "Car##{id}"
20
22
  end
23
+
21
24
  end
22
25
 
23
26
  """
@@ -47,6 +50,10 @@ Feature: Generate Models
47
50
  end
48
51
 
49
52
  """
53
+ And the file "spec/factories/factories.rb" should contain:
54
+ """
55
+ factory :car
56
+ """
50
57
 
51
58
 
52
59
  Scenario: Generate ActiveRecord Model with attributes
@@ -72,13 +79,16 @@ Feature: Generate Models
72
79
  And I successfully transform the application model including migrations
73
80
  Then the file "app/models/person.rb" should contain exactly:
74
81
  """
75
- class Person < ActiveRecord::Base
82
+ class Person < ApplicationRecord
83
+
76
84
  include DoesFlag[:locked, default: false]
85
+
77
86
  has_defaults({:homepage=>"http://www.makandra.de"})
78
87
 
79
88
  def to_s
80
89
  age.to_s
81
90
  end
91
+
82
92
  end
83
93
 
84
94
  """
@@ -148,6 +158,31 @@ Feature: Generate Models
148
158
  Then the output should contain "Katapult::Attribute does not support option :invalid_option. (Katapult::Element::UnknownOptionError)"
149
159
 
150
160
 
161
+ Scenario: Specify model associations
162
+ When I write to "lib/katapult/application_model.rb" with:
163
+ """
164
+ model('Company') { |c| c.attr :name }
165
+ model 'User' do |user|
166
+ user.belongs_to 'Company'
167
+ end
168
+ """
169
+ And I successfully transform the application model including migrations
170
+ Then the file "app/models/company.rb" should contain "has_many :users"
171
+ And the file "app/models/user.rb" should contain "belongs_to :company"
172
+ And the file "app/models/user.rb" should contain:
173
+ """
174
+ assignable_values_for :company, {:allow_blank=>true} do
175
+ Company.all.to_a
176
+ end
177
+ """
178
+
179
+ And there should be a migration with:
180
+ """
181
+ create_table :users do |t|
182
+ t.integer :company_id
183
+ """
184
+
185
+
151
186
  Scenario: Specify assignable values
152
187
  When I write to "lib/katapult/application_model.rb" with:
153
188
  """
@@ -159,10 +194,13 @@ Feature: Generate Models
159
194
  And I successfully transform the application model including migrations
160
195
  Then the file "app/models/person.rb" should contain exactly:
161
196
  """
162
- class Person < ActiveRecord::Base
197
+ class Person < ApplicationRecord
198
+
199
+
163
200
  assignable_values_for :age, {} do
164
201
  9..99
165
202
  end
203
+
166
204
  assignable_values_for :hobby, {:allow_blank=>true, :default=>"soccer"} do
167
205
  ["soccer", "baseball"]
168
206
  end
@@ -170,6 +208,7 @@ Feature: Generate Models
170
208
  def to_s
171
209
  age.to_s
172
210
  end
211
+
173
212
  end
174
213
 
175
214
  """
@@ -1,4 +1,4 @@
1
- require 'katapult/binary_util'
1
+ require 'katapult/support/binary_util'
2
2
 
3
3
  module RailsHelper
4
4
 
@@ -9,7 +9,7 @@ Feature: Web User Interface
9
9
  Scenario: Generate a Web User Interface
10
10
  When I write to "lib/katapult/application_model.rb" with:
11
11
  """
12
- model 'customer' do |customer|
12
+ crud 'customer' do |customer|
13
13
  customer.attr :name
14
14
  customer.attr :age, type: :integer
15
15
 
@@ -22,11 +22,11 @@ Feature: Web User Interface
22
22
  customer.attr :first_visit, type: :datetime
23
23
  customer.attr :indexable_data, type: :json
24
24
  customer.attr :plain_data, type: :plain_json
25
- end
26
25
 
27
- web_ui 'customer', model: 'customer' do |web_ui|
28
- web_ui.crud
26
+ customer.belongs_to 'project'
29
27
  end
28
+
29
+ model('project') { |p| p.attr :title }
30
30
  """
31
31
  And I successfully transform the application model including migrations
32
32
  Then the file "app/controllers/customers_controller.rb" should contain exactly:
@@ -107,6 +107,7 @@ Feature: Web User Interface
107
107
  :first_visit,
108
108
  :indexable_data,
109
109
  :plain_data,
110
+ :project_id,
110
111
  )
111
112
  end
112
113
 
@@ -195,6 +196,10 @@ Feature: Web User Interface
195
196
  = Customer.human_attribute_name(:first_visit)
196
197
  %dd
197
198
  = l(@customer.first_visit.to_date) if @customer.first_visit
199
+ %dt
200
+ = Customer.human_attribute_name(:project_id)
201
+ %dd
202
+ = @customer.project
198
203
 
199
204
  """
200
205
  And the file "app/views/customers/new.html.haml" should contain exactly:
@@ -250,6 +255,10 @@ Feature: Web User Interface
250
255
  .form-group
251
256
  = form.label :first_visit
252
257
  = form.date_field :first_visit, class: 'form-control'
258
+ .form-group
259
+ = form.label :project_id
260
+ = form.collection_select :project_id, form.object.assignable_projects,
261
+ :id, :title, { include_blank: true }, class: 'form-control'
253
262
 
254
263
  .action-bar
255
264
  - cancel_path = @customer.new_record? ? customers_path : customer_path(@customer)
@@ -272,6 +281,7 @@ Feature: Web User Interface
272
281
 
273
282
  Scenario: CRUD customers
274
283
  Given I am on the list of customers
284
+ And there is a project with the title "title-string"
275
285
 
276
286
  # create
277
287
  When I follow "Add customer"
@@ -284,6 +294,7 @@ Feature: Web User Interface
284
294
  And I check "Locked"
285
295
  And I fill in "Notes" with "notes-text"
286
296
  And I fill in "First visit" with "2022-03-25"
297
+ And I select "title-string" from "Project"
287
298
  And I press "Save"
288
299
 
289
300
  # read
@@ -296,6 +307,7 @@ Feature: Web User Interface
296
307
  And I should see "Locked Yes"
297
308
  And I should see "notes-text"
298
309
  And I should see "2022-03-25"
310
+ And I should see "title-string"
299
311
 
300
312
  # update
301
313
  When I follow "Edit"
@@ -308,6 +320,7 @@ Feature: Web User Interface
308
320
  And the "Locked" checkbox should be checked
309
321
  And the "Notes" field should contain "notes-text"
310
322
  And the "First visit" field should contain "2022-03-25"
323
+ And "title-string" should be selected for "Project"
311
324
 
312
325
  # destroy
313
326
  When I go to the list of customers
@@ -318,7 +331,6 @@ Feature: Web User Interface
318
331
  But I should not see "name-string"
319
332
 
320
333
  """
321
-
322
334
  When I run cucumber
323
335
  Then the features should pass
324
336
 
@@ -13,6 +13,9 @@ crud 'product' do |product|
13
13
  product.attr :mode, assignable_values: %w[public private]
14
14
  product.attr :provider, type: :url
15
15
  product.attr :import_data, type: :json
16
+
17
+ # Reference other models just like you called them
18
+ product.belongs_to 'user'
16
19
  end
17
20
 
18
21
  # Define a model
@@ -1,6 +1,6 @@
1
1
  # Generates model-independent application basics (see method names).
2
2
 
3
- require 'katapult/generator_goodies'
3
+ require 'katapult/support/generator_goodies'
4
4
  require 'katapult/version' # For writing .ruby-version
5
5
 
6
6
  module Katapult
@@ -26,16 +26,11 @@ module Katapult
26
26
  class_option :db_password, type: :string, default: '',
27
27
  description: 'The password to set in config/database.yml'
28
28
 
29
- def write_ruby_version
29
+ def add_basic_files
30
30
  template '.ruby-version'
31
- end
32
-
33
- def add_gitignore
34
31
  template '.gitignore', force: true
35
- end
36
-
37
- def add_robots_txt
38
32
  template 'public/robots.txt', force: true
33
+ template 'README.md', force: true
39
34
  end
40
35
 
41
36
  # Gems ###################################################################
@@ -0,0 +1,33 @@
1
+ # <%= app_name(:human) %>
2
+
3
+ Describe the whole project in a few sentences to a few paragraphs, just as you
4
+ would explain it to your fellow developer. What is it actually, what was it
5
+ built for, who is using it, etc
6
+
7
+ See <https://makandracards.com/makandra/48339>.
8
+
9
+
10
+ ## Architecture and models
11
+
12
+ Give a quick overview of the few core models and how they interact. Do not go
13
+ into detail – class documentation should be written atop the class file. Just
14
+ impart the very basics to grasp the application model, so a new developer knows
15
+ where to dive in.
16
+
17
+
18
+ ## Development
19
+
20
+ Describe how to get started with the project. Document employed 3rd party
21
+ services and how to use them, how to start a development server – just about
22
+ anything that a new developer needs to know.
23
+
24
+
25
+ ## Peculiarity X
26
+
27
+ Add a section for each special concept in the application, e.g. a CDN and what
28
+ it is used for, that icons are rendered from a custom icon font and how to update
29
+ it, that all posts are created from an importer, that there's a web UI *and* a
30
+ JSON API *and* an embeddable component.
31
+
32
+ Make the reader aware of a peculiarity, but remember to keep it short. Details
33
+ should be documented in the respective area.
@@ -15,7 +15,7 @@ module NavigationHelpers
15
15
  action_prose, model_prose = $1, $2
16
16
  route = "#{action_prose == 'form' ? 'edit_' : ''}#{model_prose_to_route_segment(model_prose)}_path"
17
17
  model = model_prose_to_class(model_prose)
18
- send(route, model.last)
18
+ send(route, model.reorder(:id).last!)
19
19
 
20
20
  when /^the (page|form) for the (.*?) "(.*?)"$/
21
21
  action_prose, model_prose, identifier = $1, $2, $3
@@ -19,7 +19,7 @@ module Katapult
19
19
 
20
20
  def install_clearance
21
21
  insert_into_file 'Gemfile', <<-GEM, before: "gem 'katapult'"
22
- gem 'clearance', '< 1.14.0' # Has broken InstallGenerator :(
22
+ gem 'clearance'
23
23
 
24
24
  GEM
25
25
  run 'bundle install --quiet'
@@ -122,8 +122,12 @@ resources :users do
122
122
  end
123
123
 
124
124
  def add_user_factory
125
- inject_into_file 'spec/factories/factories.rb', <<-'CONTENT', after: 'FactoryBot.define do'
125
+ factories_file = 'spec/factories/factories.rb'
126
126
 
127
+ # Remove empty factory, if it exists
128
+ gsub_file factories_file, " factory :user\n\n", ''
129
+
130
+ inject_into_file factories_file, <<-'CONTENT', before: /end\n\z/
127
131
  factory :user do
128
132
  sequence(:email) { |i| "user-#{ i }@example.com" }
129
133
  password 'password'
@@ -12,4 +12,5 @@ Clearance.configure do |config|
12
12
  # config.secure_cookie = true
13
13
  # config.sign_in_guards = []
14
14
  # config.user_model = User
15
+ config.rotate_csrf_on_sign_in = true
15
16
  end
@@ -12,12 +12,22 @@ module Katapult
12
12
  template 'feature.feature', "features/#{model.name(:variables)}.feature"
13
13
  end
14
14
 
15
+ no_tasks do
16
+ def belongs_tos
17
+ app_model.get_belongs_tos_for model.name
18
+ end
19
+ end
20
+
15
21
  private
16
22
 
17
23
  def model
18
24
  @element
19
25
  end
20
26
 
27
+ def app_model
28
+ model.application_model
29
+ end
30
+
21
31
  end
22
32
  end
23
33
  end
@@ -2,6 +2,9 @@ Feature: <%= model.name(:humans).titleize %>
2
2
 
3
3
  Scenario: CRUD <%= model.name(:humans) %>
4
4
  Given I am on the list of <%= model.name(:variables) %>
5
+ <% belongs_tos.each do |model| -%>
6
+ And there is a <%= model.name(:human) %> with the <%= model.label_attr.name(:human) %> "<%= model.label_attr.test_value %>"
7
+ <% end -%>
5
8
 
6
9
  # create
7
10
  When I follow "Add <%= model.name(:human) %>"
@@ -25,7 +28,7 @@ Feature: <%= model.name(:humans).titleize %>
25
28
  Then I should be on the page for the <%= model.name(:variable) %> above
26
29
  <% model.attrs.each do |attr| -%>
27
30
  <%- case attr.type -%>
28
- <%- when :string, :email, :url, :integer, :money, :text -%>
31
+ <%- when :string, :email, :url, :integer, :money, :text, :foreign_key -%>
29
32
  And I should see "<%= attr.test_value %>"
30
33
  <%- when :flag -%>
31
34
  And I should see "<%= attr.name.humanize %> Yes"
@@ -52,7 +55,6 @@ Feature: <%= model.name(:humans).titleize %>
52
55
  <%- end -%>
53
56
  <% end -%>
54
57
 
55
- <% if model.label_attr -%>
56
58
  # destroy
57
59
  When I go to the list of <%= model.name(:variables) %>
58
60
  Then I should see "<%= model.label_attr.test_value %>"
@@ -60,4 +62,3 @@ Feature: <%= model.name(:humans).titleize %>
60
62
  When I follow "Destroy <%= model.label_attr.test_value %>"
61
63
  Then I should be on the list of <%= model.name(:variables) %>
62
64
  But I should not see "<%= model.label_attr.test_value %>"
63
- <% end -%>
@@ -30,11 +30,26 @@ module Katapult
30
30
  template 'app/models/shared/does_flag.rb' if flag_attrs.any?
31
31
  end
32
32
 
33
+ def write_factory
34
+ insert_into_file 'spec/factories/factories.rb', <<-FACTORY, before: /end\n\z/
35
+ factory #{ model.name(:symbol) }
36
+
37
+ FACTORY
38
+ end
39
+
33
40
  def generate_unit_tests
34
41
  Generators::ModelSpecsGenerator.new(model).invoke_all
35
42
  end
36
43
 
37
44
  no_commands do
45
+ def belongs_tos
46
+ model.application_model.get_belongs_tos_for model.name
47
+ end
48
+
49
+ def has_manys
50
+ model.application_model.get_has_manys_for model.name
51
+ end
52
+
38
53
  def flag_attrs
39
54
  model.attrs.select(&:flag?)
40
55
  end