alba 0.2.0 → 0.7.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
  SHA256:
3
- metadata.gz: 9dab0921e07fb607cfceb802a42fdb5f8cc20eb745522c46dc7b451b8a0cd14e
4
- data.tar.gz: 6c6fcc0035ef543ee6d60bffa18ca83379d090e800950411d7316c21031784ad
3
+ metadata.gz: 405e177e9e1fcadf7dbb164d3ac6924e1b3563547f715fedb698211b527a9604
4
+ data.tar.gz: 2c534708583345ac9090c83b3ddc939b0c8bd335ed77017f554edb28578d0396
5
5
  SHA512:
6
- metadata.gz: c97545976f850ba0191dcabf7f34b8daeebf54d2b82c9a37305f569cc7cadaa1b9f0f92dc42f81193e9fd56eae2e862d650b023c4bcd105739c18c0baaf35e13
7
- data.tar.gz: 7423763628b13e5643193347379eefbcf2cc2d78266cafd147d8c86d3f755feca93dd3f2c9bca92e8ec008b1ec7d00c9ed7bf1590a2f26e83c99fa529a987de1
6
+ metadata.gz: 71f4712ac28d457fe9bf997fb127288ed66d7d2231ffd6dd438b2eb5c1dd82ff9e3e5c4000415c513012a582cda3d3c3e73fdf0beb4cc96b8583ff9a658dfa75
7
+ data.tar.gz: '07439ccffc5b48a0d5d4286236acadf4cc3e89ff1afa0a882a87c1fe5640015096a4cd85839cebdc4d6ef350a77043a494bfe4d7b6cff99f8e7db2ab9f8b3db0'
data/Gemfile CHANGED
@@ -5,6 +5,7 @@ gemspec
5
5
 
6
6
  gem 'coveralls', require: false
7
7
  gem 'minitest', '~> 5.0'
8
+ gem 'oj', '~> 3.10'
8
9
  gem 'rake', '~> 13.0'
9
10
  gem 'rubocop', '>= 0.79.0', require: false
