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,72 @@ | |
| 1 | 
            +
            # The base class for all katapult elements to inherit from.
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Every katapult element has a name which is a String. All options passed will
         | 
| 4 | 
            +
            # be mapped to attributes. Afterwards, the optional block will be yielded with
         | 
| 5 | 
            +
            # self.
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            module Katapult
         | 
| 8 | 
            +
              class Element
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                UnknownOptionError = Class.new(StandardError)
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                attr_accessor :name, :options
         | 
| 13 | 
            +
                attr_reader :application_model
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                # Improve semantics in element classes
         | 
| 16 | 
            +
                class << self
         | 
| 17 | 
            +
                  alias_method :options, :attr_accessor
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
             | 
| 21 | 
            +
                def initialize(name, options = {})
         | 
| 22 | 
            +
                  self.name = name.to_s
         | 
| 23 | 
            +
                  self.options = options
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  set_attributes(options)
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  yield(self) if block_given?
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                def set_application_model(app_model)
         | 
| 31 | 
            +
                  @application_model = app_model
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def name(kind = nil)
         | 
| 35 | 
            +
                  human_name = @name.downcase
         | 
| 36 | 
            +
                  machine_name = @name.underscore
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  case kind.to_s
         | 
| 39 | 
            +
                  when 'symbol'       then ":#{machine_name}"
         | 
| 40 | 
            +
                  when 'symbols'      then ":#{machine_name.pluralize}"
         | 
| 41 | 
            +
                  when 'variable'     then machine_name
         | 
| 42 | 
            +
                  when 'variables'    then machine_name.pluralize
         | 
| 43 | 
            +
                  when 'ivar'         then "@#{machine_name}"
         | 
| 44 | 
            +
                  when 'ivars'        then "@#{machine_name.pluralize}"
         | 
| 45 | 
            +
                  when 'human_plural' then human_name.pluralize
         | 
| 46 | 
            +
                  when 'human'        then human_name
         | 
| 47 | 
            +
                  when 'class'        then machine_name.classify
         | 
| 48 | 
            +
                  when 'classes'      then machine_name.classify.pluralize
         | 
| 49 | 
            +
                  else
         | 
| 50 | 
            +
                    @name
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                private
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                # Map options to attributes.
         | 
| 57 | 
            +
                # Example: set_attributes(foo: 123) sets the :foo attribute to 123 (via
         | 
| 58 | 
            +
                # #foo=) and raises UnknownOptionError if the attribute does not exist.
         | 
| 59 | 
            +
                def set_attributes(options)
         | 
| 60 | 
            +
                  options.each_pair do |option, value|
         | 
| 61 | 
            +
                    setter = "#{option}="
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                    if respond_to? setter
         | 
| 64 | 
            +
                      send(setter, value)
         | 
| 65 | 
            +
                    else
         | 
| 66 | 
            +
                      raise UnknownOptionError, "#{self.class.name} does not support option #{option.inspect}."
         | 
| 67 | 
            +
                    end
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
                end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              end
         | 
| 72 | 
            +
            end
         | 
| @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            # The katapult generator base class, slightly adapted from Rails generators.
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'rails/generators'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Katapult
         | 
| 6 | 
            +
              class Generator < Rails::Generators::NamedBase
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                attr_accessor :element
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def initialize(element)
         | 
| 11 | 
            +
                  self.element = element
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  super([element.name], {}, {}) # args, opts, config
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                private
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                def app_name
         | 
| 19 | 
            +
                  File.basename(Dir.pwd)
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def render_partial(template_path, given_binding = nil)
         | 
| 23 | 
            +
                  path = File.join(self.class.source_root, template_path)
         | 
| 24 | 
            +
                  ERB.new(::File.binread(path), nil, '%').result(given_binding || binding)
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
            end
         | 
| @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            # Models a Rails model.
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'katapult/element'
         | 
| 4 | 
            +
            require 'katapult/attribute'
         | 
| 5 | 
            +
            require 'generators/katapult/model/model_generator'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            module Katapult
         | 
