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.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +4 -0
  6. data/Guardfile +11 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +122 -0
  9. data/Rakefile +14 -0
  10. data/bin/katapult +44 -0
  11. data/features/binary.feature +48 -0
  12. data/features/configuration.feature +24 -0
  13. data/features/katapult.feature +201 -0
  14. data/features/model.feature +203 -0
  15. data/features/navigation.feature +80 -0
  16. data/features/step_definitions/db_steps.rb +8 -0
  17. data/features/step_definitions/file_steps.rb +14 -0
  18. data/features/step_definitions/katapult_steps.rb +14 -0
  19. data/features/step_definitions/rails_steps.rb +44 -0
  20. data/features/step_definitions/test_steps.rb +7 -0
  21. data/features/support/env.rb +16 -0
  22. data/features/wui.feature +319 -0
  23. data/katapult.gemspec +35 -0
  24. data/katapult.png +0 -0
  25. data/lib/generators/katapult/basics/basics_generator.rb +95 -0
  26. data/lib/generators/katapult/basics/templates/Gemfile +76 -0
  27. data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application.css.sass +6 -0
  28. data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_all.css.sass +4 -0
  29. data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_items.css.sass +11 -0
  30. data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_layout.css.sass +26 -0
  31. data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_navigation.css.sass +11 -0
  32. data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_tools.css.sass +12 -0
  33. data/lib/generators/katapult/basics/templates/config/database.sample.yml +16 -0
  34. data/lib/generators/katapult/basics/templates/config/database.yml +13 -0
  35. data/lib/generators/katapult/basics/templates/config/spring.rb +3 -0
  36. data/lib/generators/katapult/basics/templates/features/support/env-custom.rb +3 -0
  37. data/lib/generators/katapult/basics/templates/features/support/paths.rb +47 -0
  38. data/lib/generators/katapult/cucumber_features/cucumber_features_generator.rb +23 -0
  39. data/lib/generators/katapult/cucumber_features/templates/feature.feature +59 -0
  40. data/lib/generators/katapult/haml/haml_generator.rb +90 -0
  41. data/lib/generators/katapult/haml/templates/_form.html.haml +38 -0
  42. data/lib/generators/katapult/haml/templates/app/views/layouts/application.html.haml +25 -0
  43. data/lib/generators/katapult/haml/templates/custom_action.html.haml +5 -0
  44. data/lib/generators/katapult/haml/templates/edit.html.haml +4 -0
  45. data/lib/generators/katapult/haml/templates/index.html.haml +29 -0
  46. data/lib/generators/katapult/haml/templates/new.html.haml +4 -0
  47. data/lib/generators/katapult/haml/templates/show.html.haml +41 -0
  48. data/lib/generators/katapult/install/install_generator.rb +14 -0
  49. data/lib/generators/katapult/install/templates/lib/katapult/application_model.rb +18 -0
  50. data/lib/generators/katapult/model/model_generator.rb +59 -0
  51. data/lib/generators/katapult/model/templates/app/models/shared/does_flag.rb +32 -0
  52. data/lib/generators/katapult/model/templates/model.rb +21 -0
  53. data/lib/generators/katapult/model_specs/model_specs_generator.rb +51 -0
  54. data/lib/generators/katapult/model_specs/templates/model_spec.rb +34 -0
  55. data/lib/generators/katapult/navigation/navigation_generator.rb +25 -0
  56. data/lib/generators/katapult/navigation/templates/app/models/navigation.rb +12 -0
  57. data/lib/generators/katapult/transform/transform_generator.rb +47 -0
  58. data/lib/generators/katapult/w_u_i/templates/_route.rb +13 -0
  59. data/lib/generators/katapult/w_u_i/templates/controller.rb +106 -0
  60. data/lib/generators/katapult/w_u_i/w_u_i_generator.rb +57 -0
  61. data/lib/katapult.rb +5 -0
  62. data/lib/katapult/action.rb +44 -0
  63. data/lib/katapult/application_model.rb +45 -0
  64. data/lib/katapult/attribute.rb +83 -0
  65. data/lib/katapult/element.rb +72 -0
  66. data/lib/katapult/generator.rb +28 -0
  67. data/lib/katapult/model.rb +33 -0
  68. data/lib/katapult/navigation.rb +22 -0
  69. data/lib/katapult/parser.rb +39 -0
  70. data/lib/katapult/util.rb +16 -0
  71. data/lib/katapult/version.rb +3 -0
  72. data/lib/katapult/wui.rb +77 -0
  73. data/script/console +16 -0
  74. data/spec/action_spec.rb +44 -0
  75. data/spec/attribute_spec.rb +48 -0
  76. data/spec/model_spec.rb +18 -0
  77. data/spec/spec_helper.rb +19 -0
  78. data/spec/util_spec.rb +23 -0
  79. data/spec/wui_spec.rb +49 -0
  80. metadata +253 -0
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'katapult/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'katapult'
8
+ spec.version = Katapult::VERSION
9
+ spec.authors = ['Dominik Schöler']
10
+ spec.email = ['dominik.schoeler@makandra.de']
11
+ spec.summary = %q{Kickstart Rails development}
12
+ spec.description = %q{Katapult is a framework for generating base code}
13
+ spec.homepage = 'https://github.com/makandra/katapult'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.required_ruby_version = '>= 2.0'
22
+
23
+ spec.add_runtime_dependency 'rails'
24
+ spec.add_runtime_dependency 'spring' # speed-up
25
+
26
+ # Development
27
+ spec.add_development_dependency 'bundler', '~> 1.5'
28
+ spec.add_development_dependency 'rake'
29
+ spec.add_development_dependency 'pry'
30
+
31
+ # Testing
32
+ spec.add_development_dependency 'aruba'
33
+ spec.add_development_dependency 'guard-cucumber'
34
+ spec.add_development_dependency 'rspec'
35
+ end
Binary file
@@ -0,0 +1,95 @@
1
+ # Generates model-independent application basics (see method names).
2
+
3
+ module Katapult
4
+ module Generators
5
+ class BasicsGenerator < Rails::Generators::Base
6
+
7
+ SKIP_GEMS = %w(sass-rails coffee-rails turbolinks sdoc uglifier)
8
+
9
+ desc 'Generate basics like test directories and gems'
10
+ source_root File.expand_path('../templates', __FILE__)
11
+
12
+
13
+ def write_database_ymls
14
+ template 'config/database.yml', force: true
15
+ template 'config/database.sample.yml'
16
+ end
17
+
18
+ # Overwrite Gemfile with the template, but transfer all gems that are not
19
+ # skipped (see SKIP_GEMS).
20
+ def enhance_gemfile
21
+ gem_lines = File.readlines('Gemfile').select{ |line| line =~ /^gem/ }
22
+ @original_gems = gem_lines.reject do |line|
23
+ line =~ /'(#{ SKIP_GEMS.join '|' })'/
24
+ end
25
+
26
+ template 'Gemfile', force: true
27
+ end
28
+
29
+ def bundle_install
30
+ bundle 'install'
31
+ end
32
+
33
+ def remove_turbolinks_js
34
+ gsub_file 'app/assets/javascripts/application.js', "//= require turbolinks\n", ''
35
+ end
36
+
37
+ def setup_spring
38
+ bundle 'exec spring binstub --all'
39
+ template 'config/spring.rb'
40
+ run 'spring stop' # reload
41
+ end
42
+
43
+ def add_modularity_load_paths
44
+ # This results in correct formatting :)
45
+ application <<-'LOAD_PATHS'
46
+ config.autoload_paths << "#{Rails.root}/app/controllers/shared"
47
+ config.autoload_paths << "#{Rails.root}/app/models/shared"
48
+ config.autoload_paths << "#{Rails.root}/app/util"
49
+ config.autoload_paths << "#{Rails.root}/app/util/shared"
50
+ LOAD_PATHS
51
+ end
52
+
53
+ def install_cucumber
54
+ generate 'cucumber:install'
55
+
56
+ template 'features/support/paths.rb'
57
+ template 'features/support/env-custom.rb'
58
+ end
59
+
60
+ def install_rspec
61
+ generate 'rspec:install'
62
+
63
+ # Do not show Ruby warnings in RSpec runs.
64
+ gsub_file '.rspec', "--warnings\n", ''
65
+
66
+ inject_into_file 'spec/rails_helper.rb', after: "require 'rspec/rails'\n" do
67
+ "require 'shoulda/matchers'\n"
68
+ end
69
+ end
70
+
71
+ def install_styles
72
+ remove_file 'app/assets/stylesheets/application.css'
73
+ directory 'app/assets/stylesheets', force: true
74
+ end
75
+
76
+ # def install_capistrano
77
+ # capify!
78
+ # template 'config/deploy.rb'
79
+ # end
80
+
81
+ private
82
+
83
+ def app_name
84
+ File.basename(Dir.pwd)
85
+ end
86
+
87
+ def bundle(command)
88
+ Bundler.with_clean_env do
89
+ run 'bundle ' + command
90
+ end
91
+ end
92
+
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,76 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # from original Gemfile
4
+ <%= @original_gems.join %>
5
+
6
+ # engines
7
+ gem 'haml-rails'
8
+
9
+ # internal
10
+ gem 'exception_notification'
11
+ gem 'breach-mitigation-rails'
12
+
13
+ # better coding
14
+ gem 'modularity'
15
+ gem 'edge_rider'
16
+ gem 'andand'
17
+
18
+ # models
19
+ gem 'has_defaults'
20
+ gem 'assignable_values'
21
+
22
+ # gem 'carrierwave'
23
+ # gem 'mini_magick'
24
+
25
+ # gem 'spreadsheet'
26
+ # gem 'vcard'
27
+
28
+ # views
29
+ # gem 'simple_form'
30
+ # gem 'nested_form'
31
+ gem 'will_paginate'
32
+ gem 'makandra-navy', require: 'navy'
33
+
34
+ # assets
35
+ gem 'bootstrap-sass'
36
+ gem 'sass-rails'
37
+ gem 'autoprefixer-rails'
38
+ gem 'coffee-rails'
39
+ gem 'uglifier'
40
+ gem 'compass-rails'
41
+ gem 'compass-rgbapng'
42
+
43
+ group :development do
44
+ gem 'query_diet'
45
+ gem 'better_errors'
46
+ gem 'binding_of_caller'
47
+ gem 'thin'
48
+
49
+ gem 'guard-livereload', require: false
50
+ gem 'rack-livereload'
51
+ gem 'spring-commands-rspec'
52
+ gem 'spring-commands-cucumber'
53
+ end
54
+
55
+ group :development, :test do
56
+ gem 'byebug'
57
+ gem 'factory_girl_rails'
58
+ gem 'rspec-rails'
59
+ end
60
+
61
+ group :test do
62
+ gem 'parallel_tests'
63
+ gem 'database_cleaner'
64
+ gem 'timecop'
65
+ gem 'launchy'
66
+
67
+ gem 'capybara'
68
+ gem 'cucumber-rails', require: false
69
+ gem 'cucumber_factory'
70
+ gem 'cucumber_spinner'
71
+ gem 'selenium-webdriver'
72
+ gem 'spreewald'
73
+
74
+ gem 'rspec_candy'
75
+ gem 'shoulda-matchers', require: false
76
+ end
@@ -0,0 +1,6 @@
1
+ $body-bg: #ddd
2
+
3
+ @import compass
4
+ @import bootstrap
5
+
6
+ @import application/blocks/all
@@ -0,0 +1,4 @@
1
+ @import items
2
+ @import layout
3
+ @import navigation
4
+ @import tools
@@ -0,0 +1,11 @@
1
+ table.items
2
+ @extend .table
3
+ @extend .table-striped
4
+
5
+ .items__actions
6
+ @extend .btn-group
7
+
8
+ .items__action
9
+ @extend .btn
10
+ @extend .btn-default
11
+ @extend .btn-xs
@@ -0,0 +1,26 @@
1
+ @import compass/css3/box-shadow
2
+ @import bootstrap/variables
3
+
4
+ .layout
5
+ margin: 100px auto
6
+ width: 800px
7
+
8
+ background-color: white
9
+ +single-box-shadow
10
+
11
+ .layout__head
12
+ padding: 10px 35px
13
+
14
+ color: #fff
15
+ background-color: $brand-primary
16
+
17
+ .layout__main
18
+ padding: 20px 35px
19
+
20
+ .layout__tail
21
+ padding: 10px 35px
22
+
23
+ color: $gray-light
24
+ background-color: $gray-lighter
25
+ border-top: 1px solid darken($gray-lighter, 10%)
26
+ font-size: $font-size-small
@@ -0,0 +1,11 @@
1
+ .navy-layouted-sections
2
+ @extend .btn-group
3
+
4
+ .navy-section
5
+ @extend .btn
6
+ @extend .btn-info
7
+
8
+ text-transform: uppercase
9
+
10
+ &.navy-current
11
+ @extend .btn-default
@@ -0,0 +1,12 @@
1
+ @import bootstrap/variables
2
+
3
+ .tools
4
+ @extend .btn-group
5
+ margin-bottom: $line-height-computed / 2
6
+
7
+ .tools__button
8
+ @extend .btn
9
+ @extend .btn-default
10
+
11
+ .tools__button.is_primary
12
+ @extend .btn-primary
@@ -0,0 +1,16 @@
1
+ common: &common
2
+ adapter: mysql2
3
+ encoding: utf8
4
+ username: root
5
+ password:
6
+
7
+ development:
8
+ <<: *common
9
+ database: <%= app_name %>_development
10
+
11
+ test: &test
12
+ <<: *common
13
+ database: <%= app_name %>_test<%%= ENV['TEST_ENV_NUMBER'] %>
14
+
15
+ cucumber:
16
+ <<: *test
@@ -0,0 +1,13 @@
1
+ common: &common
2
+ adapter: mysql2
3
+ encoding: utf8
4
+ username: katapult
5
+ password: secret
6
+
7
+ development:
8
+ <<: *common
9
+ database: <%= app_name %>_development
10
+
11
+ test:
12
+ <<: *common
13
+ database: <%= app_name %>_test<%%= ENV['TEST_ENV_NUMBER'] %>
@@ -0,0 +1,3 @@
1
+ # Custom generator templates are put into lib/templates.
2
+ FileUtils.mkdir_p 'lib/templates'
3
+ Spring.watch 'lib/templates'
@@ -0,0 +1,3 @@
1
+ require 'rspec' # it does not work without explicitly doing this. why??
2
+ require 'rspec_candy/all'
3
+ require 'spreewald/all_steps'
@@ -0,0 +1,47 @@
1
+ module NavigationHelpers
2
+
3
+ def path_to(page_name)
4
+ case page_name
5
+
6
+ when /^the list of (.*?)$/
7
+ models_prose = $1
8
+ route = "#{model_prose_to_route_segment(models_prose)}_path"
9
+ send(route)
10
+
11
+ when /^the (page|form) for the (.*?) above$/
12
+ action_prose, model_prose = $1, $2
13
+ route = "#{action_prose == 'form' ? 'edit_' : ''}#{model_prose_to_route_segment(model_prose)}_path"
14
+ model = model_prose.classify.constantize
15
+ send(route, model.last)
16
+
17
+ when /^the (page|form) for the (.*?) "(.*?)"$/
18
+ action_prose, model_prose, identifier = $1, $2, $3
19
+ path_to_show_or_edit(action_prose, model_prose, identifier)
20
+
21
+ when /^the (.*?) (page|form) for "(.*?)"$/
22
+ model_prose, action_prose, identifier = $1, $2, $3
23
+ path_to_show_or_edit(action_prose, model_prose, identifier)
24
+
25
+ when /^the (.*?) form$/
26
+ model_prose = $1
27
+ route = "new_#{model_prose_to_route_segment(model_prose)}_path"
28
+ send(route)
29
+
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def path_to_show_or_edit(action_prose, model_prose, identifier)
36
+ model = model_prose.classify.constantize
37
+ route = "#{action_prose == 'form' ? 'edit_' : ''}#{model_prose_to_route_segment(model_prose)}_path"
38
+ send(route, model.find_by_anything!(identifier))
39
+ end
40
+
41
+ def model_prose_to_route_segment(model_prose)
42
+ model_prose.gsub(/[\ \/]/, '_')
43
+ end
44
+
45
+ end
46
+
47
+ World(NavigationHelpers)
@@ -0,0 +1,23 @@
1
+ require 'katapult/generator'
2
+
3
+ module Katapult
4
+ module Generators
5
+ class CucumberFeaturesGenerator < Katapult::Generator
6
+
7
+ desc 'Generate Cucumber features for CRUD'
8
+ source_root File.expand_path('../templates', __FILE__)
9
+
10
+
11
+ def create_crud_feature
12
+ template 'feature.feature', "features/#{model.name(:variables)}.feature"
13
+ end
14
+
15
+ private
16
+
17
+ def model
18
+ @element
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,59 @@
1
+ Feature: <%= model.name(:human_plural).titleize %>
2
+
3
+ Scenario: CRUD <%= model.name(:human_plural) %>
4
+ Given I am on the list of <%= model.name(:variables) %>
5
+
6
+ # create
7
+ When I follow "Add <%= model.name(:variable) %>"
8
+ <% model.attrs.each do |attr| -%>
9
+ <%- if attr.assignable_values -%>
10
+ And I select "<%= attr.test_value %>" from "<%= attr.name.humanize %>"
11
+ <%- else -%>
12
+ <%- case attr.type -%>
13
+ <%- when :string, :email, :url, :integer, :money, :text, :markdown, :datetime -%>
14
+ And I fill in "<%= attr.name.humanize %>" with "<%= attr.test_value %>"
15
+ <%- when :flag -%>
16
+ And I check "<%= attr.name.humanize %>"
17
+ <%- end -%>
18
+ <%- end -%>
19
+ <% end -%>
20
+ And I press "Save"
21
+
22
+ # read
23
+ Then I should be on the page for the <%= model.name(:variable) %> above
24
+ <% model.attrs.each do |attr| -%>
25
+ <%- case attr.type -%>
26
+ <%- when :string, :email, :url, :integer, :money, :text, :markdown -%>
27
+ And I should see "<%= attr.test_value %>"
28
+ <%- when :flag -%>
29
+ And I should see "<%= attr.name.humanize %> Yes"
30
+ <%- when :datetime -%>
31
+ And I should see "<%= I18n.localize(attr.test_value) %>"
32
+ <%- end -%>
33
+ <% end -%>
34
+
35
+ # update
36
+ When I follow "Edit"
37
+ Then I should be on the form for the <%= model.name(:variable) %> above
38
+ <% model.attrs.each do |attr| -%>
39
+ <%- if attr.assignable_values -%>
40
+ And "<%= attr.test_value %>" should be selected for "<%= attr.name.humanize %>"
41
+ <%- else -%>
42
+ <%- case attr.type -%>
43
+ <%- when :string, :email, :url, :integer, :money, :text, :markdown, :datetime -%>
44
+ And the "<%= attr.name.humanize %>" field should contain "<%= attr.test_value %>"
45
+ <%- when :flag -%>
46
+ And the "<%= attr.name.humanize %>" checkbox should be checked
47
+ <%- end -%>
48
+ <%- end -%>
49
+ <% end -%>
50
+
51
+ <% if model.label_attr # do not crash when the model has no label attr -%>
52
+ # destroy
53
+ When I go to the list of <%= model.name(:variables) %>
54
+ Then I should see "<%= model.label_attr.test_value %>"
55
+
56
+ When I follow "Destroy"
57
+ Then I should be on the list of <%= model.name(:variables) %>
58
+ But I should not see "<%= model.label_attr.test_value %>"
59
+ <% end -%>