instrument 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,71 @@
1
+ # ++
2
+ # Instrument, Copyright (c) 2008 Day Automation Systems, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ # --
23
+
24
+ require "instrument/control"
25
+
26
+ module Instrument
27
+ ##
28
+ # A module which you can mixin to allow for abbreviated control
29
+ # creation.
30
+ #
31
+ # == Example
32
+ #
33
+ # include Instrument::ControlBuilder
34
+ #
35
+ # select_control(:name => "base", :selections => [
36
+ # {:label => "One", :value => "1"},
37
+ # {:label => "Two", :value => "2"},
38
+ # {:label => "Three", :value => "3"},
39
+ # {:label => "Four", :value => "4"}
40
+ # ]).to_xhtml
41
+ module ControlBuilder
42
+ ##
43
+ # Prevents Kernel#select from being accidentally called.
44
+ #
45
+ # @param [Array] params the method's parameters
46
+ # @param [Proc] block the block being passed to the method
47
+ # @return [Instrument::Control] the control being created
48
+ def select(*params, &block) # :nodoc:
49
+ return self.method_missing(:select, *params, &block)
50
+ end
51
+
52
+ ##
53
+ # Initializes Instrument::Control subclasses by name.
54
+ #
55
+ # @param [Symbol] method the method being called
56
+ # @param [Array] params the method's parameters
57
+ # @param [Proc] block the block being passed to the method
58
+ # @return [Instrument::Control] the control being created
59
+ # @raise NoMethodError if the method wasn't handled
60
+ def method_missing(method, *params, &block)
61
+ control_class = ::Instrument::Control.lookup(method.to_s)
62
+ if control_class != nil
63
+ return control_class.new(*params, &block)
64
+ else
65
+ raise NoMethodError,
66
+ "undefined method `#{method}' for " +
67
+ "#{self.inspect}:#{self.class.name}"
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,35 @@
1
+ # ++
2
+ # Instrument, Copyright (c) 2008 Day Automation Systems, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ # --
23
+
24
+ module Instrument
25
+ ##
26
+ # Exception raised when a template cannot be found.
27
+ class ResourceNotFoundError < StandardError
28
+ end
29
+
30
+ ##
31
+ # Exception raised when a template is found, but it uses an unknown
32
+ # template engine.
33
+ class InvalidTemplateEngineError < StandardError
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ # ++
2
+ # Instrument, Copyright (c) 2008 Day Automation Systems, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ # --
23
+
24
+ # Used to prevent the class/module from being loaded more than once
25
+ unless defined? Instrument::VERSION
26
+ module Instrument #:nodoc:
27
+ module VERSION #:nodoc:
28
+ MAJOR = 0
29
+ MINOR = 1
30
+ TINY = 0
31
+
32
+ STRING = [MAJOR, MINOR, TINY].join('.')
33
+ end
34
+ end
35
+ end
@@ -0,0 +1 @@
1
+ %img{:src => source, :alt => alternate_text}
@@ -0,0 +1,19 @@
1
+ require "uuidtools"
2
+ require "time"
3
+ xml.instruct! :xml, :version=>"1.0"
4
+ xml.feed("xmlns" => "http://www.w3.org/2005/Atom", "xml:lang" => "en_US") do
5
+ xml.id("urn:uuid:4a11e26e-239c-11dd-adf9-001ec2186a45")
6
+ xml.title("Select Control")
7
+ xml.subtitle("Yes, this is silly, but you get the idea.")
8
+ xml.updated(Time.now.iso8601)
9
+ for selection in selections
10
+ xml.entry do
11
+ xml.id(
12
+ UUID.sha1_create(UUID_URL_NAMESPACE, "#" + selection.value).to_uri
13
+ )
14
+ xml.title(selection.label)
15
+ xml.link("#" + selection.value)
16
+ xml.updated(Time.now.iso8601)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,2 @@
1
+ # This directory exists to test that a directory cannot be loaded
2
+ # accidentally as if it were a template.
@@ -0,0 +1,5 @@
1
+ select :id => element_id, :name => element_name do
2
+ for selection in selections
3
+ option selection.label, :value => selection.value
4
+ end
5
+ end
@@ -0,0 +1,14 @@
1
+ {
2
+ "select": {
3
+ "id": "<%= element_id %>",
4
+ "name": "<%= element_name %>",
5
+ "options": [
6
+ <% for selection in selections %>
7
+ {
8
+ "label": "<%= selection.label %>",
9
+ "value": "<%= selection.value %>"
10
+ }
11
+ <% end %>
12
+ ]
13
+ }
14
+ }
@@ -0,0 +1,2 @@
1
+ # This is a bogus format.
2
+ # No handler will be registered to handle it.
@@ -0,0 +1,4 @@
1
+ %select{:id => element_id, :name => element_name}
2
+ - for selection in selections
3
+ %option{:value => selection.value}
4
+ = selection.label
@@ -0,0 +1,2 @@
1
+ %divide_by_zero_test
2
+ = 0 / 0
@@ -0,0 +1,37 @@
1
+ spec_dir = File.expand_path(File.join(File.dirname(__FILE__), ".."))
2
+ require File.join(spec_dir, "spec_helper")
3
+
4
+ class ImageControl < Instrument::Control
5
+ def source
6
+ return self.options[:source] || self.options[:src]
7
+ end
8
+
9
+ def alternate_text
10
+ return self.options[:alternate_text] || self.options[:alt]
11
+ end
12
+ end
13
+
14
+ # Verifies that Kernel#select isn't accidentally being called.
15
+ class Select < Instrument::Control
16
+ end
17
+
18
+ describe Instrument::ControlBuilder do
19
+ class ExtendedObject
20
+ include Instrument::ControlBuilder
21
+ end
22
+
23
+ before :all do
24
+ @extended_object = ExtendedObject.new
25
+ end
26
+
27
+ it "should enable mixins to function" do
28
+ @extended_object.image_control.class.should == ImageControl
29
+ @extended_object.select.class.should == Select
30
+ end
31
+
32
+ it "should still raise an Exception for non-existent methods" do
33
+ (lambda do
34
+ @extended_object.bogus
35
+ end).should raise_error(NoMethodError)
36
+ end
37
+ end
@@ -0,0 +1,179 @@
1
+ spec_dir = File.expand_path(File.join(File.dirname(__FILE__), ".."))
2
+ require File.join(spec_dir, "spec_helper")
3
+
4
+ class SelectControl < Instrument::Control
5
+ class Option
6
+ def initialize(label, value)
7
+ @label, @value = label, value
8
+ end
9
+
10
+ attr_accessor :label
11
+ attr_accessor :value
12
+ end
13
+
14
+ def element_id
15
+ return self.options[:id] || self.options[:name]
16
+ end
17
+
18
+ def element_name
19
+ return self.options[:name]
20
+ end
21
+
22
+ def selections
23
+ if !defined?(@selections) || @selections == nil
24
+ @selections = []
25
+ for selection in self.options[:selections]
26
+ if selection.kind_of?(Hash)
27
+ @selections << Option.new(selection[:label], selection[:value])
28
+ else
29
+ @selections << Option.new(selection, selection)
30
+ end
31
+ end
32
+ end
33
+ return @selections
34
+ end
35
+ end
36
+
37
+ class SuperSelectControl < SelectControl
38
+ end
39
+
40
+ describe Instrument::Control do
41
+ it "should be able to look up subclasses by name" do
42
+ Instrument::Control.lookup("select_control").should ==
43
+ SelectControl
44
+ Instrument::Control.lookup("super_select_control").should ==
45
+ SuperSelectControl
46
+ end
47
+
48
+ it "should have RAILS_ROOT/app/controls in the $CONTROL_PATH" do
49
+ $CONTROL_PATH.should include(File.join(RAILS_ROOT, "app/controls"))
50
+ end
51
+
52
+ it "should not allow invalid types to be used" do
53
+ (lambda do
54
+ Instrument::Control.processor(:bogus)
55
+ end).should raise_error(ArgumentError)
56
+ end
57
+
58
+ it "should initialize subclasses via method_missing" do
59
+ Instrument::Control.new.select_control.class.should == SelectControl
60
+ end
61
+
62
+ it "should still raise an Exception for non-existent methods" do
63
+ (lambda do
64
+ Instrument::Control.new.bogus
65
+ end).should raise_error(NoMethodError)
66
+ end
67
+
68
+ it "should raise an Exception for non-existent formats" do
69
+ (lambda do
70
+ SelectControl.new.to_bogus
71
+ end).should raise_error(Instrument::ResourceNotFoundError)
72
+ end
73
+
74
+ it "should raise an Exception if a directory is found instead of a file" do
75
+ (lambda do
76
+ SelectControl.new.to_directory
77
+ end).should raise_error(Instrument::ResourceNotFoundError)
78
+ end
79
+
80
+ it "should raise an Exception if a directory is found instead of a file" do
81
+ (lambda do
82
+ SelectControl.new.to_txt
83
+ end).should raise_error(Instrument::InvalidTemplateEngineError)
84
+ end
85
+
86
+ it "should raise an Exception if a template raises an Exception" do
87
+ (lambda do
88
+ SelectControl.new.to_xml
89
+ end).should raise_error(ZeroDivisionError)
90
+ end
91
+ end
92
+
93
+ describe Instrument::Control, "when rendered as XHTML with Haml" do
94
+ before :all do
95
+ @control = SelectControl.new(:name => "base", :selections => [
96
+ "First", "Second", "Third", "Home"
97
+ ])
98
+ @xhtml = @control.to_xhtml
99
+ end
100
+
101
+ it "should have the correct id and name" do
102
+ @xhtml.should match(/<select id="base" name="base">/)
103
+ end
104
+
105
+ it "should have options for all of the given selections" do
106
+ @xhtml.should match(/<option value="First"/)
107
+ @xhtml.should match(/<option value="Second"/)
108
+ @xhtml.should match(/<option value="Third"/)
109
+ @xhtml.should match(/<option value="Home"/)
110
+ end
111
+ end
112
+
113
+ describe Instrument::Control, "when rendered as HTML with Markaby" do
114
+ before :all do
115
+ @control = SelectControl.new(:name => "base", :selections => [
116
+ "First", "Second", "Third", "Home"
117
+ ])
118
+ @html = @control.to_html
119
+ end
120
+
121
+ it "should have the correct id and name" do
122
+ # Ordering of attributes is indeterminate.
123
+ @html.should match(/<select/)
124
+ @html.should match(/id="base"/)
125
+ @html.should match(/name="base"/)
126
+ end
127
+
128
+ it "should have options for all of the given selections" do
129
+ @html.should match(/<option value="First"/)
130
+ @html.should match(/<option value="Second"/)
131
+ @html.should match(/<option value="Third"/)
132
+ @html.should match(/<option value="Home"/)
133
+ end
134
+ end
135
+
136
+ describe Instrument::Control, "when rendered as Atom with XML Builder" do
137
+ before :all do
138
+ @control = SelectControl.new(:name => "base", :selections => [
139
+ "First", "Second", "Third", "Home"
140
+ ])
141
+ @atom = @control.to_atom
142
+ end
143
+
144
+ it "should have the correct id and name" do
145
+ @atom.should match(/<title>Select Control<\/title>/)
146
+ end
147
+
148
+ it "should have options for all of the given selections" do
149
+ @atom.should match(/<title>First<\/title>/)
150
+ @atom.should match(/<title>Second<\/title>/)
151
+ @atom.should match(/<title>Third<\/title>/)
152
+ @atom.should match(/<title>Home<\/title>/)
153
+ end
154
+ end
155
+
156
+ describe Instrument::Control, "when rendered as JSON with Erubis" do
157
+ before :all do
158
+ @control = SelectControl.new(:name => "base", :selections => [
159
+ "First", "Second", "Third", "Home"
160
+ ])
161
+ @atom = @control.to_json
162
+ end
163
+
164
+ it "should have the correct id and name" do
165
+ @atom.should match(/"id": "base"/)
166
+ @atom.should match(/"name": "base"/)
167
+ end
168
+
169
+ it "should have options for all of the given selections" do
170
+ @atom.should match(/"label": "First"/)
171
+ @atom.should match(/"value": "First"/)
172
+ @atom.should match(/"label": "Second"/)
173
+ @atom.should match(/"value": "Second"/)
174
+ @atom.should match(/"label": "Third"/)
175
+ @atom.should match(/"value": "Third"/)
176
+ @atom.should match(/"label": "Home"/)
177
+ @atom.should match(/"value": "Home"/)
178
+ end
179
+ end
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,13 @@
1
+ # We need to test for the presence of RAILS_ROOT in the $CONTROL_PATH
2
+ if !defined?(RAILS_ROOT)
3
+ RAILS_ROOT = "somewhere/over/the/rainbow"
4
+ end
5
+
6
+ spec_dir = File.expand_path(File.dirname(__FILE__))
7
+ lib_dir = File.expand_path(File.join(spec_dir, "../lib"))
8
+
9
+ $:.unshift(lib_dir)
10
+ $:.uniq!
11
+
12
+ require "instrument"
13
+ $CONTROL_PATH.unshift(File.join(spec_dir, "control_templates"))
@@ -0,0 +1,43 @@
1
+ module Rake
2
+ def self.browse(filepath)
3
+ if RUBY_PLATFORM =~ /mswin/
4
+ system(filepath)
5
+ else
6
+ try_browsers = lambda do
7
+ result = true
8
+ if !(`which firefox 2>&1` =~ /no firefox/)
9
+ system("firefox #{filepath}")
10
+ elsif !(`which mozilla 2>&1` =~ /no mozilla/)
11
+ system("mozilla #{filepath}")
12
+ elsif !(`which netscape 2>&1` =~ /no netscape/)
13
+ system("netscape #{filepath}")
14
+ elsif !(`which links 2>&1` =~ /no links/)
15
+ system("links #{filepath}")
16
+ elsif !(`which lynx 2>&1` =~ /no lynx/)
17
+ system("lynx #{filepath}")
18
+ else
19
+ result = false
20
+ end
21
+ result
22
+ end
23
+ opened = false
24
+ if RUBY_PLATFORM =~ /darwin/
25
+ opened = true
26
+ system("open #{filepath}")
27
+ elsif !(`which gnome-open 2>&1` =~ /no gnome-open/)
28
+ success =
29
+ !(`gnome-open #{filepath} 2>&1` =~ /There is no default action/)
30
+ if !success
31
+ opened = try_browsers.call()
32
+ else
33
+ opened = true
34
+ end
35
+ else
36
+ opened = try_browsers.call()
37
+ end
38
+ if !opened
39
+ puts "Don't know how to browse to location."
40
+ end
41
+ end
42
+ end
43
+ end