volt 0.9.5.pre4 → 0.9.5.pre5
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 +10 -0
- data/README.md +13 -5
- data/app/volt/assets/css/{notices.css.scss → notices.scss} +0 -0
- data/app/volt/models/active_volt_instance.rb +1 -1
- data/app/volt/tasks/live_query/live_query.rb +11 -3
- data/app/volt/tasks/store_tasks.rb +14 -17
- data/lib/volt/cli.rb +22 -0
- data/lib/volt/cli/asset_compile.rb +63 -63
- data/lib/volt/cli/base_index_renderer.rb +26 -0
- data/lib/volt/cli/generate.rb +1 -1
- data/lib/volt/config.rb +1 -0
- data/lib/volt/controllers/model_controller.rb +37 -1
- data/lib/volt/extra_core/array.rb +22 -0
- data/lib/volt/models/array_model.rb +7 -1
- data/lib/volt/models/errors.rb +1 -1
- data/lib/volt/models/field_helpers.rb +36 -21
- data/lib/volt/models/model.rb +16 -0
- data/lib/volt/models/validations/validations.rb +21 -6
- data/lib/volt/models/validators/type_validator.rb +35 -3
- data/lib/volt/page/bindings/content_binding.rb +1 -1
- data/lib/volt/page/bindings/event_binding.rb +40 -16
- data/lib/volt/page/document_events.rb +8 -6
- data/lib/volt/reactive/reactive_array.rb +18 -1
- data/lib/volt/server/forking_server.rb +7 -1
- data/lib/volt/server/html_parser/attribute_scope.rb +26 -0
- data/lib/volt/server/html_parser/component_view_scope.rb +30 -22
- data/lib/volt/server/middleware/default_middleware_stack.rb +6 -1
- data/lib/volt/server/rack/asset_files.rb +5 -3
- data/lib/volt/server/rack/opal_files.rb +35 -23
- data/lib/volt/server/rack/sprockets_helpers_setup.rb +71 -0
- data/lib/volt/server/template_handlers/view_processor.rb +1 -2
- data/lib/volt/utils/promise_extensions.rb +1 -1
- data/lib/volt/version.rb +1 -1
- data/lib/volt/volt/app.rb +0 -2
- data/lib/volt/volt/client_setup/browser.rb +11 -0
- data/spec/apps/kitchen_sink/Gemfile +37 -14
- data/spec/apps/kitchen_sink/app/main/config/routes.rb +3 -0
- data/spec/apps/kitchen_sink/app/main/controllers/events_controller.rb +26 -0
- data/spec/apps/kitchen_sink/app/main/views/events/index.html +30 -0
- data/spec/apps/kitchen_sink/app/main/views/main/bindings.html +3 -0
- data/spec/apps/kitchen_sink/app/main/views/main/yield.html +1 -6
- data/spec/apps/kitchen_sink/app/main/views/{yield-component → yield_component}/index.html +0 -0
- data/spec/extra_core/array_spec.rb +26 -0
- data/spec/integration/bindings_spec.rb +9 -0
- data/spec/integration/event_spec.rb +19 -0
- data/spec/models/array_model_spec.rb +13 -0
- data/spec/models/field_helpers_spec.rb +2 -2
- data/spec/models/validations_spec.rb +31 -0
- data/spec/models/validators/type_validator_spec.rb +47 -1
- data/spec/reactive/reactive_array_spec.rb +46 -0
- data/spec/server/forking_server_spec.rb +27 -0
- data/spec/server/html_parser/view_scope_spec.rb +44 -0
- data/spec/server/rack/asset_files_spec.rb +2 -2
- data/templates/project/Gemfile.tt +8 -0
- data/templates/project/config/app.rb.tt +2 -1
- data/volt.gemspec +1 -1
- metadata +31 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 848470b46efd1f1d8835f8501af6fc39d052cd4c
|
4
|
+
data.tar.gz: 6ff661da03f4f1e572c566b95d2b91868748148e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11b26392d7fab2365755625fafd4708cc8398eecf3aad5c83757a3fbdb6f52baa1c9f38f483d23a52ca61ae98e5e42955028e382e87abf524495851d72684644
|
7
|
+
data.tar.gz: fe2f9c21b79e7da0b478b84aaffaa86da7cf63bf73b2f0b793723c73351de40971027c17044907822b43adbc88d3028ed525a0a7a5aca54fa8718068e998b915
|
data/CHANGELOG.md
CHANGED
@@ -7,6 +7,15 @@
|
|
7
7
|
- Page load performance was improved, and more of sprockets was used for component loading.
|
8
8
|
- You can now return promises in permissions blocks. Also, can_read?, can_create?, and .can_delete?
|
9
9
|
- Anything in /public is now served via Rack::Static in the default middleware stack. (So you can put user uploaded images in there)
|
10
|
+
- You can now use _ or - in volt tag names and attributes. (We're moving to using dash ( - ) as the standard in html)
|
11
|
+
- You can now trigger events on controllers rendered as tags. The events will bubble up through the DOM and can be caught by any e- bindings. See the docs for more information.
|
12
|
+
- Rewrote the precompile pipeline.
|
13
|
+
- Added image compression by default. (using image_optim)
|
14
|
+
- All volt CLI tasks now can run from inside of any directory in the volt app (or the root)
|
15
|
+
|
16
|
+
### Changed
|
17
|
+
- fix issue with ```raw``` and promises (#275)
|
18
|
+
- fix issue with .length on store (#269)
|
10
19
|
|
11
20
|
## 0.9.4
|
12
21
|
### Lingo Change
|
@@ -34,6 +43,7 @@ the base collections will now be called "Repositories" or "Repo's" for short. T
|
|
34
43
|
- fixed issue with local_store not persisting in some cases
|
35
44
|
- runners now block until messages have propigated to the message bus and updates have been pushed.
|
36
45
|
- upgraded some dependency gems to fix a conflict
|
46
|
+
- fixed bug with .last on ReactiveArray (#259)
|
37
47
|
|
38
48
|
## 0.9.3
|
39
49
|
[0.9.3 Update Blog Post](http://blog.voltframework.com/post/121128931859/0-9-3-stuff-you-asked-for)
|
data/README.md
CHANGED
@@ -35,11 +35,19 @@ There is also a [work in progress tutorial](https://github.com/rhgraysonii/volt_
|
|
35
35
|
|
36
36
|
# More Videos
|
37
37
|
|
38
|
-
Rick Carlino has been putting together some great volt tutorial videos also.
|
39
|
-
|
40
|
-
- [Volt
|
41
|
-
- [
|
42
|
-
- [
|
38
|
+
Rick Carlino has been putting together some [great volt tutorial videos](http://datamelon.io/blog) also.
|
39
|
+
|
40
|
+
- [Volt URL Routing](http://datamelon.io/blog/2015/routes-and-multi-view-apps.html)
|
41
|
+
- [Volt Tasks](http://datamelon.io/blog/2015/creating-volt-task-objects.html)
|
42
|
+
- [Volt Views](http://datamelon.io/blog/2015/understanding-views-in-volt-with-a-card-game.html)
|
43
|
+
- [Volt Permissions](http://datamelon.io/blog/2015/twitter-clone-demonstrates-volt-permissions.html)
|
44
|
+
- [Volt Runners](http://datamelon.io/blog/2015/automation-of-everything-with-volt-runners.html)
|
45
|
+
- [Volt Components](http://datamelon.io/blog/2015/staying-productive-with-the-volt-component-ecosystem.html)
|
46
|
+
- [REST APIs in Volt](http://datamelon.io/blog/2015/building-rest-apis-with-volt.html)
|
47
|
+
- [Javascript Library Interop](http://datamelon.io/blog/2015/using-js-libraries-with-opal.html)
|
48
|
+
- [Credit Card Payments with Volt](http://datamelon.io/blog/2015/payment-form-using-volt-and-stripe.html)
|
49
|
+
- [Build a Realtime Chat App](http://datamelon.io/blog/2015/building-a-chat-app-in-volt.html)
|
50
|
+
- [6 Key Concepts for New Volt Learners](http://datamelon.io/blog/2015/6-concepts-for-volt-beginners.html)
|
43
51
|
|
44
52
|
@ahnbizcad maintains a [playlist of Volt related videos](https://www.youtube.com/watch?v=McxtO8ybxy8&list=PLmQFeDKFCPXatHb-zEXwfeMH01DPiZjP7).
|
45
53
|
|
File without changes
|
@@ -30,11 +30,14 @@ class LiveQuery
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def notify_added(index, data, skip_channel)
|
33
|
-
# puts "Added: #{index} - #{data.inspect}"
|
34
33
|
# Make model for testing permissions against
|
35
|
-
model =
|
34
|
+
model = nil
|
36
35
|
|
37
36
|
notify! do |channel|
|
37
|
+
# Only load the model for filtering if we are sending to a channel
|
38
|
+
# (skip if we are the only one listening)
|
39
|
+
model ||= model_for_filter(data)
|
40
|
+
|
38
41
|
filtered_data = nil
|
39
42
|
Volt.as_user(channel.user_id) do
|
40
43
|
filtered_data = model.filtered_attributes.sync
|
@@ -52,9 +55,14 @@ class LiveQuery
|
|
52
55
|
end
|
53
56
|
|
54
57
|
def notify_changed(id, data, skip_channel)
|
55
|
-
|
58
|
+
# puts "NOTIFY CHANGED"
|
59
|
+
model = nil
|
56
60
|
|
57
61
|
notify!(skip_channel) do |channel|
|
62
|
+
# Only load the model for filtering if we are sending to a channel
|
63
|
+
# (skip if we are the only one listening)
|
64
|
+
model ||= model_for_filter(data)
|
65
|
+
|
58
66
|
filtered_data = nil
|
59
67
|
Volt.as_user(channel.user_id) do
|
60
68
|
filtered_data = model.filtered_attributes.sync
|
@@ -9,31 +9,21 @@ class StoreTasks < Volt::Task
|
|
9
9
|
model_name = collection.singularize.camelize
|
10
10
|
|
11
11
|
# Fetch the model
|
12
|
-
collection = store.
|
12
|
+
collection = store.get(path[-2])
|
13
13
|
|
14
14
|
# See if the model has already been made
|
15
|
-
collection.where(id: data[:id]).first
|
16
|
-
# Otherwise assign to the collection
|
17
|
-
model ||= collection
|
15
|
+
model_promise = collection.where(id: data[:id]).first
|
18
16
|
|
19
|
-
|
20
|
-
buffer = model.buffer
|
21
|
-
|
22
|
-
# Assign the changed data to the buffer
|
23
|
-
buffer.assign_attributes(data, false, true)
|
24
|
-
|
25
|
-
buffer
|
26
|
-
end
|
17
|
+
return collection, model_promise
|
27
18
|
end
|
28
19
|
|
29
20
|
def save(collection, path, data)
|
30
21
|
data = data.symbolize_keys
|
31
|
-
|
22
|
+
model_promise = nil
|
32
23
|
|
33
|
-
# Don't check the permissions when we load the model, since we want all fields
|
34
24
|
Volt.skip_permissions do
|
35
25
|
Volt::Model.no_validate do
|
36
|
-
|
26
|
+
collection, model_promise = load_model(collection, path, data)
|
37
27
|
end
|
38
28
|
end
|
39
29
|
|
@@ -44,9 +34,16 @@ class StoreTasks < Volt::Task
|
|
44
34
|
# who sent the update.
|
45
35
|
#
|
46
36
|
# return another promise
|
47
|
-
|
37
|
+
model_promise.then do |model|
|
48
38
|
Thread.current['in_channel'] = @channel
|
49
|
-
|
39
|
+
|
40
|
+
result = if model
|
41
|
+
model.update(data)
|
42
|
+
else
|
43
|
+
collection.create(data)
|
44
|
+
end
|
45
|
+
|
46
|
+
save_promise = result.then do |result|
|
50
47
|
next nil
|
51
48
|
end.fail do |err|
|
52
49
|
# An error object, convert to hash
|
data/lib/volt/cli.rb
CHANGED
@@ -131,5 +131,27 @@ end
|
|
131
131
|
# Add in more features
|
132
132
|
require 'volt/cli/asset_compile'
|
133
133
|
|
134
|
+
unless Gem.win_platform?
|
135
|
+
# Change CWD to the root of the volt project
|
136
|
+
pwd = Dir.pwd
|
137
|
+
changed = false
|
138
|
+
loop do
|
139
|
+
if File.exists?(pwd + '/Gemfile')
|
140
|
+
Dir.chdir(pwd) if changed
|
141
|
+
break
|
142
|
+
else
|
143
|
+
changed = true
|
144
|
+
|
145
|
+
# Move up a directory and try again
|
146
|
+
pwd = pwd.gsub(/\/[^\/]+$/, '')
|
147
|
+
|
148
|
+
if pwd == ''
|
149
|
+
puts "You are not currently in a volt project directory"
|
150
|
+
exit 1
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
134
156
|
puts "Volt #{Volt::Version::STRING}"
|
135
157
|
Volt::CLI.start(ARGV)
|
@@ -9,9 +9,11 @@ module Volt
|
|
9
9
|
private
|
10
10
|
|
11
11
|
def compile
|
12
|
-
|
12
|
+
say "Starting Precompile...", :red
|
13
13
|
require 'fileutils'
|
14
14
|
ENV['SERVER'] = 'true'
|
15
|
+
ENV['MAPS'] = 'false'
|
16
|
+
ENV['NO_FORKING'] = 'true'
|
15
17
|
|
16
18
|
require 'opal'
|
17
19
|
require 'rack'
|
@@ -19,90 +21,88 @@ module Volt
|
|
19
21
|
require 'volt/volt/core'
|
20
22
|
require 'volt/boot'
|
21
23
|
require 'volt/server'
|
24
|
+
require 'volt/server/rack/component_paths'
|
25
|
+
require 'volt/server/rack/component_code'
|
22
26
|
|
23
27
|
@root_path ||= Dir.pwd
|
24
28
|
Volt.root = @root_path
|
25
29
|
|
26
|
-
volt_app = Volt.boot(@root_path)
|
27
|
-
|
28
|
-
require 'volt/server/rack/component_paths'
|
29
|
-
require 'volt/server/rack/component_code'
|
30
|
+
@volt_app = Volt.boot(@root_path)
|
30
31
|
|
31
32
|
@app_path = File.expand_path(File.join(@root_path, 'app'))
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
puts 'Compile Opal for components'
|
39
|
-
write_component_js
|
40
|
-
puts 'Copy assets'
|
41
|
-
write_sprockets
|
42
|
-
puts 'Compile JS/CSS'
|
43
|
-
write_js_and_css
|
44
|
-
puts 'Write index files'
|
34
|
+
say 'Compiling RB, JS, CSS, and Images...', :red
|
35
|
+
write_files_and_manifest
|
36
|
+
compile_manifests
|
37
|
+
say 'Write index files...', :red
|
45
38
|
write_index
|
46
|
-
|
47
|
-
puts "compiled"
|
48
|
-
end
|
49
|
-
|
50
|
-
def logical_paths_and_full_paths
|
51
|
-
env = @opal_files.environment
|
52
|
-
env.each_file do |full_path|
|
53
|
-
# logical_path = env[full_path].logical_path
|
54
|
-
# logical_path = @opal_files.environment.send(:logical_path_for_filename, full_path, []).to_s
|
55
|
-
# puts "FULL PATH: #{full_path.inspect} -- #{logical_path}"
|
56
|
-
|
57
|
-
# yield(logical_path, full_path.to_s)
|
58
|
-
end
|
59
|
-
|
39
|
+
say "Done", :green
|
60
40
|
end
|
61
41
|
|
62
|
-
def
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
42
|
+
def write_files_and_manifest
|
43
|
+
asset_files = AssetFiles.from_cache('main', @volt_app.component_paths)
|
44
|
+
# Write a temp css file
|
45
|
+
js = asset_files.javascript(@volt_app)
|
46
|
+
css = asset_files.css
|
47
|
+
@tmp_files = []
|
48
|
+
|
49
|
+
File.open(Volt.root + '/app/main/app.js', 'wb') do |file|
|
50
|
+
js.each do |type, src_or_body|
|
51
|
+
if type == :src
|
52
|
+
src = src_or_body
|
53
|
+
url = src.gsub(/^\/assets\//, '')
|
54
|
+
file.write("//= require '#{url}'\n")
|
55
|
+
else
|
56
|
+
body = src_or_body
|
57
|
+
|
58
|
+
# Write to a tempfile, since sprockets can't mix requires and
|
59
|
+
# code.
|
60
|
+
|
61
|
+
require 'securerandom'
|
62
|
+
hex = SecureRandom.hex
|
63
|
+
tmp_path = Volt.root + "/app/main/__#{hex}.js"
|
64
|
+
url = "main/__#{hex}"
|
65
|
+
file.write("//= require '#{url}'\n")
|
66
|
+
|
67
|
+
@tmp_files << tmp_path
|
68
|
+
File.open(tmp_path, 'wb') {|f| f.write("#{body}\n") }
|
69
|
+
end
|
71
70
|
end
|
72
71
|
end
|
73
|
-
end
|
74
72
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
write_sprocket_file(logical_path)
|
73
|
+
File.open(Volt.root + '/app/main/app.scss', 'wb') do |file|
|
74
|
+
css.each do |link|
|
75
|
+
url = link.gsub(/^\/assets\//, '')
|
76
|
+
file.write("//= require '#{url}'\n")
|
80
77
|
end
|
81
78
|
end
|
82
79
|
end
|
83
80
|
|
84
|
-
def
|
85
|
-
|
86
|
-
|
87
|
-
begin
|
88
|
-
# Only write out the assets
|
89
|
-
# if logical_path =~ /\/assets\//
|
90
|
-
content = @opal_files.environment[logical_path].to_s
|
91
|
-
write_file(path, content)
|
92
|
-
# end
|
93
|
-
rescue Sprockets::FileNotFound, SyntaxError => e
|
94
|
-
# ignore
|
95
|
-
end
|
96
|
-
end
|
81
|
+
def compile_manifests
|
82
|
+
manifest = Sprockets::Manifest.new(@volt_app.sprockets, './public/assets/manifest.json')
|
97
83
|
|
98
|
-
|
99
|
-
|
84
|
+
# Compile the files (and linked assets)
|
85
|
+
manifest.compile('main/app.js')
|
86
|
+
manifest.compile('main/app.css')
|
87
|
+
|
88
|
+
# Clear temp files
|
89
|
+
@tmp_files.each {|path| FileUtils.rm(path) }
|
90
|
+
|
91
|
+
# Remove the temp files
|
92
|
+
FileUtils.rm(Volt.root + '/app/main/app.js')
|
93
|
+
FileUtils.rm(Volt.root + '/app/main/app.scss')
|
100
94
|
end
|
101
95
|
|
102
96
|
def write_index
|
103
|
-
|
97
|
+
require 'volt/cli/base_index_renderer'
|
98
|
+
|
99
|
+
output_path = "#{@root_path}/public/index.html"
|
100
|
+
require 'json'
|
101
|
+
|
102
|
+
@manifest = JSON.parse(File.read(@root_path + '/public/assets/manifest.json'))
|
103
|
+
output_html = BaseIndexRenderer.new(@manifest).html
|
104
104
|
|
105
|
-
write_file(
|
105
|
+
write_file(output_path, output_html)
|
106
106
|
end
|
107
107
|
|
108
108
|
def write_file(path, data)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Render the config/base/index.html when precompiling. Here we only render
|
2
|
+
# one js and one css file.
|
3
|
+
|
4
|
+
module Volt
|
5
|
+
class BaseIndexRenderer
|
6
|
+
def initialize(manifest)
|
7
|
+
@manifest = manifest
|
8
|
+
end
|
9
|
+
|
10
|
+
def html
|
11
|
+
index_path = File.expand_path(File.join(Volt.root, 'config/base/index.html'))
|
12
|
+
html = File.read(index_path)
|
13
|
+
|
14
|
+
ERB.new(html, nil, '-').result(binding)
|
15
|
+
end
|
16
|
+
|
17
|
+
# When writing the index, we render the
|
18
|
+
def javascript_tags
|
19
|
+
"<script src=\"/assets/#{@manifest['assets']['main/app.js']}\"></script>"
|
20
|
+
end
|
21
|
+
|
22
|
+
def css_tags
|
23
|
+
"<link href=\"/assets/#{@manifest['assets']['main/app.css']}\" media=\"all\" rel=\"stylesheet\" type=\"text/css\" />"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/volt/cli/generate.rb
CHANGED
@@ -81,7 +81,7 @@ class Generate < Thor
|
|
81
81
|
method_option :name, type: :string, banner: 'The name of the task.'
|
82
82
|
method_option :component, type: :string, default: 'main', banner: 'The component the task should be created in.', required: false
|
83
83
|
def task(name, component = 'main')
|
84
|
-
name = name.underscore.gsub(/_tasks$/, '').singularize + '_task'
|
84
|
+
name = name.underscore.gsub(/_tasks$/, '').singularize.gsub('_task', '') + '_task'
|
85
85
|
output_file = Dir.pwd + "/app/#{component}/tasks/#{name}.rb"
|
86
86
|
spec_file = Dir.pwd + "/spec/app/#{component}/tasks/#{name}_spec.rb"
|
87
87
|
template('task/task.rb.tt', output_file, task_name: name.camelize.singularize)
|
data/lib/volt/config.rb
CHANGED
@@ -27,16 +27,19 @@ module Volt
|
|
27
27
|
|
28
28
|
# Container returns the node that is parent to all nodes in the section.
|
29
29
|
def container
|
30
|
+
check_section!('container')
|
30
31
|
section.container_node
|
31
32
|
end
|
32
33
|
|
33
34
|
def dom_nodes
|
35
|
+
check_section!('dom_nodes')
|
34
36
|
section.range
|
35
37
|
end
|
36
38
|
|
37
39
|
# Walks the dom_nodes range until it finds an element. Typically this will
|
38
40
|
# be the container element without the whitespace text nodes.
|
39
41
|
def first_element
|
42
|
+
check_section!('first_element')
|
40
43
|
range = dom_nodes
|
41
44
|
nodes = `range.startContainer.childNodes`
|
42
45
|
|
@@ -76,6 +79,24 @@ module Volt
|
|
76
79
|
end
|
77
80
|
end
|
78
81
|
|
82
|
+
def trigger(event, *args)
|
83
|
+
# Trigger on the current controller if an e- was setup on the component.
|
84
|
+
component_event = attrs.send(:"e_#{event}")
|
85
|
+
|
86
|
+
if component_event
|
87
|
+
# Add a nil arg for the event, trim to arity
|
88
|
+
args2 = (args + [nil])[0...component_event.arity]
|
89
|
+
component_event.call(*args2)
|
90
|
+
end
|
91
|
+
|
92
|
+
args.unshift(self)
|
93
|
+
# Trigger via jquery, so it bubbles up through the DOM
|
94
|
+
`$(#{first_element}).trigger(#{event}, #{args});`
|
95
|
+
|
96
|
+
# return nil, so we return a ruby object
|
97
|
+
nil
|
98
|
+
end
|
99
|
+
|
79
100
|
def self.model(val)
|
80
101
|
self.default_model = val
|
81
102
|
end
|
@@ -208,7 +229,14 @@ module Volt
|
|
208
229
|
# Raw marks a string as html safe, so bindings can be rendered as html.
|
209
230
|
# With great power comes great responsibility.
|
210
231
|
def raw(str)
|
211
|
-
|
232
|
+
# Promises need to have .to_s called using .then, since .to_s is a promise
|
233
|
+
# method, so it won't be passed down to the value.
|
234
|
+
if str.is_a?(Promise)
|
235
|
+
str = str.then(&:to_s)
|
236
|
+
else
|
237
|
+
str = str.to_s unless str.is_a?(String)
|
238
|
+
end
|
239
|
+
|
212
240
|
str.html_safe
|
213
241
|
end
|
214
242
|
|
@@ -230,5 +258,13 @@ module Volt
|
|
230
258
|
super
|
231
259
|
end
|
232
260
|
end
|
261
|
+
|
262
|
+
private
|
263
|
+
def check_section!(method_name)
|
264
|
+
unless section
|
265
|
+
raise "##{method_name} can't be called before the {action}_ready method is called"
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
233
269
|
end
|
234
270
|
end
|