katapult 0.1.0

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