restful_serializer 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -6,7 +6,7 @@ If the model has a name column, it will be used to describe the resource.
6
6
 
7
7
  This library does not attempt to provide href info for transitions, or deal much with questions of authorization beyond what is specified in the serialization configuration lines. It assumes that these issues would be resolved in the controller. It assumes standard naming conventions for routes.
8
8
 
9
- So far only tested with Rails 2.x
9
+ So far only tested with Rails 2.1.0
10
10
 
11
11
  == Example
12
12
 
@@ -73,3 +73,6 @@ Example output:
73
73
  # "column1"=>1,
74
74
  # "column2"=>2,}}
75
75
 
76
+ = More Docs
77
+
78
+ Please see the Restful rdoc and the specs for more details.
data/lib/restful.rb CHANGED
@@ -5,27 +5,29 @@ require 'restful/serializer'
5
5
  # This library is used to decorate ActiveRecord with methods to assist in generating
6
6
  # Restful content for Web Services.
7
7
  #
8
- # It produces a hash of reference, object and href information for an ActiveRecord instance
9
- # or association. Output is highly configurable both through Rails initialization and
10
- # method calls.
8
+ # It produces a hash of reference, object and href information for an
9
+ # ActiveRecord instance or association. Output is highly configurable both
10
+ # through Rails initialization and method calls.
11
11
  #
12
12
  # = Options
13
13
  #
14
- # The following options may be set in the Restful.model_configuration hash on a per model class
15
- # basis.
14
+ # The following options may be set in the Restful.model_configuration hash on a
15
+ # per model class basis.
16
16
  #
17
- # * :name => method to call on an instance to produce a human meaningful reference for the instance.
18
- # Defaults to :name.
19
- # * :serialization => options to be passed to ActiveRecord::Serialization::Serializer to configure
20
- # serialization of the ActiveRecord instance itself. See ActiveRecord::Serialization.to_json
21
- # * :url_for => if the named_route helper method cannot be guessed from normal Rails restful
22
- # syntax, it may be overriden here.
17
+ # * :name => method to call on an instance to produce a human meaningful
18
+ # reference for the instance. Defaults to :name.
19
+ # * :serialization => options to be passed to
20
+ # ActiveRecord::Serialization::Serializer to configure serialization of the
21
+ # ActiveRecord instance itself. See ActiveRecord::Serialization.to_json
22
+ # * :url_for => if the named_route helper method cannot be guessed from normal
23
+ # Rails restful syntax, it may be overriden here.
23
24
  # * :associations => you may include href references to the instance's associations
24
- # * :shallow => if you are serializing an association, by default member includes and association
25
- # references are stripped. Set this to false to traverse deeply.
26
- # * :no_inherited_options => normally a subclass inherits and overrides its base class settings.
27
- # Setting this to true prevents this so that only the options specifically set for the class
28
- # will be used. Default false.
25
+ # * :shallow => if you are serializing an association, by default member
26
+ # includes and association references are stripped. Set this to false to
27
+ # traverse deeply.
28
+ # * :no_inherited_options => normally a subclass inherits and overrides its
29
+ # base class settings. Setting this to true prevents this so that only the
30
+ # options specifically set for the class will be used. Default false.
29
31
  #
30
32
  # = Usage
31
33
  #
@@ -56,7 +58,7 @@ require 'restful/serializer'
56
58
  #
57
59
  # Restful.model_configuration = {
58
60
  # :person => {
59
- # :serialization => { :except => :secrets }
61
+ # :serialization => { :except => [:secrets] }
60
62
  # :associations => :books,
61
63
  # }
62
64
  # :book => {
@@ -74,10 +76,48 @@ require 'restful/serializer'
74
76
  # # 'first_name' => 'Bob',
75
77
  # # 'last_name' => 'Bob',
76
78
  # # 'age' : 17,
79
+ # # },
77
80
  # # 'href' => 'http://www.example.com/web_service/people/1' }
78
81
  # # 'books_href' => 'http://www.example.com/web_service/people/1/books' }
79
82
  # # }
80
83
  #
