apotomo 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES.textile ADDED
@@ -0,0 +1,8 @@
1
+ h2. 1.0.2
2
+
3
+ h3. Changes
4
+ * removals from ViewHelper: #trigger_event, #form_to_event and friends as they use deprecated Rails helpers.
5
+
6
+ h3. Bugfixes
7
+ * Widget#fire now accepts payload data for the fired event.
8
+ * triggered states now receive the event object if they expect one argument.
data/Gemfile CHANGED
@@ -1,9 +1,12 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gem "rails", "~> 3.0.0"
4
- gem "cells", "~> 3.4"
5
- gem "onfire"
6
- gem "hooks", "~> 0.1.3"
3
+ gem "rails", "~> 3.0"
4
+ #gem "rails", :path => "/home/nick/projects/rayls"
5
+
6
+ gem "cells", "~> 3.4"
7
+ gem "onfire", "~> 0.1.1"
8
+ gem "hooks", "~> 0.1.3"
9
+
7
10
 
8
11
 
9
12
  gem "jeweler"
data/README.rdoc CHANGED
@@ -22,7 +22,7 @@ Easy as hell.
22
22
 
23
23
  === Rails 3
24
24
 
25
- gem install apotomo --pre
25
+ gem install apotomo
26
26
 
27
27
  === Rails 2.3
28
28
 
data/Rakefile CHANGED
@@ -34,7 +34,7 @@ Jeweler::Tasks.new do |spec|
34
34
  spec.test_files = FileList["test/**/*"] - FileList["test/dummy/tmp", "test/dummy/tmp/**/*", "test/dummy/log/*"]
35
35
 
36
36
  spec.add_dependency 'cells', '~> 3.4.2'
37
- spec.add_dependency 'rails', '>= 3.0.0'
37
+ spec.add_dependency 'rails', '~> 3.0.0'
38
38
  spec.add_dependency 'onfire', '>= 0.1.0'
39
39
  spec.add_dependency 'hooks', '~> 0.1.3'
40
40
  end
@@ -2,19 +2,19 @@ require 'apotomo/event_handler'
2
2
 
3
3
  module Apotomo
4
4
  # Introduces event-processing functions into the StatefulWidget.
5
-
6
5
  module EventMethods
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ after_initialize :add_class_event_handlers
10
+ end
11
+
7
12
  attr_writer :page_updates
8
- # Replacement for the EventProcessor singleton queue.
13
+
9
14
  def page_updates
10
15
  @page_updates ||= []
11
16
  end
12
17
 
13
- def self.included(base)
14
- base.extend(ClassMethods)
15
- base.after_initialize :add_class_event_handlers
16
- end
17
-
18
18
  def add_class_event_handlers(*)
19
19
  self.class.responds_to_event_options.each { |options| respond_to_event(*options) }
20
20
  end
@@ -34,66 +34,55 @@ module Apotomo
34
34
  # state, which implies an update of the invoked widget.
35
35
  #
36
36
  # You may configure the event handler with the following <tt>options</tt>:
37
- # :with => (required) the state to invoke on the target widget
37
+ # :with => (optional) the state to invoke on the target widget, defaults to +type+.
38
38
  # :on => (optional) the targeted widget's id, defaults to <tt>self.name</tt>
39
39
  # :from => (optional) the source id of the widget that triggered the event, defaults to any widget
40
40
  #
41
41
  # Example:
42
42
  #
43
- # trap = cell(:input_field, :smell_like_cheese, 'mouse_trap')
43
+ # trap = widget(:trap, :charged, 'mouse_trap')
44
44
  # trap.respond_to_event :mouseOver, :with => :catch_mouse
45
45
  #
46
- # This would instruct <tt>trap</tt> to catch a <tt>:mouseOver</tt> event from any widget (including itself) and
46
+ # This would instruct +trap+ to catch a <tt>:mouseOver</tt> event from any widget (including itself) and
47
47
  # to invoke the state <tt>:catch_mouse</tt> on itself as trigger.
48
48
  #
49
49
  #
50
- # hunter = cell(:form, :hunt_for_mice, 'my_form')
51
- # hunter << cell(:input_field, :smell_like_cheese, 'mouse_trap')
52
- # hunter << cell(:text_area, :stick_like_honey, 'bear_trap')
50
+ # hunter = widget(:form, :hunt_for_mice, 'my_form')
51
+ # hunter << widget(:input_field, :smell_like_cheese, 'mouse_trap')
52
+ # hunter << widget(:text_area, :stick_like_honey, 'bear_trap')
53
53
  # hunter.respond_to_event :captured, :from => 'mouse_trap', :with => :refill_cheese, :on => 'mouse_trap'
54
54
  #
55
55
  # As both the bear- and the mouse trap can trigger a <tt>:captured</tt> event the later <tt>respond_to_event</tt>
56
56
  # would invoke <tt>:refill_cheese</tt> on the <tt>mouse_trap</tt> widget as soon as this and only this widget fired.
57
57
  # It is important to understand the <tt>:from</tt> parameter as it filters the event source - it wouldn't make
58
- # sense to refill the mouse trap if the bear trap snapped, would it?
59
-
60
- def respond_to_event(type, options)
61
- options[:once] = true if options[:once].nil?
58
+ # sense to refill the mouse trap if the bear trap snapped, would it?
59
+ def respond_to_event(type, options={})
60
+ options.reverse_merge!( :once => true,
61
+ :with => type,
62
+ :on => self.name )
62
63
 
63
- handler_opts = {}
64
- handler_opts[:widget_id] = options[:on] || self.name
65
- handler_opts[:state] = options[:with]
66
-
67
- handler = InvokeEventHandler.new(handler_opts)
64
+ handler = InvokeEventHandler.new(:widget_id => options[:on], :state => options[:with])
68
65
 
69
66
  return if options[:once] and event_table.all_handlers_for(type, options[:from]).include?(handler)
