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,90 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Generate views for a WUI.
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'katapult/generator'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'generators/katapult/cucumber_features/cucumber_features_generator'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Katapult
         
     | 
| 
      
 7 
     | 
    
         
            +
              module Generators
         
     | 
| 
      
 8 
     | 
    
         
            +
                class HamlGenerator < Katapult::Generator
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  desc 'Generate HAML views'
         
     | 
| 
      
 11 
     | 
    
         
            +
                  source_root File.expand_path('../templates', __FILE__)
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def install_application_layout
         
     | 
| 
      
 15 
     | 
    
         
            +
                    remove_file 'app/views/layouts/application.html.erb'
         
     | 
| 
      
 16 
     | 
    
         
            +
                    template 'app/views/layouts/application.html.haml'
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def create_views_directory
         
     | 
| 
      
 20 
     | 
    
         
            +
                    FileUtils.mkdir_p views_path
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def create_rails_standard_action_views
         
     | 
| 
      
 24 
     | 
    
         
            +
                    actions.select{ |a| a.get? && WUI::RAILS_ACTIONS.include?(a.name) }.each do |action|
         
     | 
| 
      
 25 
     | 
    
         
            +
                      file_name = "#{action.name}.html.haml"
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                      create_view file_name, File.join(views_path, file_name)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    end
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def create_form_partial_if_needed
         
     | 
| 
      
 32 
     | 
    
         
            +
                    _form_actions = (actions.map(&:name) & %w[new edit])
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    if _form_actions.any?
         
     | 
| 
      
 35 
     | 
    
         
            +
                      file_name = '_form.html.haml'
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                      create_view file_name, File.join(views_path, file_name)
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  def create_views_for_custom_actions
         
     | 
| 
      
 42 
     | 
    
         
            +
                    wui.custom_actions.select(&:get?).each do |action|
         
     | 
| 
      
 43 
     | 
    
         
            +
                      @action = action # Make the action object accessible in templates
         
     | 
| 
      
 44 
     | 
    
         
            +
                      create_view 'custom_action.html.haml', File.join(views_path, "#{action.name}.html.haml")
         
     | 
| 
      
 45 
     | 
    
         
            +
                    end
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  def generate_integration_tests
         
     | 
| 
      
 49 
     | 
    
         
            +
                    if wui.model.present?
         
     | 
| 
      
 50 
     | 
    
         
            +
                      Generators::CucumberFeaturesGenerator.new(wui.model).invoke_all
         
     | 
| 
      
 51 
     | 
    
         
            +
                    end
         
     | 
| 
      
 52 
     | 
    
         
            +
                  end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                  no_tasks do
         
     | 
| 
      
 55 
     | 
    
         
            +
                    def model_name(kind = nil)
         
     | 
| 
      
 56 
     | 
    
         
            +
                      wui.model_name(kind)
         
     | 
| 
      
 57 
     | 
    
         
            +
                    end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                    def views_path
         
     | 
| 
      
 60 
     | 
    
         
            +
                      File.join('app', 'views', model_name(:variables))
         
     | 
| 
      
 61 
     | 
    
         
            +
                    end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                    def navigation
         
     | 
| 
      
 64 
     | 
    
         
            +
                      wui.application_model.navigation
         
     | 
| 
      
 65 
     | 
    
         
            +
                    end
         
     | 
| 
      
 66 
     | 
    
         
            +
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                  private
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  # Rails views depend heavily on models. If the WUI has no model, do not
         
     | 
| 
      
 71 
     | 
    
         
            +
                  # use the templates but create empty files instead.
         
     | 
| 
      
 72 
     | 
    
         
            +
                  def create_view(template, destination)
         
     | 
| 
      
 73 
     | 
    
         
            +
                    if wui.model
         
     | 
| 
      
 74 
     | 
    
         
            +
                      template template, destination
         
     | 
| 
      
 75 
     | 
    
         
            +
                    else
         
     | 
| 
      
 76 
     | 
    
         
            +
                      create_file destination
         
     | 
| 
      
 77 
     | 
    
         
            +
                    end
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                  def wui
         
     | 
| 
      
 81 
     | 
    
         
            +
                    @element
         
     | 
| 
      
 82 
     | 
    
         
            +
                  end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                  def actions
         
     | 
| 
      
 85 
     | 
    
         
            +
                    wui.actions
         
     | 
| 
      
 86 
     | 
    
         
            +
                  end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                end
         
     | 
