roar 0.9.0 → 0.9.1

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.markdown CHANGED
@@ -1,3 +1,8 @@
1
+ h2. 0.9.1
2
+
3
+ * Removed @Representer#to_attributes@ and @#from_attributes@.
4
+ * Using representable-1.0.1 now.
5
+
1
6
  h2. 0.9.0
2
7
 
3
8
  * Using representable-0.12.x.
data/Rakefile CHANGED
@@ -3,7 +3,7 @@ Bundler::GemHelper.install_tasks
3
3
 
4
4
  require 'rake/testtask'
5
5
 
6
- task :default => [:test, :testrails]
6
+ task :default => [:test]
7
7
 
8
8
  Rake::TestTask.new(:test) do |test|
9
9
  test.libs << 'test'
@@ -1,12 +1,61 @@
1
- require 'test_xml/test_unit'
1
+ #require 'test_xml/test_unit'
2
+ require 'action_controller/test_case'
2
3
 
3
- ActionController::TestCase.class_eval do
4
+ module Roar::Rails
5
+ module TestCase
6
+ def process(action, *args)
7
+ raise
8
+ if args.first.is_a?(String)
9
+ puts "YO"
10
+ request.env['RAW_POST_DATA'] = args.shift
11
+ method = args.pop
12
+ args << nil
13
+ args << method
14
+ end
15
+
16
+ super
17
+ end
18
+
19
+ def assert_response(status, headers={}) # FIXME: allow message.
20
+ super
21
+
22
+ if headers.is_a?(Hash)
23
+ assert_headers(headers)
24
+ else
25
+ assert_body(headers)
26
+ end
27
+ end
28
+
29
+ def assert_headers(headers)
30
+ headers.each_pair do |k,v|
31
+ assert_equal v, @response.headers[k]
32
+ end
33
+ end
34
+
35
+ def assert_body(body, options={})
36
+ return assert_xml_equal body, @response.body if options[:format] == :xml # FIXME: how do we know whether assert_xml is appropriate?
37
+ assert_equal body, @response.body
38
+ end
39
+ end
40
+ end
41
+
42
+
43
+ ActionController::TestCase::Behavior.class_eval do
4
44
  # FIXME: ugly monkey-patching.
5
45
  # TODO: test:
6
46
  # put :create
7
47
  # put :create, :format => :xml
8
48
  # put :create, "<order/>", :format => :xml
9
49
  # put :create, "<order/>"
50
+
51
+
52
+ include Roar::Rails::TestCase
53
+ end
54
+
55
+ RSpec::Rails::ControllerExampleGroup.class_eval do
56
+ #include Roar::Rails::TestCase
57
+ # FIXME: include module!
58
+
10
59
  def process(action, *args)
11
60
  if args.first.is_a?(String)
12
61
  request.env['RAW_POST_DATA'] = args.shift
@@ -14,30 +63,7 @@ ActionController::TestCase.class_eval do
14
63
  args << nil
15
64
  args << method
16
65
  end
17
-
18
- super
19
- end
20
66
 
21
- def assert_response(status, headers={}) # FIXME: allow message.
22
67
  super
23
-
24
- if headers.is_a?(Hash)
25
- assert_headers(headers)
26
- else
27
- assert_body(headers)
28
- end
29
68
  end
30
-
31
- def assert_headers(headers)
32
- headers.each_pair do |k,v|
33
- assert_equal v, @response.headers[k]
34
- end
35
- end
36
-
37
- def assert_body(body, options={})
38
- return assert_xml_equal body, @response.body if options[:format] == :xml # FIXME: how do we know whether assert_xml is appropriate?
39
- assert_equal body, @response.body
40
- end
41
-
42
-
43
69
  end
@@ -5,40 +5,9 @@ module Roar
5
5
  def self.included(base)
6
6
  base.class_eval do
7
7
  include Representable
8
- extend ClassMethods
9
8
  end
10
9
  end
11
10
 
12
-
13
- module ClassMethods
14
- # Creates a representer instance and fills it with +attributes+.
15
- # DISCUSS: remove.
16
- def from_attributes(attributes) # DISCUSS: better move to #new? how do we handle the original #new then?
17
- new.tap do |representer|
18
- yield representer if block_given?
19
- attributes.each { |p,v| representer.public_send("#{p}=", v) }
20
- end
21
- end
22
- end
23
-
24
-
25
- # Convert representer's attributes to a nested attributes hash.
26
- def to_attributes
27
- {}.tap do |attributes|
28
- self.class.representable_attrs.each do |definition|
29
- value = public_send(definition.getter)
30
-
31
- if definition.typed?
32
- value = definition.apply(value) do |v|
33
- v.to_attributes # applied to each typed attribute (even in collections).
34
- end
35
- end
36
-
37
- attributes[definition.name] = value
38
- end
39
- end
40
- end
41
-
42
11
  private
