Skip to content

Commit

Permalink
- The {root}/config/initializers directory is now only for server sid…
Browse files Browse the repository at this point in the history
…e code.

- Redid the initializer load order so all initializers run before any controllers/models/views are loaded.
- Added error message for when an unserializable object is returned from a Task
- Fixed issue with disable_encryption option
  • Loading branch information
ryanstout committed Aug 27, 2015
1 parent 1f7b1ac commit 86d34aa
Show file tree
Hide file tree
Showing 32 changed files with 154 additions and 42 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
- You can now disable auto-import of JS/CSS with ```disable_auto_import``` in a dependencies.rb file
- Opal was upgraded to 0.8, which brings sourcemaps back (yah!)
- Page load performance was improved, and more of sprockets was used for component loading.
- You can now return promises in permissions blocks. Also, can_read?, can_create?, and .can_delete?
- You can now return promises in permissions blocks. Also, can_read?, can_create?, and .can_delete? now return promises.
- Anything in /public is now served via Rack::Static in the default middleware stack. (So you can put user uploaded images in there)
- You can now use _ or - in volt tag names and attributes. (We're moving to using dash ( - ) as the standard in html)
- 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.
Expand All @@ -21,6 +21,10 @@
### Changed
- fix issue with ```raw``` and promises (#275)
- fix issue with .length on store (#269)
- The {root}/config/initializers directory is now only for server side code.
- Redid the initializer load order so all initializers run before any controllers/models/views are loaded.
- Added error message for when an unserializable object is returned from a Task
- Fixed issue with disable_encryption option

## 0.9.4
### Lingo Change
Expand Down
8 changes: 8 additions & 0 deletions docs/UPGRADE_GUIDE.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# 0.9.4 to 0.9.5

CSS url's now should be referenced either 1) as relative paths from the css file, or 2) using the full path from inside of app (eg: main/assets/images/background.jpg)

On models, .can_delete?, .can_read?, and .can_create? now return promises.

Check the CHANGELOG for more info.

# 0.9.3 to 0.9.4

We moved logic out of Volt::User and into the generated user file, so it is easier to customize. Add the following to your app/main/models/user.rb:
Expand Down
10 changes: 8 additions & 2 deletions lib/volt/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,17 @@ def drop_collection(collection)
no_tasks do
# The logic for creating a new project. We want to be able to invoke this
# inside of a method so we can run it with Dir.chdir
def new_project(name, skip_gemfile = false)
def new_project(name, skip_gemfile = false, disable_encryption = false)
require 'securerandom'

# Grab the current volt version
directory('project', name, version: Volt::Version::STRING, name: name, domain: name.dasherize.downcase, app_name: name.capitalize)
directory('project', name, {
version: Volt::Version::STRING,
name: name,
domain: name.dasherize.downcase,
app_name: name.capitalize,
disable_encryption: disable_encryption
})

unless skip_gemfile
# Move into the directory
Expand Down
2 changes: 1 addition & 1 deletion lib/volt/cli/new_gem.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def initialize(thor, name, options)
@thor.say 'Generating dummy project for integration specs', :green
cli = Volt::CLI.new
cli.shell.mute do
cli.new_project('dummy', true)
cli.new_project('dummy', true, true)
end

# Remove gemfile
Expand Down
3 changes: 1 addition & 2 deletions lib/volt/models.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@
if RUBY_PLATFORM == 'opal'
require 'promise'
else
# Opal doesn't expose its promise library directly
require 'opal'

# Opal doesn't expose its promise library directly
gem_dir = File.join(Opal.gem_dir, '..')
require(gem_dir + '/stdlib/promise')
end
Expand Down
2 changes: 1 addition & 1 deletion lib/volt/page/tasks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def response(promise_id, result, error)
# TODO: full error handling
Volt.logger.error('Task Response:')
Volt.logger.error(error.inspect)
promise.reject(error)
promise.reject(RuntimeError.new(error))
else
promise.resolve(result)
end
Expand Down
22 changes: 14 additions & 8 deletions lib/volt/server/component_templates.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,22 @@ def initialize(component_path, component_name, client = true)
@client = client
end

def code
code = generate_routes_code + generate_view_code
def initializer_code
if @client
generate_initializers_code
else
''
end
end

def component_code
code = ''

code << generate_routes_code + generate_view_code
if @client
# On the backend, we just need the views
code << generate_controller_code + generate_model_code +
generate_tasks_code + generate_initializers_code
generate_tasks_code
end

code
Expand Down Expand Up @@ -161,16 +171,12 @@ def generate_tasks_code
end

def generate_initializers_code
# Include the root initializers
paths = Dir["#{Volt.root}/config/initializers/*.rb"]
paths += Dir["#{Volt.root}/config/initializers/client/*.rb"]

paths = Dir["#{@component_path}/config/initializers/*.rb"]
paths += Dir["#{@component_path}/config/initializers/client/*.rb"]

code = "\n" + paths.map { |path| "require '#{localize_path(path)}'" }.join("\n")

code
code + "\n\n"
end

private
Expand Down
2 changes: 1 addition & 1 deletion lib/volt/server/message_bus/message_encoder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def initialize
end

# Message bus is encrypted by default
disable = Volt.config.message_bus.try(:disable_encryption)
disable = (msg_bus = Volt.config.message_bus) && msg_bus.disable_encryption
@encrypted = !windows && (disable != true)

if @encrypted
Expand Down
14 changes: 8 additions & 6 deletions lib/volt/server/rack/component_code.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
require 'volt/server/component_templates'
require 'volt/server/rack/asset_files'

# Takes in the name and all component paths and has a .code
# method that returns all of the ruby setup code for the component.
# Takes in the name and all component paths returns all of the ruby code for the
# component and its dependencies.
module Volt
class ComponentCode
def initialize(volt_app, component_name, component_paths, client = true)
Expand All @@ -16,15 +16,17 @@ def initialize(volt_app, component_name, component_paths, client = true)
# The client argument is for if this code is being generated for the client
def code
# Start with config code
code = @client ? generate_config_code : ''
initializer_code = @client ? generate_config_code : ''
component_code = ''

asset_files = AssetFiles.from_cache(@volt_app.app_url, @component_name, @component_paths)
asset_files.component_paths.each do |component_path, component_name|
code << ComponentTemplates.new(component_path, component_name, @client).code
code << "\n\n"
comp_template = ComponentTemplates.new(component_path, component_name, @client)
initializer_code << comp_template.initializer_code + "\n\n"
component_code << comp_template.component_code + "\n\n"
end

code
initializer_code + component_code
end

def generate_config_code
Expand Down
11 changes: 9 additions & 2 deletions lib/volt/server/rack/component_paths.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,20 @@ def components
@components
end

# Setup load path for components
def setup_load_paths
unless RUBY_PLATFORM == 'opal'
app_folders do |app_folder|
$LOAD_PATH.unshift(app_folder)
end
end
end

# Makes each components classes available on the load path, require classes.
def require_in_components(volt_app)
if RUBY_PLATFORM == 'opal'
else
app_folders do |app_folder|
$LOAD_PATH.unshift(app_folder)

# Sort so we get consistent load order across platforms
Dir["#{app_folder}/*/{controllers,models,tasks}/*.rb"].each do |ruby_file|
path = ruby_file.gsub(/^#{app_folder}\//, '')[0..-4]
Expand Down
5 changes: 3 additions & 2 deletions lib/volt/server/rack/sprockets_helpers_setup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ def setup_path_helpers
end

def add_linking_in_asset_path
app_path = @volt_app.app_path
@env.context_class.class_eval do
# We "freedom-patch" sprockets-helpers asset_path method to
# automatically link assets.
def asset_path(source, options = {})
define_method(:asset_path) do |source, options = {}|
relative_path = source =~ /^[.][.]\//
if relative_path
component_root = logical_path.gsub(/\/[^\/]+$/, '')
Expand All @@ -47,7 +48,7 @@ def asset_path(source, options = {})
if relative_path
link_path = source
else
link_path = source.gsub(/^#{@volt_app.app_path}\//, '')
link_path = source.gsub(/^#{app_path}\//, '')
end

# Return for absolute urls (one's off site)
Expand Down
11 changes: 10 additions & 1 deletion lib/volt/server/socket_connection_handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,19 @@ def process_message(message)
end
end

# Used when the message is already encoded
def send_string_message(str)
send_raw_message(str)
end

def send_message(*args)
# Encode as EJSON
str = EJSON.stringify([*args])

send_raw_message(str)
end

def send_raw_message(str)
@session.send(str)

if RUNNING_SERVER == 'thin'
Expand All @@ -65,7 +75,6 @@ def send_message(*args)
# TODO: Figure out the cause of the issue and submit a fix upstream.
EM.next_tick {}
end

end

def closed
Expand Down
6 changes: 5 additions & 1 deletion lib/volt/server/template_handlers/view_processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,23 @@ def cache_key
# end

def call(input)
context = input[:environment].context_class.new(input)
# context.link_asset('main/assets/images/lombard.jpg')
# pp input
data = input[:data]

# input[:accept] = 'application/javascript'
# input[:content_type] = 'application/javascript'
# input[:environment].content_type = 'application/javascript'
input[:cache].fetch([self.cache_key, data]) do
data = input[:cache].fetch([self.cache_key, data]) do
filename = input[:filename]
# puts input[:data].inspect
# Remove all semicolons from source
# input[:content_type] = 'application/javascript'
compile(filename, input[:data])
end

context.metadata.merge(data: data.to_str)
end

def compile(view_path, html)
Expand Down
8 changes: 6 additions & 2 deletions lib/volt/tasks/dispatcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,16 @@ def dispatch_in_thread(channel, message)

# Run the promise and pass the return value/error back to the client
promise.then do |result|
channel.send_message('response', callback_id, result, nil)
reply = EJSON.stringify(['response', callback_id, result, nil])
channel.send_string_message(reply)

finish.call
end.fail do |error|
finish.call(error)
channel.send_message('response', callback_id, nil, error)
# Convert the error into a string so it can be serialized.
error_str = "#{error.class.to_s}: #{error.to_s}"

channel.send_message('response', callback_id, nil, error_str)
end

end
Expand Down
15 changes: 10 additions & 5 deletions lib/volt/utils/ejson.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

module Volt
class EJSON
class NonEjsonType < Exception ; end

OTHER_VALID_CLASSES = [String, TrueClass, FalseClass, Numeric, NilClass]

def self.stringify(obj)
encode(obj).to_json
end
Expand Down Expand Up @@ -48,12 +52,13 @@ def self.encode(obj)

[key, value]
end.to_h
elsif Time === obj
{'$date' => obj.to_i * 1_000}
elsif OTHER_VALID_CLASSES.any? {|klass| obj.is_a?(klass) }
obj
else
if obj.is_a?(Time)
{'$date' => obj.to_i * 1_000}
else
obj
end
# Not a valid class for serializing, raise an exception
raise NonEjsonType, "Unable to serialize #{obj.inspect} to EJSON"
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/volt/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module Volt
module Version
STRING = '0.9.5.pre9'
STRING = '0.9.5.pre10'
end
end
2 changes: 2 additions & 0 deletions lib/volt/volt/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ def initialize(app_path=nil)
# Require in app and initializers
run_app_and_initializers unless RUBY_PLATFORM == 'opal'

require_components

# abort_on_exception is a useful debugging tool, and in my opinion something
# you probbaly want on. That said you can disable it if you need.
unless RUBY_PLATFORM == 'opal'
Expand Down
4 changes: 4 additions & 0 deletions lib/volt/volt/server_setup/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ module App
def setup_paths
# Load component paths
@component_paths = ComponentPaths.new(@app_path)
@component_paths.setup_load_paths
end

def require_components
@component_paths.require_in_components(self)
end

Expand Down
11 changes: 11 additions & 0 deletions spec/apps/kitchen_sink/app/main/assets/css/app.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.logo1 {
width: 129px;
height: 50px;
background: asset-url('../images/volt-logo.jpg') no-repeat center center;
}

.logo2 {
width: 129px;
height: 50px;
background: asset-url('main/assets/images/volt-logo.jpg') no-repeat center center;
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Volt
class Model
def self.acts_awesome
true
end
end
end
1 change: 1 addition & 0 deletions spec/apps/kitchen_sink/app/main/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
client '/html_safe', action: 'html_safe'
client '/missing', action: 'missing'
client '/require_test', action: 'require_test'
client '/images', action: 'images'

# Events
client '/events', component: 'main', controller: 'events', action: 'index'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Main
class MainController < Volt::ModelController
model :page

reactive_accessor :blur_count, :focus_count
reactive_accessor :blur_count, :focus_count, :image_loaded

def index
a = {}
Expand Down
10 changes: 10 additions & 0 deletions spec/apps/kitchen_sink/app/main/views/main/images.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<:Title>
Images

<:Body>
<h1>Images</h1>

<div class="logo1"></div>
<div class="logo2"></div>

<img src="/app/main/assets/images/volt-logo.jpg" />

0 comments on commit 86d34aa

Please sign in to comment.