70
67
 
71
68
  on(type, :do => handler, :from => options[:from])
72
69
  end
73
70
 
71
+ # Fire an event of +type+ and let it bubble up. You may add arbitrary payload data to the event.
72
+ #
73
+ # Example:
74
+ #
75
+ # trigger(:dropped, :area => 59)
76
+ #
77
+ # which can be queried in a triggered state.
78
+ #
79
+ # def on_drop(event)
80
+ # if event.data[:area] == 59
74
81
  def trigger(*args)
75
82
  fire(*args)
76
83
  end
77
84
 
78
- # Invokes <tt>state</tt> on the widget <em>and</end> updates itself on the page. This should
79
- # never be called from outside but in setters when some internal value changed and must be
80
- # displayed instantly.
81
- #
82
- # Implements the following pattern (TODO: remove example as soon as invoke! proofed):
83
- #
84
- # def title=(str)
85
- # @title = str
86
- # peek(:update, self.name, :display, self.name)
87
- # trigger(:update)
88
- # end
89
- def invoke!(state)
90
- ### TODO: encapsulate in PageUpdateQueue:
91
- Apotomo::EventProcessor.instance.processed_handlers << [name, invoke(:state)]
92
- end
93
-
94
-
95
-
96
- protected
85
+ protected
97
86
  # Get all handlers from self for the passed event (overriding Onfire#local_event_handlers).
98
87
  def local_event_handlers(event)
99
88
  event_table.all_handlers_for(event.type, event.source.name) # we key with widget_id.
@@ -10,13 +10,7 @@ module Apotomo
10
10
  def process_event(event)
11
11
  target = event.source.root.find_by_path(widget_id) ### DISCUSS: widget_id or widget_selector?
12
12
 
13
- #::Rails.logger.debug "EventHandler: invoking #{target.name}##{state}"
14
- ### DISCUSS: let target access event?
15
- ### pass additional opts to #invoke?
16
- ### DISCUSS: pass block here?
17
- target.opts[:event] = event
18
-
19
- target.invoke(state)
13
+ target.invoke(state, event)
20
14
  end
21
15
 
22
16
  def to_s; "InvokeEventHandler:#{widget_id}##{state}"; end
@@ -5,19 +5,17 @@ require 'apotomo/rails/view_methods'
5
5
  module Rails
6
6
  module ControllerMethods
7
7
  include WidgetShortcuts
8
+ extend ActiveSupport::Concern
8
9
 
9
- def self.included(base) #:nodoc:
10
- base.class_eval do
11
- extend WidgetShortcuts
12
- extend ClassMethods
13
-
14
- class_inheritable_array :has_widgets_blocks
15
- self.has_widgets_blocks = []
16
-
17
- helper ::Apotomo::Rails::ViewMethods
18
-
19
- after_filter :apotomo_freeze
20
- end
10
+ included do
11
+ extend WidgetShortcuts
12
+
13
+ class_inheritable_array :has_widgets_blocks
14
+ self.has_widgets_blocks = []
15
+
16
+ helper ::Apotomo::Rails::ViewMethods
17
+
18
+ after_filter :apotomo_freeze
21
19
  end
22
20
 
23
21
  module ClassMethods
@@ -33,8 +31,6 @@ require 'apotomo/rails/view_methods'
33
31
  def has_widgets(&block)
34
32
  has_widgets_blocks << block
35
33
  end
36
-
37
- alias_method :uses_widgets, :has_widgets
38
34
  end
39
35
 
40
36
  def bound_use_widgets_blocks
