roar 0.11.9 → 0.11.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,7 @@
1
+ ## 0.11.10
2
+ * Fix a syntax error for Ruby 1.8.
3
+ * Store link definitions in `representable_attrs(:links)` now and no longer in the `LinksDefinition` instance itself. removing `#links_definition` in favor of `#link_configs`.
4
+
1
5
  ## 0.11.9
2
6
 
3
7
  * When using `Feature::Client` hyperlinks are no longer rendered in POST and PUT since we pass `links: false`.
data/Gemfile CHANGED
@@ -3,7 +3,7 @@ source "http://rubygems.org"
3
3
  # Specify your gem's dependencies in roar.gemspec
4
4
  gemspec
5
5
 
6
- gem "representable", ">= 1.3.1"
6
+ gem "representable", ">= 1.3.2"
7
7
 
8
8
 
9
9
  group :test do
@@ -1,3 +1,4 @@
1
1
  * Add proxies, so nested models can be lazy-loaded.
2
2
  * move #prepare_links! call to #_links or something so it doesn't need to be called in #serialize.
3
- * alias Roar::Representer to Representer
3
+ * alias Roar::Representer to Representer
4
+ * remove #before_serialize and just overwrite #serialize
@@ -37,6 +37,7 @@ module Roar
37
37
  module Hypermedia
38
38
  def self.included(base)
39
39
  base.extend ClassMethods
40
+ base.extend InheritableArray
40
41
  end
41
42
 
42
43
  def before_serialize(options={})
@@ -60,15 +61,19 @@ module Roar
60
61
  ary.each { |lnk| links.add(lnk) }
61
62
  end
62
63
 
63
- private
64
- def links_definition
65
- representable_attrs.find { |d| d.is_a?(LinksDefinition) } or [] # FIXME: this is a bug as soon as #links_definition is used somewhere else beside #prepare_links.
64
+ module LinkConfigsMethod
65
+ def link_configs
66
+ representable_attrs.inheritable_array(:links)
67
+ end
66
68
  end
67
69
 
70
+ include LinkConfigsMethod
71
+
72
+ private
68
73
  # Setup hypermedia links by invoking their blocks. Usually called by #serialize.
69
74
  def prepare_links!(*args)
70
75
  # TODO: move this method to _links or something so it doesn't need to be called in #serialize.
71
- compile_links_for(links_definition, *args).each do |lnk|
76
+ compile_links_for(link_configs, *args).each do |lnk|
72
77
  links.add(lnk) # TODO: move to LinkCollection.new.
73
78
  end
74
79
  end
@@ -117,42 +122,20 @@ module Roar
117
122
  # Note that you're free to put decider logic into #link blocks, too.
118
123
  def link(options, &block)
119
124
  options = {:rel => options} if options.is_a?(Symbol)
120
- links_definition << [options, block]
125
+ create_links_definition # this assures the links are rendered at the right position.
126
+ link_configs << [options, block]
121
127
  end
122
128
 
129
+ include LinkConfigsMethod
130
+
123
131
  private
124
132
  def create_links_definition
125
- representable_attrs << links = LinksDefinition.new(*links_definition_options)
126
- links
127
- end
128
-
129
- def links_definition
130
- representable_attrs.find { |d| d.is_a?(LinksDefinition) } or create_links_definition
133
+ return if representable_attrs.find { |d| d.is_a?(LinksDefinition) }
134
+ representable_attrs << LinksDefinition.new(*links_definition_options)
131
135
  end
132
136
  end
133
137
 
134
-
135
138
  class LinksDefinition < Representable::Definition
136
- include Enumerable
137
-
138
- attr_accessor :rel2block
139
- def initialize(*)
140
- super
141
- @rel2block = []
142
- end
143
-
144
- def <<(args)
145
- rel2block << args
146
- end
147
-
148
- def each(*args, &block)
149
- rel2block.each(*args, &block)
150
- end
151
-
152
- # DISCUSS: where do we need this?
153
- def clone
154
- super.tap { |d| d.rel2block = rel2block.clone }
155
- end
156
139
  end
157
140
 
158
141
 
@@ -171,6 +154,31 @@ module Roar
171
154
  marshal_load(hash.inject({}) { |h, (k,v)| h[k.to_sym] = v; h })