84
+ # Options may be overridden at call time, by default this overwrite the passed options completely:
85
+ #
86
+ # bob = Person.new(:first_name => 'Bob', :last_name => 'Smith', :age => 41, :secrets => 'untold')
87
+ # bob.restful(:serialization => { :except => [:id] })
88
+ # # => {
89
+ # # 'name' => 'Bob Smith'
90
+ # # 'person' => {
91
+ # # 'first_name' => 'Bob',
92
+ # # 'last_name' => 'Bob',
93
+ # # 'age' : 17,
94
+ # # 'secrets' : 'untold',
95
+ # # },
96
+ # # 'href' => 'http://www.example.com/web_service/people/1' }
97
+ # # 'books_href' => 'http://www.example.com/web_service/people/1/books' }
98
+ # # }
99
+ #
100
+ # To perform a deep merge of options instead, place the options to be deeply merged
101
+ # inside a :deep_merge hash:
102
+ #
103
+ # bob = Person.new(:first_name => 'Bob', :last_name => 'Smith', :age => 41, :secrets => 'untold')
104
+ # bob.restful(:deep_merge => { :serialization => { :except => [:id] } })
105
+ # # => {
106
+ # # 'name' => 'Bob Smith'
107
+ # # 'person' => {
108
+ # # 'first_name' => 'Bob',
109
+ # # 'last_name' => 'Bob',
110
+ # # 'age' : 17,
111
+ # # },
112
+ # # 'href' => 'http://www.example.com/web_service/people/1' }
113
+ # # 'books_href' => 'http://www.example.com/web_service/people/1/books' }
114
+ # # }
115
+ #
116
+ # These two techniques can be combined, but overwriting will occur prior to a deep merge...
117
+ #
118
+ # (There is a trap in how deep merge handles this. If the above :except values had
119
+ # not been configured as arrays, then deep merge would have overwritten rather than merging
120
+ # them. This could probably be adjusted with a closer look into the deep_merge docs.)
81
121
  module Restful
82
122
  # Route prefix for api calls.
83
123
  mattr_accessor :api_prefix
@@ -1,17 +1,19 @@
1
1
  # This file is part of restful_serializer. Copyright 2011 Joshua Partlow. This is free software, see the LICENSE file for details.
2
2
  require 'active_record'
3
3
  require 'action_controller'
4
+ require 'deep_merge'
4
5
 
5
6
  module Restful
6
7
  module UrlForHelpers
7
8
 
8
- # Used to construct and attempt to call named routes be providing resource strings out
9
- # of which an named route method name will be constructed:
9
+ # Used to construct and attempt to call named routes be providing resource
10
+ # strings out of which a named route method name will be constructed:
10
11
  #
11
12
  # Options:
12
13
  #
13
- # * :resources => a symbol, string or array of same describing segments of the helper method name.
14
- # e.g. [:user, :comments] => user_comments (to which _url will be appended...)
14
+ # * :resources => a symbol, string or array of same describing segments of
15
+ # the helper method name. e.g. [:user, :comments] => user_comments (to
16
+ # which _url will be appended...)
15
17
  # * :method => overrides the use of :resources and :prefix
16
18
  # * :args => any arguments to be passed to the named_route when it is called
17
19
  #
@@ -39,16 +41,23 @@ module Restful
39
41
  def initialize(subject, *args)
40
42
  self.subject = subject
41
43
 
42
- self.base_klass = subject.class.base_class.name.underscore if subject.class.respond_to?(:base_class)
43
- self.klass = subject.class.name.underscore
44
+ self.base_klass = subject.class.base_class.name.demodulize.underscore if subject.class.respond_to?(:base_class)
45
+ self.klass = subject.class.name.demodulize.underscore
44
46
 
45
47
  passed_options = (args.pop || {}).symbolize_keys
46
- base_options = Restful.model_configuration_for(base_klass) || {}
47
- class_options = Restful.model_configuration_for(klass) || {}
48
- self.options = (klass == base_klass || class_options[:no_inherited_options]) ?
49
- class_options :
50
- base_options.merge(class_options)
51
- self.options.merge!(passed_options)
48
+ if subject.kind_of?(Array)
49
+ # preserve options as is to be passed to array members
50
+ self.options = passed_options
51
+ else
52
+ deeply_merge = passed_options.delete(:deep_merge)
53
+ base_options = Restful.model_configuration_for(base_klass) || {}
54
+ class_options = Restful.model_configuration_for(klass) || {}
55
+ self.options = (klass == base_klass || class_options[:no_inherited_options]) ?
56
+ class_options :
57
+ base_options.merge(class_options)
58
+ self.options.merge!(passed_options)
59
+ self.options.deep_merge(deeply_merge) if deeply_merge
60
+ end
52
61
 
