Skip to content
This repository has been archived by the owner on Oct 19, 2018. It is now read-only.

Commit

Permalink
closes #102 fixes some more regressions and spec changes related to e…
Browse files Browse the repository at this point in the history
…rror handling
  • Loading branch information
catmando committed Aug 3, 2018
1 parent 86bdc65 commit 64117de
Show file tree
Hide file tree
Showing 8 changed files with 363 additions and 9 deletions.
1 change: 1 addition & 0 deletions lib/hyper-mesh.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
require "reactive_record/active_record/class_methods"
require "reactive_record/active_record/instance_methods"
require "reactive_record/active_record/base"
require 'hyper_react/input_tags'
require_relative 'hypermesh/version'
require_relative 'opal/parse_patch'
require_relative 'opal/set_patches'
Expand Down
47 changes: 47 additions & 0 deletions lib/hyper_react/input_tags.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Special handling of input tags so they ignore defaultValue (and defaultChecked) values while loading.
# This is accomplished by adding a react 'key prop' that tracks whether the default value is loading.
# When the default value transitions from loading to loaded the key will be updated causing react to
# remount the component with the new default value.
# To handle cases where defaultValue (or defaultChecked) is an expression, a proc (or lambda) can be
# provided for the default value. The proc will be called, and if it raises the waiting_on_resources
# flag then we know that within that expression there is a value still being loaded, and the react
# key will be set accordingly.

module React
module Component
module Tags
%i[INPUT SELECT TEXTAREA].each do |component|
remove_method component
send(:remove_const, component)
tag = component.downcase
klass = Class.new(Hyperloop::Component) do
collect_other_params_as :opts
render do
opts = props.dup # should be opts = params.opts.dup but requires next release candiate of hyper-react
default_value = opts[:defaultValue] || opts[:defaultChecked]
if default_value.respond_to? :call
begin
saved_waiting_on_resources = React::RenderingContext.waiting_on_resources
React::RenderingContext.waiting_on_resources = false
default_value = default_value.call
opts[:key] = React::RenderingContext.waiting_on_resources
if opts[:defaultValue]
opts[:defaultValue] = default_value
else
opts[:defaultChecked] = default_value
end
ensure
React::RenderingContext.waiting_on_resources = !!saved_waiting_on_resources
end
else
opts[:key] = !!default_value.loading?
end
opts[:value] = opts[:value].to_s if opts.key? :value # this may not be needed
React::RenderingContext.render(tag, opts) { children.each(&:render) }
end
end
const_set component, klass
end
end
end
end
2 changes: 1 addition & 1 deletion lib/reactive_record/active_record/error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def clear
@messages.clear
end

def add(attribute, message:)
def add(attribute, message = :invalid, _options = {})
@messages[attribute] << message unless @messages[attribute].include? message
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,8 @@ def send_save_to_server(save, validate, force, &block)
Broadcast.to_self backing_records[item[0]].ar_instance, item[2]
end
else
log("Reactive Record Save Failed: #{response[:message]}", :error)
response[:saved_models].each do | item |
log(response[:message], :error)
response[:saved_models].each do |item|
log(" Model: #{item[1]}[#{item[0]}] Attributes: #{item[2]} Errors: #{item[3]}", :error) if item[3]
end
end
Expand All @@ -308,7 +308,7 @@ def send_save_to_server(save, validate, force, &block)
backing_records.each { |_id, record| record.saved!(true) rescue nil } if save
end
rescue Exception => e
# debugger
debugger
log("Exception raised while saving - #{e}", :error)
yield false, e.message, [] if block
promise.resolve({success: false, message: e.message, models: []})
Expand Down Expand Up @@ -480,7 +480,7 @@ def self.save_records(models, associations, acting_user, validate, save)

saved_models = reactive_records.collect do |reactive_record_id, model|
messages = model.errors.messages if validate && !model.valid?
all_messages << messages if save && messages
all_messages << [model, messages] if save && messages
attributes = model.__hyperloop_secure_attributes(acting_user)
[reactive_record_id, model.class.name, attributes, messages]
end
Expand All @@ -494,7 +494,7 @@ def self.save_records(models, associations, acting_user, validate, save)

unless all_messages.empty?
::Rails.logger.debug "\033[0;31;1mERROR: HyperModel saving records failed:\033[0;30;21m"
all_messages.each do |message|
all_messages.each do |model, message|
::Rails.logger.debug "\033[0;31;1m\t#{model}: #{message}\033[0;30;21m"
end
raise 'HyperModel saving records failed!'
Expand Down
2 changes: 1 addition & 1 deletion spec/batch1/misc/validate_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
User.new(last_name: 'f**k').validate.then do |new_user|
new_user.errors.messages
end
end.to eq("last_name"=>[{"message"=>"no swear words allowed"}])
end.to eq("last_name"=>["no swear words allowed"])
end

it "the valid? method will return true if the model has no errors" do
Expand Down
61 changes: 61 additions & 0 deletions spec/batch1/misc/while_loading_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,67 @@ class WhileLoadingTester < Hyperloop::Component
expect(page).not_to have_content('loading...', wait: 0)
end

it "achieving while_loading behavior with state variables" do
ReactiveRecord::Operations::Fetch.semaphore.synchronize do
mount "WhileLoadingTester", {}, no_wait: true do
class MyComponent < Hyperloop::Component
render do
SPAN { 'loading...' }
end
end

class WhileLoadingTester < Hyperloop::Component

before_mount do
ReactiveRecord.load do
User.find_by_first_name('Lily').last_name
end.then do |last_name|
mutate.last_name last_name
end
end

render do
if state.last_name
DIV { state.last_name }
else
MyComponent {}
end
end
end
end
expect(page).to have_content('loading...')
expect(page).not_to have_content('DaDog', wait: 0)
end
expect(page).to have_content('DaDog')
expect(page).not_to have_content('loading...', wait: 0)
end

it "while loading display an application defined element" do
ReactiveRecord::Operations::Fetch.semaphore.synchronize do
mount "WhileLoadingTester", {}, no_wait: true do
class MyComponent < Hyperloop::Component
render do
SPAN { 'loading...' }
end
end
class WhileLoadingTester < Hyperloop::Component
render do
DIV do
User.find_by_first_name('Lily').last_name
end
.while_loading do
MyComponent {}
end
end
end
end
expect(page).to have_content('loading...')
expect(page).not_to have_content('DaDog', wait: 0)
end
expect(page).to have_content('DaDog')
expect(page).not_to have_content('loading...', wait: 0)
end

it "will display the while loading message on condition" do
isomorphic do
class FetchNow < Hyperloop::ServerOp
Expand Down
Loading

0 comments on commit 64117de

Please sign in to comment.