transcriber 0.0.3 → 0.0.4

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.
Files changed (45) hide show
  1. data/README.md +7 -5
  2. data/examples/all.rb +2 -6
  3. data/examples/embeds_many/simple.rb +2 -2
  4. data/examples/embeds_many/with_class_name.rb +4 -4
  5. data/examples/embeds_many/with_if.rb +6 -6
  6. data/examples/embeds_many/with_start_key.rb +4 -4
  7. data/examples/embeds_one/simple.rb +3 -3
  8. data/examples/embeds_one/with_class_name.rb +3 -3
  9. data/examples/embeds_one/with_if.rb +6 -6
  10. data/examples/embeds_one/with_start_key.rb +3 -3
  11. data/examples/has_many/simple.rb +3 -3
  12. data/examples/properties/collections.rb +12 -0
  13. data/examples/properties/simple.rb +3 -3
  14. data/examples/properties/with_field.rb +3 -3
  15. data/examples/properties/with_field_path.rb +3 -3
  16. data/examples/properties/with_id.rb +3 -3
  17. data/examples/properties/with_if.rb +13 -7
  18. data/examples/properties/with_key_converter.rb +3 -3
  19. data/examples/properties/with_two_key_converters.rb +29 -0
  20. data/examples/summarization/simple.rb +27 -0
  21. data/lib/transcriber.rb +8 -0
  22. data/lib/transcriber/configuration.rb +2 -0
  23. data/lib/transcriber/resource.rb +11 -18
  24. data/lib/transcriber/resource/builder.rb +1 -0
  25. data/lib/transcriber/resource/builder/keys.rb +1 -0
  26. data/lib/transcriber/resource/builder/summarizations.rb +3 -3
  27. data/lib/transcriber/resource/key.rb +3 -1
  28. data/lib/transcriber/resource/key/href.rb +11 -0
  29. data/lib/transcriber/resource/parser.rb +13 -3
  30. data/lib/transcriber/resource/response.rb +37 -5
  31. data/lib/transcriber/resource/response/href.rb +12 -0
  32. data/lib/transcriber/resource/response/relation.rb +4 -3
  33. data/lib/transcriber/version.rb +1 -1
  34. data/spec/integration/embeds_many_spec.rb +50 -0
  35. data/spec/integration/embeds_one_spec.rb +41 -0
  36. data/spec/integration/has_many_spec.rb +22 -4
  37. data/spec/integration/property_spec.rb +69 -0
  38. data/spec/integration/summarization_spec.rb +13 -0
  39. data/spec/spec_helper.rb +5 -1
  40. data/spec/support/examples.rb +6 -2
  41. data/spec/unit/input_path_spec.rb +1 -7
  42. data/spec/unit/resource/response/relation_spec.rb +3 -3
  43. data/spec/unit/resource_spec.rb +1 -1
  44. data/transcriber.gemspec +1 -1
  45. metadata +27 -16
data/README.md CHANGED
@@ -91,7 +91,7 @@ Just define your `User` class like this:
91
91
 
92
92
  ## Embedding other resources
93
93
 
94
- ### [`embeds_one`](https://github.com/rodrigues/transcriber/tree/master/examples/embeds_one)
94
+ ### [embeds_one](https://github.com/rodrigues/transcriber/tree/master/examples/embeds_one)
95
95
 
96
96
  class Customer < Transcriber::Resource
97
97
  id field: 'cust_id'
@@ -116,7 +116,7 @@ Just define your `User` class like this:
116
116
  href: "http://app/api/users/1938713897398"
117
117
  }
118
118
 
119
- ### [`embeds_many`](https://github.com/rodrigues/transcriber/tree/master/examples/embeds_many)
119
+ ### [embeds_many](https://github.com/rodrigues/transcriber/tree/master/examples/embeds_many)
120
120
 
121
121
  class OrderItems < Transcriber::Resource
122
122
  property :item_id, id: true # default serialization: String
@@ -150,7 +150,9 @@ Just define your `User` class like this:
150
150
 
151
151
  ## Relations
152
152
 
153
- ### `has_one`, `has_many` and `belongs_to`
153
+ ### has_one
154
+ ### has_many
155
+ ### belongs_to
154
156
 
155
157
  class User < Transcriber::Resource
156
158
  id
