smoke 0.5.17 → 0.5.19
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +5 -5
- data/Rakefile +1 -0
- data/VERSION.yml +2 -2
- data/lib/core_ext/array.rb +12 -0
- data/lib/smoke.rb +24 -13
- data/lib/smoke/cache.rb +4 -4
- data/lib/smoke/origin.rb +6 -11
- data/lib/smoke/request.rb +5 -14
- data/lib/smoke/transformer.rb +7 -0
- data/lib/smoke/transformers/json.rb +15 -0
- data/lib/smoke/transformers/ruby.rb +11 -0
- data/lib/smoke/{output → transformers}/xml.rb +12 -6
- data/lib/smoke/transformers/yaml.rb +15 -0
- data/spec/smoke/origin_spec.rb +4 -0
- data/spec/smoke/request_spec.rb +7 -0
- data/spec/smoke/{output → transformers}/xml_spec.rb +4 -6
- data/spec/smoke/transformers_spec.rb +35 -0
- data/spec/smoke_spec.rb +18 -10
- data/spec/supports/twitter_timeline.json +22 -0
- metadata +23 -30
- data/rdoc/classes/Smoke.html +0 -260
- data/rdoc/classes/Smoke/Origin.html +0 -340
- data/rdoc/classes/Smoke/Source/Data.html +0 -126
- data/rdoc/classes/Smoke/Source/Feed.html +0 -117
- data/rdoc/classes/Smoke/Source/YQL.html +0 -223
- data/rdoc/created.rid +0 -1
- data/rdoc/files/README_markdown.html +0 -180
- data/rdoc/files/lib/core_ext/hash_rb.html +0 -49
- data/rdoc/files/lib/smoke/origin_rb.html +0 -49
- data/rdoc/files/lib/smoke/request_rb.html +0 -49
- data/rdoc/files/lib/smoke/source/data_rb.html +0 -49
- data/rdoc/files/lib/smoke/source/feed_rb.html +0 -49
- data/rdoc/files/lib/smoke/source/join_rb.html +0 -49
- data/rdoc/files/lib/smoke/source/yql_rb.html +0 -49
- data/rdoc/files/lib/smoke_rb.html +0 -65
- data/rdoc/fr_class_index.html +0 -21
- data/rdoc/fr_file_index.html +0 -28
- data/rdoc/fr_method_index.html +0 -4459
- data/rdoc/index.html +0 -15
- data/rdoc/rdoc-style.css +0 -319
- data/spec/smoke/input/xls_spec.rb +0 -15
- data/spec/smoke/shared_spec.rb +0 -182
- data/spec/supports/gov_act_toliets.xls +0 -0
data/README.markdown
CHANGED
@@ -14,6 +14,7 @@ Then you can output as a plain ruby object or one of your other favourites (JSON
|
|
14
14
|
|
15
15
|
## Media
|
16
16
|
|
17
|
+
* [Presentation from Webjam11 in Perth](http://www.slideshare.net/benschwarz/how-to-reinterpret-the-web-in-180-seconds)
|
17
18
|
* [Presentation from Melbourne #roro](http://www.slideshare.net/benschwarz/smoke-1371124)
|
18
19
|
* Early [screencast](http://vimeo.com/4272804) to get developer / peer feedback
|
19
20
|
|
@@ -77,11 +78,10 @@ Execution:
|
|
77
78
|
|
78
79
|
|
79
80
|
### TODO (working on, just mental notes)
|
80
|
-
|
81
|
-
*
|
82
|
-
*
|
83
|
-
*
|
84
|
-
|
81
|
+
* Items returned from smoke to be Hashie "rich" objects
|
82
|
+
* Output as a web feed (atom, rss)
|
83
|
+
* How to push through values like "author"?
|
84
|
+
* Passing modified time headers through to the atom formatter
|
85
85
|
|
86
86
|
#### For wiki pages (docs, later)
|
87
87
|
* Document all sources with their irrespective differential methods
|
data/Rakefile
CHANGED
@@ -18,6 +18,7 @@ begin
|
|
18
18
|
gem.add_dependency("moneta", "0.6.0")
|
19
19
|
gem.add_dependency("rest-client", "1.0.3")
|
20
20
|
gem.add_dependency("nokogiri", "1.3.2")
|
21
|
+
gem.add_dependency("registry", ">=0.1.2")
|
21
22
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
22
23
|
end
|
23
24
|
rescue LoadError
|
data/VERSION.yml
CHANGED
data/lib/smoke.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'logger'
|
2
2
|
require 'digest/md5'
|
3
|
+
require 'yaml'
|
3
4
|
|
4
5
|
require 'simple-rss'
|
5
6
|
require 'json'
|
@@ -7,8 +8,11 @@ require 'crack'
|
|
7
8
|
require 'moneta'
|
8
9
|
require 'restclient'
|
9
10
|
require 'nokogiri'
|
11
|
+
require 'registry'
|
10
12
|
|
11
|
-
module Smoke
|
13
|
+
module Smoke
|
14
|
+
class NotRegistered < StandardError; end
|
15
|
+
|
12
16
|
class << self
|
13
17
|
@@active_sources = {}
|
14
18
|
@@config = {
|
@@ -22,6 +26,15 @@ module Smoke
|
|
22
26
|
}
|
23
27
|
}
|
24
28
|
|
29
|
+
def root
|
30
|
+
File.join(File.dirname(__FILE__))
|
31
|
+
end
|
32
|
+
|
33
|
+
def version
|
34
|
+
@@version ||= YAML::load(File.read("#{root}/../VERSION.YML"))
|
35
|
+
"#{@@version[:major]}.#{@@version[:minor]}.#{@@version[:patch]}"
|
36
|
+
end
|
37
|
+
|
25
38
|
# Access registered smoke source instances
|
26
39
|
#
|
27
40
|
# Define your source:
|
@@ -39,6 +52,8 @@ module Smoke
|
|
39
52
|
# Usage:
|
40
53
|
# Smoke.twitter(:username => "benschwarz")
|
41
54
|
def method_missing(sym, args = {})
|
55
|
+
raise NotRegistered, "Smoke source not registered" if self[sym].nil?
|
56
|
+
|
42
57
|
args.each_pair {|k, v| self[sym].send(k, v) }
|
43
58
|
self[sym]
|
44
59
|
end
|
@@ -47,8 +62,8 @@ module Smoke
|
|
47
62
|
# Source instances are stored within the
|
48
63
|
# @@active_sources class variable for later use
|
49
64
|
def activate(name, source)
|
50
|
-
if active_sources.
|
51
|
-
Smoke.log.warn "Smoke source activation: Source with
|
65
|
+
if active_sources.key?(name)
|
66
|
+
Smoke.log.warn "Smoke source activation: Source with identical name already initialized"
|
52
67
|
end
|
53
68
|
active_sources.update({ name => source })
|
54
69
|
end
|
@@ -115,15 +130,11 @@ module Smoke
|
|
115
130
|
# end
|
116
131
|
def join(*names, &block); Smoke::Join.new(names, &block); end
|
117
132
|
end
|
133
|
+
|
134
|
+
autoload :YQL, "smoke/source/yql"
|
135
|
+
autoload :Data, "smoke/source/data"
|
136
|
+
autoload :Feed, "smoke/source/feed"
|
137
|
+
autoload :Join, "smoke/source/join"
|
118
138
|
end
|
119
139
|
|
120
|
-
|
121
|
-
|
122
|
-
# Autoload the source classes
|
123
|
-
%w(YQL Data Feed Join).each do |r|
|
124
|
-
Smoke.autoload(r.to_sym, File.join(File.dirname(__FILE__), "smoke", "source", r.downcase))
|
125
|
-
end
|
126
|
-
|
127
|
-
class Object # :nodoc:
|
128
|
-
include Smoke
|
129
|
-
end
|
140
|
+
Dir["#{File.dirname(__FILE__)}/{core_ext,smoke,smoke/transformers}/*.rb"].each {|r| require r}
|
data/lib/smoke/cache.rb
CHANGED
@@ -39,8 +39,8 @@ module Smoke
|
|
39
39
|
|
40
40
|
def query(uri, options)
|
41
41
|
request = RestClient.get(uri, options)
|
42
|
-
write(uri, request, request.headers
|
43
|
-
{:body => request, :
|
42
|
+
write(uri, request, request.headers) if enabled?
|
43
|
+
{:body => request, :headers => request.headers}
|
44
44
|
end
|
45
45
|
|
46
46
|
def read(uri)
|
@@ -48,8 +48,8 @@ module Smoke
|
|
48
48
|
return cache[key]
|
49
49
|
end
|
50
50
|
|
51
|
-
def write(uri, body,
|
52
|
-
store = {:body => body, :
|
51
|
+
def write(uri, body, headers)
|
52
|
+
store = {:body => body, :headers => headers}
|
53
53
|
self.cache.store(generate_key(uri), store, :expire_in => Smoke.config[:cache][:expiry])
|
54
54
|
end
|
55
55
|
|
data/lib/smoke/origin.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module Smoke
|
2
2
|
class Origin
|
3
|
+
class UnavailableFormat < StandardError; end
|
4
|
+
|
3
5
|
attr_reader :items, :requirements, :exposed
|
4
6
|
attr_accessor :name
|
5
7
|
|
@@ -13,7 +15,7 @@ module Smoke
|
|
13
15
|
instance_eval(&block) if block_given?
|
14
16
|
end
|
15
17
|
|
16
|
-
# Output your items in a range of formats (:ruby, :json and :yaml currently)
|
18
|
+
# Output your items in a range of formats (:ruby, :json, :xml and :yaml currently)
|
17
19
|
# Ruby is the default format and will automagically yielded from your source
|
18
20
|
#
|
19
21
|
# Usage
|
@@ -24,16 +26,9 @@ module Smoke
|
|
24
26
|
prepare!
|
25
27
|
dispatch if respond_to? :dispatch
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
when :yaml
|
31
|
-
return YAML.dump(@items)
|
32
|
-
when :xml
|
33
|
-
return Smoke::Output::XML.generate(@name, @items)
|
34
|
-
else
|
35
|
-
return @items
|
36
|
-
end
|
29
|
+
Transformer.for(type).generate(name, items)
|
30
|
+
rescue Registry::NotRegistered => e
|
31
|
+
raise UnavailableFormat, e.message
|
37
32
|
end
|
38
33
|
|
39
34
|
def items=(response) # :nodoc:
|
data/lib/smoke/request.rb
CHANGED
@@ -9,7 +9,7 @@ module Smoke
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
-
SUPPORTED_TYPES = %w(json xml javascript
|
12
|
+
SUPPORTED_TYPES = %w(json xml javascript)
|
13
13
|
@@request_options = {
|
14
14
|
:user_agent => Smoke.config[:user_agent],
|
15
15
|
:accept_encoding => "gzip, deflate"
|
@@ -30,7 +30,7 @@ module Smoke
|
|
30
30
|
def dispatch
|
31
31
|
get = Smoke::Cache.fetch @uri, @@request_options
|
32
32
|
@body = get[:body]
|
33
|
-
@content_type = get[:content_type]
|
33
|
+
@content_type = get[:headers][:content_type]
|
34
34
|
|
35
35
|
parse! unless @options[:raw_response]
|
36
36
|
|
@@ -39,18 +39,9 @@ module Smoke
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def parse!
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
when :xml
|
46
|
-
@body = ::Crack::XML.parse(@body).symbolize_keys!
|
47
|
-
when :excel
|
48
|
-
# Convert the excel document into an XML document
|
49
|
-
doc = @body
|
50
|
-
::Crack::XML.parse().symbolize_keys!
|
51
|
-
when :unknown
|
52
|
-
Smoke.log.warn "Smoke Request: Format unknown for #{@uri} (#{@content_type})"
|
53
|
-
end
|
42
|
+
@body = Transformer.for(type).parse(body).symbolize_keys!
|
43
|
+
rescue Registry::NotRegistered
|
44
|
+
Smoke.log.warn "Smoke Request: Format unknown for #{@uri} (#{@content_type})"
|
54
45
|
end
|
55
46
|
end
|
56
47
|
end
|
@@ -1,23 +1,29 @@
|
|
1
1
|
module Smoke
|
2
|
-
module
|
3
|
-
|
2
|
+
module Transformers
|
3
|
+
class XML < Transformer
|
4
|
+
identifier :xml
|
5
|
+
|
4
6
|
def self.generate(tree_name, items)
|
5
7
|
builder = Nokogiri::XML::Builder.new do |xml|
|
6
8
|
xml.items {
|
7
9
|
items.each do |item|
|
8
10
|
xml.item {
|
9
|
-
%w(id type class).each{|m| item["#{m}_".to_sym] = item.delete(m.to_sym) }
|
10
|
-
|
11
|
+
%w(id type class fork).each{|m| item["#{m}_".to_sym] = item.delete(m.to_sym) }
|
12
|
+
|
11
13
|
item.each do |k, v|
|
12
|
-
xml.
|
14
|
+
xml.__send__(k, v)
|
13
15
|
end
|
14
16
|
}
|
15
17
|
end
|
16
18
|
}
|
17
19
|
end
|
18
|
-
|
20
|
+
|
19
21
|
builder.to_xml
|
20
22
|
end
|
23
|
+
|
24
|
+
def self.parse(string)
|
25
|
+
::Crack::XML.parse(string)
|
26
|
+
end
|
21
27
|
end
|
22
28
|
end
|
23
29
|
end
|
data/spec/smoke/origin_spec.rb
CHANGED
@@ -49,6 +49,10 @@ describe Smoke::Origin do
|
|
49
49
|
Smoke.test.output(:xml).should include "<?xml version=\"1.0\"?>"
|
50
50
|
end
|
51
51
|
|
52
|
+
it "should raise a UnavailableFormat error" do
|
53
|
+
lambda { Smoke.test.output(:xyz) }.should raise_error(Smoke::Origin::UnavailableFormat)
|
54
|
+
end
|
55
|
+
|
52
56
|
describe "filtering" do
|
53
57
|
before :all do
|
54
58
|
TestSource.source(:keep) do
|
data/spec/smoke/request_spec.rb
CHANGED
@@ -35,6 +35,13 @@ describe Smoke::Request do
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
+
it "should handle direct array responses" do
|
39
|
+
url = "http://fake.tld/canned/twitter.json"
|
40
|
+
FakeWeb.register_uri(:get, url, :response => File.join(SPEC_DIR, 'supports', 'twitter_timeline.json'))
|
41
|
+
|
42
|
+
lambda { Smoke::Request.new(url) }.should_not raise_error(NoMethodError)
|
43
|
+
end
|
44
|
+
|
38
45
|
describe "format returns" do
|
39
46
|
it "should have a content type of :manual" do
|
40
47
|
request = Smoke::Request.new(@url, :type => :manual)
|
@@ -1,18 +1,18 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), "..", "..", "spec_helper.rb")
|
2
2
|
|
3
|
-
describe Smoke::
|
3
|
+
describe Smoke::Transformers::XML do
|
4
4
|
before do
|
5
5
|
@tree = :tree
|
6
6
|
@items = [
|
7
7
|
{:id => 1, :class => "first", :type => "mammal", :animal => "monkey"},
|
8
8
|
{:id => 2, :class => "second", :type => "mammal", :animal => "elephant"}
|
9
9
|
]
|
10
|
-
@xml = Smoke::
|
10
|
+
@xml = Smoke::Transformers::XML.generate(@tree, @items)
|
11
11
|
@document = Nokogiri::XML(@xml)
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should respond to generate" do
|
15
|
-
Smoke::
|
15
|
+
Smoke::Transformers::XML.should respond_to(:generate)
|
16
16
|
end
|
17
17
|
|
18
18
|
it "should start the tree off with a named key" do
|
@@ -20,9 +20,7 @@ describe Smoke::Output::XML do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
it "should contain items" do
|
23
|
-
@document.css("
|
24
|
-
item.content.should =~ /monkey/
|
25
|
-
end
|
23
|
+
@document.css("item").size.should == 2
|
26
24
|
end
|
27
25
|
end
|
28
26
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../spec_helper"
|
2
|
+
|
3
|
+
describe Smoke::Transformer do
|
4
|
+
describe "parsers" do
|
5
|
+
it "should respond to parse" do
|
6
|
+
Smoke::Transformers::Json.should respond_to(:parse)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should respond to parse" do
|
10
|
+
Smoke::Transformers::XML.should respond_to(:parse)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should respond to parse" do
|
14
|
+
Smoke::Transformers::Yaml.should respond_to(:parse)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "generators" do
|
19
|
+
it "should respond to generate" do
|
20
|
+
Smoke::Transformers::Json.should respond_to(:generate)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should respond to generate" do
|
24
|
+
Smoke::Transformers::XML.should respond_to(:generate)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should respond to generate" do
|
28
|
+
Smoke::Transformers::Yaml.should respond_to(:generate)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should respond to generate" do
|
32
|
+
Smoke::Transformers::Ruby.should respond_to(:generate)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/spec/smoke_spec.rb
CHANGED
@@ -6,6 +6,16 @@ describe Smoke do
|
|
6
6
|
@source_b = TestSource.source :b
|
7
7
|
end
|
8
8
|
|
9
|
+
it "should have a root" do
|
10
|
+
Smoke.should respond_to(:root)
|
11
|
+
Smoke.root.should be_an_instance_of(String)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should have a version string" do
|
15
|
+
Smoke.should respond_to :version
|
16
|
+
Smoke.version.should be_an_instance_of(String)
|
17
|
+
end
|
18
|
+
|
9
19
|
describe "active sources" do
|
10
20
|
it "should allow access to sources via an array accessor" do
|
11
21
|
Smoke[:a].should == @source_a
|
@@ -17,17 +27,15 @@ describe Smoke do
|
|
17
27
|
|
18
28
|
it "should have its name as the hash key" do
|
19
29
|
key = Smoke.active_sources.keys.first
|
20
|
-
Smoke.active_sources[key].name.should == key
|
30
|
+
Smoke.active_sources[key].name.to_s.should == key.to_s
|
21
31
|
end
|
22
32
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
Smoke.b.should raise_error(NoMethodError)
|
30
|
-
end
|
33
|
+
it "should allow access to the sources via a method call" do
|
34
|
+
Smoke.a.should == @source_a
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should throw an error when missing" do
|
38
|
+
lambda { Smoke.frank }.should raise_error(Smoke::NotRegistered)
|
31
39
|
end
|
32
40
|
|
33
41
|
it "should be able to be renamed" do
|
@@ -40,7 +48,7 @@ describe Smoke do
|
|
40
48
|
Smoke[:b].name.should == "b"
|
41
49
|
end
|
42
50
|
end
|
43
|
-
|
51
|
+
|
44
52
|
describe "configuration" do
|
45
53
|
it "should be configurable" do
|
46
54
|
Smoke.should respond_to(:configure)
|