43
12
  def before_serialize(*)
44
13
  end
@@ -38,10 +38,10 @@ module Roar
38
38
  hyperlink_class = links_def.sought_type
39
39
 
40
40
  links_def.rel2block.each do |link|
41
- links.update_link(hyperlink_class.from_attributes( # create Hyperlink representer.
42
- :rel => link[:rel],
43
- :href => run_link_block(link[:block]))
44
- )
41
+ links.update_link(hyperlink_class.new.tap do |hyperlink| # create Hyperlink representer.
42
+ hyperlink.rel = link[:rel]
43
+ hyperlink.href = run_link_block(link[:block])
44
+ end)
45
45
  end
46
46
  end
47
47
 
@@ -52,6 +52,7 @@ module Roar
52
52
  # Encapsulates a hypermedia link.
53
53
  class Hyperlink
54
54
  include JSON
55
+ attr_accessor :rel, :href
55
56
 
56
57
  property :rel
57
58
  property :href
@@ -50,12 +50,13 @@ module Roar
50
50
  # Encapsulates a hypermedia <link ...>.
51
51
  class Hyperlink
52
52
  # TODO: make XML a module to include in Hyperlink < Base.
53
+ attr_accessor :rel, :href
53
54
  include XML
54
55
 
55
56
  self.representation_wrap = :link
56
57
 
57
- property :rel, :from => "@rel"
58
- property :href, :from => "@href"
58
+ property :rel, :from => "rel", :attribute => true
59
+ property :href, :from => "href", :attribute => true
59
60
  end
60
61
 
61
62
  end
data/lib/roar/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Roar
2
- VERSION = "0.9.0"
2
+ VERSION = "0.9.1"
3
3
  end
data/roar.gemspec CHANGED
@@ -19,8 +19,7 @@ Gem::Specification.new do |s|
19
19
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
20
  s.require_paths = ["lib"]
21
21
 
22
- s.add_runtime_dependency "representable", "~> 0.12"
23
- s.add_runtime_dependency "hooks", "~> 0.1.4"
22
+ s.add_runtime_dependency "representable", "~> 1.0.1"
24
23
 
25
24
  s.add_development_dependency "test_xml"
26
25
  s.add_development_dependency "minitest", "~> 1.6.0"
@@ -10,19 +10,27 @@ class HttpVerbsTest < MiniTest::Spec
10
10
  property :label
11
11
  end
12
12
 
13
+ # keep this class clear of Roar modules.
14
+ class Band
15
+ attr_accessor :name, :label
16
+ end
17
+
18
+
13
19
  describe "HttpVerbs" do
14
20
  before do
15
- @band = Object.new
21
+ @band = Band.new
16
22
  @band.extend(BandRepresenter)
17
23
  @band.extend(Roar::Representer::Feature::HttpVerbs)
18
24
  end
19
25
 
20
26
  describe "HttpVerbs.get" do
21
27
  it "returns instance from incoming representation" do
28
+ # let's pretend the user wants Roar class methods.
22
29
  @Band = Class.new do
23
30
  include Roar::Representer::JSON
24
31
  include BandRepresenter
25
32
  include Roar::Representer::Feature::HttpVerbs
33
+ attr_accessor :name, :label
26
34
  end
27
35
  @band = @Band.get("http://localhost:9999/bands/slayer", "application/json")
28
36
  assert_equal "Slayer", @band.name
@@ -6,6 +6,7 @@ class HypermediaTest
6
6
  describe "Hypermedia Feature" do
7
7
  before do
8
8
  @bookmarks = Class.new do
9
+ include AttributesContructor
9
10
  include Roar::Representer::XML
10
11
  include Roar::Representer::Feature::Hypermedia
11
12
 
@@ -19,6 +20,8 @@ class HypermediaTest
19
20
  property :id
20
21
  link :self do "http://bookmarks" end
21
22
  link :all do "http://bookmarks/all" end
23
+
24
+ attr_accessor :id, :self, :all
22
25
  end