@@ -163,7 +165,7 @@ Just define your `User` class like this:
163
165
  {
164
166
  id: 19837139879,
165
167
  login: 'jsmith180',
166
- links: [
168
+ link: [
167
169
  {
168
170
  rel: 'avatar',
169
171
  href: 'http://app/api/users/19837139879/avatar'
@@ -195,7 +197,7 @@ If you want your api to handle `http://app/api/users/19371897318937?include[]=av
195
197
  guilda: {
196
198
  name: 'K1ll3rs'
197
199
  },
198
- links: [
200
+ link: [
199
201
  {
200
202
  rel: 'achievements',
201
203
  href: 'http://app/api/users/19837139879/achievements'
data/examples/all.rb CHANGED
@@ -1,14 +1,10 @@
1
1
  $:.push 'lib'; require 'transcriber'
2
2
 
3
3
  Dir["examples/*/**.rb"].each do |file|
4
- [:Root, :Item, :Customer, :Entry].each do |klass|
4
+ [:Root, :Item, :Customer, :Entry, :Service].each do |klass|
5
5
  Object.send(:remove_const, klass) if Object.const_defined? klass
6
6
  end
7
7
 
8
- puts
9
- puts
10
- p "example file: #{file}"
11
- puts
12
- puts
8
+ puts "\n\nexample file: #{file}\n\n"
13
9
  load file
14
10
  end
@@ -1,14 +1,14 @@
1
1
  $:.push 'lib'; require 'transcriber'
2
2
 
3
3
  class Item < Transcriber::Resource
4
- property :id
4
+ property :id, type: Integer
5
5
  end
6
6
 
7
7
  class Root < Transcriber::Resource
8
8
  embeds_many :items
9
9
  end
10
10
 
11
- @root = Root.parse({"items" => [{"id" => 2000}]}).first
11
+ @root = Root.parse({"items" => [{"id" => 2000}, {"id" => 2001}]}).first
12
12
 
13
13
  puts "root: #{@root.inspect}"
14
14
  puts "resource: #{@root.resource}"
@@ -1,14 +1,14 @@
1
1
  $:.push 'lib'; require 'transcriber'
2
2
 
3
3
  class Entry < Transcriber::Resource
4
- property :id
4
+ property :id, type: Integer
5
5
  end
6
6
 
7
7
  class Root < Transcriber::Resource
8
8
  embeds_many :items, class_name: :entry
9
9
  end
10
10
 
11
- root = Root.parse({"items" => [{"id" => 2000}]}).first
11
+ @root = Root.parse({"items" => [{"id" => 2000}]}).first
12
12
 
13
- puts "root: #{root.inspect}"
14
- puts "resource: #{root.resource}"
13
+ puts "root: #{@root.inspect}"
14
+ puts "resource: #{@root.resource}"
@@ -9,13 +9,13 @@ class Root < Transcriber::Resource
9
9
  embeds_many :items, if: proc {id == "10"}
10
10
  end
11
11
 
12
- root = Root.parse({"id" => 10, "items" => [{"id" => 2000}]}).first
12
+ @root_with_items = Root.parse({"id" => 10, "items" => [{"id" => 2000}]}).first
13
13
 
14
- puts "root: #{root.inspect}"
15
- puts "resource: #{root.resource}"
14
+ puts "root: #{@root_with_items.inspect}"
15
+ puts "resource: #{@root_with_items.resource}"
16
16
 
17
17
 
18
- root = Root.parse({"id" => 1, "items" => [{"id" => 2000}]}).first
18
+ @root_without_items = Root.parse({"id" => 1, "items" => [{"id" => 2000}]}).first
19
19
 
20
- puts "root: #{root.inspect}"
21
- puts "resource: #{root.resource}"
20
+ puts "root: #{@root_without_items.inspect}"
21
+ puts "resource: #{@root_without_items.resource}"
@@ -10,8 +10,8 @@ class Root < Transcriber::Resource
10
10
  embeds_many :items, start_key: 'detalhe.itens'
11
11
  end
12
12
 
13
- root = Root.parse({"detalhe" => {"itens" => [{"item_id" => 2000}]}}).first
13
+ @root = Root.parse({"detalhe" => {"itens" => [{"item_id" => 2000}]}}).first
14
14
 
15
- puts "root: #{root.inspect}"
16
- puts "resource: #{root.resource}"
17
- puts "to_json: #{root.resource.to_json}"
15
+ puts "root: #{@root.inspect}"
16
+ puts "resource: #{@root.resource}"
17
+ puts "to_json: #{@root.resource.to_json}"
@@ -8,7 +8,7 @@ class Item < Transcriber::Resource
8
8
  property :id
9
9
  end
10
10
 
11
- root = Root.parse({"item" => {"id" => 2000}}).first
11
+ @root = Root.parse({"item" => {"id" => 2000}}).first
12
12
 
13
- puts "root: #{root.inspect}"
14
- puts "resource: #{root.resource}"
13
+ puts "root: #{@root.inspect}"
14
+ puts "resource: #{@root.resource}"
@@ -8,7 +8,7 @@ class Root < Transcriber::Resource
8
8
  embeds_one :item, class_name: :entry
9
9
  end
10
10
 
11
- root = Root.parse({"item" => {"id" => 2000}}).first
11
+ @root = Root.parse({"item" => {"id" => 2000}}).first
12
12
 
13
- puts "root: #{root.inspect}"
14
- puts "resource: #{root.resource}"
13
+ puts "root: #{@root.inspect}"
14
+ puts "resource: #{@root.resource}"
@@ -9,13 +9,13 @@ class Item < Transcriber::Resource
9
9
  property :id
10
10
  end
11
11
 
12
- root = Root.parse({"id"=> 1, "item" => {"id" => 2000}}).first
12
+ @root_with_item = Root.parse({"id"=> 1, "item" => {"id" => 2000}}).first
13
13
 
14
- puts "root: #{root.inspect}"
15
- puts "resource: #{root.resource}"
14
+ puts "root: #{@root_with_item.inspect}"
15
+ puts "resource: #{@root_with_item.resource}"
16
16
 
17
17
 
18
- root = Root.parse({"id"=> 100, "item" => {"id" => 2000}}).first
18
+ @root_without_item = Root.parse({"id"=> 100, "item" => {"id" => 2000}}).first
19
19
 
20
- puts "root: #{root.inspect}"
21
- puts "resource: #{root.resource}"
20
+ puts "root: #{@root_without_item.inspect}"
21
+ puts "resource: #{@root_without_item.resource}"
@@ -8,7 +8,7 @@ class Item < Transcriber::Resource
8
8
  property :id
9
9
  end
10
10
 
11
- root = Root.parse({"ugly_nesting_key" => {"id" => 2000}}).first
11
+ @root = Root.parse({"ugly_nesting_key" => {"id" => 2000}}).first
12
12
 
13
- puts "root: #{root.inspect}"
14
- puts "resource: #{root.resource}"
13
+ puts "root: #{@root.inspect}"
14
+ puts "resource: #{@root.resource}"
@@ -16,14 +16,14 @@ class Developer < Transcriber::Resource
16
16
  end
17
17
 
18
18
  class Customer < Transcriber::Resource
19
- id field: :customer_id
19
+ id field: :customer_id, type: Integer
20
20
  property :login
21
21
  has_many :services
22
22
  has_one :billing
23
- has_one :devopada, class_name: :developer
23
+ has_one :devops, class_name: :developer
24
24
  end
25
25
 
26
- @root = Customer.parse({"customer_id" => 123, "login" => 2000}).first
26
+ @root = Customer.parse({"customer_id" => 123, "login" => 'jackiechan2010'}).first
27
27
 
28
28
  puts "root: #{@root.inspect}"
29
29
  puts "resource: #{@root.resource}"
@@ -0,0 +1,12 @@
1
+ $:.push 'lib'; require 'transcriber'
2
+
3
+ class Customer < Transcriber::Resource
4
+ property :login
5
+ end
6
+
7
+ @customers = Customer.parse([{"login" => "jackiechan2010"},
8
+ {"login" => "brucelee"},
9
+ {"login" => "vcr2"}])
10
+
11
+ puts "root: #{@customers.inspect}"
12
+ puts "resource: #{Customer.resources @customers}"
@@ -4,7 +4,7 @@ class Customer < Transcriber::Resource
4
4
  property :login
5
5
  end
6
6
 
7
- root = Customer.parse({"login" => 2000}).first
7
+ @root = Customer.parse({"login" => 'jackiechan2010'}).first
8
8
 
9
- puts "root: #{root.inspect}"
10
- puts "resource: #{root.resource}"
9
+ puts "root: #{@root.inspect}"
10
+ puts "resource: #{@root.resource}"
@@ -4,7 +4,7 @@ class Customer < Transcriber::Resource
4
4
  property :login, field: :customer_login
5
5
  end
6
6
 
7
- root = Customer.parse({"customer_login" => 2000}).first
7
+ @root = Customer.parse({"customer_login" => 'jackiechan2010'}).first
8
8
 
9
- puts "root: #{root.inspect}"
10
- puts "resource: #{root.resource}"
9
+ puts "root: #{@root.inspect}"
10
+ puts "resource: #{@root.resource}"
@@ -4,7 +4,7 @@ class Customer < Transcriber::Resource
4
4
  property :login, field: 'hidden.login'
5
5
  end
6
6
 
7
- root = Customer.parse({"hidden" => {"login" => 2000}}).first
7
+ @root = Customer.parse({"hidden" => {"login" => 'jackiechan2010'}}).first
8
8
 
9
- puts "root: #{root.inspect}"
10
- puts "resource: #{root.resource}"
9
+ puts "root: #{@root.inspect}"
10
+ puts "resource: #{@root.resource}"
@@ -4,7 +4,7 @@ class Customer < Transcriber::Resource
4
4
  id
5
5
  end
6
6
 
7
- root = Customer.parse({"id" => 2000}).first
7
+ @root = Customer.parse({"id" => 2000}).first
8
8
 
9
- puts "root: #{root.inspect}"
10
- puts "resource: #{root.resource}"
9
+ puts "root: #{@root.inspect}"
10
+ puts "resource: #{@root.resource}"
@@ -3,17 +3,23 @@ $:.push 'lib'; require 'transcriber'
3
3
  class Customer < Transcriber::Resource
4
4
  property :login
5
5
  property :password
6
- property :some_text, if: proc {password == "abc"}
6
+ property :description, if: proc {password == "abc"}
7
7
  end
8
8
 
9
- root = Customer.parse({"login" => 2000, "password" => "abc", "some_text" => "some text"}).first
9
+ @root_with_description = Customer.parse({
10
+ "login" => 2000,
11
+ "password" => "abc",
12
+ "description" => "description"}).first
10
13
 
11
14
 
12
- puts "root: #{root.inspect}"
13
- puts "resource: #{root.resource}"
15
+ puts "root: #{@root_with_description.inspect}"
16
+ puts "resource: #{@root_with_description.resource}"
14
17
 
15
18
 
16
- root = Customer.parse({"login" => 2000, "password" => "abcd", "some_text" => "some text II"}).first
19
+ @root_without_description = Customer.parse({
20
+ "login" => 2000,
21
+ "password" => "abcd",
22
+ "description" => "some text II"}).first
17
23
 
18
- puts "root: #{root.inspect}"
19
- puts "resource: #{root.resource}"
24
+ puts "root: #{@root_without_description.inspect}"
25
+ puts "resource: #{@root_without_description.resource}"
@@ -14,7 +14,7 @@ class Customer < Transcriber::Resource
14
14
  property :login
15
15
  end
16
16
 
17
- root = Customer.parse({"LOGIN" => 2000}).first
17
+ @root = Customer.parse({"LOGIN" => 'jackiechan2010'}).first
18
18
 
19
- puts "root: #{root.inspect}"
20
- puts "resource: #{root.resource}"
19
+ puts "root: #{@root.inspect}"
20
+ puts "resource: #{@root.resource}"
@@ -0,0 +1,29 @@
1
+ $:.push 'lib'; require 'transcriber'
2
+
3
+ module Upcasing
4
+ def self.call(keys)
5
+ keys.map {|key| key.to_s.upcase}
6
+ end
7
+ end
8
+
9
+ module Camelizing
10
+ def self.call(keys)
11
+ keys.map {|key| key.to_s.camelize}
12
+ end
13
+ end
14
+
15
+ class Customer < Transcriber::Resource
16
+ convert_input_keys Upcasing
17
+ property :login
18
+ embeds_one :product
19
+ end
20
+
21
+ class Product < Transcriber::Resource
22
+ convert_input_keys Camelizing
23
+ property :unit_price, type: Float
24
+ end
25
+
26
+ @root = Customer.parse({"LOGIN" => 'jackiechan2010', "PRODUCT" => {"UnitPrice" => 29.9}}).first
27
+
28
+ puts "root: #{@root.inspect}"
29
+ puts "resource: #{@root.resource}"
@@ -0,0 +1,27 @@
1
+ $:.push 'lib'; require 'transcriber'
2
+
3
+ module AsDefined
4
+ def self.call(keys)
5
+ keys
6
+ end
7
+ end
8
+
9
+ class Customer < Transcriber::Resource
10
+ convert_input_keys AsDefined
11
+ id
12
+ properties :login, :name, :postal_code, :email, :secondary_email
13
+ summarizes :id, :login
14
+ end
15
+
16
+ input = {
17
+ id: 138911938,
18
+ login: 'jackiechan2010',
19
+ name: 'jackie chan',
20
+ postal_code: '05492-092',
21
+ email: 'jachan@gmail.com',
22
+ secondary_email: 'jackiepeligroso@yahoo.com'
23
+ }
24
+
25
+ @root = Customer.transcribe(input)
26
+
27
+ puts "resources: #{@root.inspect}"
data/lib/transcriber.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'date'
2
2
  require 'active_support/inflector'
3
+ require 'active_support/concern'
3
4
  require 'active_support/core_ext/class/attribute_accessors'
4
5
  require 'active_support/core_ext/object/try'
5
6
  require 'active_support/core_ext/array/wrap'
@@ -19,14 +20,17 @@ require 'transcriber/resource/parser/embeddable'
19
20
  require 'transcriber/resource/response/property'
20
21
  require 'transcriber/resource/response/embeddable'
21
22
  require 'transcriber/resource/response/relation'
23
+ require 'transcriber/resource/response/href'
22
24
  require 'transcriber/resource/key/property'
23
25
  require 'transcriber/resource/key/association'
24
26
  require 'transcriber/resource/key/relation'
25
27
  require 'transcriber/resource/key/embeddable'
28
+ require 'transcriber/resource/key/href'
26
29
  require 'transcriber/resource/builder/keys'
27
30
  require 'transcriber/resource/builder/relations'
28
31
  require 'transcriber/resource/builder/embeddables'
29
32
  require 'transcriber/resource/builder/properties'
33
+ require 'transcriber/resource/builder/summarizations'
30
34
  require 'transcriber/resource/builder'
31
35
  require 'transcriber/resource'
32
36
  require 'transcriber/configuration'
@@ -39,4 +43,8 @@ module Transcriber
39
43
  def self.configure
40
44
  yield configuration if block_given?
41
45
  end
46
+
47
+ def self.host
48
+ configuration.host
49
+ end
42
50
  end
@@ -1,5 +1,7 @@
1
1
  module Transcriber
2
2
  class Configuration
3
+ attr_accessor :host
4
+
3
5
  DefaultHandler = lambda {|keys| keys.map(&:to_s)}
4
6
 
5
7
  def convert_input_keys
@@ -2,7 +2,7 @@ module Transcriber
2
2
  class Resource
3
3
  extend Builder
4
4
  extend Parser
5
- extend Response
5
+ include Response
6
6
  include Serialization
7
7
 
8
8
  cattr_accessor :id_key
@@ -16,6 +16,10 @@ module Transcriber
16
16
  @keys ||= []
17
17
  end
18
18
 
19
+ def self.summarized_keys
20
+ @summarized_keys ||= []
21
+ end
22
+
19
23
  def self.relations
20
24
  @keys.find_all {|k| k.kind_of?(Relation)}
21
25
  end
@@ -24,24 +28,13 @@ module Transcriber
24
28
  @resource_name ||= custom_name or to_s.demodulize.tableize
25
29
  end
26
30
 
27
- def resource_id
28
- __send__(id_key.name)
29
- end
30
-
31
- def resource(options = {})
32
- root = options.fetch(:root, true)
33
- {}.tap do |resource|
34
- self.class.keys.inject(resource) {|buffer, key| buffer.merge!(key.to_resource(self))}
35
- resource.merge!({links: links}) if root and self.class.relations.any?
36
- end
37
- end
38
-
39
- def links
40
- self.class.relations.map {|key| key.to_relation(self)}
31
+ def self.convert_input_keys(converter = nil)
32
+ @convert_input_keys = converter if converter
33
+ @convert_input_keys
41
34
  end
42
35
 
43
- def self.transcribe(input, options = {})
44
- normalize(parse(input, options), options)
36
+ def resource_id
37
+ __send__(id_key.name)
45
38
  end
46
39
 
47
40
  def self.method_added(method_name)
@@ -50,7 +43,7 @@ module Transcriber
50
43
  end
51
44
 
52
45
  def self.not_allowed_names
53
- ["resource_id", "resource", "links"]
46
+ ["resource_id", "resource", "link"]
54
47
  end
55
48
  end
56
49
  end
@@ -5,6 +5,7 @@ module Transcriber
5
5
  include Relations
6
6
  include Embeddables
7
7
  include Properties
8
+ include Summarizations
8
9
  end
9
10
  end
10
11
  end
@@ -4,6 +4,7 @@ module Transcriber
4
4
  module Keys
5
5
  def key(key)
6
6
  fail "you can't define a key with name '#{key.name}'" if not_allowed?(key)
7
+ key.model = self
7
8
  attr_accessor key.name
8
9
  self.keys << key
9
10
  self.id_key = key if key.options[:id]
@@ -1,11 +1,11 @@
1
1
  module Transcriber
2
2
  class Resource
3
3
  module Builder
4
- module Summarization
5
- def summarizes(*args = [])
4
+ module Summarizations
5
+ def summarizes(*args)
6
6
  args.each do |name|
7
7
  key = keys.find {|key| key.name == name}
8
- key.summarize = true if key
8
+ summarized_keys << key if key
9
9
  end
10
10
  end
11
11
  end
@@ -2,6 +2,7 @@ module Transcriber
2
2
  class Resource
3
3
  class Key
4
4
  attr_accessor :name
5
+ attr_accessor :model
5
6
  attr_accessor :options
6
7
  attr_accessor :summarize
7
8
 
@@ -31,7 +32,8 @@ module Transcriber
31
32
  end
32
33
 
33
34
  def convert_input_keys
34
- options.fetch(:convert_input_keys, Transcriber.configuration.convert_input_keys)
35
+ options.fetch(:convert_input_keys, model.try(:convert_input_keys) ||
36
+ Transcriber.configuration.convert_input_keys)
35
37
  end
36
38
  end
37
39
  end
@@ -0,0 +1,11 @@
1
+ module Transcriber
2
+ class Resource
3
+ class Href < Key
4
+ include Response::Href
5
+
6
+ def initialize
7
+ super(:href)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,8 +1,14 @@
1
1
  module Transcriber
2
2
  class Resource
3
3
  module Parser
4
+ def parse!(input, options = {})
5
+ parse(input, options.merge(fail: true))
6
+ end
7
+
4
8
  def parse(input, options = {})
5
- prepare_entries(input, options).collect &method(:parse_item)
9
+ prepare_entries(input, options).collect do |item|
10
+ parse_item(item, options)
11
+ end
6
12
  end
7
13
 
8
14
  private
@@ -12,11 +18,15 @@ module Transcriber
12
18
  Array.wrap digg(input, path)
13
19
  end
14
20
 
15
- def parse_item(item)
21
+ def parse_item(item, options)
16
22
  self.new.tap do |resource|
17
23
  keys.each do |key|
18
24
  value = digg(item, key.input_path)
19
- resource.__send__("#{key.name}=", key.parse(value, resource)) if key.present?(resource)
25
+ begin
26
+ resource.__send__("#{key.name}=", key.parse(value, resource)) if key.present?(resource)
27
+ rescue => exception
28
+ raise exception if options[:fail]
29
+ end
20
30
  end
21
31
  end
22
32
  end
@@ -1,12 +1,44 @@
1
1
  module Transcriber
2
2
  class Resource
3
3
  module Response
4
- def normalize(model, options = {})
5
- model.kind_of?(Enumerable) ?
6
- {entries: model.map(&:resource)}
7
- : model.resource
4
+ extend ActiveSupport::Concern
5
+
6
+ def resource(options = {})
7
+ root = options.fetch(:root, true)
8
+ {}.tap do |resource|
9
+ resource_keys(options).inject(resource) do |buffer, key|
10
+ buffer.merge!(key.to_resource(self))
11
+ end
12
+ resource.merge!({link: link}) if root and self.class.relations.any?
13
+ end
14
+ end
15
+
16
+ def link
17
+ self.class.relations.map {|key| key.to_relation(self)}
18
+ end
19
+
20
+ def resource_keys(options)
21
+ return self.class.keys unless summarize?(options)
22
+ self.class.summarized_keys + [Resource::Href.new]
23
+ end
24
+
25
+ def summarize?(options)
26
+ options[:summarize] and self.class.summarized_keys.any?
27
+ end
28
+
29
+ module ClassMethods
30
+ def normalize(model, options = {})
31
+ model.kind_of?(Enumerable) ?
32
+ {entries: model.map {|m| m.resource(options.merge(summarize: true))}}
33
+ : model.resource(options)
34
+ end
35
+
36
+ alias :resources :normalize
37
+
38
+ def transcribe(input, options = {})
39
+ normalize(parse(input, options), options)
40
+ end
8
41
  end
9
- alias :resources :normalize
10
42
  end
11
43
  end
12
44
  end
@@ -0,0 +1,12 @@
1
+ module Transcriber
2
+ class Resource
3
+ module Response
4
+ module Href
5
+ def to_resource(parent)
6
+ id_key = parent.class.id_key.name
7
+ {name => "#{Transcriber.host}/#{parent.class.resource_name}/#{parent.send(id_key)}"}
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -9,7 +9,7 @@ module Transcriber
9
9
  end
10
10
 
11
11
  def to_relation(parent)
12
- {:rel => name, :href => href(parent)}
12
+ {rel: name, href: href(parent)}
13
13
  end
14
14
 
15
15
  private
@@ -29,9 +29,10 @@ module Transcriber
29
29
  end
30
30
 
31
31
  def href(parent)
32
+ id_key = parent.class.id_key.name
32
33
  has? ?
33
- "/#{parent.class.resource_name}/#{parent.id}/#{relation_name(parent)}"
34
- : "/#{relation_name(parent).to_s.pluralize}/#{parent.id}/#{parent.class.resource_name}"
34
+ "#{Transcriber.host}/#{parent.class.resource_name}/#{parent.send(id_key)}/#{relation_name(parent)}"
35
+ : "#{Transcriber.host}/#{relation_name(parent).to_s.pluralize}/#{parent.send(id_key)}/#{parent.class.resource_name}"
35
36
  end
36
37
  end
37
38
  end
@@ -1,3 +1,3 @@
1
1
  module Transcriber
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe_example 'embeds_many/simple' do
4
+ it 'parses first embedded item' do
5
+ root.items[0].id.should == 2000
6
+ end
7
+
8
+ it 'parses second embedded item' do
9
+ root.items[1].id.should == 2001
10
+ end
11
+ end
12
+
13
+
14
+ describe_example 'embeds_many/invisible' do
15
+ it 'parses invisible item correctly' do
16
+ root.locale.should == 'pt-BR'
17
+ end
18
+
19
+ it "doesn't show embedded items in resource" do
20
+ root.resource.should_not have_key('locale')
21
+ end
22
+ end
23
+
24
+ describe_example 'embeds_many/with_class_name' do
25
+ it 'parses embedded item' do
26
+ root.items[0].id.should == 2000
27
+ end
28
+ end
29
+
30
+ describe_example 'embeds_many/with_if' do
31
+ context 'when an embeddable has a conditional proc (:if)' do
32
+ context 'and it evaluates to true' do
33
+ it 'parses embedded item' do
34
+ root_with_items.items.first.id.should == "2000"
35
+ end
36
+ end
37
+
38
+ context 'and it evaluates to false' do
39
+ it "doesn't parse embedded item" do
40
+ root_without_items.items.should_not be
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ describe_example 'embeds_many/with_start_key' do
47
+ it 'parses embedded items' do
48
+ root.items.first.id.should == "2000"
49
+ end
50
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe_example "embeds_one/simple" do
4
+ it 'parses embedded item' do
5
+ root.item.id.should == "2000"
6
+ end
7
+ end
8
+
9
+ describe_example "embeds_one/with_class_name" do
10
+ context 'when a different class name is used for embeddable' do
11
+ it 'parses embedded item' do
12
+ root.item.id.should == "2000"
13
+ end
14
+ end
15
+ end
16
+
17
+ describe_example "embeds_one/with_if" do
18
+ context 'when an embeddable has a conditional proc (:if)' do
19
+ context 'and it evaluates to true' do
20
+ it 'parses embedded item' do
21
+ root_with_item.id.should == "1"
22
+ root_with_item.item.id.should == "2000"
23
+ end
24
+ end
25
+
26
+ context 'and it evaluates to false' do
27
+ it "doesn't parse embedded item" do
28
+ root_without_item.id.should == "100"
29
+ root_without_item.item.should_not be
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ describe_example "embeds_one/with_start_key" do
36
+ context 'when there is a start key to parse input' do
37
+ it 'parses embedded item' do
38
+ root.item.id.should == "2000"
39
+ end
40
+ end
41
+ end
@@ -1,9 +1,27 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "has many" do
4
- context_from_example "has_many/simple" do
5
- it "sets root" do
6
- root.resource.should be_a(Hash)
3
+ describe_example "has_many/simple" do
4
+ it 'parses properly' do
5
+ root.id.should == 123
6
+ root.login.should == 'jackiechan2010'
7
+ end
8
+
9
+ describe "#resource" do
10
+ subject {root.resource}
11
+
12
+ it 'has a link' do
13
+ subject[:link].should be_an(Array)
14
+ end
15
+
16
+ [:services, :billing, :devops].each do |rel|
17
+ it "has a #{rel} relation" do
18
+ subject[:link].any? {|l| l[:rel] == rel}.should be_true
19
+ end
20
+
21
+ it "has a href for #{rel} relation" do
22
+ link = subject[:link].find {|l| l[:rel] == rel}
23
+ link[:href].should =~ %r{/customers/123/#{rel}}
24
+ end
7
25
  end
8
26
  end
9
27
  end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ def it_parses_property
4
+ it 'parses property' do
5
+ root.login.should == 'jackiechan2010'
6
+ end
7
+ end
8
+
9
+ describe_example 'properties/simple' do
10
+ it_parses_property
11
+ end
12
+
13
+ describe_example 'properties/with_field' do
14
+ context 'when input has a different name for the property' do
15
+ it_parses_property
16
+ end
17
+ end
18
+
19
+ describe_example 'properties/with_field_path' do
20
+ context 'when input has a different path for the property' do
21
+ it_parses_property
22
+ end
23
+ end
24
+
25
+ describe_example 'properties/with_id' do
26
+ context 'when property is an id' do
27
+ it 'parses id' do
28
+ root.id.should == "2000"
29
+ end
30
+ end
31
+ end
32
+
33
+ describe_example 'properties/with_if' do
34
+ context 'when a property has a conditional proc (:if)' do
35
+ context 'and it evaluates to true' do
36
+ it 'parses property' do
37
+ root_with_description.description.should == "description"
38
+ end
39
+ end
40
+
41
+ context 'and it evaluates to false' do
42
+ it "doesn't parse property" do
43
+ root_without_description.description.should_not be
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ describe_example 'properties/with_key_converter' do
50
+ after do
51
+ Transcriber.configure do |c|
52
+ c.convert_input_keys = nil
53
+ end
54
+ end
55
+
56
+ context 'when a diferent key converter is configured on transcriber' do
57
+ it_parses_property
58
+ end
59
+ end
60
+
61
+ describe_example 'properties/with_two_key_converters' do
62
+ context 'when key converters are configured for each class' do
63
+ it_parses_property
64
+
65
+ it 'parses other property with different key converter' do
66
+ root.product.unit_price.should == 29.9
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe_example 'summarization/simple' do
4
+
5
+ subject {root[:entries].first}
6
+
7
+ it 'summarizes resources' do
8
+ subject.keys.count.should == 3
9
+ subject[:id].should == '138911938'
10
+ subject[:login].should == 'jackiechan2010'
11
+ subject[:href].should == 'http://example.com/customers/138911938'
12
+ end
13
+ end
data/spec/spec_helper.rb CHANGED
@@ -10,7 +10,7 @@ require 'support/examples'
10
10
  require 'support/out'
11
11
 
12
12
  RSpec.configure do |config|
13
- config.before(:each) do
13
+ config.before do
14
14
  [:Example, :ExampleChild].each do |klass|
15
15
  Object.send(:remove_const, klass) if Object.const_defined? klass
16
16
  end
@@ -20,3 +20,7 @@ end
20
20
  include Transcriber
21
21
  include Output
22
22
  include Examples
23
+
24
+ Transcriber.configure do |c|
25
+ c.host = 'http://example.com'
26
+ end
@@ -1,6 +1,10 @@
1
1
  module Examples
2
- def context_from_example(file, &block)
3
- context "example #{file}" do
2
+ def describe_example(file, &block)
3
+ describe "example #{file}" do
4
+ [:Root, :Item, :Customer, :Entry].each do |klass|
5
+ Examples.send(:remove_const, klass) if Examples.const_defined?(klass)
6
+ end
7
+
4
8
  silently {eval File.read("examples/#{file}.rb")}
5
9
 
6
10
  variables = instance_variables.reject {|var| var.to_s =~ /metadata$/}
@@ -53,13 +53,7 @@ describe Resource::InputPath do
53
53
  end
54
54
 
55
55
  context "and there is a custom keys input converter" do
56
- let(:options) do
57
- {
58
- start_key: 'yay.upcase.path',
59
- convert_input_keys: Upcasing
60
- }
61
- end
62
-
56
+ let(:options) {{start_key: 'yay.upcase.path', convert_input_keys: Upcasing}}
63
57
  subject {Resource::Key.new(:name, options)}
64
58
  let(:path) {['YAY', 'UPCASE', 'PATH']}
65
59
  it_behaves_like "an input path"
@@ -44,7 +44,7 @@ describe Resource::Response do
44
44
  subject {Example.keys[1]}
45
45
 
46
46
  let(:example) {Example.new(id: 100)}
47
- let(:result) {{rel: :example_child, href: "/examples/100/example_child"}}
47
+ let(:result) {{rel: :example_child, href: "http://example.com/examples/100/example_child"}}
48
48
 
49
49
  it_behaves_like "a relation"
50
50
  end
@@ -65,7 +65,7 @@ describe Resource::Response do
65
65
  subject {Example.keys[1]}
66
66
 
67
67
  let(:example) {Example.new(id: 200)}
68
- let(:result) {{rel: :example_children, href: "/examples/200/example_children"}}
68
+ let(:result) {{rel: :example_children, href: "http://example.com/examples/200/example_children"}}
69
69
 
70
70
  it_behaves_like "a relation"
71
71
  end
@@ -86,7 +86,7 @@ describe Resource::Response do
86
86
  subject {ExampleChild.keys[1]}
87
87
 
88
88
  let(:example) {ExampleChild.new(id: 200)}
89
- let(:result) {{rel: :example, href: "/examples/200/example_children"}}
89
+ let(:result) {{rel: :example, href: "http://example.com/examples/200/example_children"}}
90
90
 
91
91
  it_behaves_like "a relation"
92
92
  end
@@ -17,7 +17,7 @@ describe Resource do
17
17
  end
18
18
 
19
19
  context "when using not allowed names" do
20
- [:resource_id, :resource, :links].each do |unallowed|
20
+ [:resource_id, :resource, :link].each do |unallowed|
21
21
  it "warns when method #{unallowed} is redefined" do
22
22
  output = out do
23
23
  eval <<-RUBY
data/transcriber.gemspec CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.require_paths = ["lib"]
19
19
 
20
20
  s.add_dependency "activesupport", "~> 3.0"
21
- s.add_dependency "i18n", "~> 0.6"
21
+ s.add_dependency "i18n", ">= 0.5"
22
22
  s.add_development_dependency "rspec", "~> 2.6"
23
23
  s.add_development_dependency "guard", "~> 0.5"
24
24
  s.add_development_dependency "guard-rspec", "~> 0.4"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: transcriber
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,11 +11,11 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2011-08-15 00:00:00.000000000Z
14
+ date: 2011-08-23 00:00:00.000000000Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: activesupport
18
- requirement: &70342384534920 !ruby/object:Gem::Requirement
18
+ requirement: &70173958045380 !ruby/object:Gem::Requirement
19
19
  none: false
20
20
  requirements:
21
21
  - - ~>
@@ -23,21 +23,21 @@ dependencies:
23
23
  version: '3.0'
24
24
  type: :runtime
25
25
  prerelease: false
26
- version_requirements: *70342384534920
26
+ version_requirements: *70173958045380
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: i18n
29
- requirement: &70342384534420 !ruby/object:Gem::Requirement
29
+ requirement: &70173958044880 !ruby/object:Gem::Requirement
30
30
  none: false
31
31
  requirements:
32
- - - ~>
32
+ - - ! '>='
33
33
  - !ruby/object:Gem::Version
34
- version: '0.6'
34
+ version: '0.5'
35
35
  type: :runtime
36
36
  prerelease: false
37
- version_requirements: *70342384534420
37
+ version_requirements: *70173958044880
38
38
  - !ruby/object:Gem::Dependency
39
39
  name: rspec
40
- requirement: &70342384533960 !ruby/object:Gem::Requirement
40
+ requirement: &70173958044420 !ruby/object:Gem::Requirement
41
41
  none: false
42
42
  requirements:
43
43
  - - ~>
@@ -45,10 +45,10 @@ dependencies:
45
45
  version: '2.6'
46
46
  type: :development
47
47
  prerelease: false
48
- version_requirements: *70342384533960
48
+ version_requirements: *70173958044420
49
49
  - !ruby/object:Gem::Dependency
50
50
  name: guard
51
- requirement: &70342384533500 !ruby/object:Gem::Requirement
51
+ requirement: &70173958043920 !ruby/object:Gem::Requirement
52
52
  none: false
53
53
  requirements:
54
54
  - - ~>
@@ -56,10 +56,10 @@ dependencies:
56
56
  version: '0.5'
57
57
  type: :development
58
58
  prerelease: false
59
- version_requirements: *70342384533500
59
+ version_requirements: *70173958043920
60
60
  - !ruby/object:Gem::Dependency
61
61
  name: guard-rspec
62
- requirement: &70342384533040 !ruby/object:Gem::Requirement
62
+ requirement: &70173958043460 !ruby/object:Gem::Requirement
63
63
  none: false
64
64
  requirements:
65
65
  - - ~>
@@ -67,10 +67,10 @@ dependencies:
67
67
  version: '0.4'
68
68
  type: :development
69
69
  prerelease: false
70
- version_requirements: *70342384533040
70
+ version_requirements: *70173958043460
71
71
  - !ruby/object:Gem::Dependency
72
72
  name: growl
73
- requirement: &70342384532580 !ruby/object:Gem::Requirement
73
+ requirement: &70173958043000 !ruby/object:Gem::Requirement
74
74
  none: false
75
75
  requirements:
76
76
  - - ~>
@@ -78,7 +78,7 @@ dependencies:
78
78
  version: '1.0'
79
79
  type: :development
80
80
  prerelease: false
81
- version_requirements: *70342384532580
81
+ version_requirements: *70173958043000
82
82
  description: ''
83
83
  email:
84
84
  - victorcrodrigues@gmail.com
@@ -104,12 +104,15 @@ files:
104
104
  - examples/embeds_one/with_if.rb
105
105
  - examples/embeds_one/with_start_key.rb
106
106
  - examples/has_many/simple.rb
107
+ - examples/properties/collections.rb
107
108
  - examples/properties/simple.rb
108
109
  - examples/properties/with_field.rb
109
110
  - examples/properties/with_field_path.rb
110
111
  - examples/properties/with_id.rb
111
112
  - examples/properties/with_if.rb
112
113
  - examples/properties/with_key_converter.rb
114
+ - examples/properties/with_two_key_converters.rb
115
+ - examples/summarization/simple.rb
113
116
  - lib/transcriber.rb
114
117
  - lib/transcriber/configuration.rb
115
118
  - lib/transcriber/resource.rb
@@ -123,6 +126,7 @@ files:
123
126
  - lib/transcriber/resource/key.rb
124
127
  - lib/transcriber/resource/key/association.rb
125
128
  - lib/transcriber/resource/key/embeddable.rb
129
+ - lib/transcriber/resource/key/href.rb
126
130
  - lib/transcriber/resource/key/property.rb
127
131
  - lib/transcriber/resource/key/relation.rb
128
132
  - lib/transcriber/resource/parser.rb
@@ -130,6 +134,7 @@ files:
130
134
  - lib/transcriber/resource/parser/property.rb
131
135
  - lib/transcriber/resource/response.rb
132
136
  - lib/transcriber/resource/response/embeddable.rb
137
+ - lib/transcriber/resource/response/href.rb
133
138
  - lib/transcriber/resource/response/property.rb
134
139
  - lib/transcriber/resource/response/relation.rb
135
140
  - lib/transcriber/resource/serialization/boolean.rb
@@ -138,8 +143,11 @@ files:
138
143
  - lib/transcriber/resource/serialization/integer.rb
139
144
  - lib/transcriber/resource/serialization/string.rb
140
145
  - lib/transcriber/version.rb
146
+ - spec/integration/embeds_many_spec.rb
147
+ - spec/integration/embeds_one_spec.rb
141
148
  - spec/integration/has_many_spec.rb
142
149
  - spec/integration/property_spec.rb
150
+ - spec/integration/summarization_spec.rb
143
151
  - spec/spec_helper.rb
144
152
  - spec/support/examples.rb
145
153
  - spec/support/out.rb
@@ -194,8 +202,11 @@ signing_key:
194
202
  specification_version: 3
195
203
  summary: ''
196
204
  test_files:
205
+ - spec/integration/embeds_many_spec.rb
206
+ - spec/integration/embeds_one_spec.rb
197
207
  - spec/integration/has_many_spec.rb
198
208
  - spec/integration/property_spec.rb
209
+ - spec/integration/summarization_spec.rb
199
210
  - spec/spec_helper.rb
200
211
  - spec/support/examples.rb
201
212
  - spec/support/out.rb