transcoder 0.3.0 → 0.4.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/CHANGES CHANGED
@@ -1,4 +1,10 @@
1
- = 0.2.0
1
+ = 0.4.0 (10/02/2010)
2
+ * Added ability to transcode from a ruby hash or array to: json, yaml or xml
3
+
4
+ = 0.3.0 (08/02/2010)
5
+ * Re-factored autoloading (http://www.germanforblack.com/articles/ruby-autoload)
6
+
7
+ = 0.2.0 (08/02/2010)
2
8
  * Added Transcoder.for method for a shorter version of Transcoder::Parser.for
3
9
  * Added Yaml parser
4
10
  * Switched all parsers to use autoload for their associated library dependencies (http://gist.github.com/324367)
data/README.md CHANGED
@@ -1,19 +1,16 @@
1
1
  # transcoder
2
2
 
3
- Transcode from common web based formats into plain old Ruby.
3
+ Transcode between common web formats and Ruby.
4
4
 
5
- ## Scenario
5
+ ## Scenario (Web->Ruby)
6
6
  Say you'd pulled an API based resource using `rest-client`
7
7
 
8
8
  * All that you wanted was a ruby object.
9
- * You don't want to know anything about the format that the API uses.
9
+ * You don't want to know anything about the format that the API serves.
10
10
  * You're pretty sure its something pretty common.
11
11
 
12
- ## Install
13
-
14
- gem install transcoder
15
12
 
16
- ## Example
13
+ ## Example (Web->Ruby)
17
14
  $ irb -rubygems
18
15
 
19
16
  >> require 'restclient'
@@ -25,21 +22,50 @@ Say you'd pulled an API based resource using `rest-client`
25
22
 
26
23
  What you'll get back is a Ruby object. Lovley.
27
24
 
25
+ ## Scenario (Ruby→Web)
26
+
27
+ You have a Ruby array or a hash and you want to pack it up and post it off somewhere else
28
+
29
+ * You have a target (content|mime)-type in mind
30
+
31
+ or
32
+
33
+ * You have a named format eg: "json"
34
+
35
+ ## Example (Ruby→Web)
36
+ $ irb -rubygems
37
+
38
+ >> require 'transcoder'
39
+
40
+ >> Transcoder.for(:xml).generate({:title => "Hamlyn's Guide to Sauces and Saucemaking"})
41
+ => "<?xml version=\"1.0\"?>\n<items>\n <item>\n <title>Hamlyn's Guide to Sauces and Saucemaking</title>\n </item>\n</items>\n"
42
+
43
+ >> Transcoder.for(:yaml).generate({:title => "Hamlyn's Guide to Sauces and Saucemaking"})
44
+ => "--- \n:title: Hamlyn's Guide to Sauces and Saucemaking\n"
45
+
46
+
28
47
  ## Supported formats
29
48
 
30
49
  * Json
31
50
  * XML
32
51
  * RSS / Atom
52
+ * Yaml
53
+
54
+ ## Install
33
55
 
34
- ### Note about RSS / Atom
56
+ gem install transcoder
35
57
 
36
- Transcoder will return a SimpleRSS object rather than a straight up Ruby hash, this shouldn't be (much) of a reason for concern.
37
- This simply means that you'll want to call the properties of the returned object with method calls rather than hash access.
58
+ ### Notes about RSS / Atom parsing and generation
38
59
 
39
- ## Future thoughts
60
+ * Transcoder will return a SimpleRSS object rather than a straight up Ruby hash, this shouldn't be (much) of a reason for concern.
61
+
62
+ This simply means that you'll want to call the properties of the returned object with method calls rather than hash access.
63
+ * There is no 'generate' method for feeds. This is simply because they require much more information than a raw feed.
40
64
 
41
- * Add something to cast attributes to a native ruby object, eg - if its key is created_at, try to date parse it.
65
+ ## Future thoughts
42
66
 
67
+ * Add something to cast attributes to a native ruby object, eg - if its key is `created_at`, try to date parse it.
68
+ * Generator methods to unpack and generate object trees (XML generator)
43
69
 
44
70
  ## Note on Patches/Pull Requests
45
71
 
data/Rakefile CHANGED
@@ -16,6 +16,7 @@ begin
16
16
  gem.add_dependency "json"
17
17
  gem.add_dependency "crack"
18
18
  gem.add_dependency "simple-rss"
19
+ gem.add_dependency "nokogiri"
19
20
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
20
21
  end
21
22
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
@@ -4,6 +4,8 @@ module Transcoder
4
4
  VERSION = File.read(File.join(File.dirname(__FILE__), "..", "VERSION"))
5
5
 
6
6
  class Parser
7
+ class TypeError < StandardError; end
8
+
7
9
  extend Registry
8
10
  end
9
11
 
@@ -1,10 +1,16 @@
1
1
  module Transcoder
2
2
  class Feed < Parser
3
- identifier "application/atom+xml",
3
+ identifier "atom",
4
+ "rss",
5
+ "application/atom+xml",
4
6
  "application/rss+xml"
5
7
 
6
8
  autoload :Handler, "feed/handler"
7
-
9
+
10
+ def self.generate(objects)
11
+ raise "NotImplemented"
12
+ end
13
+
8
14
  def self.parse(raw)
9
15
  Feed::Handler.parse(raw)
10
16
  end
@@ -1,6 +1,7 @@
1
1
  module Transcoder
2
2
  class Json < Parser
3
- identifier "application/json",
3
+ identifier "json",
4
+ "application/json",
4
5
  "application/x-javascript",
5
6
  "text/javascript",
6
7
  "text/x-javascript",
@@ -8,6 +9,11 @@ module Transcoder
8
9
 
9
10
  autoload :Handler, "json/handler"
10
11
 
12
+ def self.generate(objects)
13
+ raise TypeError unless objects.is_a? Hash or objects.is_a? Array
14
+ Json::Handler.generate(objects)
15
+ end
16
+
11
17
  def self.parse(raw)
12
18
  Json::Handler.parse(raw)
13
19
  end
@@ -0,0 +1,5 @@
1
+ require 'nokogiri'
2
+
3
+ class Transcoder::XML
4
+ GeneratorHandler = Nokogiri::XML::Builder
5
+ end
@@ -1,12 +1,39 @@
1
1
  module Transcoder
2
2
  class XML < Parser
3
- identifier "text/xml",
3
+ identifier "xml",
4
+ "text/xml",
4
5
  "application/xml"
5
6
 
6
- autoload :Handler, "xml/handler"
7
+ autoload :GeneratorHandler, "xml/generator_handler"
8
+ autoload :ParserHandler, "xml/parser_handler"
9
+
10
+ def self.generate(object)
11
+ raise TypeError unless object.is_a? Hash or object.is_a? Array
12
+ builder = XML::GeneratorHandler.new do |xml|
13
+ xml.items {
14
+ if object.is_a? Array
15
+ object.each{|item| xml.item(:value => item) }
16
+ elsif object.is_a? Hash
17
+ # stringify all the keys
18
+ object.each {|key, value| object[key.to_s] = object.delete(key) }
19
+
20
+ xml.item {
21
+ object.each do |key, value|
22
+ # id, type, class and fork must be appended with _
23
+ key = "#{key}_" if key =~ /(id|type|class|fork)/
24
+
25
+ xml.send(key, value)
26
+ end
27
+ }
28
+ end
29
+ }
30
+ end
31
+
32
+ builder.to_xml
33
+ end
7
34
 
8
35
  def self.parse(raw)
9
- XML::Handler.parse(raw)
36
+ XML::ParserHandler.parse(raw)
10
37
  end
11
38
  end
12
- end
39
+ end
@@ -1,5 +1,5 @@
1
1
  require 'crack'
2
2
 
3
3
  class Transcoder::XML
4
- Handler = Crack::XML
4
+ ParserHandler = Crack::XML
5
5
  end
@@ -3,11 +3,17 @@ autoload :YAML, "yaml"
3
3
 
4
4
  module Transcoder
5
5
  class Yaml < Parser
6
- identifier "text/yaml",
6
+ identifier "yaml",
7
+ "text/yaml",
7
8
  "text/x-yaml",
8
9
  "application/yaml",
9
10
  "application/x-yaml"
10
11
 
12
+ def self.generate(objects)
13
+ raise TypeError unless objects.is_a? Hash or objects.is_a? Array
14
+ YAML.dump(objects)
15
+ end
16
+
11
17
  def self.parse(raw)
12
18
  YAML.load(raw)
13
19
  end
@@ -33,4 +33,8 @@ describe Transcoder::Feed do
33
33
 
34
34
  Transcoder.for("application/atom+xml").parse(atom).should be_an_instance_of(SimpleRSS)
35
35
  end
36
+
37
+ it "should raise NotImplemented from a ruby object" do
38
+ lambda { Transcoder.for("application/atom+xml").generate({:key => "value"}) }.should raise_error("NotImplemented")
39
+ end
36
40
  end
@@ -4,4 +4,27 @@ describe Transcoder::Json do
4
4
  it "should parse the json and return a ruby object" do
5
5
  Transcoder.for("application/json").parse('{"key": "value"}').should == {"key" => "value"}
6
6
  end
7
+
8
+
9
+ describe "generate" do
10
+ it "json from a ruby object" do
11
+ Transcoder.for("json").generate({:key => "value"}).should == "{\"key\":\"value\"}"
12
+ end
13
+
14
+ it "should accept an array" do
15
+ lambda { Transcoder.for("json").generate([1, 2, 3]) }.should_not raise_error
16
+ end
17
+
18
+ it "should accept a hash" do
19
+ lambda { Transcoder.for("json").generate({:key => "value"}) }.should_not raise_error
20
+ end
21
+
22
+ it "should not accept a string" do
23
+ lambda { Transcoder.for("json").generate("value") }.should raise_error
24
+ end
25
+
26
+ it "should not accept an object" do
27
+ lambda { Transcoder.for("json").generate(Object.new) }.should raise_error
28
+ end
29
+ end
7
30
  end
@@ -4,4 +4,44 @@ describe Transcoder::XML do
4
4
  it "should parse the xml and return a ruby object" do
5
5
  Transcoder.for("application/xml").parse("<key>value</key>").should == {"key" => "value"}
6
6
  end
7
+
8
+ describe "generate" do
9
+ it "xml from a ruby object" do
10
+ Transcoder.for("xml").generate({"key" => "value"}).should == "<?xml version=\"1.0\"?>\n<items>\n <item>\n <key>value</key>\n </item>\n</items>\n"
11
+ end
12
+
13
+ describe "nokogiri inefficiencies" do
14
+ it "should handle keys of id" do
15
+ Transcoder.for("xml").generate({"id" => "value"}).should == "<?xml version=\"1.0\"?>\n<items>\n <item>\n <id>value</id>\n </item>\n</items>\n"
16
+ end
17
+
18
+ it "should handle keys of type" do
19
+ Transcoder.for("xml").generate({"type" => "value"}).should == "<?xml version=\"1.0\"?>\n<items>\n <item>\n <type>value</type>\n </item>\n</items>\n"
20
+ end
21
+
22
+ it "should handle keys of class" do
23
+ Transcoder.for("xml").generate({"class" => "value"}).should == "<?xml version=\"1.0\"?>\n<items>\n <item>\n <class>value</class>\n </item>\n</items>\n"
24
+ end
25
+
26
+ it "should handle keys of fork" do
27
+ Transcoder.for("xml").generate({"fork" => "value"}).should == "<?xml version=\"1.0\"?>\n<items>\n <item>\n <fork>value</fork>\n </item>\n</items>\n"
28
+ end
29
+ end
30
+
31
+ it "should accept an array" do
32
+ lambda { Transcoder.for("xml").generate([1, 2, 3]) }.should_not raise_error
33
+ end
34
+
35
+ it "should accept a hash" do
36
+ lambda { Transcoder.for("xml").generate({:key => "value"}) }.should_not raise_error
37
+ end
38
+
39
+ it "should not accept a string" do
40
+ lambda { Transcoder.for("xml").generate("value") }.should raise_error
41
+ end
42
+
43
+ it "should not accept an object" do
44
+ lambda { Transcoder.for("xml").generate(Object.new) }.should raise_error
45
+ end
46
+ end
7
47
  end
@@ -4,4 +4,26 @@ describe Transcoder::Yaml do
4
4
  it "should parse the yaml and return a ruby object" do
5
5
  Transcoder.for("application/x-yaml").parse("key: value").should == {"key" => "value"}
6
6
  end
7
+
8
+ describe "generate" do
9
+ it "yaml from a ruby object" do
10
+ Transcoder.for("yaml").generate({:key => "value"}).should == "--- \n:key: value\n"
11
+ end
12
+
13
+ it "should accept an array" do
14
+ lambda { Transcoder.for("yaml").generate([1, 2, 3]) }.should_not raise_error
15
+ end
16
+
17
+ it "should accept a hash" do
18
+ lambda { Transcoder.for("yaml").generate({:key => "value"}) }.should_not raise_error
19
+ end
20
+
21
+ it "should not accept a string" do
22
+ lambda { Transcoder.for("yaml").generate("value") }.should raise_error
23
+ end
24
+
25
+ it "should not accept an object" do
26
+ lambda { Transcoder.for("yaml").generate(Object.new) }.should raise_error
27
+ end
28
+ end
7
29
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{transcoder}
8
- s.version = "0.3.0"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Ben Schwarz"]
12
- s.date = %q{2010-03-08}
12
+ s.date = %q{2010-03-21}
13
13
  s.description = %q{Transcode from json, xml or atom/rss feeds to Ruby.}
14
14
  s.email = %q{ben.schwarz@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -29,8 +29,9 @@ Gem::Specification.new do |s|
29
29
  "lib/transcoder/parser/feed/identifier.rb",
30
30
  "lib/transcoder/parser/json/handler.rb",
31
31
  "lib/transcoder/parser/json/identifier.rb",
32
- "lib/transcoder/parser/xml/handler.rb",
32
+ "lib/transcoder/parser/xml/generator_handler.rb",
33
33
  "lib/transcoder/parser/xml/identifier.rb",
34
+ "lib/transcoder/parser/xml/parser_handler.rb",
34
35
  "lib/transcoder/parser/yaml/identifier.rb",
35
36
  "spec/parser/feed_spec.rb",
36
37
  "spec/parser/json_spec.rb",
@@ -66,6 +67,7 @@ Gem::Specification.new do |s|
66
67
  s.add_runtime_dependency(%q<json>, [">= 0"])
67
68
  s.add_runtime_dependency(%q<crack>, [">= 0"])
68
69
  s.add_runtime_dependency(%q<simple-rss>, [">= 0"])
70
+ s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
69
71
  else
70
72
  s.add_dependency(%q<rspec>, [">= 1.2.9"])
71
73
  s.add_dependency(%q<rest-client>, [">= 0"])
@@ -73,6 +75,7 @@ Gem::Specification.new do |s|
73
75
  s.add_dependency(%q<json>, [">= 0"])
74
76
  s.add_dependency(%q<crack>, [">= 0"])
75
77
  s.add_dependency(%q<simple-rss>, [">= 0"])
78
+ s.add_dependency(%q<nokogiri>, [">= 0"])
76
79
  end
77
80
  else
78
81
  s.add_dependency(%q<rspec>, [">= 1.2.9"])
@@ -81,6 +84,7 @@ Gem::Specification.new do |s|
81
84
  s.add_dependency(%q<json>, [">= 0"])
82
85
  s.add_dependency(%q<crack>, [">= 0"])
83
86
  s.add_dependency(%q<simple-rss>, [">= 0"])
87
+ s.add_dependency(%q<nokogiri>, [">= 0"])
84
88
  end
85
89
  end
86
90
 
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 3
7
+ - 4
8
8
  - 0
9
- version: 0.3.0
9
+ version: 0.4.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Ben Schwarz
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-03-08 00:00:00 +11:00
17
+ date: 2010-03-21 00:00:00 +11:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -93,6 +93,18 @@ dependencies:
93
93
  version: "0"
94
94
  type: :runtime
95
95
  version_requirements: *id006
96
+ - !ruby/object:Gem::Dependency
97
+ name: nokogiri
98
+ prerelease: false
99
+ requirement: &id007 !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ segments:
104
+ - 0
105
+ version: "0"
106
+ type: :runtime
107
+ version_requirements: *id007
96
108
  description: Transcode from json, xml or atom/rss feeds to Ruby.
97
109
  email: ben.schwarz@gmail.com
98
110
  executables: []
@@ -115,8 +127,9 @@ files:
115
127
  - lib/transcoder/parser/feed/identifier.rb
116
128
  - lib/transcoder/parser/json/handler.rb
117
129
  - lib/transcoder/parser/json/identifier.rb
118
- - lib/transcoder/parser/xml/handler.rb
130
+ - lib/transcoder/parser/xml/generator_handler.rb
119
131
  - lib/transcoder/parser/xml/identifier.rb
132
+ - lib/transcoder/parser/xml/parser_handler.rb
120
133
  - lib/transcoder/parser/yaml/identifier.rb
121
134
  - spec/parser/feed_spec.rb
122
135
  - spec/parser/json_spec.rb