23
26
  end
24
27
 
@@ -29,7 +32,7 @@ class HypermediaTest
29
32
  <id>1</id>
30
33
  <link rel="self" href="http://bookmarks"/>
31
34
  <link rel="all" href="http://bookmarks/all"/>
32
- </bookmarks>', @bookmarks_with_links.from_attributes(:id => 1).to_xml
35
+ </bookmarks>', @bookmarks_with_links.new(:id => 1).to_xml
33
36
  end
34
37
 
35
38
  it "still works even if there are no links defined" do
@@ -40,7 +43,7 @@ class HypermediaTest
40
43
  assert_xml_equal '<bookmarks>
41
44
  <id>1</id>
42
45
  </bookmarks>',
43
- @bookmarks_with_links.from_attributes(:id => 1).to_xml(:links => false)
46
+ @bookmarks_with_links.new(:id => 1).to_xml(:links => false)
44
47
  end
45
48
  end
46
49
 
@@ -58,11 +61,13 @@ class HypermediaTest
58
61
 
59
62
  it "sets up links even when nested" do
60
63
  class Page
64
+ include AttributesContructor
61
65
  include Roar::Representer::JSON
62
66
  property :note, :class => Note
67
+ attr_accessor :note
63
68
  end
64
69
 
65
- assert_equal "{\"note\":{\"links\":[{\"rel\":\"self\",\"href\":\"http://me\"}]}}", Page.from_attributes(note: Note.new).to_json
70
+ assert_equal "{\"note\":{\"links\":[{\"rel\":\"self\",\"href\":\"http://me\"}]}}", Page.new(note: Note.new).to_json
66
71
  end
67
72
  end
68
73
 
@@ -78,7 +83,7 @@ class HypermediaTest
78
83
 
79
84
  assert_kind_of Roar::Representer::Feature::Hypermedia::LinkCollection, doc.links
80
85
  assert_equal 1, doc.links.size
81
- assert_equal({"rel"=>"self", "href"=>"http://bookmarks"}, doc.links.first.to_attributes)
86
+ assert_equal(["self", "http://bookmarks"], [doc.links.first.rel, doc.links.first.href])
82
87
  end
83
88
 
84
89
  it "sets up an empty link list if no links found in the document" do
@@ -92,8 +97,14 @@ class HypermediaTest
92
97
  @set = @bookmarks.new
93
98
  hyper = Roar::Representer::XML::Hyperlink
94
99
 
95
- @set.links = [hyper.from_attributes({"rel" => "self", "href" => "http://self"}),
96
- hyper.from_attributes({"rel" => "next", "href" => "http://next"})]
100
+ @set.links = [
101
+ {:rel => "self", :href => "http://self"},
102
+ {:rel => "next", :href => "http://next"}].collect do |config|
103
+ link = hyper.new
104
+ link.rel = config[:rel]
105
+ link.href = config[:href]
106
+ link
107
+ end
97
108
  end
98
109
 
99
110
  describe "#links=" do
@@ -160,7 +171,7 @@ class LinkCollectionTest < MiniTest::Spec
160
171
  describe "LinkCollection" do
161
172
  it "provides #update_link" do
162
173
  collection = Roar::Representer::Feature::Hypermedia::LinkCollection.new
163
- link = Roar::Representer::XML::Hyperlink.from_attributes(rel: "self", href: "http://self")
174
+ link = Roar::Representer::XML::Hyperlink.new(rel: "self", href: "http://self")
164
175
 
165
176
  collection.update_link(link)
166
177
  assert_equal 1, collection.size
@@ -8,6 +8,7 @@ class JsonRepresenterTest < MiniTest::Spec
8
8
  include Roar::Representer::JSON
9
9
  property :id
10
10
  property :pending
11
+ attr_accessor :id, :pending
11
12
  end
12
13
 
13
14
 
@@ -76,8 +77,10 @@ class JsonHypermediaTest
76
77
  describe "Hypermedia API" do
77
78
  before do
78
79
  @c = Class.new do
80
+ include AttributesContructor
79
81
  include Roar::Representer::JSON
80
82
  include Roar::Representer::Feature::Hypermedia
83
+ attr_accessor :id, :self, :next
81
84
 
82
85
  property :id
83
86
 
@@ -96,11 +99,11 @@ class JsonHypermediaTest
96
99
  @r = @c.from_json({:links => [{:rel => "self", :href => "http://self"}]}.to_json)