53
62
  self.shallow = options[:shallow]
54
63
  end
@@ -1,3 +1,3 @@
1
1
  module Restful
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -27,4 +27,5 @@ Gem::Specification.new do |s|
27
27
  s.add_runtime_dependency(%q<activerecord>, [">= 2.1.0", "<3.0.0"])
28
28
  s.add_runtime_dependency(%q<activesupport>, [">= 2.1.0", "<3.0.0"])
29
29
  s.add_runtime_dependency(%q<actionpack>, [">= 2.1.0", "<3.0.0"])
30
+ s.add_runtime_dependency(%q<deep_merge>, [">= 0.1.0"])
30
31
  end
data/spec/restful_spec.rb CHANGED
@@ -19,13 +19,13 @@ describe Restful do
19
19
 
20
20
  describe "looking up model configurations" do
21
21
 
22
- class Foo; end
23
- class FooBar < Foo; end
22
+ class Super; end
23
+ class SubClass < Super; end
24
24
 
25
25
  before(:each) do
26
26
  Restful.model_configuration = {
27
- :foo => :foo_config,
28
- :foo_bar => :foo_bar_config,
27
+ :super => :super_config,
28
+ :sub_class => :sub_class_config,
29
29
  }
30
30
  end
31
31
 
@@ -34,36 +34,36 @@ describe Restful do
34
34
  end
35
35
 
36
36
  it "should lookup entries by symbol" do
37
- Restful.model_configuration_for(:foo).should == :foo_config
37
+ Restful.model_configuration_for(:super).should == :super_config
38
38
  end
39
39
 
40
40
  it "should lookup entries from a string" do
41
- Restful.model_configuration_for('foo').should == :foo_config
41
+ Restful.model_configuration_for('super').should == :super_config
42
42
  end
43
43
 
44
44
  it "should lookup entries by Class" do
45
- Restful.model_configuration_for(Foo).should == :foo_config
46
- Restful.model_configuration_for(FooBar).should == :foo_bar_config
45
+ Restful.model_configuration_for(Super).should == :super_config
46
+ Restful.model_configuration_for(SubClass).should == :sub_class_config
47
47
  end
48
48
 
49
49
  it "should lookup entries by instance class" do
50
- Restful.model_configuration_for(Foo.new).should == :foo_config
51
- Restful.model_configuration_for(FooBar.new).should == :foo_bar_config
50
+ Restful.model_configuration_for(Super.new).should == :super_config
51
+ Restful.model_configuration_for(SubClass.new).should == :sub_class_config
52
52
  end
53
53
 
54
54
  describe "with deep structures" do
55
55
 
56
56
  before(:each) do
57
57
  Restful.model_configuration = {
58
- :foo => { :setting => {:with => :nested_hash } }
58
+ :super => { :setting => {:with => :nested_hash } }
59
59
  }
60
60
  end
61
61
 
62
62
  it "should provide deep clones of model_configuration elements" do
63
- config = Restful.model_configuration_for(:foo)
63
+ config = Restful.model_configuration_for(:super)
64
64
  config[:setting][:with] = "changed"
65
65
  Restful.model_configuration.should == {
66
- :foo => { :setting => {:with => :nested_hash } }
66
+ :super => { :setting => {:with => :nested_hash } }
67
67
  }
68
68
  end
69
69
 
@@ -140,6 +140,20 @@ describe Restful::Serializer do
140
140
  }
141
141
  end
142
142
 
143
+ it "should deeply merge overridden options" do
144
+ rs = Restful::Serializer.new(@foo,
145
+ :deep_merge => { :serialization => { :only => [:id] } }
146
+ )
147
+ rs.serialize.should == {
148
+ 'name' => @foo.fancy_name,
149
+ 'foo' => {
150
+ 'id' => @foo.id,
151
+ 'name' => @foo.name,
152
+ :a_method => @foo.a_method,
153
+ },
154
+ 'href' => "http://test.org/prefix/foos/#{@foo.id}",
155
+ }
156
+ end
143
157
  end
