serial 0.2.0 → 1.0.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 29eb0ebd62982d93650098a3f2f4f54f11879bf3
4
- data.tar.gz: 6d516f85165f6a46f767925a48c4d40d5a0cb1c9
3
+ metadata.gz: bfac09f4727b81d0b72935e00e38a5584f1203cf
4
+ data.tar.gz: aab5f90c21fa6356fda1c115b9e2a93cb71d694a
5
5
  SHA512:
6
- metadata.gz: 60d63e4986fc120337231c0ad4e0f1145947d6975e856fe61924c6760f3bb29c60218aafef65899015c19fb1a23241bf83558d81ca6b398a0b10fe7f5123d657
7
- data.tar.gz: 6922159d7d31c6e77abc2c9e1cc3f4b7b3fc3f1990afc8c6d5c11303e9364ef940ee21f3428a4be577764a476fd5c931b8507be74e673abd9f7b94e3b504f588
6
+ metadata.gz: 6e675f5cb4da83f143bec4fd7706e05a1267e35039e01192ed9268a44a7298dfe7807b3ef60047178b54079be4b92c252a71607ea8045f907d9b5dc2edd86eba
7
+ data.tar.gz: 8916083402ec5d799da188484c999bdaaf496def62156362f12b06c824f66c05e75ef1e857bd9cfac0e398220139b2293d06309c8d7523f520f4a4e75c6746f0
data/.yardopts CHANGED
@@ -1 +1,2 @@
1
1
  --asset elabs-logo.png
2
+ --files CODE_OF_CONDUCT.md,CHANGELOG.md
@@ -1,5 +1,10 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.0.0
4
+
5
+ - Add HashBuilder#merge. [cb11a3c5]
6
+ - Raise an error by default if a key already exists in HashBuilder. [4b46db57]
7
+
3
8
  ## 0.2.0
4
9
 
5
10
  - Raise an error if serializer is not given a block.