| 
      
 89 
     | 
    
         
            +
              end
         
     | 
| 
      
 90 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,38 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            = form_for <%= model_name(:ivar) %> do |form|
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              %dl.controls
         
     | 
| 
      
 4 
     | 
    
         
            +
            <% wui.model.attrs.each do |attribute| -%>
         
     | 
| 
      
 5 
     | 
    
         
            +
                %dt
         
     | 
| 
      
 6 
     | 
    
         
            +
                  = form.label <%= attribute.name(:symbol) %>
         
     | 
| 
      
 7 
     | 
    
         
            +
                %dd
         
     | 
| 
      
 8 
     | 
    
         
            +
              <%- if attribute.assignable_values -%>
         
     | 
| 
      
 9 
     | 
    
         
            +
                  = form.select <%= attribute.name(:symbol) %>, form.object.assignable_<%= attribute.name(:variables) %>
         
     | 
| 
      
 10 
     | 
    
         
            +
              <%- else -%>
         
     | 
| 
      
 11 
     | 
    
         
            +
                <%- case attribute.type -%>
         
     | 
| 
      
 12 
     | 
    
         
            +
                <%- when :string -%>
         
     | 
| 
      
 13 
     | 
    
         
            +
                  = form.text_field <%= attribute.name(:symbol) %>
         
     | 
| 
      
 14 
     | 
    
         
            +
                <%- when :email -%>
         
     | 
| 
      
 15 
     | 
    
         
            +
                  = form.email_field <%= attribute.name(:symbol) %>
         
     | 
| 
      
 16 
     | 
    
         
            +
                <%- when :url -%>
         
     | 
| 
      
 17 
     | 
    
         
            +
                  = form.url_field <%= attribute.name(:symbol) %>
         
     | 
| 
      
 18 
     | 
    
         
            +
                <%- when :integer -%>
         
     | 
| 
      
 19 
     | 
    
         
            +
                  = form.number_field <%= attribute.name(:symbol) %>
         
     | 
| 
      
 20 
     | 
    
         
            +
                <%- when :money -%>
         
     | 
| 
      
 21 
     | 
    
         
            +
                  = form.number_field <%= attribute.name(:symbol) %>
         
     | 
| 
      
 22 
     | 
    
         
            +
                  €
         
     | 
| 
      
 23 
     | 
    
         
            +
                <%- when :text -%>
         
     | 
| 
      
 24 
     | 
    
         
            +
                  = form.text_area <%= attribute.name(:symbol) %>, rows: 5
         
     | 
| 
      
 25 
     | 
    
         
            +
                <%- when :markdown -%>
         
     | 
| 
      
 26 
     | 
    
         
            +
                  = form.text_area <%= attribute.name(:symbol) %>, rows: 15
         
     | 
| 
      
 27 
     | 
    
         
            +
                <%- when :flag -%>
         
     | 
| 
      
 28 
     | 
    
         
            +
                  = form.check_box <%= attribute.name(:symbol) %>
         
     | 
| 
      
 29 
     | 
    
         
            +
                <%- when :datetime -%>
         
     | 
| 
      
 30 
     | 
    
         
            +
                  = form.datetime_field <%= attribute.name(:symbol) %>
         
     | 
| 
      
 31 
     | 
    
         
            +
                <%- end -%>
         
     | 
| 
      
 32 
     | 
    
         
            +
              <%- end -%>
         
     | 
| 
      
 33 
     | 
    
         
            +
            <% end -%>
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              .tools
         
     | 
| 
      
 36 
     | 
    
         
            +
                = form.submit 'Save', class: 'tools__button is_primary'
         
     | 
| 
      
 37 
     | 
    
         
            +
                - cancel_path = <%= model_name(:ivar) %>.new_record? ? <%= wui.path(:index) %> : <%= wui.path(:show, model_name(:ivar)) %>
         
     | 
| 
      
 38 
     | 
    
         
            +
                = link_to 'Cancel', cancel_path, class: 'tools__button'
         
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            !!!
         
     | 
| 
      
 2 
     | 
    
         
            +
            %html
         
     | 
| 
      
 3 
     | 
    
         
            +
              %head
         
     | 
| 
      
 4 
     | 
    
         
            +
                %title
         
     | 
| 
      
 5 
     | 
    
         
            +
                  <%= app_name.titlecase %>
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                = stylesheet_link_tag 'application', media: 'all'
         
     | 
| 
      
 8 
     | 
    
         
            +
                = javascript_include_tag 'application'
         
     | 