| 8 | 
            +
              class Model < Element
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                UnknownAttributeError = Class.new(StandardError)
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                attr_accessor :attrs
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def initialize(*args)
         | 
| 15 | 
            +
                  self.attrs = []
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  super
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                def attr(attr_name, options = {})
         | 
| 21 | 
            +
                  attrs << Attribute.new(attr_name, options)
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                def label_attr
         | 
| 25 | 
            +
                  attrs.first
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                def render
         | 
| 29 | 
            +
                  Generators::ModelGenerator.new(self).invoke_all
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
            end
         | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            # Models a navigation.
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'katapult/element'
         | 
| 4 | 
            +
            require 'generators/katapult/navigation/navigation_generator'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module Katapult
         | 
| 7 | 
            +
              class Navigation < Element
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def wuis
         | 
| 10 | 
            +
                  application_model.wuis
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def section_name(wui)
         | 
| 14 | 
            +
                  wui.model_name(:symbols)
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def render
         | 
| 18 | 
            +
                  Generators::NavigationGenerator.new(self).invoke_all
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
            end
         | 
| @@ -0,0 +1,39 @@ | |
| 1 | 
            +
            # This class reads an application model file and turns it into an
         | 
| 2 | 
            +
            # ApplicationModel instance.
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            require_relative 'application_model'
         | 
| 5 | 
            +
            require 'katapult/model'
         | 
| 6 | 
            +
            require 'katapult/wui'
         | 
| 7 | 
            +
            require 'katapult/navigation'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            module Katapult
         | 
| 10 | 
            +
              class Parser
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def initialize
         | 
| 13 | 
            +
                  self.application_model = Katapult::ApplicationModel.new
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def parse(path_to_app_model_file)
         | 
| 17 | 
            +
                  instance_eval File.read(path_to_app_model_file), path_to_app_model_file
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  application_model
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def model(name, options = {}, &block)
         | 
| 23 | 
            +
                  application_model.add_model Model.new(name, options, &block)
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                def wui(name, options = {}, &block)
         | 
| 27 | 
            +
                  application_model.add_wui WUI.new(name, options, &block)
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                def navigation(name)
         | 
| 31 | 
            +
                  application_model.set_navigation Navigation.new(name)
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                private
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                attr_accessor :application_model
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
            end
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            # Utility methods.
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # The Katapult::Util module is used inside the `katapult` script. It should not
         | 
| 4 | 
            +
            # require any gems in order to prevent version conflicts.
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module Katapult
         | 
| 7 | 
            +
              module Util
         | 
| 8 | 
            +
                extend self
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def git_commit(message)
         | 
| 11 | 
            +
                  message.gsub! /'/, "" # remove single quotes
         | 
| 12 | 
            +
                  system "git add --all; git commit -m '#{ message }' --author='katapult <katapult@makandra.com>'"
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
            end
         | 
    
        data/lib/katapult/wui.rb
    ADDED
    
    | @@ -0,0 +1,77 @@ | |
| 1 | 
            +
            # Models a controller, including routes and views. Little more than a container
         | 
| 2 | 
            +
            # class for the Attribute element.
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            require 'katapult/element'
         | 
| 5 | 
            +
            require 'katapult/action'
         | 
| 6 | 
            +
            require 'generators/katapult/w_u_i/w_u_i_generator'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            module Katapult
         | 
| 9 | 
            +
              class WUI < Element
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                options :model
         | 
| 12 | 
            +
                attr_accessor :actions
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                RAILS_ACTIONS = %w[ index show new create edit update destroy ]
         | 
| 15 | 
            +
                UnknownActionError = Class.new(StandardError)
         | 
| 16 | 
            +
                UnknownModelError = Class.new(StandardError)
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                def initialize(*args)
         | 
| 19 | 
            +
                  self.actions = []
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  super
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                # DSL
         | 
| 25 | 
            +
                def action(name, options = {})
         | 
| 26 | 
            +
                  actions << Action.new(:new, options) if name.to_s == 'create'
         | 