@@ -138,25 +134,6 @@ with(window.parent) { setTimeout(function() { window.eval('#{escaped_script}');
138
134
  </script></body></html>", :content_type => 'text/html'
139
135
  end
140
136
 
141
- def respond_to_event(type, options)
142
- handler = ProcEventHandler.new
143
- handler.proc = options[:with]
144
- ### TODO: pass :from => (event source).
145
-
146
- # attach once, not every request:
147
- apotomo_root.evt_table.add_handler_once(handler, :event_type => type)
148
- end
149
-
150
-
151
-
152
- ### DISCUSS: rename? should say "this controller action wants apotomo's deep linking!"
153
- ### DISCUSS: move to deep_link_methods?
154
- def respond_to_url_change
155
- return if apotomo_root.find_widget('deep_link') # add only once.
156
- apotomo_root << widget("apotomo/deep_link_widget", :setup, 'deep_link')
157
- end
158
-
159
-
160
137
  class ProcHash < Array
161
138
  def id_for_proc(proc)
162
139
  proc.to_s.split('@').last
@@ -7,31 +7,7 @@ module Apotomo
7
7
  def js_generator
8
8
  Apotomo.js_generator
9
9
  end
10
-
11
-
12
- # Generates the JavaScript code to report an event of <tt>type</tt> to Apotomo with AJAX.
13
- # As always per default the event source is the currently rendered widget.
14
- # Internally this method just uses <tt>remote_function</tt> for JS output.
15
- #
16
- # Example:
17
- #
18
- # <%= image_tag "cheese.png", :onMouseover => trigger_event(:mouseAlarm) %>
19
- #
20
- # will trigger the event <tt>:mouseAlarm</tt> when moving the mouse over the cheese image.
21
- def trigger_event(type, options={})
22
- js_generator.xhr(url_for_event(type, options))
23
- end
24
-
25
- # Creates a form tag that triggers an event via AJAX when submitted.
26
- # See StatefulWidget::address_for_event for options.
27
- #
28
- # The values of form elements are available via StatefulWidget#param.
29
- def form_to_event(type, options={}, html_options={}, &block)
30
- return multipart_form_to_event(type, options, html_options, &block) if options.delete(:multipart)
31
-
32
- form_remote_tag({:url => url_for_event(type, options), :html => html_options}, &block)
33
- end
34
-
10
+
35
11
  # Creates a form that submits itself via an iFrame and executes the response
36
12
  # in the parent window. This is needed to upload files via AJAX.
37
13
  #
@@ -53,12 +29,7 @@ module Apotomo
53
29
  # url_for_event(:paginate, :page => 2)
54
30
  # #=> http://apotomo.de/mouse/process_event_request?type=paginate&source=mouse&page=2
55
31
  def url_for_event(type, options={})
56
- @cell.url_for_event(type, options)
57
- end
58
-
59
- ### TODO: test me.
60
- def update_url(fragment)
61
- 'SWFAddress.setValue("' + fragment + '");'
32
+ controller.url_for_event(type, options)
62
33
  end
63
34
 
64
35
  ### TODO: test me.
@@ -93,7 +64,7 @@ module Apotomo
93
64
 
94
65
  # Returns the widget id you passed in a has_widgets block.
95
66
  def widget_id
96
- @cell.name
67
+ controller.name
97
68
  end
98
69
  end
99
70
  end
@@ -1,3 +1,3 @@
1
1
  module Apotomo
2
- VERSION = '1.0.1'
2
+ VERSION = '1.0.2'
3
3
  end
@@ -31,8 +31,6 @@ module Apotomo
31
31
  attr_accessor :opts
32
32
  attr_writer :visible
33
33
 
34
- attr_writer :controller
35
-
36
34
  include TreeNode
37
35
 
38
36
  include Onfire
@@ -43,6 +41,8 @@ module Apotomo
43
41
 
44
42
  helper Apotomo::Rails::ViewHelper
45
43
 
44
+ abstract!
45
+ undef :display # We don't want #display to be listed in #internal_methods.
46
46
 
47
47
  # Runs callbacks for +name+ hook in instance context.
48
48
  def run_widget_hook(name, *args)
@@ -80,8 +80,7 @@ module Apotomo
80
80
 
81
81
  # Returns the rendered content for the widget by running the state method for <tt>state</tt>.
82
82
  # This might lead us to some other state since the state method could call #jump_to_state.
83
- def invoke(state=nil, &block)
84
- @invoke_block = block ### DISCUSS: store block so we don't have to pass it 10 times?
83
+ def invoke(state=nil, event=nil)
85
84
  logger.debug "\ninvoke on #{name} with #{state.inspect}"
86
85
 
87
86
  if state.blank?
@@ -91,7 +90,12 @@ module Apotomo
91
90
  logger.debug "#{name}: transition: #{last_state} to #{state}"
92
91
  logger.debug " ...#{state}"
93
92
 
94
- render_state(state)
93
+ #render_state(state)
94
+
95
+ return process(state, event) if method(state).arity == 1
96
+
97
+ opts[:event] = event
98
+ process(state)
95
99
  end
96
100
 
97
101
 
@@ -236,7 +240,7 @@ module Apotomo
236
240
  def address_for_event(type, options={})
237
241
  options.reverse_merge! :source => name,
238
242
  :type => type,
239
- :controller => parent_controller.controller_name # DISCUSS: dependency to parent_controller.
243
+ :controller => parent_controller.controller_path # DISCUSS: dependency to parent_controller.
240
244
  end
241
245
 
242
246
  def url_for_event(type, options={})
@@ -38,6 +38,7 @@ module Apotomo
38
38
  container(*args)
39
39
  end
40
40
 
41
+ # TODO: deprecate.
41
42
  def cell(base_name, states, id, *args)
42
43
  widget(base_name.to_s + '_cell', states, id, *args)
43
44
  end
@@ -116,7 +116,7 @@ class ControllerMethodsTest < ActionController::TestCase
116
116
 
117
117
  context "invoking #url_for_event" do
118
118
  should "compute an url for any widget" do
119
- assert_equal "/barn/render_event_response?source=mouse&volume=9&type=footsteps", @controller.url_for_event(:footsteps, :source => :mouse, :volume => 9)
119
+ assert_equal "/barn/render_event_response?source=mouse&type=footsteps&volume=9", @controller.url_for_event(:footsteps, :source => :mouse, :volume => 9)
120
120
  end
121
121
  end
122
122
 
@@ -1,74 +1,92 @@
1
1
  require 'test_helper'
2
2
  require 'action_view/test_case'
3
3
 
4
- class ViewHelperTest < ActionView::TestCase
5
- include Apotomo::TestCaseMethods::TestController
4
+ class ViewHelperTest < Apotomo::TestCase
5
+ include ActionDispatch::Assertions::DomAssertions
6
+ include Apotomo::TestCase::TestController
6
7
 
7
- tests Apotomo::Rails::ViewHelper
8
-
9
- context "A widget state view" do
10
- setup do
11
- @cell = mouse_mock('mum')
8
+ # TODO: move to Apotomo::TestCase, refactor, test.
9
+ class MouseWidget < Apotomo::Widget
10
+ end
11
+ def in_view(subject, &block)
12
+ if subject.kind_of?(Apotomo::Widget)
13
+ subject.opts[:block] = block
14
+ else
15
+ subject = subject.new(@controller, 'mum', :display, :block => block)
12
16
  end
17
+
18
+ setup_test_states_in(subject) unless subject.respond_to?(:in_view)# add #in_view state to subject cell.
13
19
 
20
+ subject.class.action_methods << "in_view"
21
+
22
+ subject.invoke(:in_view)
23
+ end
24
+ def mouse_mock(id='mum', start_state=:eat, opts={}, &block)
25
+ mouse = MouseWidget.new(parent_controller, id, start_state, opts)
26
+ mouse.instance_eval &block if block_given?
27
+ mouse
28
+ end
29
+
30
+
31
+ context "A widget state view" do
14
32
  teardown do
15
33
  Apotomo.js_framework = :prototype
16
34
  end
17
35
 
18
-
19
- should "respond to #multipart_form_to_event" do
20
- assert_dom_equal "<iframe id=\"apotomo_iframe\" name=\"apotomo_iframe\" style=\"display: none;\"></iframe><form accept-charset=\"UTF-8\" action=\"/barn/render_event_response?apotomo_iframe=true&amp;source=mum&amp;type=footsteps\" enctype=\"multipart/form-data\" method=\"post\" target=\"apotomo_iframe\"><div style=\"margin:0;padding:0;display:inline\"><input name=\"utf8\" type=\"hidden\" value=\"&#x2713;\" /></div></form>",
21
- multipart_form_to_event(:footsteps)
22
- end
23
-
24
- should "render multipart form if :multipart => true" do
25
- assert_dom_equal "<iframe id=\"apotomo_iframe\" name=\"apotomo_iframe\" style=\"display: none;\"></iframe><form accept-charset=\"UTF-8\" action=\"/barn/render_event_response?apotomo_iframe=true&amp;source=mum&amp;type=footsteps\" enctype=\"multipart/form-data\" method=\"post\" target=\"apotomo_iframe\"><div style=\"margin:0;padding:0;display:inline\"><input name=\"utf8\" type=\"hidden\" value=\"&#x2713;\" /></div></form>",
26
- form_to_event(:footsteps, :multipart => true)
36
+ should_eventually "respond to #multipart_form_to_event" do
37
+ assert_dom_equal( "<iframe id=\"apotomo_iframe\" name=\"apotomo_iframe\" style=\"display: none;\"></iframe><form accept-charset=\"UTF-8\" action=\"/barn/render_event_response?apotomo_iframe=true&amp;source=mum&amp;type=footsteps\" enctype=\"multipart/form-data\" method=\"post\" target=\"apotomo_iframe\"><div style=\"margin:0;padding:0;display:inline\"><input name=\"utf8\" type=\"hidden\" value=\"&#x2713;\" /></div></form>",
38
+ in_view(MouseWidget) do
39
+ multipart_form_to_event(:footsteps)
40
+ end)
27
41
  end
28
42
 
29
- should "respond to #trigger_event" do
30
- assert_dom_equal "new Ajax.Request(\"/barn/render_event_response?source=mum&type=footsteps\")",
31
- trigger_event(:footsteps)
32
- end
33
-
34
- should "render RightJS if set" do
35
- Apotomo.js_framework = :right
36
-
37
- assert_dom_equal "new Xhr(\"/barn/render_event_response?source=mum&type=footsteps\", {evalScripts:true}).send()", trigger_event(:footsteps)
43
+ should "respond to #url_for_event" do
44
+ assert_equal("/barn/render_event_response?source=mum&amp;type=footsteps", in_view(MouseWidget) do
45
+ url_for_event(:footsteps)
46
+ end)
38
47
  end
39
48
 
40
- should "respond to #url_for_event" do
41
- assert_equal("/barn/render_event_response?source=mum&type=footsteps", url_for_event(:footsteps))
49
+ should "respond to #url_for_event with a namespaced controller" do
50
+ @controller = namespaced_controller
51
+ assert_equal("/farm/barn/render_event_response?source=mum&amp;type=footsteps", in_view(MouseWidget) do
52
+ url_for_event(:footsteps)
53
+ end)
42
54
  end
43
55
 
44
56
  should "respond to #widget_div" do
45
- assert_equal '<div id="mum">squeak!</div>', widget_div { "squeak!" }
57
+ assert_equal('<div id="mum">squeak!</div>', in_view(MouseWidget) do widget_div { "squeak!" } end)
46
58
  end
47
59
 
48
60
  should "respond to #widget_div with options" do
49
- assert_equal '<div class="mouse" id="kid">squeak!</div>', widget_div(:id => 'kid', :class => "mouse") { "squeak!" }
61
+ assert_equal('<div class="mouse" id="kid">squeak!</div>', in_view(MouseWidget) do
62
+ widget_div(:id => 'kid', :class => "mouse") { "squeak!" }
63
+ end)
50
64
  end
51
65
 
52
66
  should "respond to #widget_id" do
53
- assert_equal 'mum', widget_id
67
+ assert_equal('mum', in_view(MouseWidget){ widget_id })
54
68
  end
55
69
 
56
70
  context "#widget_javascript" do
57
71
 
58
72
  should "usually render a javascript block" do
59
- assert_equal "<script type=\"text/javascript\">\n//<![CDATA[\nalert(\"Beer!\")\n//]]>\n</script>", widget_javascript { 'alert("Beer!")' }
73
+ assert_equal("<script type=\"text/javascript\">\n//<![CDATA[\nalert(&quot;Beer!&quot;)\n//]]>\n</script>", in_view(MouseWidget) do
74
+ widget_javascript { 'alert("Beer!")' }
75
+ end)
60
76
  end
61
77
 
62
- should "be quiet if suppress_js is set" do
78
+ # FIXME: get the test running?
79
+ should_eventually "be quiet if suppress_js is set" do
63
80
  @suppress_js = true ### TODO: use a local, not an instance variable.
64
- assert_equal nil, widget_javascript { 'alert("Beer!")' }
65
- end
66
-
67
- should_eventually "capture" do
68
- puts "capturing"
69
- v = ActionView::Base.new
70
- c = v.capture do "capture me!" end
71
- puts c.inspect
81
+ mum = mouse_mock do
82
+ def in_view
83
+ render :suppress_js => true
84
+ end
85
+ end
86
+
87
+ assert_equal(nil, in_view(mum) do
88
+ widget_javascript { 'alert("Beer!")' }
89
+ end)
72
90
  end
73
91
  end
74
92
  end
@@ -71,25 +71,28 @@ module Apotomo
71
71
  # Creates a mock controller instance. Currently, each widget needs a parent controller instance due to some
72
72
  # sucky dependency in cells.
73
73
  def barn_controller!
74
- @controller = Class.new(ActionController::Base) do
75
- def initialize
76
- extend ActionController::UrlWriter
77
- self.params = {}
74
+ @controller = Class.new(ApotomoController) do
75
+ def initialize(*)
76
+ super
78
77
  self.request = ActionController::TestRequest.new
79
78
  end
80
79
 
81
80
  def self.name; "BarnController"; end
82
81
 
83
82
  def self.default_url_options; {:controller => :barn}; end
84
- include Apotomo::Rails::ControllerMethods
85
83
  end.new
86
- ### FIXME: @controller.session = {}
87
84
  end
88
85
 
89
86
  def parent_controller
90
87
  @controller
91
88
  end
92
89
 
90
+ def namespaced_controller
91
+ controller = Farm::BarnController.new
92
+ controller.request = ActionController::TestRequest.new
93
+ controller
94
+ end
95
+
93
96
  end
94
97
  end
95
98
  end
data/test/test_helper.rb CHANGED
@@ -29,12 +29,29 @@ end
29
29
 
30
30
  class ApotomoController < ActionController::Base
31
31
  include Apotomo::Rails::ControllerMethods
32
+ include Rails.application.routes.url_helpers
32
33
  end
33
34
 
35
+ module Farm
36
+ class BarnController < ApotomoController
37
+ end
38
+ end
39
+
40
+
34
41
  class MouseCell < Apotomo::StatefulWidget
35
42
  def eating; render; end
43
+ def squeak; render; end
44
+ def educate; render; end
45
+ def snooze; render; end
46
+ def listen; render; end
47
+ def answer_squeak; render; end
48
+ def peek; render; end
49
+ def alert; end
50
+ def escape; end
51
+ def snuggle; end
36
52
  end
37
53
 
54
+ ### TODO: 2brm?
38
55
  class RenderingTestCell < Apotomo::StatefulWidget
39
56
  attr_reader :brain
40
57
  attr_reader :rendered_children
@@ -48,6 +65,6 @@ end
48
65
 
49
66
 
50
67
  # Enable dynamic states so we can do Cell.class_eval { def ... } at runtime.
51
- class Apotomo::Widget
68
+ Apotomo::Widget.class_eval do
52
69
  def action_method?(*); true; end
53
70
  end
@@ -39,6 +39,38 @@ class EventMethodsTest < Test::Unit::TestCase
39
39
  assert_equal ['answer squeak', 'answer squeak'], @mum.list
40
40
  end
41
41
 
42
+ should "also accept an event argument only" do
43
+ @mum.respond_to_event :answer_squeak
44
+ @mum.fire :answer_squeak
45
+ assert_equal ['answer squeak'], @mum.list
46
+ end
47
+
48
+ should "make pass the event into the triggered state" do
49
+ @mum.instance_eval do
50
+ respond_to_event :footsteps
51
+
52
+ def footsteps(evt)
53
+ list << evt.type
54
+ end
55
+ end
56
+
57
+ @mum.trigger :footsteps
58
+ assert_equal ["escape", :footsteps], @mum.list
59
+ end
60
+
61
+ should "accept payload data for the event" do
62
+ @mum.respond_to_event :answer_squeak
63
+ @mum.instance_eval do
64
+ def answer_squeak
65
+ evt = @opts[:event]
66
+ list << evt.data
67
+ end
68
+ end
69
+
70
+ @mum.fire :answer_squeak, :volume => 9
71
+ assert_equal [{:volume => 9}], @mum.list
72
+ end
73
+
42
74
  context "#responds_to_event in class context" do
43
75
  setup do
44
76
  class AdultMouseCell < MouseCell
@@ -58,7 +90,6 @@ class EventMethodsTest < Test::Unit::TestCase
58
90
  end
59
91
  end
60
92
 
61
-
62
93
  context "#trigger" do
63
94
  should "be an alias for #fire" do
64
95
  @kid.trigger :footsteps
@@ -77,7 +108,6 @@ class EventMethodsTest < Test::Unit::TestCase
77
108
  @mum.fire :footsteps
78
109
  assert_equal ["escape"], @mum.page_updates
79
110
  end
80
-
81
111
  end
82
112
 
83
113
  end
@@ -44,8 +44,6 @@ class InvokeTest < Test::Unit::TestCase
44
44
 
45
45
  should "automatically follow the transitions if defined" do
46
46
  assert_equal 'snuggle', @mum.last_state
47
- puts "invoooooooooooooogue"
48
- puts @mum.last_state.inspect
49
47
  @mum.invoke
50
48
  assert_equal 'educate', @mum.last_state
51
49
  end
@@ -75,6 +75,11 @@ class WidgetTest < ActiveSupport::TestCase
75
75
  should "accept arbitrary options" do
76
76
  assert_equal({:volume=>"loud", :source=>"mum", :type=>:squeak, :controller=>"barn"}, @mum.address_for_event(:squeak, :volume => 'loud'))
77
77
  end
78
+
79
+ should "work with controller namespaces" do
80
+ @mum = Apotomo::Widget.new(namespaced_controller, 'mum', :squeak)
81
+ assert_equal({:source=>"mum", :type=>:squeak, :controller=>"farm/barn"}, @mum.address_for_event(:squeak))
82
+ end
78
83
  end
79
84
 
80
85
  context "implementing visibility" do
@@ -132,5 +137,20 @@ class WidgetTest < ActiveSupport::TestCase
132
137
  assert_equal 'shrew', @mum.param(:type)
133
138
  assert_equal 'Logitech', @mum.param(:brand)
134
139
  end
140
+
141
+
142
+ # internal_methods:
143
+ should "not list internal methods in action_methods" do
144
+ assert_equal [], Class.new(Apotomo::Widget).action_methods
145
+ end
146
+
147
+ should "list both local and inherited states in Widget.action_methods" do
148
+ assert MouseCell.action_methods.collect{ |m| m.to_s }.include?("eating")
149
+ assert Class.new(MouseCell).action_methods.collect{ |m| m.to_s }.include?("eating")
150
+ end
151
+
152
+ should "not list #display in internal_methods although it's defined in Object" do
153
+ assert_not Apotomo::Widget.internal_methods.include?(:display)
154
+ end
135
155
  end
136
156
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 1
7
7
  - 0
8
- - 1
9
- version: 1.0.1
8
+ - 2
9
+ version: 1.0.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Nick Sutterer
@@ -14,13 +14,138 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-11-21 00:00:00 +01:00
17
+ date: 2011-01-06 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
- name: cells
21
+ name: rails
22
22
  prerelease: false
23
23
  requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 3
30
+ - 0
31
+ version: "3.0"
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: cells
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 3
44
+ - 4
45
+ version: "3.4"
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: onfire
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 0
58
+ - 1
59
+ - 1
60
+ version: 0.1.1
61
+ type: :runtime
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: hooks
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ~>
70
+ - !ruby/object:Gem::Version
71
+ segments:
72
+ - 0
73
+ - 1
74
+ - 3
75
+ version: 0.1.3
76
+ type: :runtime
77
+ version_requirements: *id004
78
+ - !ruby/object:Gem::Dependency
79
+ name: jeweler
80
+ prerelease: false
81
+ requirement: &id005 !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ type: :runtime
90
+ version_requirements: *id005
91
+ - !ruby/object:Gem::Dependency
92
+ name: shoulda
93
+ prerelease: false
94
+ requirement: &id006 !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ segments:
100
+ - 0
101
+ version: "0"
102
+ type: :runtime
103
+ version_requirements: *id006
104
+ - !ruby/object:Gem::Dependency
105
+ name: mocha
106
+ prerelease: false
107
+ requirement: &id007 !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ segments:
113
+ - 0
114
+ version: "0"
115
+ type: :runtime
116
+ version_requirements: *id007
117
+ - !ruby/object:Gem::Dependency
118
+ name: sqlite3-ruby
119
+ prerelease: false
120
+ requirement: &id008 !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - "="
124
+ - !ruby/object:Gem::Version
125
+ segments:
126
+ - 1
127
+ - 2
128
+ - 5
129
+ version: 1.2.5
130
+ type: :runtime
131
+ version_requirements: *id008
132
+ - !ruby/object:Gem::Dependency
133
+ name: capybara
134
+ prerelease: false
135
+ requirement: &id009 !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ segments:
141
+ - 0
142
+ version: "0"
143
+ type: :runtime
144
+ version_requirements: *id009
145
+ - !ruby/object:Gem::Dependency
146
+ name: cells
147
+ prerelease: false
148
+ requirement: &id010 !ruby/object:Gem::Requirement
24
149
  none: false
25
150
  requirements:
26
151
  - - ~>
@@ -31,14 +156,14 @@ dependencies:
31
156
  - 2
32
157
  version: 3.4.2
33
158
  type: :runtime
34
- version_requirements: *id001
159
+ version_requirements: *id010
35
160
  - !ruby/object:Gem::Dependency
36
161
  name: rails
37
162
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
163
+ requirement: &id011 !ruby/object:Gem::Requirement
39
164
  none: false
40
165
  requirements:
41
- - - ">="
166
+ - - ~>
42
167
  - !ruby/object:Gem::Version
43
168
  segments:
44
169
  - 3
@@ -46,11 +171,11 @@ dependencies:
46
171
  - 0
47
172
  version: 3.0.0
48
173
  type: :runtime
49
- version_requirements: *id002
174
+ version_requirements: *id011
50
175
  - !ruby/object:Gem::Dependency
51
176
  name: onfire
52
177
  prerelease: false
53
- requirement: &id003 !ruby/object:Gem::Requirement
178
+ requirement: &id012 !ruby/object:Gem::Requirement
54
179
  none: false
55
180
  requirements:
56
181
  - - ">="
@@ -61,11 +186,11 @@ dependencies:
61
186
  - 0
62
187
  version: 0.1.0
63
188
  type: :runtime
64
- version_requirements: *id003
189
+ version_requirements: *id012
65
190
  - !ruby/object:Gem::Dependency
66
191
  name: hooks
67
192
  prerelease: false
68
- requirement: &id004 !ruby/object:Gem::Requirement
193
+ requirement: &id013 !ruby/object:Gem::Requirement
69
194
  none: false
70
195
  requirements:
71
196
  - - ~>
@@ -76,7 +201,7 @@ dependencies:
76
201
  - 3
77
202
  version: 0.1.3
78
203
  type: :runtime
79
- version_requirements: *id004
204
+ version_requirements: *id013
80
205
  description: Web component framework for Rails providing page widgets that trigger events and know when and how to update themselves with AJAX.
81
206
  email: apotonick@gmail.com
82
207
  executables: []
@@ -87,6 +212,7 @@ extra_rdoc_files:
87
212
  - README.rdoc
88
213
  - TODO
89
214
  files:
215
+ - CHANGES.textile
90
216
  - Gemfile
91
217
  - README.rdoc
92
218
  - Rakefile
@@ -119,78 +245,78 @@ files:
119
245
  - lib/generators/apotomo/templates/widget_test.rb
120
246
  - lib/generators/apotomo/widget_generator.rb
121
247
  - lib/tasks.rake
122
- - test/fixtures/mouse/feed.html.erb
123
- - test/fixtures/mouse/eating.html.erb
124
- - test/fixtures/mouse/make_me_squeak.html.erb
125
- - test/fixtures/mouse/posing.html.erb
126
- - test/fixtures/mouse/educate.html.erb
127
- - test/fixtures/mouse/snuggle.html.erb
128
- - test/fixtures/mouse/content.html.erb
129
- - test/fixtures/application_widget_tree.rb
130
- - test/rails/view_methods_test.rb
131
- - test/rails/controller_methods_test.rb
132
- - test/rails/view_helper_test.rb
133
- - test/rails/widget_generator_test.rb
134
- - test/rails/rails_integration_test.rb
135
- - test/test_helper.rb
136
- - test/support/test_case_methods.rb
248
+ - test/dummy/Rakefile
249
+ - test/dummy/app/controllers/application_controller.rb
250
+ - test/dummy/app/helpers/application_helper.rb
251
+ - test/dummy/app/views/layouts/application.html.erb
252
+ - test/dummy/config.ru
137
253
  - test/dummy/config/application.rb
138
- - test/dummy/config/initializers/session_store.rb
139
- - test/dummy/config/initializers/mime_types.rb
140
- - test/dummy/config/initializers/secret_token.rb
141
- - test/dummy/config/initializers/inflections.rb
142
- - test/dummy/config/initializers/backtrace_silencers.rb
143
- - test/dummy/config/locales/en.yml
144
- - test/dummy/config/routes.rb
145
254
  - test/dummy/config/boot.rb
255
+ - test/dummy/config/database.yml
146
256
  - test/dummy/config/environment.rb
257
+ - test/dummy/config/environments/development.rb
147
258
  - test/dummy/config/environments/production.rb
148
259
  - test/dummy/config/environments/test.rb
149
- - test/dummy/config/environments/development.rb
150
- - test/dummy/config/database.yml
151
- - test/dummy/script/rails
152
- - test/dummy/config.ru
260
+ - test/dummy/config/initializers/backtrace_silencers.rb
261
+ - test/dummy/config/initializers/inflections.rb
262
+ - test/dummy/config/initializers/mime_types.rb
263
+ - test/dummy/config/initializers/secret_token.rb
264
+ - test/dummy/config/initializers/session_store.rb
265
+ - test/dummy/config/locales/en.yml
266
+ - test/dummy/config/routes.rb
153
267
  - test/dummy/db/test.sqlite3
154
- - test/dummy/Rakefile
268
+ - test/dummy/public/404.html
155
269
  - test/dummy/public/422.html
156
- - test/dummy/public/favicon.ico
157
270
  - test/dummy/public/500.html
158
- - test/dummy/public/404.html
159
- - test/dummy/public/javascripts/controls.js
271
+ - test/dummy/public/favicon.ico
160
272
  - test/dummy/public/javascripts/application.js
161
- - test/dummy/public/javascripts/rails.js
273
+ - test/dummy/public/javascripts/controls.js
162
274
  - test/dummy/public/javascripts/dragdrop.js
163
- - test/dummy/public/javascripts/prototype.js
164
275
  - test/dummy/public/javascripts/effects.js
165
- - test/dummy/app/controllers/application_controller.rb
166
- - test/dummy/app/views/layouts/application.html.erb
167
- - test/dummy/app/helpers/application_helper.rb
276
+ - test/dummy/public/javascripts/prototype.js
277
+ - test/dummy/public/javascripts/rails.js
278
+ - test/dummy/script/rails
279
+ - test/fixtures/application_widget_tree.rb
280
+ - test/fixtures/mouse/content.html.erb
281
+ - test/fixtures/mouse/eating.html.erb
282
+ - test/fixtures/mouse/educate.html.erb
283
+ - test/fixtures/mouse/feed.html.erb
284
+ - test/fixtures/mouse/make_me_squeak.html.erb
285
+ - test/fixtures/mouse/posing.html.erb
286
+ - test/fixtures/mouse/snuggle.html.erb
287
+ - test/rails/controller_methods_test.rb
288
+ - test/rails/rails_integration_test.rb
289
+ - test/rails/view_helper_test.rb
290
+ - test/rails/view_methods_test.rb
291
+ - test/rails/widget_generator_test.rb
292
+ - test/support/test_case_methods.rb
293
+ - test/test_helper.rb
294
+ - test/unit/apotomo_test.rb
295
+ - test/unit/container_test.rb
168
296
  - test/unit/event_handler_test.rb
169
- - test/unit/widget_shortcuts_test.rb
170
- - test/unit/stateful_widget_test.rb
171
- - test/unit/test_addressing.rb
297
+ - test/unit/event_methods_test.rb
298
+ - test/unit/event_test.rb
172
299
  - test/unit/invoke_test.rb
173
- - test/unit/container_test.rb
174
- - test/unit/test_tab_panel.rb
175
- - test/unit/test_jump_to_state.rb
176
- - test/unit/render_test.rb
177
- - test/unit/test_case_test.rb
178
- - test/unit/apotomo_test.rb
179
- - test/unit/request_processor_test.rb
180
300
  - test/unit/javascript_generator_test.rb
181
301
  - test/unit/onfire_integration_test.rb
182
302
  - test/unit/persistence_test.rb
303
+ - test/unit/render_test.rb
304
+ - test/unit/request_processor_test.rb
305
+ - test/unit/stateful_widget_test.rb
306
+ - test/unit/test_addressing.rb
307
+ - test/unit/test_case_test.rb
308
+ - test/unit/test_jump_to_state.rb
309
+ - test/unit/test_tab_panel.rb
183
310
  - test/unit/transition_test.rb
184
- - test/unit/event_test.rb
185
- - test/unit/event_methods_test.rb
311
+ - test/unit/widget_shortcuts_test.rb
186
312
  - test/unit/widget_test.rb
187
313
  has_rdoc: true
188
314
  homepage: http://apotomo.de
189
315
  licenses: []
190
316
 
191
317
  post_install_message:
192
- rdoc_options:
193
- - --charset=UTF-8
318
+ rdoc_options: []
319
+
194
320
  require_paths:
195
321
  - lib
196
322
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -217,68 +343,68 @@ signing_key:
217
343
  specification_version: 3
218
344
  summary: Web components for Rails.
219
345
  test_files:
220
- - test/fixtures/mouse/feed.html.erb
221
- - test/fixtures/mouse/eating.html.erb
222
- - test/fixtures/mouse/make_me_squeak.html.erb
223
- - test/fixtures/mouse/posing.html.erb
224
- - test/fixtures/mouse/educate.html.erb
225
- - test/fixtures/mouse/snuggle.html.erb
226
- - test/fixtures/mouse/content.html.erb
227
- - test/fixtures/application_widget_tree.rb
228
- - test/rails/view_methods_test.rb
229
- - test/rails/controller_methods_test.rb
230
- - test/rails/view_helper_test.rb
231
- - test/rails/widget_generator_test.rb
232
- - test/rails/rails_integration_test.rb
233
- - test/test_helper.rb
234
- - test/support/test_case_methods.rb
346
+ - test/dummy/Rakefile
347
+ - test/dummy/app/controllers/application_controller.rb
348
+ - test/dummy/app/helpers/application_helper.rb
349
+ - test/dummy/app/views/layouts/application.html.erb
350
+ - test/dummy/config.ru
235
351
  - test/dummy/config/application.rb
236
- - test/dummy/config/initializers/session_store.rb
237
- - test/dummy/config/initializers/mime_types.rb
238
- - test/dummy/config/initializers/secret_token.rb
239
- - test/dummy/config/initializers/inflections.rb
240
- - test/dummy/config/initializers/backtrace_silencers.rb
241
- - test/dummy/config/locales/en.yml
242
- - test/dummy/config/routes.rb
243
352
  - test/dummy/config/boot.rb
353
+ - test/dummy/config/database.yml
244
354
  - test/dummy/config/environment.rb
355
+ - test/dummy/config/environments/development.rb
245
356
  - test/dummy/config/environments/production.rb
246
357
  - test/dummy/config/environments/test.rb
247
- - test/dummy/config/environments/development.rb
248
- - test/dummy/config/database.yml
249
- - test/dummy/script/rails
250
- - test/dummy/config.ru
358
+ - test/dummy/config/initializers/backtrace_silencers.rb
359
+ - test/dummy/config/initializers/inflections.rb
360
+ - test/dummy/config/initializers/mime_types.rb
361
+ - test/dummy/config/initializers/secret_token.rb
362
+ - test/dummy/config/initializers/session_store.rb
363
+ - test/dummy/config/locales/en.yml
364
+ - test/dummy/config/routes.rb
251
365
  - test/dummy/db/test.sqlite3
252
- - test/dummy/Rakefile
366
+ - test/dummy/public/404.html
253
367
  - test/dummy/public/422.html
254
- - test/dummy/public/favicon.ico
255
368
  - test/dummy/public/500.html
256
- - test/dummy/public/404.html
257
- - test/dummy/public/javascripts/controls.js
369
+ - test/dummy/public/favicon.ico
258
370
  - test/dummy/public/javascripts/application.js
259
- - test/dummy/public/javascripts/rails.js
371
+ - test/dummy/public/javascripts/controls.js
260
372
  - test/dummy/public/javascripts/dragdrop.js
261
- - test/dummy/public/javascripts/prototype.js
262
373
  - test/dummy/public/javascripts/effects.js
263
- - test/dummy/app/controllers/application_controller.rb
264
- - test/dummy/app/views/layouts/application.html.erb
265
- - test/dummy/app/helpers/application_helper.rb
374
+ - test/dummy/public/javascripts/prototype.js
375
+ - test/dummy/public/javascripts/rails.js
376
+ - test/dummy/script/rails
377
+ - test/fixtures/application_widget_tree.rb
378
+ - test/fixtures/mouse/content.html.erb
379
+ - test/fixtures/mouse/eating.html.erb
380
+ - test/fixtures/mouse/educate.html.erb
381
+ - test/fixtures/mouse/feed.html.erb
382
+ - test/fixtures/mouse/make_me_squeak.html.erb
383
+ - test/fixtures/mouse/posing.html.erb
384
+ - test/fixtures/mouse/snuggle.html.erb
385
+ - test/rails/controller_methods_test.rb
386
+ - test/rails/rails_integration_test.rb
387
+ - test/rails/view_helper_test.rb
388
+ - test/rails/view_methods_test.rb
389
+ - test/rails/widget_generator_test.rb
390
+ - test/support/test_case_methods.rb
391
+ - test/test_helper.rb
392
+ - test/unit/apotomo_test.rb
393
+ - test/unit/container_test.rb
266
394
  - test/unit/event_handler_test.rb
267
- - test/unit/widget_shortcuts_test.rb
268
- - test/unit/stateful_widget_test.rb
269
- - test/unit/test_addressing.rb
395
+ - test/unit/event_methods_test.rb
396
+ - test/unit/event_test.rb
270
397
  - test/unit/invoke_test.rb
271
- - test/unit/container_test.rb
272
- - test/unit/test_tab_panel.rb
273
- - test/unit/test_jump_to_state.rb
274
- - test/unit/render_test.rb
275
- - test/unit/test_case_test.rb
276
- - test/unit/apotomo_test.rb
277
- - test/unit/request_processor_test.rb
278
398
  - test/unit/javascript_generator_test.rb
279
399
  - test/unit/onfire_integration_test.rb
280
400
  - test/unit/persistence_test.rb
401
+ - test/unit/render_test.rb
402
+ - test/unit/request_processor_test.rb
403
+ - test/unit/stateful_widget_test.rb
404
+ - test/unit/test_addressing.rb
405
+ - test/unit/test_case_test.rb
406
+ - test/unit/test_jump_to_state.rb
407
+ - test/unit/test_tab_panel.rb
281
408
  - test/unit/transition_test.rb
282
- - test/unit/event_test.rb
283
- - test/unit/event_methods_test.rb
409
+ - test/unit/widget_shortcuts_test.rb
284
410
  - test/unit/widget_test.rb