| 
      
 9 
     | 
    
         
            +
                = csrf_meta_tags
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              %body
         
     | 
| 
      
 12 
     | 
    
         
            +
                .layout
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  .layout__head
         
     | 
| 
      
 15 
     | 
    
         
            +
                    %h2 <%= app_name.titlecase %>
         
     | 
| 
      
 16 
     | 
    
         
            +
                    <%- if navigation -%>
         
     | 
| 
      
 17 
     | 
    
         
            +
                    = render_navigation Navigation.<%= navigation.name(:variable) %>
         
     | 
| 
      
 18 
     | 
    
         
            +
                    <%- end -%>
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  .layout__main
         
     | 
| 
      
 21 
     | 
    
         
            +
                    =# render 'layouts/flashes'
         
     | 
| 
      
 22 
     | 
    
         
            +
                    = yield
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  .layout__tail
         
     | 
| 
      
 25 
     | 
    
         
            +
                    powered by makandra
         
     | 
| 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            %h1
         
     | 
| 
      
 2 
     | 
    
         
            +
              <%= model_name(:human_plural).capitalize %>
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            .tools
         
     | 
| 
      
 5 
     | 
    
         
            +
              = link_to 'Add <%= model_name(:human) %>', <%= wui.path(:new) %>, class: 'tools__button is_primary'
         
     | 
| 
      
 6 
     | 
    
         
            +
            <% wui.custom_actions.select(&:collection?).each do |action| -%>
         
     | 
| 
      
 7 
     | 
    
         
            +
              = link_to '<%= action.name.humanize.titleize %>', <%= wui.path(action) %>, class: 'tools__button'
         
     | 
| 
      
 8 
     | 
    
         
            +
            <% end -%>
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            - if <%= model_name(:ivars) %>.any?
         
     | 
| 
      
 11 
     | 
    
         
            +
              %table.items
         
     | 
| 
      
 12 
     | 
    
         
            +
                <%- object_name = model_name(:variable) -%>
         
     | 
| 
      
 13 
     | 
    
         
            +
                - <%= model_name(:ivars) %>.each do |<%= object_name %>|
         
     | 
| 
      
 14 
     | 
    
         
            +
                  %tr
         
     | 
| 
      
 15 
     | 
    
         
            +
                    %td
         
     | 
| 
      
 16 
     | 
    
         
            +
                      = link_to <%= object_name %>.to_s, <%= object_name %>, class: 'hyperlink'
         
     | 
| 
      
 17 
     | 
    
         
            +
                    %td
         
     | 
| 
      
 18 
     | 
    
         
            +
                      .items__actions
         
     | 
| 
      
 19 
     | 
    
         
            +
                        = link_to 'Edit', <%= wui.path(:edit, object_name) %>, class: 'items__action'
         
     | 
| 
      
 20 
     | 
    
         
            +
                        = link_to 'Destroy', <%= wui.path(:destroy, object_name) %>, method: :delete, class: 'items__action', confirm: 'Really destroy?'
         
     | 
| 
      
 21 
     | 
    
         
            +
                      <%- wui.custom_actions.select(&:member?).each do |action| -%>
         
     | 
| 
      
 22 
     | 
    
         
            +
                        = link_to '<%= action.name.humanize.titleize %>', <%= wui.path(action, object_name) %>, class: 'items__action'<%=
         
     | 
| 
      
 23 
     | 
    
         
            +
                            ", method: :#{action.method}" unless action.get?
         
     | 
| 
      
 24 
     | 
    
         
            +
                          %>
         
     | 
| 
      
 25 
     | 
    
         
            +
                      <%- end -%>
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            - else
         
     | 
| 
      
 28 
     | 
    
         
            +
              %p.help-block
         
     | 
| 
      
 29 
     | 
    
         
            +
                There are no <%= model_name(:human_plural) %> yet.
         
     | 
| 
         @@ -0,0 +1,41 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            %h1
         
     | 
| 
      
 2 
     | 
    
         
            +
              = <%= model_name(:ivar) %>.to_s
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            .tools
         
     | 
| 
      
 5 
     | 
    
         
            +
              = link_to 'All <%= model_name(:human_plural) %>', <%= wui.path(:index) %>, class: 'tools__button'
         
     | 
| 
      
 6 
     | 
    
         
            +
              = link_to 'Edit', <%= wui.path(:edit, model_name(:ivar)) %>, class: 'tools__button is_primary'
         
     | 