172
155
  end
173
156
  end
157
+
158
+ # TODO: move to separate module
159
+ # DISCUSS: experimental. this will soon be moved to a separate gem
160
+ module InheritableArray
161
+ def representable_attrs
162
+ super.extend(ConfigExtensions)
163
+ end
164
+
165
+ module ConfigExtensions
166
+ def inheritable_array(name)
167
+ inheritable_arrays[name] ||= []
168
+ end
169
+ def inheritable_arrays
170
+ @inheritable_arrays ||= {}
171
+ end
172
+
173
+ def inherit(parent)
174
+ super
175
+
176
+ parent.inheritable_arrays.keys.each do |k|
177
+ inheritable_array(k).push *parent.inheritable_array(k).clone
178
+ end
179
+ end
180
+ end
181
+ end
174
182
  end
175
183
  end
176
184
  end
@@ -23,7 +23,7 @@ module Roar::Representer::JSON
23
23
 
24
24
  collection :queries, :extend => Roar::Representer::JSON::HyperlinkRepresenter
25
25
  def queries
26
- compile_links_for(representable_attrs.collection_representers[:queries].representable_attrs.first)
26
+ compile_links_for(representable_attrs.collection_representers[:queries].link_configs)
27
27
  end
28
28
  def queries=(v)
29
29
  end
@@ -43,7 +43,7 @@ module Roar::Representer::JSON
43
43
 
44
44
  property :__href, :as => :href
45
45
  def __href
46
- compile_links_for(representable_attrs.collection_representers[:href].representable_attrs.first).first.href
46
+ compile_links_for(representable_attrs.collection_representers[:href].link_configs).first.href
47
47
  end
48
48
 
49
49
 
@@ -119,7 +119,7 @@ module Roar::Representer::JSON
119
119
  # TODO: share with main module!
120
120
  property :__href, :as => :href
121
121
  def __href
122
- compile_links_for(representable_attrs.collection_representers[:href].representable_attrs.first).first.href
122
+ compile_links_for(representable_attrs.collection_representers[:href].link_configs).first.href
123
123
  end
124
124
  def __href=(v)
125
125
  @__href = Roar::Representer::Feature::Hypermedia::Hyperlink.new(:href => v)
@@ -81,28 +81,28 @@ module Roar::Representer
81
81
  module Links
82
82
  def self.included(base)
83
83
  base.class_eval do
84
+ extend Links::ClassMethods # ::links_definition_options
84
85
  include Roar::Representer::Feature::Hypermedia
85
- include InstanceMethods
86
- extend Links::ClassMethods
86
+ include InstanceMethods
87
87
  end
88
88
  end
89
-
89
+
90
90
  module InstanceMethods
91
91
  private
92
92
  def prepare_link_for(href, options)
93
93
  return super(href, options) unless options[:array] # TODO: remove :array and use special instan
94
-
94
+
95
95
  list = href.collect { |opts| Feature::Hypermedia::Hyperlink.new(opts.merge!(:rel => options[:rel])) }
96
96
  LinkArray.new(list)
97
97
  end
98
-
98
+
99
99
  # TODO: move to LinksDefinition.
100
100
  def link_array_rels
101
- links_definition.collect { |cfg| cfg.first[:array] ? cfg.first[:rel] : nil }.compact
101
+ link_configs.collect { |cfg| cfg.first[:array] ? cfg.first[:rel] : nil }.compact
102
102
  end
103
103
  end
104
-
105
-
104
+
105
+
106
106
  require 'representable/json/hash'
107
107
  module LinkCollectionRepresenter
108
108
  include Representable::JSON::Hash
@@ -115,11 +115,11 @@ module Roar::Representer
115
115
  hsh.each { |k,v| v.delete(:rel) }
116
116
  end
117
117
  end
118
-
118
+
119
119
 
120
120
  def from_hash(hash, options={})
121
121
  hash.each { |k,v| hash[k] = LinkArray.new(v) if is_array?(k) }
122
-
122
+
123
123
  hsh = super(hash) # this is where :class and :extend do the work.
124
124
 
125
125
  hsh.each { |k, v| v.rel = k }
@@ -154,16 +154,18 @@ module Roar::Representer
154
154
  module ClassMethods
155
155
  def links_definition_options