@@ -0,0 +1,28 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all
4
+ people who contribute through reporting issues, posting feature requests,
5
+ updating documentation, submitting pull requests or patches, and other
6
+ activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, age, or religion.
12
+
13
+ Examples of unacceptable behavior by participants include the use of sexual
14
+ language or imagery, derogatory comments or personal attacks, trolling, public
15
+ or private harassment, insults, or other unprofessional conduct.
16
+
17
+ Project maintainers have the right and responsibility to remove, edit, or
18
+ reject comments, commits, code, wiki edits, issues, and other contributions
19
+ that are not aligned to this Code of Conduct. Project maintainers who do not
20
+ follow the Code of Conduct may be removed from the project team.
21
+
22
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
23
+ reported by opening an issue or contacting one or more of the project
24
+ maintainers.
25
+
26
+ This Code of Conduct is adapted from the [Contributor
27
+ Covenant](http:contributor-covenant.org), version 1.0.0, available at
28
+ [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/README.md CHANGED
@@ -36,9 +36,13 @@ And then execute:
36
36
 
37
37
  - All keys are turned into strings.
38
38
  - There is no automatic camel-casing. You name your keys the way you want them.
39
+ - Using the same key twice will raise an error by default.
40
+ - To override the value for an existing key, use the respective !-method DSL, i.e. `#attribute!`, `#collection!`, `#map!`, or `#merge!`.
39
41
 
40
42
  ### Simple attributes
41
43
 
44
+ `#attribute` creates a simple attribute with a value.
45
+
42
46
  ``` ruby
43
47
  ProjectSerializer = Serial::Serializer.new do |h, project|
44
48
  h.attribute(:id, project.id)
@@ -48,6 +52,8 @@ end # => { "id" => …, "displayName" => … }
48
52
 
49
53
  ### Nested attributes
50
54
 
55
+ `#attribute` supports nesting by giving it a block.
56
+
51
57
  ``` ruby
52
58
  ProjectSerializer = Serial::Serializer.new do |h, project|
53
59
  h.attribute(:owner, project.owner) do |h, owner|
@@ -85,6 +91,21 @@ ProjectSerializer = Serial::Serializer.new do |h, project|
85
91
  end # => { "indices" => [{…}, {…}, [{…}, {…}]] }
86
92
  ```
87
93
 
94
+ ### Merging
95
+
96
+ `#merge` will let you merge another serializer without introducing a new nesting level.
97
+
98
+ ``` ruby
99
+ ProjectSerializer = Serial::Serializer.new do |h, project|
100
+ h.attribute(:name, project.name)
101
+ end # => { "name" => … }
102
+
103
+ FullProjectSerializer = Serial::Serializer.new do |h, project|
104
+ h.merge(project, &ProjectSerializer)
105
+ h.attribute(:description, project.description)
106
+ end # { "name" => …, "description" => … }
107
+ ```
108
+
88
109
  ### Composition
89
110
 
90
111
  You can compose serializers by passing them as blocks to the DSL methods.
@@ -125,6 +146,13 @@ ProjectSerializer.map(context, projects) # => [{ … }, …]
125
146
 
126
147
  ### Using with Rails
127
148
 
149
+ ```ruby
150
+ # app/serializers/project_serializer.rb
151
+ ProjectSerializer = Serial::Serializer.new do |h, project|
152
+
153
+ end
154
+ ```
155
+
128
156
  ``` ruby
129
157
  # app/controllers/project_controller.rb
130
158
  class ProjectController < ApplicationController
@@ -161,7 +189,7 @@ git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygem
161
189
  Bug reports and pull requests are welcome on GitHub at
162
190
  https://github.com/elabs/serial. This project is intended to be a safe,
163
191
  welcoming space for collaboration, and contributors are expected to adhere to
164
- the [Contributor Covenant](contributor-covenant.org) code of conduct.
192
+ the [Contributor Covenant](CODE_OF_CONDUCT.md) code of conduct.
165
193
 
166
194
  ## License
167
195
 
@@ -7,4 +7,11 @@ require "serial/rails_helpers"
7
7
 
8
8
  # Serial namespace. See {Serial::Serializer} for reference.
9
9
  module Serial
10
+ # All serial-specific errors inherit from this error.
11
+ class Error < StandardError
12
+ end
13
+
14
+ # Raised when an already-defined key is defined again.
15
+ class DuplicateKeyError < StandardError
16
+ end
10
17
  end
@@ -30,8 +30,10 @@ module Serial
30
30
  def exec(*args, &block)
31
31
  if @context
32
32
  @context.instance_exec(self, *args, &block)
33
- else
33
+ elsif block
34
34
  block.call(self, *args)
35
+ else
36
+ raise ArgumentError, "no serializer block given"
35
37
  end
36
38
  end
37
39
  end
@@ -24,7 +24,20 @@ module Serial
24
24
  # @yield [builder, value] declare nested attribute if block is given
25
25
  # @yieldparam builder [HashBuilder] (keep in mind the examples shadow the outer `h` variable)
26
26
  # @yieldparam value
27
+ # @raise [DuplicateKeyError] if the same key has already been defined.
27
28
  def attribute(key, value = nil, &block)
29
+ check_duplicate_key!(key)
30
+ attribute!(key, value, &block)
31
+ end
32
+
33
+ # @api public
34
+ # Same as {#attribute}, but will not raise an error on duplicate keys.
35
+ #
36
+ # @see #attribute
37
+ # @param (see #attribute)
38
+ # @yield (see #attribute)
39
+ # @yieldparam (see #attribute)
40
+ def attribute!(key, value = nil, &block)
28
41
  value = HashBuilder.build(@context, value, &block) if block
29
42
  @data[key.to_s] = value
30
43
  end
@@ -49,9 +62,22 @@ module Serial
49
62
  #
50
63
  # @see ArrayBuilder
51
64
  # @param key [#to_s]
65
+ # @yield [builder]
52
66
  # @yieldparam builder [ArrayBuilder]
53
67
  def collection(key, &block)
54
- attribute(key, ArrayBuilder.build(@context, &block))
68
+ check_duplicate_key!(key)
69
+ collection!(key, &block)
70
+ end
71
+
72
+ # @api public
73
+ # Same as {#collection}, but will not raise an error on duplicate keys.
74
+ #
75
+ # @see #collection
76
+ # @param (see #collection)
77
+ # @yield (see #collection)
78
+ # @yieldparam (see #collection)
79
+ def collection!(key, &block)
80
+ attribute!(key, ArrayBuilder.build(@context, &block))
55
81
  end
56
82
 
57
83
  # @api public
@@ -69,7 +95,19 @@ module Serial
69
95
  # @yieldparam builder [HashBuilder]
70
96
  # @yieldparam value
71
97
  def map(key, list, &block)
72
- collection(key) do |builder|
98
+ check_duplicate_key!(key)
99
+ map!(key, list, &block)
100
+ end
101
+
102
+ # @api public
103
+ # Same as {#map}, but will not raise an error on duplicate keys.
104
+ #
105
+ # @see #map
106
+ # @param (see #map)
107
+ # @yield (see #map)
108
+ # @yieldparam (see #map)
109
+ def map!(key, list, &block)
110
+ collection!(key) do |builder|
73
111
  list.each do |item|
74
112
  builder.element do |element|
75
113
  element.exec(item, &block)
@@ -77,5 +115,48 @@ module Serial
77
115
  end
78
116
  end
79
117
  end
118
+
119
+ # @api public
120
+ # Merge another serializer into the current serialization.
121
+ #
122
+ # @example
123
+ # ExtendedProjectSerializer = Serial::Serializer.new do |h, project|
124
+ # h.merge(project, &ProjectSerializer)
125
+ # h.attribute(:extra, project.extra_info)
126
+ # end # => { "name" => …, …, "extra" => … }
127
+ #
128
+ # @param value
129
+ # @yield [builder, value] to another serializer
130
+ # @yieldparam builder [HashBuilder]
131
+ # @yieldparam value
132
+ # @raise [DuplicateKeyError] if a key to be merged is already defined.
133
+ def merge(value, &serializer)
134
+ hash = HashBuilder.build(@context, value, &serializer)
135
+ hash.keys.each { |key| check_duplicate_key!(key) }
136
+ @data.merge!(hash)
137
+ end
138
+
139
+ # @api public
140
+ # Same as {#merge}, but will not raise an error on duplicate keys.
141
+ #
142
+ # @see #merge
143
+ # @param (see #merge)
144
+ # @yield (see #merge)
145
+ # @yieldparam (see #merge)
146
+ def merge!(value, &serializer)
147
+ hash = HashBuilder.build(@context, value, &serializer)
148
+ @data.merge!(hash)
149
+ end
150
+
151
+ private
152
+
153
+ # @param key [#to_s]
154
+ # @raise [DuplicateKeyError] if key is defined
155
+ # @return [nil]
156
+ def check_duplicate_key!(key)
157
+ if @data.has_key?(key.to_s)
158
+ raise DuplicateKeyError, "'#{key}' is already defined"
159
+ end
160
+ end
80
161
  end
81
162
  end
@@ -1,6 +1,7 @@
1
1
  module Serial
2
2
  # Helpers for using Serial with Rails.
3
3
  module RailsHelpers
4
+ # @api public
4
5
  # Find the serializer for `model` and serialize it in the context of self.
5
6
  #
6
7
  # @example serializing a single object
@@ -17,6 +18,8 @@ module Serial
17
18
  #
18
19
  # @param context [#instance_exec]
19
20
  # @param model [#model_name, #each?]
21
+ # @yield [builder, model] yields if a block is given to use a custom serializer
22
+ # @yieldparam builder [HashBuilder]
20
23
  def serialize(context = self, model, &serializer)
21
24
  serializer &&= Serializer.new(&serializer)
22
25
  serializer ||= "#{model.model_name}Serializer".constantize
@@ -1,4 +1,4 @@
1
1
  module Serial
2
2
  # Gem version, uses SemVer.
3
- VERSION = "0.2.0"
3
+ VERSION = "1.0.0"
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: serial
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elabs
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2015-09-18 00:00:00.000000000 Z
13
+ date: 2015-09-23 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -110,6 +110,7 @@ files:
110
110
  - ".travis.yml"
111
111
  - ".yardopts"
112
112
  - CHANGELOG.md
113
+ - CODE_OF_CONDUCT.md
113
114
  - Gemfile
114
115
  - README.md
115
116
  - Rakefile