shaf 0.5.2 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a9af4fa12d1002e4c4fcfe233c640e0efff4d779d8bed3b884dec7da3d2d7eef
4
- data.tar.gz: 7748f68242de611ece5e8f556686e924f627f6346f5c90e56b1b15d3bbd4ce04
3
+ metadata.gz: 5fa1ac79ab7ea9af45c8d160116ab1aee7ed964254927fe9045664930405e2c6
4
+ data.tar.gz: bf9dc19468e7b25d5e0c94c8484558f89bd6ec84e47d4d00211c3d57029909fc
5
5
  SHA512:
6
- metadata.gz: 0dc246772c0a1c5d74d738a4618173e83819a67d9cb88e17b37c7894ffbc27ce977f1acfb2edcf3cf88bc12fc34f202e9e974d930976ff997c26f2cceaa1b3cb
7
- data.tar.gz: 4fb0286154086c4859b109f79fd70836d3dd44d777688964b235cb32a2ad1afc897f8ae3df9544616934d9b63363c2714e6d11d81d4d0c327238b46aae3db50d
6
+ metadata.gz: d383a3b23dd5675fc3683a8b2c76407bcc9cf25ff17eb699b4cbd75898d053fdd1d1a2b8fb522eedf4fe8c7330a726dfc126d39508ce7c50c0a211b0ba6e8a86
7
+ data.tar.gz: f03870ee03fdc20f04541c9bff9cde8a1d2fa1ef3b1a0a0a52b0a20724cee752a5abe3b6f5eb5ec330125c010f8bc1f85acd9e18eaa3f97884ff33d66fe087ea
checksums.yaml.gz.sig CHANGED
Binary file
@@ -0,0 +1,61 @@
1
+ require 'shaf/formable/form'
2
+
3
+ module Shaf
4
+ module Formable
5
+ class Builder
6
+ DELEGATES = %i[title name action method type fields].freeze
7
+
8
+ attr_reader :forms
9
+
10
+ def initialize(&block)
11
+ @forms = []
12
+ @instance_accessors = []
13
+
14
+ exec_with_form(block)
15
+ end
16
+
17
+ def instance_accessor_for?(form)
18
+ @instance_accessors.include? form
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :form
24
+
25
+ def exec_with_form(block, action: nil)
26
+ current, @form = form, new_form
27
+ form.action = action if action
28
+ instance_exec(&block)
29
+ ensure
30
+ @form = current
31
+ end
32
+
33
+ def new_form
34
+ (form&.dup || Formable::Form.new).tap { |f| @forms << f }
35
+ end
36
+
37
+ def instance_accessor
38
+ @instance_accessors << form
39
+ end
40
+
41
+ DELEGATES.each do |name|
42
+ define_method(name) do |arg|
43
+ form.send("#{name}=".to_sym, arg)
44
+ end
45
+ end
46
+
47
+ def field(name, opts = {})
48
+ form.add_field(name, opts)
49
+ end
50
+
51
+ def method_missing(method, *args, &block)
52
+ return super unless args.empty? && block
53
+ exec_with_form(block, action: method)
54
+ end
55
+
56
+ def respond_to_missing?(*)
57
+ true
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,60 @@
1
+ require 'shaf/immutable_attr'
2
+
3
+ module Shaf
4
+ module Formable
5
+ class Field
6
+ extend Shaf::ImmutableAttr
7
+
8
+ immutable_reader :name, :type, :value, :label, :required
9
+
10
+ HTML_TYPE_MAPPINGS = {
11
+ 'string' => 'text',
12
+ 'boolean' => 'checkbox',
13
+ }.freeze
14
+
15
+ def initialize(name, params = {})
16
+ @name = name
17
+ @type = params[:type]
18
+ @label = params[:label]
19
+ @has_value = params.key? :value
20
+ @value = params[:value]
21
+ @required = params[:required] || false
22
+ end
23
+
24
+ def has_value?
25
+ @has_value
26
+ end
27
+
28
+ def to_html
29
+ [
30
+ '<div class="form--input-group">',
31
+ label_element,
32
+ input_element,
33
+ '</div>'
34
+ ].compact.join("\n")
35
+ end
36
+
37
+ private
38
+
39
+ def label_element
40
+ str = (label || name || "").to_s
41
+ %Q(<label for="#{name}" class="form--label">#{str}</label>)
42
+ end
43
+
44
+ def input_element
45
+ _value = value ? %Q(value="#{value.to_s}") : nil
46
+ _required = required ? "required" : nil
47
+ attributes = [
48
+ %Q(type="#{HTML_TYPE_MAPPINGS[type.to_s]}"),
49
+ 'class="form--input"',
50
+ %Q(id="#{name.to_s}"),
51
+ %Q(name="#{name.to_s}"),
52
+ ]
53
+ attributes << %Q(value="#{value.to_s}") if value
54
+ attributes << "required" if required
55
+
56
+ "<input #{attributes.join(" ")}>"
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,98 @@
1
+ require 'shaf/formable/field'
2
+ require 'shaf/immutable_attr'
3
+
4
+ module Shaf
5
+ module Formable
6
+ class Form
7
+ extend Shaf::ImmutableAttr
8
+
9
+ DEFAULT_TYPE = 'application/json'.freeze
10
+
11
+ attr_accessor :resource
12
+ immutable_accessor :title, :name, :href, :type, :self_link
13
+ immutable_reader :fields, :action
14
+
15
+ def initialize(params = {})
16
+ @title = params[:title]
17
+ @action = params[:action]
18
+ @name = params[:name] || name_from(@action)
19
+ @method = params[:method] ||= http_method_from(@action)
20
+ @type = params[:type] || DEFAULT_TYPE
21
+ @fields = (params[:fields] || {}).map do |name, args|
22
+ Field.new(name, args)
23
+ end
24
+ end
25
+
26
+ def method=(http_method)
27
+ @method = http_method.to_s.upcase
28
+ end
29
+
30
+ def method
31
+ return unless @method
32
+ @method.to_s.upcase
33
+ end
34
+
35
+ def fields=(fields)
36
+ @fields = fields.map { |name, args| Field.new(name, args) }
37
+ end
38
+
39
+ def action=(action)
40
+ @action = action
41
+ @name ||= name_from action
42
+ @method ||= http_method_from action
43
+ end
44
+
45
+ def add_field(name, opts)
46
+ @fields << Field.new(name, opts)
47
+ end
48
+
49
+ def dup
50
+ super.tap do |obj|
51
+ obj.instance_variable_set(:@fields, @fields.map(&:dup))
52
+ end
53
+ end
54
+
55
+ def clone
56
+ dup.tap { |obj| obj.freeze if frozen? }
57
+ end
58
+
59
+ def to_html
60
+ form_element do
61
+ [
62
+ hidden_method_element,
63
+ fields.map(&:to_html).join("\n"),
64
+ submit_element
65
+ ].compact.join("\n")
66
+ end
67
+ end
68
+
69
+ private
70
+
71
+ def name_from(action)
72
+ :"#{action}-form" if action
73
+ end
74
+
75
+ def http_method_from(action)
76
+ return unless action
77
+ action&.to_sym == :edit ? 'PUT' : 'POST'
78
+ end
79
+
80
+ def form_element
81
+ [
82
+ %Q(<form class="form" method=#{method == 'GET' ? 'GET' : 'POST'}#{href ? %Q( action="#{href.to_s}") : ''}>),
83
+ block_given? ? yield : nil,
84
+ '</form>'
85
+ ].compact.join("\n")
86
+ end
87
+
88
+ def hidden_method_element
89
+ return if %w[GET POST].include? method
90
+ %Q(<input type="hidden" name="_method" value="#{method}">)
91
+ end
92
+
93
+ def submit_element
94
+ %Q(<div class="form--input-group"><input type="submit" class="button" value="Submit"</div>)
95
+ end
96
+ end
97
+ end
98
+ end
data/lib/shaf/formable.rb CHANGED
@@ -1,204 +1,20 @@
1
+ require 'shaf/formable/builder'
2
+
1
3
  module Shaf
2
4
  module Formable
3
- class Field
4
- attr_reader :name, :type, :value, :label, :required
5
-
6
- HTML_TYPE_MAPPINGS = {
7
- 'string' => 'text',
8
- 'boolean' => 'checkbox',
9
- }.freeze
10
-
11
- def initialize(name, params = {})
12
- @name = name
13
- @type = params[:type]
14
- @label = params[:label]
15
- @has_value = params.key? :value
16
- @value = params[:value]
17
- @required = params[:required] || false
18
- end
19
-
20
- def has_value?
21
- @has_value
22
- end
23
-
24
- def to_html
25
- [
26
- '<div class="form--input-group">',
27
- label_element,
28
- input_element,
29
- '</div>'
30
- ].compact.join("\n")
31
- end
32
-
33
- private
34
-
35
- def label_element
36
- str = (label || name || "").to_s
37
- %Q(<label for="#{name}" class="form--label">#{str}</label>)
38
- end
39
-
40
- def input_element
41
- _value = value ? %Q(value="#{value.to_s}") : nil
42
- _required = required ? "required" : nil
43
- attributes = [
44
- %Q(type="#{HTML_TYPE_MAPPINGS[type.to_s]}"),
45
- 'class="form--input"',
46
- %Q(id="#{name.to_s}"),
47
- %Q(name="#{name.to_s}"),
48
- ]
49
- attributes << %Q(value="#{value.to_s}") if value
50
- attributes << "required" if required
51
-
52
- "<input #{attributes.join(" ")}>"
53
- end
54
- end
5
+ def form(&block)
6
+ builder = Formable::Builder.new(&block)
7
+ builder.forms.each do |f|
8
+ next unless f.action
9
+ getter = "#{f.action}_form"
55
10
 
56
- class Form
57
-
58
- DEFAULT_TYPE = 'application/json'
59
-
60
- attr_accessor :resource, :name, :title, :href, :type, :self_link
61
- attr_reader :fields
62
-
63
- def initialize(params = {})
64
- @name = params[:name]
65
- @title = params[:title]
66
- @method = params[:method] || 'POST'
67
- @type = params[:type] || DEFAULT_TYPE
68
- @fields = (params[:fields] || {}).map { |name, args| Field.new(name, args) }
69
- end
11
+ define_singleton_method(getter) { f }
12
+ next unless builder.instance_accessor_for? f
70
13
 
71
- def method=(m)
72
- @method = m.to_s.upcase
73
- end
74
-
75
- def method
76
- @method.to_s.upcase
77
- end
78
-
79
- def fields=(fields)
80
- @fields = fields.map { |name, args| Field.new(name, args) }
81
- end
82
-
83
- def add_field(name, opts)
84
- @fields << Field.new(name, opts)
85
- end
86
-
87
- def to_html
88
- form_element do
89
- [
90
- hidden_method_element,
91
- fields.map { |f| f.to_html }.join("\n"),
92
- submit_element,
93
- ].compact.join("\n")
14
+ define_method(getter) do
15
+ f.dup.tap { |fm| fm.resource = self }
94
16
  end
95
17
  end
96
-
97
- private
98
-
99
- def form_element
100
- [
101
- %Q(<form class="form" method=#{method == 'GET' ? 'GET' : 'POST'}#{href ? %Q( action="#{href.to_s}") : ''}>),
102
- block_given? ? yield : nil,
103
- "</form>",
104
- ].compact.join("\n")
105
- end
106
-
107
- def hidden_method_element
108
- return if ['GET', 'POST'].include?(method)
109
- %Q(<input type="hidden" name="_method" value="#{method}">)
110
- end
111
-
112
- def submit_element
113
- %Q(<div class="form--input-group"><input type="submit" class="button" value="Submit"</div>)
114
- end
115
- end
116
-
117
- class Builder
118
- def self.call(block)
119
- [
120
- new(block, create: true).call,
121
- new(block, edit: true).call
122
- ]
123
- end
124
-
125
- attr_reader :block
126
-
127
- def initialize(block, create: false, edit: false)
128
- @block = block
129
- @create = create
130
- @edit = edit
131
- @form = nil
132
- @default_method = @create ? :post : :put
133
- end
134
-
135
- def call
136
- instance_exec(&block)
137
- @form
138
- end
139
-
140
- def form
141
- @form ||= Form.new(method: @default_method)
142
- end
143
-
144
- def name(name)
145
- form.name = name
146
- end
147
-
148
- def title(title)
149
- form.title = title
150
- end
151
-
152
- def method(method)
153
- form.method = method
154
- end
155
-
156
- def type(type)
157
- form.type = type
158
- end
159
-
160
- def fields(fields)
161
- form.fields = fields
162
- end
163
-
164
- def field(name, opts = {})
165
- form.add_field(name, opts)
166
- end
167
-
168
- def create(&b)
169
- return unless @create
170
- call_nested_block(b)
171
- end
172
-
173
- def edit(&b)
174
- return unless @edit
175
- call_nested_block(b)
176
- end
177
-
178
- def call_nested_block(b)
179
- old, @block = @block, b
180
- call
181
- ensure
182
- @block = old
183
- end
184
- end
185
-
186
- module ClassMethods
187
- attr_reader :create_form, :edit_form
188
-
189
- def form(&block)
190
- @create_form, @edit_form = Builder.(block)
191
- end
192
- end
193
-
194
- def self.included(base)
195
- base.extend(ClassMethods)
196
- end
197
-
198
- def edit_form
199
- self.class.edit_form.tap do |form|
200
- form&.resource = self
201
- end
202
18
  end
203
19
  end
204
20
  end
@@ -99,14 +99,13 @@ module Shaf
99
99
  end
100
100
 
101
101
  def regexp_db_format_string(type)
102
- COMPLEX_DB_TYPES.each do |complex_type|
102
+ COMPLEX_DB_TYPES.find do |complex_type|
103
103
  match = complex_type[:pattern].match(type) or next
104
104
  validator = complex_type[:validator]
105
105
  errors = validator&.call(type, match)
106
- if errors.nil? || errors.empty?
107
- return complex_type[:strings].map { |s| replace_backreferences(match, s) }
108
- end
109
- raise "Failed to process '#{type}': #{errors.join(', ')}"
106
+ raise "Failed to process '#{type}': #{errors&.join(', ')}" unless Array(errors).empty?
107
+
108
+ break complex_type[:strings].map { |s| replace_backreferences(match, s) }
110
109
  end
111
110
  end
112
111
 
@@ -118,13 +117,13 @@ module Shaf
118
117
  end
119
118
 
120
119
  def render
121
- <<~EOS
120
+ <<~RUBY
122
121
  Sequel.migration do
123
122
  change do
124
123
  #{@changes.flatten.join("\n ")}
125
124
  end
126
125
  end
127
- EOS
126
+ RUBY
128
127
  end
129
128
  end
130
129
 
@@ -6,7 +6,7 @@ module Shaf
6
6
  extend RegistrableFactory
7
7
  end
8
8
 
9
- class Generator < Generator::Base
9
+ class Generator < Shaf::Generator::Base
10
10
  identifier :migration
11
11
  usage { Factory.usage }
12
12
 
@@ -1,5 +1,5 @@
1
1
  class <%= class_name %> < Sequel::Model
2
- include Shaf::Formable
2
+ extend Shaf::Formable
3
3
 
4
4
  <% if form_fields.any? %>
5
5
  form do
@@ -11,6 +11,7 @@ class <%= class_name %> < Sequel::Model
11
11
  end
12
12
 
13
13
  edit do
14
+ instance_accessor
14
15
  title 'Update <%= class_name %>'
15
16
  name 'update-<%= model_name %>'
16
17
  end
@@ -8,7 +8,7 @@ module Shaf
8
8
 
9
9
  def paginate!(collection, per_page = PAGINATION_PER_PAGE)
10
10
  unless collection.respond_to? :paginate
11
- log.warning "Trying to paginate a collection that doesn't " \
11
+ log.warn "Trying to paginate a collection that doesn't " \
12
12
  "support pagination: #{collection}"
13
13
  return
14
14
  end
@@ -0,0 +1,51 @@
1
+ module Shaf
2
+ module ImmutableAttr
3
+ NON_DUPABLE_CLASSES = [
4
+ NilClass,
5
+ TrueClass,
6
+ FalseClass,
7
+ Symbol
8
+ ]
9
+
10
+ def self.dup(obj)
11
+ return obj unless obj.respond_to? :dup
12
+ return obj if NON_DUPABLE_CLASSES.include? obj.class
13
+ obj.dup
14
+ end
15
+
16
+ def immutable_reader(*methods)
17
+ methods.each do |method|
18
+ define_method(method) do
19
+ value = instance_variable_get(:"@#{method}")
20
+ ImmutableAttr.dup(value)
21
+ end
22
+ end
23
+ end
24
+
25
+ def immutable_writer(*methods)
26
+ methods.each do |method|
27
+ define_method(:"#{method}=") do |value|
28
+ instance_variable_set(
29
+ :"@#{method}",
30
+ ImmutableAttr.dup(value)
31
+ )
32
+ end
33
+ end
34
+ end
35
+
36
+ def immutable_accessor(*methods)
37
+ methods.each do |method|
38
+ define_method(method) do
39
+ value = instance_variable_get(:"@#{method}")
40
+ ImmutableAttr.dup(value)
41
+ end
42
+ define_method(:"#{method}=") do |value|
43
+ instance_variable_set(
44
+ :"@#{method}",
45
+ ImmutableAttr.dup(value)
46
+ )
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -55,6 +55,8 @@ module Shaf
55
55
  field[:name].size
56
56
  when 'string'
57
57
  "value for #{field[:name]}"
58
+ when 'boolean'
59
+ true
58
60
  else
59
61
  "type not supported"
60
62
  end
@@ -5,17 +5,21 @@ module Shaf
5
5
  class Manifest
6
6
  attr_reader :target_version, :files
7
7
 
8
- def initialize(target_version:, patches: nil, add: nil, drop: nil)
9
- @target_version = target_version
8
+ def initialize(**params)
9
+ @target_version = params[:target_version]
10
10
  @files = {}
11
- @files[:patch] = build_patterns(patches)
12
- @files[:add] = add || {}
13
- @files[:drop] = (drop || []).map { |d| Regexp.new(d) }
11
+ @files[:patch] = build_patterns(params[:patches])
12
+ @files[:add] = params[:add] || {}
13
+ @files[:drop] = (params[:drop] || []).map { |d| Regexp.new(d) }
14
+ @files[:regexp] = build_patterns(params[:substitutes])
14
15
  end
15
16
 
16
17
  def patch_for(file)
17
- first_match = files[:patch].find { |_, pattern| file =~ pattern }
18
- (first_match || []).first
18
+ files[:patch].select { |_, pattern| file =~ pattern }.keys
19
+ end
20
+
21
+ def regexp_for(file)
22
+ files[:regexp].select { |_, pattern| file =~ pattern }.keys
19
23
  end
20
24
 
21
25
  def drop?(file)
@@ -25,7 +29,8 @@ module Shaf
25
29
  def stats
26
30
  "Add: #{files[:add].size}, " \
27
31
  "Del: #{files[:drop].size}, " \
28
- "Patch: #{files[:patch].size}"
32
+ "Patch: #{files[:patch].size}, " \
33
+ "Regexp: #{files[:regexp].size}"
29
34
  end
30
35
 
31
36
  private
@@ -50,3 +55,5 @@ end
50
55
  # 8ece24b8c440675bd3d188155909431c: api/policies/base_policy.rb
51
56
  # drop:
52
57
  # - api/policies/base_policy.rb
58
+ # substitutes:
59
+ # d3b07384d113edec49eaa6238ad5ff00: api/models/.*.rb
@@ -4,6 +4,8 @@ require 'set'
4
4
  require 'digest'
5
5
  require 'open3'
6
6
  require 'fileutils'
7
+ require 'tempfile'
8
+ require 'yaml'
7
9
 
8
10
  module Shaf
9
11
  module Upgrade
@@ -15,7 +17,6 @@ module Shaf
15
17
  class VersionConflictError < UpgradeError; end
16
18
  class ManifestNotFoundError < UpgradeError; end
17
19
  class MissingFileError < UpgradeError; end
18
- class FileNotInManifestError < UpgradeError; end
19
20
  class BadChecksumError < UpgradeError; end
20
21
 
21
22
  UPGRADE_FILES_PATH = File.join(Utils.gem_root, 'upgrades').freeze
@@ -78,6 +79,7 @@ module Shaf
78
79
  apply_patches(dir)
79
80
  apply_additions
80
81
  apply_drops(dir)
82
+ apply_substitutes(dir)
81
83
  end
82
84
 
83
85
  def to_s
@@ -111,7 +113,8 @@ module Shaf
111
113
  target_version: hash["target_version"],
112
114
  patches: hash["patches"],
113
115
  add: hash["add"],
114
- drop: hash["drop"]
116
+ drop: hash["drop"],
117
+ substitutes: hash["substitutes"]
115
118
  )
116
119
  end
117
120
 
@@ -124,12 +127,9 @@ module Shaf
124
127
  manifest_patches = @manifest.files[:patch].keys.to_set
125
128
  raise MissingFileError if from_file < manifest_patches
126
129
 
127
-
128
130
  to_add = @manifest.files[:add].keys.to_set
129
131
  raise MissingFileError if from_file < to_add
130
132
 
131
- raise FileNotInManifestError if (manifest_patches + to_add) < from_file
132
-
133
133
  @files.each do |md5, content|
134
134
  raise BadChecksumError unless Digest::MD5.hexdigest(content) == md5
135
135
  end
@@ -144,10 +144,10 @@ module Shaf
144
144
 
145
145
  def apply_patches(dir = nil)
146
146
  files_in(dir).all? do |file|
147
- name = @manifest.patch_for(file) # returns nil when file
148
- next true unless name # shouldn't be patched
149
- patch = @files[name]
150
- apply_patch(file, patch)
147
+ @manifest.patch_for(file).all? do |name|
148
+ patch = @files[name]
149
+ apply_patch(file, patch)
150
+ end
151
151
  end
152
152
  end
153
153
 
@@ -177,6 +177,32 @@ module Shaf
177
177
  File.unlink(file) if @manifest.drop?(file)
178
178
  end
179
179
  end
180
+
181
+ def apply_substitutes(dir = nil)
182
+ files_in(dir).all? do |file|
183
+ @manifest.regexp_for(file).all? do |name|
184
+ params = symbolize_keys(YAML.safe_load(@files[name]))
185
+ apply_substitute(file, params)
186
+ end
187
+ end
188
+ end
189
+
190
+ def apply_substitute(file, params)
191
+ pattern = params[:pattern] or return
192
+ replacement = params[:replace] or return
193
+ tmp = Tempfile.open do |new_file|
194
+ File.readlines(file).each do |line|
195
+ new_file << line.sub(Regexp.new(pattern), replacement)
196
+ end
197
+ new_file
198
+ end
199
+ FileUtils.mv(tmp.path, file)
200
+ end
201
+
202
+ # Refactor this when support for ruby < 2.5 is dropped
203
+ def symbolize_keys(hash)
204
+ hash.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
205
+ end
180
206
  end
181
207
  end
182
208
  end
data/lib/shaf/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Shaf
2
- VERSION = "0.5.2"
2
+ VERSION = "0.6.0"
3
3
  end
Binary file
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shaf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sammy Henningsson
@@ -30,7 +30,7 @@ cert_chain:
30
30
  ZMhjYR7sRczGJx+GxGU2EaR0bjRsPVlC4ywtFxoOfRG3WaJcpWGEoAoMJX6Z0bRv
31
31
  M40=
32
32
  -----END CERTIFICATE-----
33
- date: 2018-10-21 00:00:00.000000000 Z
33
+ date: 2018-11-14 00:00:00.000000000 Z
34
34
  dependencies:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: rake
@@ -137,6 +137,9 @@ files:
137
137
  - lib/shaf/extensions/resource_uris.rb
138
138
  - lib/shaf/extensions/symbolic_routes.rb
139
139
  - lib/shaf/formable.rb
140
+ - lib/shaf/formable/builder.rb
141
+ - lib/shaf/formable/field.rb
142
+ - lib/shaf/formable/form.rb
140
143
  - lib/shaf/generator.rb
141
144
  - lib/shaf/generator/base.rb
142
145
  - lib/shaf/generator/controller.rb
@@ -164,6 +167,7 @@ files:
164
167
  - lib/shaf/helpers/json_html.rb
165
168
  - lib/shaf/helpers/paginate.rb
166
169
  - lib/shaf/helpers/payload.rb
170
+ - lib/shaf/immutable_attr.rb
167
171
  - lib/shaf/middleware.rb
168
172
  - lib/shaf/middleware/request_id.rb
169
173
  - lib/shaf/rake.rb
@@ -222,6 +226,7 @@ files:
222
226
  - templates/spec/spec_helper.rb
223
227
  - upgrades/0.4.0.tar.gz
224
228
  - upgrades/0.5.0.tar.gz
229
+ - upgrades/0.6.0.tar.gz
225
230
  homepage: https://github.com/sammyhenningsson/shaf
226
231
  licenses:
227
232
  - MIT
metadata.gz.sig CHANGED
Binary file