156
156
  [:links,
157
- :from => :links,
158
- :extend => HAL::Links::LinkCollectionRepresenter,
159
- :instance => lambda { |hsh| LinkCollection.new(link_array_rels) } # defined in InstanceMethods as this is executed in represented context.
157
+ {
158
+ :from => :links,
159
+ :extend => HAL::Links::LinkCollectionRepresenter,
160
+ :instance => lambda { |hsh| LinkCollection.new(link_array_rels) } # defined in InstanceMethods as this is executed in represented context.
161
+ }
160
162
  ]
161
163
  end
162
164
 
163
165
  # Use this to define link arrays. It accepts the shared rel attribute and an array of options per link object.
164
166
  #
165
167
  # links :self do
166
- # [{:lang => "en", :href => "http://en.hit"},
168
+ # [{:lang => "en", :href => "http://en.hit"},
167
169
  # {:lang => "de", :href => "http://de.hit"}]
168
170
  # end
169
171
  def links(options, &block)
@@ -1,3 +1,3 @@
1
1
  module Roar
2
- VERSION = "0.11.9"
2
+ VERSION = "0.11.10"
3
3
  end
@@ -18,7 +18,7 @@ class HalLinkTest < MiniTest::Spec
18
18
 
19
19
  describe "#to_json" do
20
20
  it "uses 'links' key" do
21
- assert_equal subject.to_json, "{\"links\":{\"self\":{\"href\":\"//songs\"}}}"
21
+ subject.to_json.must_equal "{\"links\":{\"self\":{\"href\":\"//songs\"}}}"
22
22
  end
23
23
  end
24
24
 
@@ -134,39 +134,3 @@ class LinkCollectionTest < MiniTest::Spec
134
134
  end
135
135
  end
136
136
  end
137
-
138
- class HyperlinkInheritanceTest < MiniTest::Spec
139
- describe "when the base representer has a link" do
140
- before do
141
- module BaseRepresenter
142
- include Roar::Representer::JSON
143
- include Roar::Representer::Feature::Hypermedia
144
-
145
- link(:base) { "http://base" }
146
- end
147
-
148
- module Foo
149
- include Roar::Representer::JSON
150
- include Roar::Representer::Feature::Hypermedia
151
- include BaseRepresenter
152
-
153
- link(:foo) { "http://foo" }
154
- end
155
-
156
- module Bar
157
- include Roar::Representer::JSON
158
- include Roar::Representer::Feature::Hypermedia
159
- include BaseRepresenter
160
-
161
- link(:bar) { "http://bar" }
162
- end
163
- end
164
-
165
- it "should inherit parent links" do
166
- foo = Object.new.extend(Foo)
167
-
168
- assert_equal "{\"links\":[{\"rel\":\"base\",\"href\":\"http://base\"},{\"rel\":\"foo\",\"href\":\"http://foo\"}]}", foo.to_json
169
- end
170
-
171
- end
172
- end
@@ -1,6 +1,44 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class HypermediaTest < MiniTest::Spec
4
+ describe "inheritance" do
5
+ before do
6
+ module BaseRepresenter
7
+ include Roar::Representer::JSON
8
+ include Roar::Representer::Feature::Hypermedia
9
+
10
+ link(:base) { "http://base" }
11
+ end
12
+
13
+ module Bar
14
+ include Roar::Representer::JSON
15
+ include Roar::Representer::Feature::Hypermedia
16
+
17
+ link(:bar) { "http://bar" }
18
+ end
19
+
20
+ module Foo
21
+ include Roar::Representer::JSON
22
+ include Roar::Representer::Feature::Hypermedia
23
+ include BaseRepresenter
24
+ include Bar
25
+
26
+ link(:foo) { "http://foo" }
27
+ end
28
+ end
29
+
30
+ it "inherits parent links" do
31
+ foo = Object.new.extend(Foo)
32
+
33
+ assert_equal "{\"links\":[{\"rel\":\"base\",\"href\":\"http://base\"},{\"rel\":\"bar\",\"href\":\"http://bar\"},{\"rel\":\"foo\",\"href\":\"http://foo\"}]}", foo.to_json
34
+ end
35
+
36
+ it "inherits links from all mixed-in representers" do
37
+ skip
38
+ Object.new.extend(BaseRepresenter).extend(Bar).to_json.must_equal "{\"links\":[{\"rel\":\"base\",\"href\":\"http://base\"},{\"rel\":\"bar\",\"href\":\"http://bar\"}]}"
39
+ end
40
+ end
41
+
4
42
  describe "#links_array" do