97
100
 
98
101
  assert_equal 1, @r.links.size
99
- assert_equal({"rel"=>"self", "href"=>"http://self"}, @r.links.first.to_attributes)
102
+ assert_equal(["self", "http://self"], [@r.links.first.rel, @r.links.first.href])
100
103
  end
101
104
 
102
105
  it "renders link: correctly in JSON" do
103
- assert_equal "{\"id\":1,\"links\":[{\"rel\":\"self\",\"href\":\"http://self\"},{\"rel\":\"next\",\"href\":\"http://next/1\"}]}", @c.from_attributes(:id => 1).to_json
106
+ assert_equal "{\"id\":1,\"links\":[{\"rel\":\"self\",\"href\":\"http://self\"},{\"rel\":\"next\",\"href\":\"http://next/1\"}]}", @c.new(:id => 1).to_json
104
107
  end
105
108
  end
106
109
  end
@@ -17,27 +17,6 @@ class RepresenterTest < MiniTest::Spec
17
17
  @c.collection :songs
18
18
  assert_equal "songs", @c.representable_attrs.first.name
19
19
  end
20
-
21
-
22
- describe "#from_attributes" do
23
- it "accepts a block yielding the created representer instance" do
24
- @c.class_eval { attr_accessor :name }
25
-
26
- assert_equal("Conan", @c.from_attributes({}) { |rep| rep.name = "Conan" }.name)
27
- end
28
-
29
- it "copies known properties, only, but doesn't complain" do
30
- @c.class_eval { property :id }
31
-
32
- assert_equal 1, @c.from_attributes("id" => 1, "unknown" => "don't use me").id
33
- end
34
-
35
- it "accepts symbols and strings as property name" do
36
- @c.class_eval { property :id }
37
-
38
- assert_equal @c.from_attributes(:id => 1).id, @c.from_attributes("id" => 1).id
39
- end
40
- end
41
20
  end
42
21
 
43
22
  describe "Inheritance" do
@@ -48,11 +27,13 @@ class RepresenterTest < MiniTest::Spec
48
27
  end
49
28
 
50
29
  class Person
30
+ include AttributesContructor
51
31
  include Roar::Representer::JSON
52
32
  include PersonRepresentation
33
+ attr_accessor :name
53
34
  end
54
35
 
55
- assert_equal "{\"name\":\"Paulo\"}", Person.from_attributes(:name => "Paulo").to_json
36
+ assert_equal "{\"name\":\"Paulo\"}", Person.new(:name => "Paulo").to_json
56
37
  end
57
38
 
58
39
  end
data/test/test_helper.rb CHANGED
@@ -8,6 +8,7 @@ require 'roar/representer'
8
8
  require 'roar/representer/feature/hypermedia'
9
9
  require 'roar/representer/feature/http_verbs'
10
10
 
11
+ # TODO: 2BRM.
11
12
  module TestModel
12
13
  def self.included(base)
13
14
  base.extend ClassMethods
@@ -31,6 +32,15 @@ require 'roar/representer/feature/http_verbs'
31
32
  end
32
33
  end
33
34
 
35
+ module AttributesContructor
36
+ def initialize(attrs={})
37
+ attrs.each do |k,v|
38
+ instance_variable_set("@#{k}", v)
39
+ end
40
+ end
41
+ end
42
+
43
+
34
44
 
35
45
  class Item
36
46
  include TestModel
@@ -1,16 +1,20 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class ItemRepresenter
4
+ include AttributesContructor
4
5
  include Roar::Representer::XML
5
6
  self.representation_wrap= :item
6
7
  property :value
8
+ attr_accessor :value
7
9
  end
8
10
 
9
11
  class PositionRepresenter
12
+ include AttributesContructor
10
13
  include Roar::Representer::XML
11
14
  self.representation_wrap= :position
12
15
  property :id
13
16
  property :item, :class => ItemRepresenter
17
+ attr_accessor :id, :item
14
18
  end
15
19
 
16
20
 
@@ -50,6 +54,7 @@ class XMLRepresenterFunctionalTest < MiniTest::Spec
50
54
  include Roar::Representer::XML
51
55
  self.representation_wrap= :order
52
56
  property :id
57
+ attr_accessor :id
53
58
  end
54
59
 
55
60
 
@@ -62,14 +67,6 @@ class XMLRepresenterFunctionalTest < MiniTest::Spec
62
67
  @i.value = "Beer"