| 
      
 7 
     | 
    
         
            +
              = link_to 'Destroy', <%= wui.path(:destroy, model_name(:ivar)) %>, method: :delete, class: 'tools__button', confirm: 'Really destroy?'
         
     | 
| 
      
 8 
     | 
    
         
            +
            <% wui.custom_actions.select(&:member?).each do |action| -%>
         
     | 
| 
      
 9 
     | 
    
         
            +
              = link_to '<%= action.name(:human).titleize %>', <%= wui.path(action, model_name(:ivar)) %>, class: 'tools__button'<%=
         
     | 
| 
      
 10 
     | 
    
         
            +
                  ", method: :#{action.method}" unless action.get?
         
     | 
| 
      
 11 
     | 
    
         
            +
                %>
         
     | 
| 
      
 12 
     | 
    
         
            +
            <% end -%>
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            %dl.values
         
     | 
| 
      
 15 
     | 
    
         
            +
            <% wui.model.attrs.each do |attribute| -%>
         
     | 
| 
      
 16 
     | 
    
         
            +
              <%- model_attribute = "#{model_name(:ivar)}.#{attribute.name}" -%>
         
     | 
| 
      
 17 
     | 
    
         
            +
              %dt
         
     | 
| 
      
 18 
     | 
    
         
            +
                = <%= model_name(:class_name) %>.human_attribute_name(:<%= attribute.name %>)
         
     | 
| 
      
 19 
     | 
    
         
            +
              %dd
         
     | 
| 
      
 20 
     | 
    
         
            +
              <%- case attribute.type -%>
         
     | 
| 
      
 21 
     | 
    
         
            +
              <%- when :string -%>
         
     | 
| 
      
 22 
     | 
    
         
            +
                = <%= model_attribute %>
         
     | 
| 
      
 23 
     | 
    
         
            +
              <%- when :email -%>
         
     | 
| 
      
 24 
     | 
    
         
            +
                = mail_to <%= model_attribute %>, nil, class: 'hyperlink'
         
     | 
| 
      
 25 
     | 
    
         
            +
              <%- when :url -%>
         
     | 
| 
      
 26 
     | 
    
         
            +
                = link_to <%= model_attribute %>, <%= model_attribute %>, class: 'hyperlink'
         
     | 
| 
      
 27 
     | 
    
         
            +
              <%- when :integer -%>
         
     | 
| 
      
 28 
     | 
    
         
            +
                = <%= model_attribute %>
         
     | 
| 
      
 29 
     | 
    
         
            +
              <%- when :money -%>
         
     | 
| 
      
 30 
     | 
    
         
            +
                = <%= model_attribute %>
         
     | 
| 
      
 31 
     | 
    
         
            +
                €
         
     | 
| 
      
 32 
     | 
    
         
            +
              <%- when :text -%>
         
     | 
| 
      
 33 
     | 
    
         
            +
                = simple_format(<%= model_attribute %>)
         
     | 
| 
      
 34 
     | 
    
         
            +
              <%- when :markdown -%>
         
     | 
| 
      
 35 
     | 
    
         
            +
                = markdown(<%= model_attribute %>)
         
     | 
| 
      
 36 
     | 
    
         
            +
              <%- when :flag -%>
         
     | 
| 
      
 37 
     | 
    
         
            +
                = <%= model_attribute %> ? 'Yes' : 'No'
         
     | 
| 
      
 38 
     | 
    
         
            +
              <%- when :datetime -%>
         
     | 
| 
      
 39 
     | 
    
         
            +
                = l(<%= model_attribute %>) if <%= model_attribute %>
         
     | 
| 
      
 40 
     | 
    
         
            +
              <%- end -%>
         
     | 
| 
      
 41 
     | 
    
         
            +
            <%- end -%>
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Install katapult into an application.
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Katapult
         
     | 
| 
      
 4 
     | 
    
         
            +
              class InstallGenerator < Rails::Generators::Base
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                desc 'Install katapult into a Rails app'
         
     | 
| 
      
 7 
     | 
    
         
            +
                source_root File.expand_path('../templates', __FILE__)
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def setup_lib
         
     | 
| 
      
 10 
     | 
    
         
            +
                  template 'lib/katapult/application_model.rb'
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Here you define the fundamentals of your application.
         
     | 
| 
      
 2 
     | 
    
         
            +
            #
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Add a model:
         
     | 
| 
      
 4 
     | 
    
         
            +
            # model 'customer' do |customer|
         
     | 