144
158
 
145
159
  describe "with associations" do
@@ -183,7 +197,6 @@ describe Restful::Serializer do
183
197
  'special_href' => "http://test.org/foos/#{@bar1.foo_id}",
184
198
  }
185
199
  end
186
-
187
200
  end
188
201
 
189
202
  describe "with subclasses" do
@@ -218,7 +231,7 @@ describe Restful::Serializer do
218
231
  :associations => :bars,
219
232
  },
220
233
  :bar => {
221
- :serialization => { :only => :name, :include => { :dingos => { :only => [ :name, :id] } } },
234
+ :serialization => { :only => [:name], :include => { :dingos => { :only => [ :name, :id] } } },
222
235
  :associations => [:foo, :dingos],
223
236
  },
224
237
  }
@@ -276,6 +289,52 @@ describe Restful::Serializer do
276
289
  },
277
290
  ]
278
291
  end
292
+
293
+ it "should override options during initialization for each member" do
294
+ rs = Restful::Serializer.new(@foo.bars,
295
+ :serialization => { :only => :id }
296
+ )
297
+ rs.serialize.should == [
298
+ {
299
+ 'name' => @bar1.name,
300
+ 'href' => "http://test.org/bars/#{@bar1.id}",
301
+ 'bar' => {
302
+ 'id' => @bar1.id,
303
+ },
304
+ },
305
+ {
306
+ 'name' => @bar2.name,
307
+ 'href' => "http://test.org/bars/#{@bar2.id}",
308
+ 'bar' => {
309
+ 'id' => @bar2.id,
310
+ },
311
+ },
312
+ ]
313
+ end
314
+
315
+ it "should deeply merge overridden options for each member" do
316
+ rs = Restful::Serializer.new(@foo.bars,
317
+ :deep_merge => { :serialization => { :only => [:id] } }
318
+ )
319
+ rs.serialize.should == [
320
+ {
321
+ 'name' => @bar1.name,
322
+ 'href' => "http://test.org/bars/#{@bar1.id}",
323
+ 'bar' => {
324
+ 'id' => @bar1.id,
325
+ 'name' => @bar1.name,
326
+ },
327
+ },
328
+ {
329
+ 'name' => @bar2.name,
330
+ 'href' => "http://test.org/bars/#{@bar2.id}",
331
+ 'bar' => {
332
+ 'id' => @bar2.id,
333
+ 'name' => @bar2.name,
334
+ },
335
+ },
336
+ ]
337
+ end
279
338
  end
280
339
 
281
340
  it "should hook into activerecord" do
data/spec/spec.opts CHANGED
@@ -1,2 +1,4 @@
1
1
  --color
2
2
  --format nested
3
+ --diff
4
+ --debugger
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'rubygems'
3
4
  require 'restful'
4
5
  require 'spec'
5
6
  require 'spec/autorun'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: restful_serializer
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
5
- prerelease:
4
+ hash: 25
5
+ prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 0
10
- version: 0.1.0
9
+ - 1
10
+ version: 0.1.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Josh Partlow
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-04-08 00:00:00 -07:00
18
+ date: 2011-04-21 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -106,6 +106,22 @@ dependencies:
106
106
  version: 3.0.0
107
107
  type: :runtime
108
108
  version_requirements: *id004
109
+ - !ruby/object:Gem::Dependency
110
+ name: deep_merge
111
+ prerelease: false
112
+ requirement: &id005 !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ hash: 27
118
+ segments:
119
+ - 0
120
+ - 1
121
+ - 0
122
+ version: 0.1.0
123
+ type: :runtime
124
+ version_requirements: *id005
109
125
  description: This library is used to decorate ActiveRecord with methods to assist in generating Restful content for Web Services.
110
126
  email: jpartlow@glatisant.org
111
127
  executables: []
@@ -162,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
162
178
  requirements: []
163
179
 
164
180
  rubyforge_project:
165
- rubygems_version: 1.6.2
181
+ rubygems_version: 1.3.7
166
182
  signing_key:
167
183
  specification_version: 3
168
184
  summary: Helps with serializing activerecord instances as Restful resources.