63
68
  end
64
69
 
65
- describe "#to_attributes" do
66
- it "returns a nested attributes hash" do
67
- @r = PositionRepresenter.from_attributes("id" => 1, "item" => @i)
68
- assert_equal({"id" => 1, "item" => {"value" => "Beer"}}, @r.to_attributes)
69
- end
70
- end
71
-
72
-
73
70
  describe "#to_xml" do
74
71
  it "serializes the model" do
75
72
  assert_xml_equal "<order/>", @r.to_xml
@@ -104,10 +101,11 @@ class XMLRepresenterFunctionalTest < MiniTest::Spec
104
101
  include Roar::Representer::XML
105
102
  property :id
106
103
  property :pending
104
+ attr_accessor :id, :pending
107
105
  end
108
106
 
109
107
  it "is aliased to #deserialize" do
110
- assert_equal TestXmlRepresenter.from_xml("<order/>").to_attributes, TestXmlRepresenter.deserialize("<order/>").to_attributes
108
+ assert_equal TestXmlRepresenter.from_xml("<order/>").id, TestXmlRepresenter.deserialize("<order/>").id
111
109
  end
112
110
 
113
111
  it "accepts :except option" do
@@ -139,7 +137,7 @@ class XMLRepresenterFunctionalTest < MiniTest::Spec
139
137
 
140
138
  describe "with a typed attribute" do
141
139
  before do
142
- @r = PositionRepresenter.from_attributes("id" => "1")
140
+ @r = PositionRepresenter.new("id" => "1")
143
141
  end
144
142
 
145
143
  it "#serialize skips empty :item" do
@@ -163,14 +161,16 @@ class XMLRepresenterFunctionalTest < MiniTest::Spec
163
161
  describe "with a typed list" do
164
162
  before do
165
163
  @c = Class.new do
164
+ include AttributesContructor
166
165
  include Roar::Representer::XML
167
166
 
168
167
  self.representation_wrap= :order
169
168
  property :id
170
169
  collection :items, :class => ItemRepresenter, :from => :item
170
+ attr_accessor :id, :items
171
171
  end
172
172
 
173
- @r = @c.from_attributes("id" => 1)
173
+ @r = @c.new("id" => 1)
174
174
  end
175
175
 
176
176
  it "#serialize_model skips empty :item" do
@@ -178,7 +178,7 @@ class XMLRepresenterFunctionalTest < MiniTest::Spec
178
178
  end
179
179
 
180
180
  it "#serialize delegates to ItemXmlRepresenter#to_xml in list" do
181
- @r.items = [ItemRepresenter.from_attributes("value" => "Bier")]
181
+ @r.items = [ItemRepresenter.new("value" => "Bier")]
182
182
 
183
183
  assert_xml_equal "<order><id>1</id><item><value>Bier</value></item></order>",
184
184
  @r.to_xml
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 9
8
- - 0
9
- version: 0.9.0
8
+ - 1
9
+ version: 0.9.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Nick Sutterer
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-12-20 00:00:00 +01:00
17
+ date: 2011-12-28 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -26,30 +26,16 @@ dependencies:
26
26
  - - ~>
27
27
  - !ruby/object:Gem::Version
28
28
  segments:
29
- - 0
30
- - 12
31
- version: "0.12"
32
- type: :runtime
33
- version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
35
- name: hooks
36
- prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
38
- none: false
39
- requirements:
40
- - - ~>
41
- - !ruby/object:Gem::Version
42
- segments:
29
+ - 1
43
30
  - 0
44
31
  - 1
45
- - 4
46
- version: 0.1.4
32
+ version: 1.0.1
47
33
  type: :runtime
48
- version_requirements: *id002
34
+ version_requirements: *id001
49
35
  - !ruby/object:Gem::Dependency
50
36
  name: test_xml
51
37
  prerelease: false
52
- requirement: &id003 !ruby/object:Gem::Requirement
38
+ requirement: &id002 !ruby/object:Gem::Requirement
53
39
  none: false
54
40
  requirements:
55
41
  - - ">="
@@ -58,11 +44,11 @@ dependencies:
58
44
  - 0
59
45
  version: "0"
60
46
  type: :development
61
- version_requirements: *id003
47
+ version_requirements: *id002
62
48
  - !ruby/object:Gem::Dependency
63
49
  name: minitest
64
50
  prerelease: false