| 
      
 5 
     | 
    
         
            +
            #   customer.attr :name
         
     | 
| 
      
 6 
     | 
    
         
            +
            #   customer.attr :birth, type: :date
         
     | 
| 
      
 7 
     | 
    
         
            +
            #   customer.attr :email
         
     | 
| 
      
 8 
     | 
    
         
            +
            # end
         
     | 
| 
      
 9 
     | 
    
         
            +
            #
         
     | 
| 
      
 10 
     | 
    
         
            +
            # Add a web user interface:
         
     | 
| 
      
 11 
     | 
    
         
            +
            # wui 'customer' do |wui|
         
     | 
| 
      
 12 
     | 
    
         
            +
            #   wui.action :index
         
     | 
| 
      
 13 
     | 
    
         
            +
            #   wui.action :show
         
     | 
| 
      
 14 
     | 
    
         
            +
            #   wui.action :lock, scope: :member, method: :post
         
     | 
| 
      
 15 
     | 
    
         
            +
            # end
         
     | 
| 
      
 16 
     | 
    
         
            +
            #
         
     | 
| 
      
 17 
     | 
    
         
            +
            # Add navigation
         
     | 
| 
      
 18 
     | 
    
         
            +
            # navigation :main
         
     | 
| 
         @@ -0,0 +1,59 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Generate a Rails model, including migration and spec.
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'katapult/generator'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'generators/katapult/model_specs/model_specs_generator'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Katapult
         
     | 
| 
      
 7 
     | 
    
         
            +
              module Generators
         
     | 
| 
      
 8 
     | 
    
         
            +
                class ModelGenerator < Katapult::Generator
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  desc 'Generate a Rails Model'
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  check_class_collision
         
     | 
| 
      
 13 
     | 
    
         
            +
                  source_root File.expand_path('../templates', __FILE__)
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def create_migration_file
         
     | 
| 
      
 17 
     | 
    
         
            +
                    migration_name = "create_#{table_name}"
         
     | 
| 
      
 18 
     | 
    
         
            +
                    migration_attributes = model.attrs.map(&:for_migration)
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                    args = [migration_name] + migration_attributes
         
     | 
| 
      
 21 
     | 
    
         
            +
                    options = { timestamps: true, force: true }
         
     | 
| 
      
 22 
     | 
    
         
            +
                    invoke 'active_record:migration', args, options
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  def create_model_file
         
     | 
| 
      
 26 
     | 
    
         
            +
                    template 'model.rb', File.join('app', 'models', "#{file_name}.rb")
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  def write_traits
         
     | 
| 
      
 30 
     | 
    
         
            +
                    template 'app/models/shared/does_flag.rb' if flag_attrs.any?
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  def generate_unit_tests
         
     | 
| 
      
 34 
     | 
    
         
            +
                    Generators::ModelSpecsGenerator.new(model).invoke_all
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  no_commands do
         
     | 
| 
      
 38 
     | 
    
         
            +
                    def flag_attrs
         
     | 
| 
      
 39 
     | 
    
         
            +
                      model.attrs.select(&:flag?)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                    def defaults
         
     | 
| 
      
 43 
     | 
    
         
            +
                      {}.tap do |defaults|
         
     | 
| 
      
 44 
     | 
    
         
            +
                        model.attrs.select(&:has_defaults?).each do |attr|
         
     | 
| 
      
 45 
     | 
    
         
            +
                          defaults[attr.name.to_sym] = attr.default
         
     | 
| 
      
 46 
     | 
    
         
            +
                        end
         
     | 
| 
      
 47 
     | 
    
         
            +
                      end
         
     | 
| 
      
 48 
     | 
    
         
            +
                    end
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  private
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  def model
         
     | 
| 
      
 54 
     | 
    
         
            +
                    @element
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
              end
         
     | 
| 
      
 59 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module DoesFlag
         
     | 
| 
      
 2 
     | 
    
         
            +
              as_trait do |field, options = {}|
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                default = options[:default]
         
     | 
| 
      
 5 
     | 
    
         
            +
                virtual = options[:virtual]
         
     | 
| 
      
 6 
     | 
    
         
            +
                field_var = "@#{field}"
         
     | 
| 
      
 7 
     | 
    
         
            +
                set_field = "#{field}="
         
     | 
| 
      
 8 
     | 
    
         
            +
                field_query = "#{field}?"
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                validates field.to_sym, inclusion: { in: [true, false] }, allow_nil: !!virtual
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                unless default.nil?
         
     | 