| 27 | 
            +
                  actions << Action.new(:edit, options) if name.to_s == 'update'
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  actions << Action.new(name, options)
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                # DSL
         | 
| 33 | 
            +
                def crud
         | 
| 34 | 
            +
                  %i(index show create update destroy).each &method(:action)
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                def model
         | 
| 38 | 
            +
                  model_name = @model || self.name
         | 
| 39 | 
            +
                  application_model.get_model(model_name) or raise UnknownModelError,
         | 
| 40 | 
            +
                    "Could not find a model named #{model_name}"
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                def custom_actions
         | 
| 44 | 
            +
                  actions.reject { |a| RAILS_ACTIONS.include? a.name }
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                def find_action(action_name)
         | 
| 48 | 
            +
                  actions.find { |a| a.name == action_name.to_s }
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                def path(action, object_name = nil)
         | 
| 52 | 
            +
                  unless action.is_a?(Action)
         | 
| 53 | 
            +
                    not_found_message = "Unknown action '#{action}'"
         | 
| 54 | 
            +
                    action = find_action(action) or raise UnknownActionError, not_found_message
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  member_path = "#{model.name(:variable)}_path"
         | 
| 58 | 
            +
                  collection_path = "#{model.name(:variables)}_path"
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                  path = ''
         | 
| 61 | 
            +
                  path << action.name << '_' unless %w[index show destroy].include?(action.name)
         | 
| 62 | 
            +
                  path << (action.member? ? member_path : collection_path)
         | 
| 63 | 
            +
                  path << "(#{object_name})" if object_name
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                  path
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                def model_name(kind = nil)
         | 
| 69 | 
            +
                  model.name(kind)
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                def render
         | 
| 73 | 
            +
                  Generators::WUIGenerator.new(self).invoke_all
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
              end
         | 
| 77 | 
            +
            end
         | 
    
        data/script/console
    ADDED
    
    | @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # This file imitates the Rails console to ease debugging the gem.
         | 
| 4 | 
            +
            # Run `script/console` from the gem root to start an IRB with the gem loaded.
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            # Remember to require classes before using them,
         | 
| 7 | 
            +
            # i.e. run `require 'katapult/wui'` before `Katapult::WUI.new :example_name`.
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            irb_options = [
         | 
| 10 | 
            +
              '-Ilib',      # add lib/ to load_path
         | 
| 11 | 
            +
              '-d',         # set $DEBUG = true
         | 
| 12 | 
            +
              '-rkatapult', # require katapult
         | 
| 13 | 
            +
              '-f'          # don't read ~/.irbrc
         | 
| 14 | 
            +
            ]
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            exec 'irb', *irb_options
         | 
    
        data/spec/action_spec.rb
    ADDED
    
    | @@ -0,0 +1,44 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
            require 'katapult/action'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            describe Katapult::Action do
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              subject { described_class.new 'action' }
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              describe '#post?' do
         | 
| 9 | 
            +
                it 'returns true when its method is :post' do
         | 
| 10 | 
            +
                  subject.method = :post
         | 
| 11 | 
            +
                  expect(subject.post?).to be true
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                it 'returns false when its method is :get' do
         | 
| 15 | 
            +
                  subject.method = :get
         | 
| 16 | 
            +
                  expect(subject.post?).to be false
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              describe '#member?' do
         | 
| 21 | 
            +
                it 'returns true when its scope is :member' do
         | 
| 22 | 
            +
                  subject.scope = :member
         | 
| 23 | 
            +
                  expect(subject.member?).to be true
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                it 'returns false when its scope is :collection' do
         | 
| 27 | 
            +
                  subject.scope = :collection
         | 
| 28 | 
            +
                  expect(subject.member?).to be false
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                it 'returns false when it is an index action' do
         | 
| 32 | 
            +
                  subject = described_class.new :index
         | 
| 33 | 
            +
                  expect(subject.member?).to be false
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              describe '#collection?' do
         | 
| 38 | 
            +
                it 'returns true when it is an index action' do
         | 