65
- requirement: &id004 !ruby/object:Gem::Requirement
51
+ requirement: &id003 !ruby/object:Gem::Requirement
66
52
  none: false
67
53
  requirements:
68
54
  - - ~>
@@ -73,11 +59,11 @@ dependencies:
73
59
  - 0
74
60
  version: 1.6.0
75
61
  type: :development
76
- version_requirements: *id004
62
+ version_requirements: *id003
77
63
  - !ruby/object:Gem::Dependency
78
64
  name: sinatra
79
65
  prerelease: false
80
- requirement: &id005 !ruby/object:Gem::Requirement
66
+ requirement: &id004 !ruby/object:Gem::Requirement
81
67
  none: false
82
68
  requirements:
83
69
  - - ~>
@@ -88,7 +74,7 @@ dependencies:
88
74
  - 6
89
75
  version: 1.2.6
90
76
  type: :development
91
- version_requirements: *id005
77
+ version_requirements: *id004
92
78
  description: Streamlines the development of RESTful, resource-oriented architectures in Ruby.
93
79
  email:
94
80
  - apotonick@gmail.com
@@ -113,7 +99,6 @@ files:
113
99
  - lib/roar/representer.rb
114
100
  - lib/roar/representer/feature/http_verbs.rb
115
101
  - lib/roar/representer/feature/hypermedia.rb
116
- - lib/roar/representer/feature/model_representing.rb
117
102
  - lib/roar/representer/feature/transport.rb
118
103
  - lib/roar/representer/json.rb
119
104
  - lib/roar/representer/xml.rb
@@ -160,7 +145,6 @@ files:
160
145
  - test/hypermedia_feature_test.rb
161
146
  - test/integration_test.rb
162
147
  - test/json_representer_test.rb
163
- - test/model_representing_test.rb
164
148
  - test/order_representers.rb
165
149
  - test/rails/controller_methods_test.rb
166
150
  - test/rails/rails_representer_methods_test.rb
