Class: Volt::ModelController
- Includes:
- CollectionHelpers, LifecycleCallbacks, ReactiveAccessors
- Defined in:
- lib/volt/controllers/model_controller.rb
Direct Known Subclasses
Instance Attribute Summary collapse
-
#attrs ⇒ Object
Returns the value of attribute attrs.
-
#section ⇒ Object
The section is assigned a reference to a “DomSection” which has the dom for the controllers view.
Class Method Summary collapse
Instance Method Summary collapse
-
#container ⇒ Object
Container returns the node that is parent to all nodes in the section.
- #controller ⇒ Object
- #dom_nodes ⇒ Object
-
#first_element ⇒ Object
Walks the dom_nodes range until it finds an element.
- #go(url) ⇒ Object
-
#initialize(volt_app, *args) ⇒ ModelController
constructor
A new instance of ModelController.
-
#loaded? ⇒ Boolean
loaded? is a quick way to see if the model for the controller is loaded yet.
- #method_missing(method_name, *args, &block) ⇒ Object
- #model ⇒ Object
-
#model=(val) ⇒ Object
Sets the current model on this controller.
-
#raw(str) ⇒ Object
Raw marks a string as html safe, so bindings can be rendered as html.
-
#redirect_to(url) ⇒ Object
Change the url.
- #require_login(message = 'You must login to access this area.') ⇒ Object
-
#respond_to?(method_name) ⇒ Boolean
Check if this controller responds_to method, or the model.
- #trigger(event, *args) ⇒ Object
-
#u ⇒ Object
the u method provides an easy helper to render an unbonud binding.
-
#yield_html ⇒ Object
yield_html renders the content passed into a tag as a string.
Methods included from CollectionHelpers
#channel, #cookies, #flash, #local_store, #page, #params, #store, #tasks, #url, #url_for, #url_with
Methods included from LifecycleCallbacks
included, #run_callbacks, #stop_chain
Methods included from ReactiveAccessors
#__reactive_dependency_get, included
Constructor Details
#initialize(volt_app, *args) ⇒ ModelController
Returns a new instance of ModelController.
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/volt/controllers/model_controller.rb', line 166 def initialize(volt_app, *args) @volt_app = volt_app # Track that the initialize was called @__init_called = true default_model = self.class.default_model self.model = default_model if default_model if args[0] # Assign the first passed in argument to attrs self.attrs = args[0] # If a model attribute is passed in, we assign it directly self.model = attrs.locals[:model] if attrs.respond_to?(:model) end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args, &block) ⇒ Object
252 253 254 255 256 257 258 259 260 |
# File 'lib/volt/controllers/model_controller.rb', line 252 def method_missing(method_name, *args, &block) model = self.model if model model.send(method_name, *args, &block) else super end end |
Instance Attribute Details
#attrs ⇒ Object
Returns the value of attribute attrs.
164 165 166 |
# File 'lib/volt/controllers/model_controller.rb', line 164 def attrs @attrs end |
#section ⇒ Object
The section is assigned a reference to a “DomSection” which has the dom for the controllers view.
23 24 25 |
# File 'lib/volt/controllers/model_controller.rb', line 23 def section @section end |
Class Method Details
.model(val) ⇒ Object
100 101 102 |
# File 'lib/volt/controllers/model_controller.rb', line 100 def self.model(val) self.default_model = val end |
.new(volt_app, *args, &block) ⇒ Object
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/volt/controllers/model_controller.rb', line 147 def self.new(volt_app, *args, &block) inst = allocate # In MRI initialize is private for some reason, so call it with send inst.send(:initialize, volt_app, *args, &block) if inst.instance_variable_get('@__init_called') inst.instance_variable_set('@__init_called', nil) else # Initialize was not called, we should warn since this is probably not # the intended behavior. Volt.logger.warn("super should be called when creating a custom initialize on class #{inst.class.to_s}") end inst end |
Instance Method Details
#container ⇒ Object
Container returns the node that is parent to all nodes in the section.
29 30 31 32 |
# File 'lib/volt/controllers/model_controller.rb', line 29 def container check_section!('container') section.container_node end |
#controller ⇒ Object
200 201 202 |
# File 'lib/volt/controllers/model_controller.rb', line 200 def controller @controller ||= Model.new end |
#dom_nodes ⇒ Object
34 35 36 37 |
# File 'lib/volt/controllers/model_controller.rb', line 34 def dom_nodes check_section!('dom_nodes') section.range end |
#first_element ⇒ Object
Walks the dom_nodes range until it finds an element. Typically this will be the container element without the whitespace text nodes.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/volt/controllers/model_controller.rb', line 41 def first_element check_section!('first_element') range = dom_nodes nodes = `range.startContainer.childNodes` start_index = `range.startOffset` end_index = `range.endOffset` start_index.upto(end_index) do |index| node = `nodes[index]` # Return if an element if `node.nodeType === 1` return node end end return nil end |
#go(url) ⇒ Object
185 186 187 188 189 |
# File 'lib/volt/controllers/model_controller.rb', line 185 def go(url) Volt.logger.warn('Deprecation warning: `go` has been renamed to `redirect_to` for consistency with other frameworks.') redirect_to(url) end |
#loaded? ⇒ Boolean
loaded? is a quick way to see if the model for the controller is loaded yet. If the model is there, it asks the model if its loaded. If the model was set to a promise, it waits for the promise to resolve.
207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/volt/controllers/model_controller.rb', line 207 def loaded? if model.respond_to?(:loaded?) # There is a model and it is loaded return model.loaded? elsif last_promise || model.is_a?(Promise) # The model is a promise or is resolving return false else # Otherwise, its loaded return true end end |
#model ⇒ Object
138 139 140 141 142 143 144 145 |
# File 'lib/volt/controllers/model_controller.rb', line 138 def model model = self.current_model # If the model is a proc, call it now model = model.call if model && model.is_a?(Proc) model end |
#model=(val) ⇒ Object
Sets the current model on this controller
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 136 |
# File 'lib/volt/controllers/model_controller.rb', line 105 def model=(val) if val.is_a?(Promise) # Resolve the promise before setting self.last_promise = val val.then do |result| # Only assign if nothing else has been assigned since we started the resolve self.model = result if last_promise == val end.fail do |err| Volt.logger.error("Unable to resolve promise assigned to model on #{inspect}") end return end # Clear self.last_promise = nil # Start with a nil reactive value. self.current_model ||= Model.new if Symbol === val || String === val collections = [:page, :store, :params, :controller] if collections.include?(val.to_sym) self.current_model = send(val) else fail "#{val} is not the name of a valid model, choose from: #{collections.join(', ')}" end else self.current_model = val end end |
#raw(str) ⇒ Object
Raw marks a string as html safe, so bindings can be rendered as html. With great power comes great responsibility.
231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/volt/controllers/model_controller.rb', line 231 def raw(str) # Promises need to have .to_s called using .then, since .to_s is a promise # method, so it won't be passed down to the value. if str.is_a?(Promise) str = str.then(&:to_s) else str = str.to_s unless str.is_a?(String) end str.html_safe end |
#redirect_to(url) ⇒ Object
Change the url
192 193 194 195 196 197 198 |
# File 'lib/volt/controllers/model_controller.rb', line 192 def redirect_to(url) # We might be in the rendering loop, so wait until the next tick before # we change the url Timers.next_tick do self.url.parse(url) end end |
#require_login(message = 'You must login to access this area.') ⇒ Object
220 221 222 223 224 225 226 227 |
# File 'lib/volt/controllers/model_controller.rb', line 220 def require_login( = 'You must login to access this area.') unless Volt.current_user_id flash._notices << redirect_to '/login' stop_chain end end |
#respond_to?(method_name) ⇒ Boolean
Check if this controller responds_to method, or the model
244 245 246 247 248 249 250 |
# File 'lib/volt/controllers/model_controller.rb', line 244 def respond_to?(method_name) super || begin model = self.model model.respond_to?(method_name) if model end end |
#trigger(event, *args) ⇒ Object
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/volt/controllers/model_controller.rb', line 82 def trigger(event, *args) # Trigger on the current controller if an e- was setup on the component. component_event = attrs.send(:"e_#{event}") if component_event # Add a nil arg for the event, trim to arity args2 = (args + [nil])[0...component_event.arity] component_event.call(*args2) end args.unshift(self) # Trigger via jquery, so it bubbles up through the DOM `$(#{first_element}).trigger(#{event}, #{args});` # return nil, so we return a ruby object nil end |
#u ⇒ Object
the u method provides an easy helper to render an unbonud binding. This means that the binding will not reactively update. If no bindings are bound on any model’s from a query, the query will not be reactively listened to.
65 66 67 68 |
# File 'lib/volt/controllers/model_controller.rb', line 65 def u raise "the 'u' method requires a block" unless block_given? Volt::Computation.run_without_tracking { yield } end |
#yield_html ⇒ Object
yield_html renders the content passed into a tag as a string. You can “‘.watch!“` “`yield_html“` and it will be run again when anything in the template changes.
72 73 74 75 76 77 78 79 80 |
# File 'lib/volt/controllers/model_controller.rb', line 72 def yield_html if (template_path = attrs.content_template_path) @yield_renderer ||= StringTemplateRenderer.new(@volt_app, attrs.content_controller, template_path) @yield_renderer.html else # no template, empty string '' end end |