| 
      
 13 
     | 
    
         
            +
                  has_defaults field.to_sym => default
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                if virtual
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  attr_reader field
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  define_method field_query do
         
     | 
| 
      
 21 
     | 
    
         
            +
                    send(field)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  define_method set_field do |value|
         
     | 
| 
      
 25 
     | 
    
         
            +
                    value = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    instance_variable_set(field_var, value)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class <%= class_name %> < ActiveRecord::Base
         
     | 
| 
      
 2 
     | 
    
         
            +
            <%- flag_attrs.each do |attr| -%>
         
     | 
| 
      
 3 
     | 
    
         
            +
              include DoesFlag[<%= attr.name(:symbol) %>, default: <%= attr.default %>]
         
     | 
| 
      
 4 
     | 
    
         
            +
            <%- end -%>
         
     | 
| 
      
 5 
     | 
    
         
            +
            <%- if defaults.any? -%>
         
     | 
| 
      
 6 
     | 
    
         
            +
              has_defaults(<%= defaults %>)
         
     | 
| 
      
 7 
     | 
    
         
            +
            <%- end -%>
         
     | 
| 
      
 8 
     | 
    
         
            +
            <%- model.attrs.select(&:assignable_values).each do |attr|  -%>
         
     | 
| 
      
 9 
     | 
    
         
            +
              assignable_values_for :<%= attr.name %>, <%= attr.options.slice(:allow_blank, :default) %> do
         
     | 
| 
      
 10 
     | 
    
         
            +
                <%= attr.assignable_values %>
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
            <%- end -%>
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              def to_s
         
     | 
| 
      
 15 
     | 
    
         
            +
            <% if model.label_attr -%>
         
     | 
| 
      
 16 
     | 
    
         
            +
                <%= model.label_attr.name %>.to_s
         
     | 
| 
      
 17 
     | 
    
         
            +
            <% else -%>
         
     | 
| 
      
 18 
     | 
    
         
            +
                "<%= model.name %>##{id}"
         
     | 
| 
      
 19 
     | 
    
         
            +
            <% end -%>
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,51 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Generate model specs.
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'katapult/generator'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Katapult
         
     | 
| 
      
 6 
     | 
    
         
            +
              module Generators
         
     | 
| 
      
 7 
     | 
    
         
            +
                class ModelSpecsGenerator < Katapult::Generator
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  desc 'Generate model specs'
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  check_class_collision
         
     | 
| 
      
 12 
     | 
    
         
            +
                  source_root File.expand_path('../templates', __FILE__)
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def create_model_spec
         
     | 
| 
      
 16 
     | 
    
         
            +
                    template 'model_spec.rb', File.join('spec', 'models', "#{file_name}_spec.rb")
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  no_tasks do
         
     | 
| 
      
 20 
     | 
    
         
            +
                    def specable_attrs
         
     | 
| 
      
 21 
     | 
    
         
            +
                      model.attrs.select do |attr|
         
     | 
| 
      
 22 
     | 
    
         
            +
                        attr.assignable_values.present? or attr.default != nil
         
     | 
| 
      
 23 
     | 
    
         
            +
                      end
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                    def assignable_value_for(attr)
         
     | 
| 
      
 27 
     | 
    
         
            +
                      attr.assignable_values.last
         
     | 
| 
      
 28 
     | 
    
         
            +
                    end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                    # Guess a value that is not assignable
         
     | 
| 
      
 31 
     | 
    
         
            +
                    def unassignable_value_for(attr)
         
     | 
| 
      
 32 
     | 
    
         
            +
                      case attr.type
         
     | 
| 
      
 33 
     | 
    
         
            +
                      when :integer
         
     | 
| 
      
 34 
     | 
    
         
            +
                        attr.assignable_values.max + 1
         
     | 
| 
      
 35 
     | 
    
         
            +
                      when :string
         
     | 
| 
      
 36 
     | 
    
         
            +
                        assignable_value_for(attr) + '-unassignable'
         
     | 
| 
      
 37 
     | 
    
         
            +
                      else
         
     | 
| 
      
 38 
     | 
    
         
            +
                        raise "Assignable values for :#{attr.type} attributes not supported"
         
     | 
| 
      
 39 
     | 
    
         
            +
                      end
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  private
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  def model
         
     | 
| 
      
 46 
     | 
    
         
            +
                    @element
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
              end
         
     | 
| 
      
 51 
     | 
    
         
            +
            end
         
     |