| 39 | 
            +
                  subject = described_class.new :index
         | 
| 40 | 
            +
                  expect(subject.collection?).to be true
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            end
         | 
| @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
            require 'katapult/attribute'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            describe Katapult::Attribute do
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              it 'is of type :string by default' do
         | 
| 7 | 
            +
                expect(described_class.new('name').type).to eql(:string)
         | 
| 8 | 
            +
                expect(described_class.new('address').type).to eql(:string)
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              it 'requires a default for :flag attributes' do
         | 
| 12 | 
            +
                expect do
         | 
| 13 | 
            +
                  described_class.new('attr', type: :flag)
         | 
| 14 | 
            +
                end.to raise_error(Katapult::Attribute::MissingOptionError,
         | 
| 15 | 
            +
                  "The :flag attribute 'attr' requires a default (true or false).")
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              describe '#flag?' do
         | 
| 19 | 
            +
                it 'returns whether it is of type :flag' do
         | 
| 20 | 
            +
                  expect(described_class.new('attr', type: :flag, default: false).flag?).to be true
         | 
| 21 | 
            +
                  expect(described_class.new('attr', type: :string).flag?).to be false
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              describe 'available types' do
         | 
| 26 | 
            +
                it 'raises an error if the specified type is not supported' do
         | 
| 27 | 
            +
                  expect do
         | 
| 28 | 
            +
                    described_class.new('attr', type: :undefined)
         | 
| 29 | 
            +
                  end.to raise_error(Katapult::Attribute::UnknownTypeError,
         | 
| 30 | 
            +
                    "Attribute type :undefined is not supported. Use one of #{Katapult::Attribute::TYPES.inspect}."
         | 
| 31 | 
            +
                  )
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              describe 'email attributes' do
         | 
| 36 | 
            +
                it 'recognizes email attributes' do
         | 
| 37 | 
            +
                  expect(described_class.new('email').type).to eql(:email)
         | 
| 38 | 
            +
                  expect(described_class.new('customer_email').type).to eql(:email)
         | 
| 39 | 
            +
                  expect(described_class.new('name').type).to_not eql(:email)
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                it 'does not overwrite a given type' do
         | 
| 43 | 
            +
                  expect(described_class.new('email', type: :url).type).to eql(:url)
         | 
| 44 | 
            +
                  expect(described_class.new('email_updated_at', type: :datetime).type).to eql(:datetime)
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            end
         | 
    
        data/spec/model_spec.rb
    ADDED
    
    | @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
            require 'katapult/model'
         | 
| 3 | 
            +
            require 'katapult/attribute'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            describe Katapult::Model do
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              subject { described_class.new('model') }
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              describe '#label_attr' do
         | 
| 10 | 
            +
                it 'returns the model’s first attribute' do
         | 
| 11 | 
            +
                  subject.attr('first_attr')
         | 
| 12 | 
            +
                  subject.attr('second_attr')
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  expect(subject.label_attr.name).to eql('first_attr')
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            end
         | 
    
        data/spec/spec_helper.rb
    ADDED
    
    | @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            require 'bundler/setup'
         | 
| 2 | 
            +
            Bundler.setup
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            require 'pry'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            # Require some Rails for the specs to pass
         | 
| 7 | 
            +
            require 'active_support/core_ext/string/inflections'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            RSpec.configure do |config|
         | 
| 10 | 
            +
              config.treat_symbols_as_metadata_keys_with_true_values = true
         | 
| 11 | 
            +
              config.run_all_when_everything_filtered = true
         | 
| 12 | 
            +
              config.filter_run :focus
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              # Run specs in random order to surface order dependencies. If you find an
         | 
| 15 | 
            +
              # order dependency and want to debug it, you can fix the order by providing
         | 
| 16 | 
            +
              # the seed, which is printed after each run.
         | 
| 17 | 
            +
              #     --seed 1234
         | 
| 18 | 
            +
              config.order = 'random'
         | 
| 19 | 
            +
            end
         |