5
43
  subject { Object.new.extend(rpr) }
6
44
 
@@ -89,35 +127,6 @@ class HypermediaTest < MiniTest::Spec
89
127
  end
90
128
  end
91
129
 
92
- class LinksDefinitionTest < MiniTest::Spec
93
- describe "LinksDefinition" do
94
- subject { Roar::Representer::Feature::Hypermedia::LinksDefinition.new(:links) }
95
-
96
- it "responds to #<<" do
97
- subject << "arbitrary bullshit"
98
- subject.to_a.must_equal ["arbitrary bullshit"]
99
- end
100
-
101
- it "responds to #each" do
102
- subject.to_a.must_equal []
103
- end
104
-
105
- it "accepts options in constructor" do
106
- assert_equal [], subject.rel2block
107
- end
108
-
109
- it "accepts configuration" do
110
- subject.rel2block << {:rel => :self}
111
- assert_equal [{:rel=>:self}], subject.rel2block
112
- end
113
-
114
- it "responds to #clone" do
115
- subject.rel2block << {:rel => :self}
116
- assert subject.clone.rel2block.object_id != subject.rel2block.object_id
117
- end
118
- end
119
- end
120
-
121
130
  class HyperlinkTest < MiniTest::Spec
122
131
  describe "Hyperlink" do
123
132
  subject { link(:rel => "self", "href" => "http://self", "data-whatever" => "Hey, @myabc") }
@@ -144,4 +153,61 @@ class HyperlinkTest < MiniTest::Spec
144
153
  assert_equal ["rel:self", "href:http://self", "data-whatever:Hey, @myabc"], subject.collect { |k,v| "#{k}:#{v}" }
145
154
  end
146
155
  end
156
+
157
+ describe "Config inheritance" do
158
+ # TODO: this section will soon be moved to uber.
159
+ describe "inheritance when including" do
160
+ # TODO: test all the below issues AND if cloning works.
161
+ module TestMethods
162
+ def representer_for(modules=[Roar::Representer::Feature::Hypermedia, Representable], &block)
163
+ Module.new do
164
+ extend TestMethods
165
+ include *modules
166
+ module_exec(&block)
167
+ end
168
+ end
169
+ end
170
+ include TestMethods
171
+
172
+ it "inherits to uninitialized child" do
173
+ representer_for do # child
174
+ include(representer_for do # parent
175
+ representable_attrs.inheritable_array(:links) << "bar"
176
+ end)
177
+ end.representable_attrs.inheritable_array(:links).must_equal(["bar"])
178
+ end
179
+
180
+ it "works with uninitialized parent" do
181
+ representer_for do # child
182
+ representable_attrs.inheritable_array(:links) << "bar"
183
+
184
+ include(representer_for do # parent
185
+ end)
186
+ end.representable_attrs.inheritable_array(:links).must_equal(["bar"])
187
+ end
188
+
189
+ it "inherits when both are initialized" do
190
+ representer_for do # child
191
+ representable_attrs.inheritable_array(:links) << "bar"
192
+
193
+ include(representer_for do # parent
194
+ representable_attrs.inheritable_array(:links) << "stadium"
195
+ end)
196
+ end.representable_attrs.inheritable_array(:links).must_equal(["bar", "stadium"])
197
+ end
198
+
199
+ it "clones parent inheritables" do # FIXME: actually we don't clone here!
200
+ representer_for do # child
201
+ representable_attrs.inheritable_array(:links) << "bar"
202
+
203
+ include(parent = representer_for do # parent
204
+ representable_attrs.inheritable_array(:links) << "stadium"
205
+ end)
206
+
207
+ parent.representable_attrs.inheritable_array(:links) << "park" # modify parent array.
208
+
209
+ end.representable_attrs.inheritable_array(:links).must_equal(["bar", "stadium"])
210
+ end
211
+ end
212
+ end
147
213
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roar
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.9
4
+ version: 0.11.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-06 00:00:00.000000000 Z
12
+ date: 2013-02-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: representable