shaf 0.5.2 → 0.6.0

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