Class: ReactiveValue
- Inherits:
- BasicObject
- Defined in:
- lib/volt/reactive/reactive_value.rb
Constant Summary collapse
- SKIP_METHODS =
Methods we should skip wrapping the results in We skip .hash because in uniq it has .to_int called on it, which needs to return a Fixnum instance. :hash - needs something where .to_int can be called on it and it will
return an int
:methods- needs to return a straight up array to work with irb tab completion :eql? - needed for .uniq to work correctly :to_ary - in some places ruby expects to get an array back from this method
[:hash, :methods, :eql?, :respond_to?, :respond_to_missing?, :to_ary, :to_int]
Instance Method Summary collapse
-
#! ⇒ Object
TODO: this is broke in opal.
-
#==(val) ⇒ Object
Not 100% sure why, but we need to define this directly, it doesn’t call on method missing.
- #check_tag(method_name, tag_name) ⇒ Object
- #coerce(other) ⇒ Object
-
#initialize(getter, setter = nil, scope = nil) ⇒ ReactiveValue
constructor
A new instance of ReactiveValue.
- #inspect ⇒ Object
- #method_missing(method_name, *args, &block) ⇒ Object
- #pretty_inspect ⇒ Object
- #puts(*args) ⇒ Object
- #reactive? ⇒ Boolean
- #reactive_manager ⇒ Object (also: #rm)
-
#respond_to_missing?(name, include_private = false) ⇒ Boolean
def respond_to?(name, include_private=false) [:event_added, :event_removed].include?(name) || super end.
- #setup_setter(manager, method_name, args) ⇒ Object
- #to_s ⇒ Object
- #with(*args, &block) ⇒ Object
Constructor Details
#initialize(getter, setter = nil, scope = nil) ⇒ ReactiveValue
Returns a new instance of ReactiveValue.
33 34 35 |
# File 'lib/volt/reactive/reactive_value.rb', line 33 def initialize(getter, setter=nil, scope=nil) @reactive_manager = ::ReactiveManager.new(getter, setter, scope) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args, &block) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/volt/reactive/reactive_value.rb', line 79 def method_missing(method_name, *args, &block) # Unroll send into a direct call if method_name == :send method_name, *args = args end # Check to see if the method we're calling wants to receive reactive values. pass_reactive = check_tag(method_name, :pass_reactive) # For some methods, we pass directly to the current object. This # helps ReactiveValue's be well behaved ruby citizens. # Also skip if this is a destructive method if SKIP_METHODS.include?(method_name) || check_tag(method_name, :destructive)# || (method_name[0] =~ /[a-zA-Z]/ && !cur.is_a?(::Exception)) pass_args = pass_reactive ? args : args.map{|v| v.cur } return cur.__send__(method_name, *pass_args, &block) end @block_reactives = [] result = @reactive_manager.(args, pass_reactive) do |val, in_args| # When a method is called with a block, we pass in our own block that wraps the # block passed in. This way we can pass in any arguments as reactive and track # the return values. new_block = block # index_cache = [] # index = 0 # # if false && new_block # new_block = ::Proc.new do |*block_args| # res = block.call(*block_args.map {|v| ::ReactiveValue.new(v) }) # # result.rm.remove_parent!(index_cache[index]) if index_cache[index] # puts "index: #{index}" # index_cache[index] = res # # # @block_reactives << res # result.rm.add_parent!(res) # # puts "Parent Size: #{result.rm.parents.size}" # # index += 1 # # res.cur # end # end val.__send__(method_name, *in_args, &new_block) end manager = result.reactive_manager setup_setter(manager, method_name, args) manager.set_scope!([method_name, *args, block]) # result = result.with(block_reactives) if block return result end |
Instance Method Details
#! ⇒ Object
TODO: this is broke in opal
182 183 184 |
# File 'lib/volt/reactive/reactive_value.rb', line 182 def ! method_missing(:!) end |
#==(val) ⇒ Object
Not 100% sure why, but we need to define this directly, it doesn’t call on method missing
177 178 179 |
# File 'lib/volt/reactive/reactive_value.rb', line 177 def ==(val) method_missing(:==, val) end |
#check_tag(method_name, tag_name) ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/volt/reactive/reactive_value.rb', line 55 def check_tag(method_name, tag_name) current_obj = cur # TODO: should be cached somehow if current_obj.respond_to?(:reactive_method_tag) tag = current_obj.reactive_method_tag(method_name, tag_name) unless tag # Get the tag from the all methods if its not directly specified tag = current_obj.reactive_method_tag(:__all_methods, tag_name) end # Evaluate now if its a proc tag = tag.call(method_name) if tag.class == ::Proc return tag end return nil end |
#coerce(other) ⇒ Object
190 191 192 193 194 195 196 197 |
# File 'lib/volt/reactive/reactive_value.rb', line 190 def coerce(other) if other.reactive? return [other, self] else wrapped_object = ::ReactiveValue.new(other, []) return [wrapped_object, self] end end |
#inspect ⇒ Object
167 168 169 |
# File 'lib/volt/reactive/reactive_value.rb', line 167 def inspect "@#{cur.inspect}" end |
#pretty_inspect ⇒ Object
171 172 173 |
# File 'lib/volt/reactive/reactive_value.rb', line 171 def pretty_inspect inspect end |
#puts(*args) ⇒ Object
75 76 77 |
# File 'lib/volt/reactive/reactive_value.rb', line 75 def puts(*args) ::Object.send(:puts, *args) end |
#reactive? ⇒ Boolean
37 38 39 |
# File 'lib/volt/reactive/reactive_value.rb', line 37 def reactive? true end |
#reactive_manager ⇒ Object Also known as: rm
50 51 52 |
# File 'lib/volt/reactive/reactive_value.rb', line 50 def reactive_manager @reactive_manager end |
#respond_to_missing?(name, include_private = false) ⇒ Boolean
def respond_to?(name, include_private=false)
[:event_added, :event_removed].include?(name) || super
end
159 160 161 |
# File 'lib/volt/reactive/reactive_value.rb', line 159 def respond_to_missing?(name, include_private=false) cur.respond_to?(name) end |
#setup_setter(manager, method_name, args) ⇒ Object
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/volt/reactive/reactive_value.rb', line 137 def setup_setter(manager, method_name, args) # See if we can automatically create a setter. If we are fetching a # value via a read, we can probably reassign it with .name= if args.size == 0 # TODO: At the moment we are defining a setter on all "reads", this # probably has some performance implications manager.setter! do |val| # Call setter self.cur.send(:"#{method_name}=", val) end elsif args.size == 1 && method_name == :[] manager.setter! do |val| # Call an array setter self.cur.send(:"#{method_name}=", args[0], val) end end end |
#to_s ⇒ Object
186 187 188 |
# File 'lib/volt/reactive/reactive_value.rb', line 186 def to_s cur.to_s end |
#with(*args, &block) ⇒ Object
163 164 165 |
# File 'lib/volt/reactive/reactive_value.rb', line 163 def with(*args, &block) return @reactive_manager.with(*args, &block) end |