@@ -1,80 +0,0 @@
1
- module Roar
2
- module Representer
3
- module Feature
4
- module ModelRepresenting
5
- attr_accessor :represented
6
-
7
- def self.included(base)
8
- base.extend ClassMethods
9
- end
10
-
11
- module ClassMethods
12
- def for_model(represented)
13
- # DISCUSS: split that into #for_model_attributes so it's easier overridable?
14
- from_attributes(compute_attributes_for(represented)) { |rep| rep.represented = represented }
15
- end
16
-
17
- def serialize_model(represented)
18
- for_model(represented).serialize
19
- end
20
-
21
- private
22
- def definition_class
23
- ModelDefinition
24
- end
25
-
26
- # Called in for_model.
27
- def compute_attributes_for(represented)
28
- {}.tap do |attributes|
29
- self.representable_attrs.each do |definition|
30
- next unless definition.kind_of?(ModelDefinition) # for now, really only use "our" model attributes.
31
- definition.compute_attribute_for(represented, attributes)
32
- end
33
- end
34
- end
35
-
36
-
37
- end # ClassMethods
38
-
39
- # Properties that are mapped to a model attribute.
40
- class ModelDefinition < ::Representable::Definition
41
- def compute_attribute_for(represented, attributes)
42
- value = represented.send(getter)
43
-
44
- if typed?
45
- value = apply(value) do |v|
46
- sought_type.for_model(v) # applied to each typed attribute (even in collections).
47
- end
48
- end
49
-
50
- attributes[name] = value
51
- end
52
- end
53
- end
54
-
55
-
56
- module ActiveRecordMethods
57
- def to_nested_attributes # FIXME: extract iterating with #to_attributes.
58
- {}.tap do |attributes|
59
- self.class.representable_attrs.each do |definition|
60
- next unless definition.kind_of?(ModelRepresenting::ModelDefinition)
61
-
62
- value = public_send(definition.getter)
63
-
64
- if definition.typed?
65
- value = definition.apply(value) do |v|
66
- v.to_nested_attributes # applied to each typed attribute (even in collections).
67
- end
68
- end
69
-
70
- key = definition.name
71
- key = "#{key}_attributes" if definition.typed?
72
-
73
- attributes[key] = value
74
- end
75
- end
76
- end
77
- end
78
- end
79
- end
80
- end
@@ -1,119 +0,0 @@
1
- require 'test_helper'
2
- require 'roar/representer/feature/model_representing'
3
-
4
- class ModelRepresentingTest < MiniTest::Spec
5
- describe "ModelRepresenting" do
6
- class ItemRepresenter
7
- include Roar::Representer::XML
8
- include Roar::Representer::Feature::ModelRepresenting
9
- self.representation_wrap= :item
10
- property :value
11
- end
12
-
13
- class PositionRepresenter
14
- include Roar::Representer::XML
15
- include Roar::Representer::Feature::ModelRepresenting
16
- self.representation_wrap= :position
17
- property :id
18
- property :item, :class => ItemRepresenter
19
- end
20
-
21
- class OrderRepresenter
22
- include Roar::Representer::XML
23
- include Roar::Representer::Feature::ModelRepresenting
24
- self.representation_wrap= :order
25
- property :id
26
- collection :items, :class => ItemRepresenter
27
- end
28
-
29
- describe "#definition_class" do
30
- it "returns ModelDefinition" do
31
- assert_equal Roar::Representer::Feature::ModelRepresenting::ModelDefinition, OrderRepresenter.send(:definition_class)
32
- end
33
-
34
- end
35
-
36
- describe "#for_model" do
37
- it "copies represented model attributes, nothing more" do
38
- @o = Position.new("id" => 1, "item" => Item.new("value" => "Beer"))
39
- @r = PositionRepresenter.for_model(@o)
40
- assert_kind_of PositionRepresenter, @r
41
- assert_equal 1, @r.id
42
-
43
- @i = @r.item
44
- assert_kind_of ItemRepresenter, @i
45
- assert_equal "Beer", @i.value
46
- end
47
-
48
- it "references the model in @represented" do
49
- @o = Position.new("id" => 1, "item" => @i = Item.new("value" => "Beer"))
50
-
51
- @r = PositionRepresenter.for_model(@o)
52
- assert_equal @o, @r.represented
53
- assert_equal @i, @r.item.represented
54
- end
55
- end
56
-
57
- describe "#serialize_model" do
58
- it "skips empty :item" do
59
- @o = Position.new("id" => 1)
60
- assert_xml_equal "<position><id>1</id></position>", PositionRepresenter.serialize_model(@o)
61
- end
62
-
63
- it "skips empty [:items]" do
64
- assert_xml_equal "<order><id>1</id></order>", OrderRepresenter.serialize_model(Order.new("id" => 1))
65
- end
66
-
67
- it "serializes the model" do
68
- @o = Order.new("id" => 1, "items" => [Item.new("value" => "Beer")])
69
- assert_xml_equal %{
70
- <order>
71
- <id>1</id>
72
- <item>
73
- <value>Beer</value>
74
- </item>
75
- </order>}"", OrderRepresenter.serialize_model(@o)
76
- end
77
-
78
- end
79
-
80
- describe "#to_nested_attributes" do
81
- it "provides a AR-compatible hash" do
82
- @o = Order.new("id" => 1, "items" => [Item.new("value" => "Beer")])
83
- @r = OrderRepresenter.for_model(@o)
84
-
85
- OrderRepresenter.class_eval do
86
- include Roar::Representer::Feature::ActiveRecordMethods
87
- end
88
- ItemRepresenter.class_eval do
89
- include Roar::Representer::Feature::ActiveRecordMethods
90
- end
91
- assert_equal({"id" => 1, "items_attributes" => [{"value" => "Beer"}]}, @r.to_nested_attributes) # DISCUSS: overwrite #to_attributes.
92
- end
93
-
94
- it "doesn't include :links" do
95
- @o = Order.new("id" => 1, "items" => [Item.new("value" => "Beer")])
96
-
97
-
98
-
99
- OrderRepresenter.class_eval do
100
- include Roar::Representer::Feature::ActiveRecordMethods
101
- include Roar::Representer::Feature::Hypermedia
102
- link :self do
103
- # "bla"
104
- end
105
- end
106
- ItemRepresenter.class_eval do
107
- include Roar::Representer::Feature::ActiveRecordMethods
108
- include Roar::Representer::Feature::Hypermedia
109
- link :self do
110
-
111
- end
112
- end
113
- @r = OrderRepresenter.for_model(@o)
114
-
115
- assert_equal({"id" => 1, "items_attributes" => [{"value" => "Beer"}]}, @r.to_nested_attributes) # DISCUSS: overwrite #to_attributes.
116
- end
117
- end
118
- end
119
- end