roar 0.9.0 → 0.9.1

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