transcoder 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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