katapult 0.3.0 → 0.4.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 +4 -4
- data/CHANGELOG.md +30 -0
- data/README.md +57 -9
- data/bin/katapult +7 -3
- data/features/application_model.feature +4 -1
- data/features/authenticate.feature +1 -18
- data/features/basics.feature +1 -0
- data/features/binary.feature +5 -7
- data/features/model.feature +42 -3
- data/features/step_definitions/rails_steps.rb +1 -1
- data/features/web_ui.feature +17 -5
- data/lib/generators/katapult/app_model/templates/lib/katapult/application_model.rb +3 -0
- data/lib/generators/katapult/basics/basics_generator.rb +3 -8
- data/lib/generators/katapult/basics/templates/README.md.tt +33 -0
- data/lib/generators/katapult/basics/templates/features/support/paths.rb +1 -1
- data/lib/generators/katapult/clearance/clearance_generator.rb +6 -2
- data/lib/generators/katapult/clearance/templates/config/initializers/clearance.rb +1 -0
- data/lib/generators/katapult/cucumber_features/cucumber_features_generator.rb +10 -0
- data/lib/generators/katapult/cucumber_features/templates/feature.feature +4 -3
- data/lib/generators/katapult/model/model_generator.rb +15 -0
- data/lib/generators/katapult/model/templates/model.rb +13 -3
- data/lib/generators/katapult/model_specs/model_specs_generator.rb +1 -1
- data/lib/generators/katapult/model_specs/templates/model_spec.rb +1 -1
- data/lib/generators/katapult/transform/transform_generator.rb +4 -7
- data/lib/generators/katapult/views/templates/_form.html.haml +16 -13
- data/lib/generators/katapult/views/templates/show.html.haml +2 -0
- data/lib/katapult/application_model.rb +68 -19
- data/lib/katapult/element.rb +13 -18
- data/lib/katapult/{action.rb → elements/action.rb} +0 -0
- data/lib/katapult/elements/association.rb +35 -0
- data/lib/katapult/{attribute.rb → elements/attribute.rb} +14 -5
- data/lib/katapult/{authentication.rb → elements/authentication.rb} +2 -5
- data/lib/katapult/elements/model.rb +76 -0
- data/lib/katapult/{navigation.rb → elements/navigation.rb} +0 -0
- data/lib/katapult/{web_ui.rb → elements/web_ui.rb} +2 -12
- data/lib/katapult/generator.rb +2 -2
- data/lib/katapult/{binary_util.rb → support/binary_util.rb} +2 -1
- data/lib/katapult/{generator_goodies.rb → support/generator_goodies.rb} +9 -2
- data/lib/katapult/version.rb +1 -1
- data/script/console +5 -2
- data/script/update +1 -1
- data/spec/action_spec.rb +1 -1
- data/spec/application_model_spec.rb +26 -0
- data/spec/association_spec.rb +12 -0
- data/spec/attribute_spec.rb +35 -1
- data/spec/model_spec.rb +5 -2
- data/spec/util_spec.rb +1 -1
- data/spec/web_ui_spec.rb +11 -33
- metadata +17 -13
- data/lib/katapult/model.rb +0 -45
- data/lib/katapult/parser.rb +0 -53
- data/spec/parser_spec.rb +0 -26
@@ -1,21 +1,31 @@
|
|
1
|
-
class <%= class_name %> <
|
1
|
+
class <%= class_name %> < ApplicationRecord
|
2
|
+
|
2
3
|
<%- flag_attrs.each do |attr| -%>
|
3
4
|
include DoesFlag[<%= attr.name(:symbol) %>, default: <%= attr.default %>]
|
4
5
|
<%- end -%>
|
6
|
+
<% has_manys.each do |model| -%>
|
7
|
+
has_many <%= model.name(:symbols) %>
|
8
|
+
<% end -%>
|
9
|
+
<% belongs_tos.each do |model| -%>
|
10
|
+
belongs_to <%= model.name(:symbol) %>, optional: true
|
11
|
+
<% end -%>
|
5
12
|
<%- if defaults.any? -%>
|
13
|
+
|
6
14
|
has_defaults(<%= defaults %>)
|
7
15
|
<%- end -%>
|
8
16
|
<%- model.attrs.select(&:assignable_values).each do |attr| -%>
|
9
|
-
|
17
|
+
|
18
|
+
assignable_values_for :<%= attr.name(:variable).sub /_id$/, '' %>, <%= attr.options.slice(:allow_blank, :default) %> do
|
10
19
|
<%= attr.assignable_values %>
|
11
20
|
end
|
12
21
|
<%- end -%>
|
13
22
|
|
14
23
|
def to_s
|
15
|
-
<% if model.label_attr -%>
|
24
|
+
<% if model.label_attr? -%>
|
16
25
|
<%= model.label_attr.name %>.to_s
|
17
26
|
<% else -%>
|
18
27
|
"<%= model.name %>##{id}"
|
19
28
|
<% end -%>
|
20
29
|
end
|
30
|
+
|
21
31
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
describe <%= model.name :class %> do
|
2
2
|
|
3
3
|
describe '#to_s' do
|
4
|
-
<%- if model.label_attr -%>
|
4
|
+
<%- if model.label_attr? -%>
|
5
5
|
it 'returns the #<%= model.label_attr.name %> attribute' do
|
6
6
|
subject.<%= model.label_attr.name %> = <%= model.label_attr.test_value.inspect %>
|
7
7
|
expect(subject.to_s).to eq(<%= model.label_attr.test_value.to_s.inspect %>)
|
@@ -1,12 +1,9 @@
|
|
1
1
|
# Generate files and directories from an application model file. Afterwards do
|
2
2
|
# any setup left necessary (e.g. updating the database).
|
3
3
|
|
4
|
-
#
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
require 'katapult/parser'
|
9
|
-
require 'katapult/generator_goodies'
|
4
|
+
# A normal #require would load the application model from the generated app
|
5
|
+
require_relative '../../../katapult/application_model'
|
6
|
+
require 'katapult/support/generator_goodies'
|
10
7
|
|
11
8
|
module Katapult
|
12
9
|
class TransformGenerator < Rails::Generators::Base
|
@@ -20,7 +17,7 @@ module Katapult
|
|
20
17
|
def transform_application_model
|
21
18
|
say_status :parse, path
|
22
19
|
application_model = File.read(path)
|
23
|
-
@app_model = Katapult::
|
20
|
+
@app_model = Katapult::ApplicationModel.parse(application_model, path)
|
24
21
|
|
25
22
|
say_status :render, "into #{app_name}"
|
26
23
|
@app_model.render
|
@@ -4,36 +4,39 @@
|
|
4
4
|
<% web_ui.model.editable_attrs.each do |attribute| -%>
|
5
5
|
.form-group
|
6
6
|
= form.label <%= attribute.name(:symbol) %>
|
7
|
-
|
7
|
+
<% if attribute.type == :foreign_key -%>
|
8
|
+
= form.collection_select <%= attribute.name(:symbol) %>, form.object.assignable_<%= attribute.name(:variables).sub(/_ids$/, 's') %>,
|
9
|
+
:id, <%= attribute.associated_model.label_attr.name(:symbol) %>, { include_blank: true }, class: 'form-control'
|
10
|
+
<% elsif attribute.assignable_values -%>
|
8
11
|
= form.select <%= attribute.name(:symbol) %>, form.object.assignable_<%= attribute.name(:variables) %>
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
+
<% else -%>
|
13
|
+
<%- case attribute.type -%>
|
14
|
+
<%- when :string -%>
|
12
15
|
= form.text_field <%= attribute.name(:symbol) %>, class: 'form-control'
|
13
|
-
|
16
|
+
<%- when :email -%>
|
14
17
|
= form.email_field <%= attribute.name(:symbol) %>, class: 'form-control'
|
15
|
-
|
18
|
+
<%- when :password -%>
|
16
19
|
= form.password_field <%= attribute.name(:symbol) %>, class: 'form-control',
|
17
20
|
autocomplete: 'new-password'
|
18
|
-
|
21
|
+
<%- when :url -%>
|
19
22
|
= form.url_field <%= attribute.name(:symbol) %>, class: 'form-control'
|
20
|
-
|
23
|
+
<%- when :integer -%>
|
21
24
|
= form.number_field <%= attribute.name(:symbol) %>, class: 'form-control'
|
22
|
-
|
25
|
+
<%- when :money -%>
|
23
26
|
.input-group
|
24
27
|
= form.number_field <%= attribute.name(:symbol) %>, class: 'form-control'
|
25
28
|
.input-group-addon
|
26
29
|
€
|
27
|
-
|
30
|
+
<%- when :text -%>
|
28
31
|
= form.text_area <%= attribute.name(:symbol) %>, rows: 5, class: 'form-control'
|
29
|
-
|
32
|
+
<%- when :flag -%>
|
30
33
|
.checkbox
|
31
34
|
= form.label <%= attribute.name(:symbol) %> do
|
32
35
|
= form.check_box <%= attribute.name(:symbol) %>
|
33
|
-
|
36
|
+
<%- when :datetime -%>
|
34
37
|
= form.date_field <%= attribute.name(:symbol) %>, class: 'form-control'
|
35
|
-
<%- end -%>
|
36
38
|
<%- end -%>
|
39
|
+
<% end -%>
|
37
40
|
<% end -%>
|
38
41
|
|
39
42
|
.action-bar
|
@@ -1,52 +1,101 @@
|
|
1
|
-
#
|
1
|
+
# Root of the internal representation of an application model file
|
2
|
+
|
3
|
+
require 'katapult/elements/model'
|
4
|
+
require 'katapult/elements/web_ui'
|
5
|
+
require 'katapult/elements/navigation'
|
6
|
+
require 'katapult/elements/authentication'
|
7
|
+
require 'katapult/elements/association'
|
2
8
|
|
3
9
|
module Katapult
|
4
10
|
class ApplicationModel
|
5
11
|
|
6
|
-
|
12
|
+
NotFound = Class.new(StandardError)
|
13
|
+
|
14
|
+
attr_reader :models, :web_uis, :navigation, :authentication, :associations
|
15
|
+
|
16
|
+
def self.parse(application_model_string, path_to_model = '')
|
17
|
+
new.tap do |model|
|
18
|
+
model.instance_eval application_model_string, path_to_model
|
19
|
+
end
|
20
|
+
end
|
7
21
|
|
8
22
|
def initialize
|
9
23
|
@models = []
|
24
|
+
@associations = []
|
10
25
|
@web_uis = []
|
11
26
|
end
|
12
27
|
|
13
|
-
|
14
|
-
|
15
|
-
|
28
|
+
# DSL
|
29
|
+
def model(name, &block)
|
30
|
+
models << Model.new(name, application_model: self, &block)
|
31
|
+
end
|
32
|
+
|
33
|
+
# DSL
|
34
|
+
def web_ui(name, options = {}, &block)
|
35
|
+
options[:application_model] = self
|
36
|
+
web_uis << WebUI.new(name, options, &block)
|
37
|
+
end
|
38
|
+
|
39
|
+
# DSL
|
40
|
+
def navigation(name = :main)
|
41
|
+
@navigation = Navigation.new(name, application_model: self)
|
42
|
+
end
|
43
|
+
|
44
|
+
# DSL
|
45
|
+
def authenticate(user_model_name, system_email:)
|
46
|
+
@authentication = Authentication.new(user_model_name,
|
47
|
+
system_email: system_email, application_model: self)
|
16
48
|
end
|
17
49
|
|
18
|
-
|
19
|
-
|
50
|
+
# DSL
|
51
|
+
def crud(name, &block)
|
52
|
+
model name, &block
|
53
|
+
web_ui name, &:crud
|
20
54
|
end
|
21
55
|
|
22
|
-
|
23
|
-
|
24
|
-
|
56
|
+
|
57
|
+
def association(name, options = {})
|
58
|
+
options[:application_model] = self
|
59
|
+
associations << Association.new(name, options)
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_model!(name)
|
63
|
+
models.find { |m| m.name == name } or raise NotFound,
|
64
|
+
"Could not find a model named #{ name }"
|
25
65
|
end
|
26
66
|
|
27
67
|
def get_web_ui(name)
|
28
68
|
web_uis.find { |w| w.name == name }
|
29
69
|
end
|
30
70
|
|
31
|
-
|
32
|
-
|
33
|
-
|
71
|
+
# Returns all models that `model_name` belongs_to
|
72
|
+
def get_belongs_tos_for(model_name)
|
73
|
+
associations.select { |a| a.name == model_name }.map(&:belongs_to_model)
|
34
74
|
end
|
35
75
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
@authentication = auth
|
76
|
+
# Returns all models that `model_name` has_many of
|
77
|
+
def get_has_manys_for(model_name)
|
78
|
+
associations.select { |a| a.belongs_to == model_name }.map(&:model)
|
40
79
|
end
|
41
80
|
|
42
|
-
# ---
|
43
|
-
|
44
81
|
def render
|
82
|
+
prepare_render
|
83
|
+
|
45
84
|
models.each &:render
|
46
85
|
web_uis.each &:render
|
47
86
|
navigation.render if navigation
|
48
87
|
authentication.render if authentication
|
49
88
|
end
|
50
89
|
|
90
|
+
private
|
91
|
+
|
92
|
+
def prepare_render
|
93
|
+
authentication &.ensure_user_model_attributes_present
|
94
|
+
models.each do |model|
|
95
|
+
belongs_tos = get_belongs_tos_for(model.name)
|
96
|
+
model.add_foreign_key_attrs(belongs_tos)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
51
100
|
end
|
52
101
|
end
|
data/lib/katapult/element.rb
CHANGED
@@ -10,10 +10,9 @@ module Katapult
|
|
10
10
|
UnknownOptionError = Class.new(StandardError)
|
11
11
|
UnknownFormattingError = Class.new(StandardError)
|
12
12
|
|
13
|
-
attr_accessor :name, :options
|
14
|
-
attr_reader :application_model
|
13
|
+
attr_accessor :name, :options, :application_model
|
15
14
|
|
16
|
-
#
|
15
|
+
# Use #options for DSL/API, attr_accessor for internal attributes
|
17
16
|
class << self
|
18
17
|
alias_method :options, :attr_accessor
|
19
18
|
end
|
@@ -28,26 +27,22 @@ module Katapult
|
|
28
27
|
yield(self) if block_given?
|
29
28
|
end
|
30
29
|
|
31
|
-
def set_application_model(app_model)
|
32
|
-
@application_model = app_model
|
33
|
-
end
|
34
|
-
|
35
30
|
def name(kind = nil)
|
36
31
|
machine_name = @name.underscore
|
37
32
|
human_name = machine_name.humanize.downcase
|
38
33
|
|
39
34
|
case kind.to_s
|
40
|
-
when '' then @name
|
41
|
-
when 'symbol' then ":#{machine_name}"
|
42
|
-
when 'symbols' then ":#{machine_name.pluralize}"
|
43
|
-
when 'variable' then machine_name
|
44
|
-
when 'variables' then machine_name.pluralize
|
45
|
-
when 'ivar' then "@#{machine_name}"
|
46
|
-
when 'ivars' then "@#{machine_name.pluralize}"
|
47
|
-
when 'human' then human_name
|
48
|
-
when 'humans' then human_name.pluralize
|
49
|
-
when 'class' then machine_name.classify
|
50
|
-
when 'classes' then machine_name.classify.pluralize
|
35
|
+
when '' then @name ## Example
|
36
|
+
when 'symbol' then ":#{machine_name}" # :user_task
|
37
|
+
when 'symbols' then ":#{machine_name.pluralize}" # :user_tasks
|
38
|
+
when 'variable' then machine_name # user_task
|
39
|
+
when 'variables' then machine_name.pluralize # user_tasks
|
40
|
+
when 'ivar' then "@#{machine_name}" # @user_task
|
41
|
+
when 'ivars' then "@#{machine_name.pluralize}" # @user_tasks
|
42
|
+
when 'human' then human_name # user task
|
43
|
+
when 'humans' then human_name.pluralize # user tasks
|
44
|
+
when 'class' then machine_name.classify # UserTask
|
45
|
+
when 'classes' then machine_name.classify.pluralize # UserTasks
|
51
46
|
else raise UnknownFormattingError, "Unknown name formatting: #{ kind.inspect }"
|
52
47
|
end
|
53
48
|
end
|
File without changes
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Models an association between models
|
2
|
+
|
3
|
+
require 'katapult/element'
|
4
|
+
|
5
|
+
module Katapult
|
6
|
+
class Association < Element
|
7
|
+
|
8
|
+
IncompleteAssociationError = Class.new(StandardError)
|
9
|
+
|
10
|
+
options :belongs_to
|
11
|
+
|
12
|
+
def initialize(*args)
|
13
|
+
super
|
14
|
+
validate!
|
15
|
+
|
16
|
+
self.belongs_to = belongs_to.to_s # Normalize
|
17
|
+
end
|
18
|
+
|
19
|
+
def model
|
20
|
+
application_model.get_model! name
|
21
|
+
end
|
22
|
+
|
23
|
+
def belongs_to_model
|
24
|
+
application_model.get_model! belongs_to
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def validate!
|
30
|
+
belongs_to.present? or raise IncompleteAssociationError,
|
31
|
+
'Missing :belongs_to option'
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -9,10 +9,12 @@ module Katapult
|
|
9
9
|
class Attribute < Element
|
10
10
|
|
11
11
|
options :type, :default, :assignable_values, :allow_blank, :skip_db
|
12
|
+
attr_accessor :model, :associated_model
|
12
13
|
|
13
14
|
UnknownTypeError = Class.new(StandardError)
|
14
15
|
MissingOptionError = Class.new(StandardError)
|
15
|
-
TYPES = %i
|
16
|
+
TYPES = %i[string email password url integer money text flag datetime json
|
17
|
+
plain_json foreign_key]
|
16
18
|
|
17
19
|
def initialize(*args)
|
18
20
|
super
|
@@ -21,13 +23,13 @@ module Katapult
|
|
21
23
|
self.type ||= :password if name.to_s =~ /password/
|
22
24
|
self.type ||= :string
|
23
25
|
|
24
|
-
validate
|
26
|
+
validate!
|
25
27
|
end
|
26
28
|
|
27
29
|
delegate :flag?, to: :type_inquiry
|
28
30
|
|
29
31
|
def has_defaults?
|
30
|
-
default and not [flag?, assignable_values].any?
|
32
|
+
!default.nil? and not [flag?, assignable_values].any?
|
31
33
|
end
|
32
34
|
|
33
35
|
def for_migration
|
@@ -37,13 +39,16 @@ module Katapult
|
|
37
39
|
when :money then 'decimal{10,2}' # {precision,scale} = total digits, decimal places
|
38
40
|
when :json then 'jsonb' # Indexable JSON
|
39
41
|
when :plain_json then 'json' # Only use this if you need to
|
42
|
+
when :foreign_key then 'integer'
|
40
43
|
else type end
|
41
44
|
|
42
45
|
"#{name}:#{db_type}"
|
43
46
|
end
|
44
47
|
|
45
48
|
def test_value
|
46
|
-
if
|
49
|
+
if type == :foreign_key
|
50
|
+
associated_model.label_attr.test_value
|
51
|
+
elsif assignable_values
|
47
52
|
assignable_values.first
|
48
53
|
|
49
54
|
else
|
@@ -62,13 +67,17 @@ module Katapult
|
|
62
67
|
end
|
63
68
|
end
|
64
69
|
|
70
|
+
def assignable_values_as_list?
|
71
|
+
assignable_values.try(:to_a).present?
|
72
|
+
end
|
73
|
+
|
65
74
|
private
|
66
75
|
|
67
76
|
def type_inquiry
|
68
77
|
@type.to_s.inquiry
|
69
78
|
end
|
70
79
|
|
71
|
-
def validate
|
80
|
+
def validate!
|
72
81
|
TYPES.include?(type) or raise UnknownTypeError,
|
73
82
|
"Attribute type :#{type} is not supported. Use one of #{TYPES.inspect}."
|
74
83
|
|
@@ -3,14 +3,11 @@ require 'generators/katapult/clearance/clearance_generator'
|
|
3
3
|
module Katapult
|
4
4
|
class Authentication < Element
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
# attr name: The user model name
|
6
|
+
# @attr name: The user model name
|
9
7
|
attr_accessor :system_email
|
10
8
|
|
11
9
|
def ensure_user_model_attributes_present
|
12
|
-
user_model = application_model.get_model(name)
|
13
|
-
"Could not find a model named #{ name }"
|
10
|
+
user_model = application_model.get_model!(name)
|
14
11
|
user_attrs = user_model.attrs.map(&:name)
|
15
12
|
|
16
13
|
user_model.attr(:email) unless user_attrs.include?('email')
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# Models a Rails model
|
2
|
+
|
3
|
+
require 'katapult/element'
|
4
|
+
require 'katapult/elements/attribute'
|
5
|
+
require 'generators/katapult/model/model_generator'
|
6
|
+
|
7
|
+
module Katapult
|
8
|
+
class Model < Element
|
9
|
+
|
10
|
+
UnknownAttributeError = Class.new(StandardError)
|
11
|
+
MissingLabelAttributeError = Class.new(StandardError)
|
12
|
+
|
13
|
+
attr_accessor :attrs, :belongs_tos, :has_manys
|
14
|
+
|
15
|
+
def initialize(*args)
|
16
|
+
self.attrs = []
|
17
|
+
self._belongs_tos = []
|
18
|
+
self.belongs_tos = []
|
19
|
+
self.has_manys = []
|
20
|
+
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
# DSL
|
25
|
+
def attr(attr_name, options = {})
|
26
|
+
options[:model] = self
|
27
|
+
attrs << Attribute.new(attr_name, options)
|
28
|
+
end
|
29
|
+
|
30
|
+
# DSL
|
31
|
+
def belongs_to(model_name)
|
32
|
+
application_model.association name, belongs_to: model_name
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def label_attr
|
37
|
+
renderable_attrs.first.presence or raise MissingLabelAttributeError
|
38
|
+
end
|
39
|
+
|
40
|
+
def label_attr?
|
41
|
+
label_attr.present?
|
42
|
+
rescue MissingLabelAttributeError
|
43
|
+
false
|
44
|
+
end
|
45
|
+
|
46
|
+
def db_fields
|
47
|
+
attrs.reject(&:skip_db)
|
48
|
+
end
|
49
|
+
|
50
|
+
def renderable_attrs
|
51
|
+
attrs.reject { |a| %w[plain_json json password].include? a.type.to_s }
|
52
|
+
end
|
53
|
+
|
54
|
+
def editable_attrs
|
55
|
+
attrs.reject { |a| %w[plain_json json].include? a.type.to_s }
|
56
|
+
end
|
57
|
+
|
58
|
+
def add_foreign_key_attrs(belongs_tos)
|
59
|
+
belongs_tos.each do |other_model|
|
60
|
+
attr "#{ other_model.name :variable }_id", type: :foreign_key,
|
61
|
+
assignable_values: "#{ other_model.name(:class) }.all.to_a",
|
62
|
+
allow_blank: true,
|
63
|
+
associated_model: other_model
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def render
|
68
|
+
Generators::ModelGenerator.new(self).invoke_all
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
attr_accessor :_belongs_tos
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
File without changes
|
@@ -2,7 +2,7 @@
|
|
2
2
|
# class for the Attribute element.
|
3
3
|
|
4
4
|
require 'katapult/element'
|
5
|
-
require 'katapult/action'
|
5
|
+
require 'katapult/elements/action'
|
6
6
|
require 'generators/katapult/web_ui/web_ui_generator'
|
7
7
|
|
8
8
|
module Katapult
|
@@ -14,7 +14,6 @@ module Katapult
|
|
14
14
|
RAILS_ACTIONS = %w[ index show new create edit update destroy ]
|
15
15
|
UnknownActionError = Class.new(StandardError)
|
16
16
|
UnknownModelError = Class.new(StandardError)
|
17
|
-
MissingLabelAttrError = Class.new(StandardError)
|
18
17
|
|
19
18
|
def initialize(*args)
|
20
19
|
self.actions = []
|
@@ -41,8 +40,7 @@ module Katapult
|
|
41
40
|
|
42
41
|
def model
|
43
42
|
model_name = @model || self.name
|
44
|
-
application_model.get_model
|
45
|
-
"Cannot find a model named #{model_name}"
|
43
|
+
application_model.get_model! model_name
|
46
44
|
end
|
47
45
|
|
48
46
|
def params
|
@@ -81,16 +79,8 @@ module Katapult
|
|
81
79
|
end
|
82
80
|
|
83
81
|
def render
|
84
|
-
validate!
|
85
82
|
Generators::WebUIGenerator.new(self).invoke_all
|
86
83
|
end
|
87
84
|
|
88
|
-
private
|
89
|
-
|
90
|
-
def validate!
|
91
|
-
model.label_attr.present? or raise MissingLabelAttrError,
|
92
|
-
'Cannot render a WebUI without a model with a label attribute'
|
93
|
-
end
|
94
|
-
|
95
85
|
end
|
96
86
|
end
|
data/lib/katapult/generator.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
# The
|
1
|
+
# The base class for katapult element generators
|
2
2
|
|
3
3
|
require 'rails/generators'
|
4
|
-
require 'katapult/generator_goodies'
|
4
|
+
require 'katapult/support/generator_goodies'
|
5
5
|
|
6
6
|
module Katapult
|
7
7
|
class Generator < Rails::Generators::NamedBase
|
@@ -7,8 +7,15 @@ module Katapult::GeneratorGoodies
|
|
7
7
|
|
8
8
|
private
|
9
9
|
|
10
|
-
def app_name
|
11
|
-
File.basename(Dir.pwd)
|
10
|
+
def app_name(kind = nil)
|
11
|
+
machine_name = File.basename(Dir.pwd)
|
12
|
+
human_name = machine_name.tr('_', ' ').gsub(/\w+/, &:capitalize)
|
13
|
+
|
14
|
+
case kind.to_s
|
15
|
+
when '' then machine_name
|
16
|
+
when 'human' then human_name
|
17
|
+
else raise ArgumentError, "Unknown formatting: #{kind.inspect}"
|
18
|
+
end
|
12
19
|
end
|
13
20
|
|
14
21
|
# Override Thor method
|
data/lib/katapult/version.rb
CHANGED
data/script/console
CHANGED
@@ -4,11 +4,14 @@
|
|
4
4
|
# Run `script/console` from the gem root to start an IRB with the gem loaded.
|
5
5
|
|
6
6
|
# Remember to require classes before using them,
|
7
|
-
# i.e. `require 'katapult/model'` before `Katapult::Model
|
7
|
+
# i.e. `require 'katapult/elements/model'` before using `Katapult::Model`
|
8
|
+
|
9
|
+
require 'bundler/setup'
|
8
10
|
|
9
11
|
irb_options = [
|
10
12
|
'-Ilib', # add lib/ to load_path
|
11
|
-
'-d', # set $DEBUG = true
|
13
|
+
# '-d', # set $DEBUG = true
|
14
|
+
|
12
15
|
# Requires
|
13
16
|
'-rkatapult/version',
|
14
17
|
'-rrails',
|
data/script/update
CHANGED
data/spec/action_spec.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'katapult/application_model'
|
2
|
+
|
3
|
+
describe Katapult::ApplicationModel do
|
4
|
+
|
5
|
+
describe '#crud' do
|
6
|
+
it 'adds a model plus a web UI with CRUD actions' do
|
7
|
+
model = <<-MODEL
|
8
|
+
crud 'user' do |user|
|
9
|
+
user.attr :age
|
10
|
+
end
|
11
|
+
MODEL
|
12
|
+
|
13
|
+
subject = described_class.parse(model)
|
14
|
+
expect(subject.models.count).to be 1
|
15
|
+
user = subject.models.first
|
16
|
+
expect(user.name).to eq 'user'
|
17
|
+
expect(user.attrs.count).to be 1
|
18
|
+
expect(user.attrs.first.name).to eq 'age'
|
19
|
+
|
20
|
+
expect(subject.web_uis.count).to be 1
|
21
|
+
web_ui = subject.web_uis.first
|
22
|
+
expect(web_ui.actions.map(&:name)).to match Katapult::WebUI::RAILS_ACTIONS
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|