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.
- data/CHANGELOG +0 -0
- data/LICENSE +20 -0
- data/README +97 -0
- data/Rakefile +45 -0
- data/lib/instrument.rb +27 -0
- data/lib/instrument/control.rb +269 -0
- data/lib/instrument/control_builder.rb +71 -0
- data/lib/instrument/errors.rb +35 -0
- data/lib/instrument/version.rb +35 -0
- data/spec/control_templates/image_control.xhtml.haml +1 -0
- data/spec/control_templates/select_control.atom.rxml +19 -0
- data/spec/control_templates/select_control.directory.haml/explanation.txt +2 -0
- data/spec/control_templates/select_control.html.mab +5 -0
- data/spec/control_templates/select_control.json.erb +14 -0
- data/spec/control_templates/select_control.txt.bogus +2 -0
- data/spec/control_templates/select_control.xhtml.haml +4 -0
- data/spec/control_templates/select_control.xml.haml +2 -0
- data/spec/instrument/control_builder_spec.rb +37 -0
- data/spec/instrument/control_spec.rb +179 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +13 -0
- data/tasks/browse.rake +43 -0
- data/tasks/clobber.rake +2 -0
- data/tasks/gem.rake +62 -0
- data/tasks/git.rake +27 -0
- data/tasks/metrics.rake +22 -0
- data/tasks/rdoc.rake +29 -0
- data/tasks/rubyforge.rake +77 -0
- data/tasks/spec.rake +43 -0
- data/website/index.html +95 -0
- metadata +104 -0
@@ -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,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
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/spec/spec_helper.rb
ADDED
@@ -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"))
|
data/tasks/browse.rake
ADDED
@@ -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
|