10
11
  gem 'rubocop-performance', '~> 1.7.1', require: false
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- alba (0.2.0)
4
+ alba (0.7.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -16,6 +16,7 @@ GEM
16
16
  docile (1.3.2)
17
17
  json (2.3.1)
18
18
  minitest (5.14.1)
19
+ oj (3.10.8)
19
20
  parallel (1.19.2)
20
21
  parser (2.7.1.4)
21
22
  ast (~> 2.4.1)
@@ -59,6 +60,7 @@ DEPENDENCIES
59
60
  alba!
60
61
  coveralls
61
62
  minitest (~> 5.0)
63
+ oj (~> 3.10)
62
64
  rake (~> 13.0)
63
65
  rubocop (>= 0.79.0)
64
66
  rubocop-performance (~> 1.7.1)
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # Alba
6
6
 
7
- `Alba` is a fast and flexible JSON serializer.
7
+ `Alba` is a stupid, fast and easy to use JSON serializer.
8
8
 
9
9
  ## Installation
10
10
 
@@ -24,6 +24,8 @@ Or install it yourself as:
24
24
 
25
25
  ## Usage
26
26
 
27
+ ### Simple serialization with key
28
+
27
29
  ```ruby
28
30
  class User
29
31
  attr_accessor :id, :name, :email, :created_at, :updated_at
@@ -57,6 +59,80 @@ UserResource.new(user).serialize
57
59
  # => "{\"id\":1,\"name\":\"Masafumi OKURA\",\"name_with_email\":\"Masafumi OKURA: masafumi@example.com\"}"
58
60
  ```
59
61
 
62
+ ### Serialization with associations
63
+
64
+ ```ruby
65
+ class User
66
+ attr_reader :id, :created_at, :updated_at
67
+ attr_accessor :articles
68
+
69
+ def initialize(id)
70
+ @id = id
71
+ @created_at = Time.now
72
+ @updated_at = Time.now
73
+ @articles = []
74
+ end
75
+ end
76
+
77
+ class Article
78
+ attr_accessor :user_id, :title, :body
79
+
80
+ def initialize(user_id, title, body)
81
+ @user_id = user_id
82
+ @title = title
83
+ @body = body
84
+ end
85
+ end
86
+
87
+ class ArticleResource
88
+ include Alba::Resource
89
+
90
+ attributes :title
91
+ end
92
+
93
+ class UserResource1
94
+ include Alba::Resource
95
+
96
+ attributes :id
97
+
98
+ many :articles, resource: ArticleResource
99
+ end
100
+
101
+ user = User.new(1)
102
+ article1 = Article.new(1, 'Hello World!', 'Hello World!!!')
103
+ user.articles << article1
104
+ article2 = Article.new(2, 'Super nice', 'Really nice!')
105
+ user.articles << article2
106
+
107
+ UserResource1.new(user).serialize
108
+ # => '{"id":1,"articles":[{"title":"Hello World!"},{"title":"Super nice"}]}'
109
+ ```
110
+
111
+ ### Inline definition with `Alba.serialize`
112
+
113
+ `Alba.serialize` method is a shortcut to define everything inline.
114
+
115
+ ```ruby
116
+ Alba.serialize(user, with: proc { set key: :foo }) do
117
+ attributes :id
118
+ many :articles do
119
+ attributes :title, :body
120
+ end
121
+ end
122
+ # => '{"foo":{"id":1,"articles":[{"title":"Hello World!","body":"Hello World!!!"},{"title":"Super nice","body":"Really nice!"}]}}'
123
+ ```
124
+
125
+ Although this might be useful sometimes, it's generally recommended to define a class for both Resource and Serializer.
126
+
127
+ ## Comparison
128
+
129
+ Since Alba is intended to be stupid, there are many things Alba can't do while other gems can. However, from the same reason, it's extremely faster than alternatives.
130
+ For a performance benchmark, see https://gist.github.com/okuramasafumi/4e375525bd3a28e4ca812d2a3b3e5829.
131
+
132
+ ## Why named "Alba"?
133
+
134
+ The name "Alba" comes from "albatross", a kind of birds. In Japanese, this bird is called "Aho-dori", which means "stupid bird". I find it funny because in fact albatrosses fly really fast. I hope Alba looks stupid but in fact it does its job quick.
135
+
60
136
  ## Development
61
137
 
62
138
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -1,6 +1,8 @@
1
1
  require 'alba/version'
2
+ require 'alba/serializers/default_serializer'
3
+ require 'alba/serializer'
2
4
  require 'alba/resource'
3
- require 'json'
5
+ require 'alba/resources/default_resource'
4
6
 
5
7
  # Core module
6
8
  module Alba
@@ -8,24 +10,25 @@ module Alba
8
10
 
9
11
  class << self
10
12
  attr_reader :backend
11
- end
13
+ attr_accessor :default_serializer
12
14
 
13
- def self.backend=(backend)
14
- @backend = backend&.to_sym
15
- end
15
+ def backend=(backend)
16
+ @backend = backend&.to_sym
17
+ end
18
+
19
+ def serialize(object, with: nil, &block)
20
+ raise ArgumentError, 'Block required' unless block
21
+
22
+ resource_class.class_eval(&block)
23
+ resource = resource_class.new(object)
24
+ with ||= @default_serializer
25
+ resource.serialize(with: with)
26
+ end
27
+
28
+ private
16
29
 
17
- def self.serialize(object)
18
- fallback = ->(resource) { resource.to_json }
19
- case backend
20
- when :oj
21
- begin
22
- require 'oj'
23
- ->(resource) { Oj.dump(resource) }
24
- rescue LoadError
25
- fallback
26
- end
27
- else
28
- fallback
29
- end.call(object)
30
+ def resource_class
31
+ ::Alba::Resources::DefaultResource.clone
32
+ end
30
33
  end
31
34
  end
@@ -9,7 +9,7 @@ module Alba
9
9
  end
10
10
 
11
11
  def to_hash(target)
12
- objects = target.__send__(@name)
12
+ objects = target.public_send(@name)
13
13
  @resource ||= resource_class
14
14
  objects.map { |o| @resource.new(o).to_hash }
15
15
  end
@@ -9,7 +9,7 @@ module Alba
9
9
  end
10
10
 
11
11
  def to_hash(target)
12
- object = target.__send__(@name)
12
+ object = target.public_send(@name)
13
13
  @resource ||= resource_class
14
14
  @resource.new(object).to_hash
15
15
  end
@@ -7,12 +7,17 @@ require 'alba/serializers/default_serializer'
7
7
  module Alba
8
8
  # This module represents what should be serialized
9
9
  module Resource
10
- DSLS = [:_attributes, :_one, :_many, :_serializer].freeze
10
+ DSLS = [:_attributes, :_serializer, :_key].freeze
11
11
  def self.included(base)
12
12
  base.class_eval do
13
13
  # Initialize
14
14
  DSLS.each do |name|
15
- initial = name == :_serializer ? nil : {}
15
+ initial = case name
16
+ when :_attributes
17
+ {}
18
+ when :_serializer, :_name
19
+ nil
20
+ end
16
21
  instance_variable_set("@#{name}", initial) unless instance_variable_defined?("@#{name}")
17
22
  end
18
23
  end
@@ -29,41 +34,47 @@ module Alba
29
34
 
30
35
  def serialize(with: nil)
31
36
  serializer = case with
32
- when ->(obj) { obj.is_a?(Class) && obj <= Alba::Serializer }
33
- with
34
- when Symbol
35
- const_get(with.to_s.capitalize)
36
- when String
37
- const_get(with)
38
37
  when nil
39
38
  @_serializer || Alba::Serializers::DefaultSerializer
39
+ when ->(obj) { obj.is_a?(Class) && obj <= Alba::Serializer }
40
+ with
41
+ when Proc
42
+ inline_extended_serializer(with)
43
+ else
44
+ raise ArgumentError, 'Unexpected type for with, possible types are Class or Proc'
40
45
  end
41
- serializer.new(serializable_hash).serialize
46
+ serializer.new(self).serialize
42
47
  end
43
48
 
44
- def serializable_hash
45
- attrs.merge(ones).merge(manies)
49
+ def serializable_hash(with_key: true)
50
+ get_attribute = lambda do |resource|
51
+ @_attributes.transform_values do |attribute|
52
+ attribute.to_hash(resource)
53
+ end
54
+ end
55
+ serializable_hash = if collection?
56
+ @_resource.map(&get_attribute)
57
+ else
58
+ get_attribute.call(@_resource)
59
+ end
60
+ with_key && @_key ? {@_key => serializable_hash} : serializable_hash
46
61
  end
47
62
  alias to_hash serializable_hash
48
63
 
49
- private
50
-
51
- def attrs
52
- @_attributes.transform_values do |attribute|
53
- attribute.to_hash(@_resource)
54
- end || {}
64
+ def key
65
+ @_key || self.class.name.delete_suffix('Resource').downcase.gsub(/:{2}/, '_').to_sym
55
66
  end
56
67
 
57
- def ones
58
- @_one.transform_values do |one|
59
- one.to_hash(@_resource)
60
- end || {}
68
+ private
69
+
70
+ def inline_extended_serializer(with)
71
+ klass = ::Alba::Serializers::DefaultSerializer.clone
72
+ klass.class_eval(&with)
73
+ klass
61
74
  end
62
75
 
63
- def manies
64
- @_many.transform_values do |many|
65
- many.to_hash(@_resource)
66
- end || {}
76
+ def collection?
77
+ @_resource.is_a?(Enumerable)
67
78
  end
68
79
  end
69
80
 
@@ -86,16 +97,20 @@ module Alba
86
97
  end
87
98
 
88
99
  def one(name, resource: nil, &block)
89
- @_one[name.to_sym] = One.new(name: name, resource: resource, &block)
100
+ @_attributes[name.to_sym] = One.new(name: name, resource: resource, &block)
90
101
  end
91
102
 
92
103
  def many(name, resource: nil, &block)
93
- @_many[name.to_sym] = Many.new(name: name, resource: resource, &block)
104
+ @_attributes[name.to_sym] = Many.new(name: name, resource: resource, &block)
94
105
  end
95
106
 
96
107
  def serializer(name)
97
108
  @_serializer = name <= Alba::Serializer ? name : nil
98
109
  end
110
+
111
+ def key(key)
112
+ @_key = key.to_sym
113
+ end
99
114
  end
100
115
  end
101
116
  end
@@ -0,0 +1,9 @@
1
+ module Alba
2
+ module Resources
3
+ # Empty resource class, use this with `class_eval` for
4
+ # inline associations and serializations.
5
+ class DefaultResource
6
+ include ::Alba::Resource
7
+ end
8
+ end
9
+ end
@@ -1,6 +1,5 @@
1
1
  module Alba
2
2
  # This module represents how a resource should be serialized.
3
- #
4
3
  module Serializer
5
4
  def self.included(base)
6
5
  base.include InstanceMethods
@@ -10,19 +9,27 @@ module Alba
10
9
  # Instance methods
11
10
  module InstanceMethods
12
11
  def initialize(resource)
13
- @_resource = resource
14
12
  @_opts = self.class._opts || {}
15
- key = @_opts[:key]
16
- @_resource = {key.to_sym => @_resource} if key
13
+ key = case @_opts[:key]
14
+ when true
15
+ resource.key
16
+ else
17
+ @_opts[:key]
18
+ end
19
+ @hash = resource.serializable_hash(with_key: false)
20
+ @hash = {key.to_sym => @hash} if key
17
21
  end
18
22
 
19
23
  def serialize
20
- fallback = -> { @_resource.to_json }
24
+ fallback = lambda do
25
+ require 'json'
26
+ JSON.dump(@hash)
27
+ end
21
28
  case Alba.backend
22
29
  when :oj
23
30
  begin
24
31
  require 'oj'
25
- -> { Oj.dump(@_resource) }
32
+ -> { Oj.dump(@hash, mode: :strict) }
26
33
  rescue LoadError
27
34
  fallback
28
35
  end
@@ -1,3 +1,5 @@
1
+ require 'alba/serializer'
2
+
1
3
  module Alba
2
4
  module Serializers
3
5
  # DefaultSerializer class is used when a user doesn't specify serializer opt.
@@ -1,3 +1,3 @@
1
1
  module Alba
2
- VERSION = '0.2.0'.freeze
2
+ VERSION = '0.7.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alba
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - OKURA Masafumi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-25 00:00:00.000000000 Z
11
+ date: 2020-07-31 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Fast and flexible JSON serializer
14
14
  email:
@@ -34,6 +34,7 @@ files:
34
34
  - lib/alba/many.rb
35
35
  - lib/alba/one.rb
36
36
  - lib/alba/resource.rb
37
+ - lib/alba/resources/default_resource.rb
37
38
  - lib/alba/serializer.rb
38
39
  - lib/alba/serializers/default_serializer.rb
39
40
  - lib/alba/version.rb