mimi-struct 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4ce18d3926ef7a9a05740b35362bd3c8d285f6ea
4
- data.tar.gz: 0b668e2e2e2424ccdc1b792aa6c83748a5e6ab54
3
+ metadata.gz: 8064ab3ebc35af445e5be33a322db6d14a31693e
4
+ data.tar.gz: f8d1a850531925e12fe0c473647dc519538072f0
5
5
  SHA512:
6
- metadata.gz: '0478d07e8a60c92362638ae261410d4cb96889958b192920d935ce0a5fa2cbdfd7907c27f0ae495273223bc143bb1850aa8490e3960dbd3f4864bb1baa70ba44'
7
- data.tar.gz: 1523ca2197640b826f7b7a524ccd45763bc857c7e53d32620686de912bcc0bc3ebd711166fe5e7c5c33d5919a61a2d8b7ede0b64b73693b5327e18ff72053927
6
+ metadata.gz: 3d62b706cf2bffafb74bd09ead748382b95e1a4d297c6976832968065f5ecc7c9a6ca65b9daa7baed14f741c46719891ceaa23fcd7fdc921b8a73b0344e90fea
7
+ data.tar.gz: ad312292e8c75438467baa6754658f26e101040dd9ee1121dc6a4ddf349975c09d72f5ebe72e91566ddc384a33a8e3bd6fe835d982373de8dce817ddc9a8c506
data/.gitignore CHANGED
@@ -1,11 +1,10 @@
1
1
  /.bundle/
2
2
  /.yardoc
3
+ /Gemfile.lock
3
4
  /_yardoc/
4
5
  /coverage/
5
6
  /doc/
6
7
  /pkg/
7
8
  /spec/reports/
8
9
  /tmp/
9
-
10
- # rspec failure tracking
11
- .rspec_status
10
+ /.rspec_status
data/bin/console CHANGED
@@ -6,9 +6,5 @@ require "mimi/struct"
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
8
8
 
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start(__FILE__)
9
+ require "pry"
10
+ Pry.start
@@ -0,0 +1,29 @@
1
+ require "mimi/struct"
2
+ require "json"
3
+
4
+ class User < Mimi::Struct
5
+ attribute :id
6
+ attribute :name, from: :username
7
+ end
8
+
9
+ class Comment < Mimi::Struct
10
+ attribute :author, from: :user, using: User
11
+ attribute :text
12
+ end
13
+
14
+ class Post < Mimi::Struct
15
+ attribute :id
16
+ attribute :author, using: User
17
+ attribute :text
18
+ attribute :comments, using: Comment
19
+ end
20
+
21
+ user1 = { id: 1, username: "Alice", email: "alice@gmail.com" }
22
+ user2 = { id: 2, username: "Bob", email: "bob@gmail.com" }
23
+ comm1 = { user: user1, text: "Mmm?" }
24
+ comm2 = { user: user2, text: "Hi!" }
25
+ post_params = { id: 1, author: user1, text: "Hello, world!", comments: [comm1, comm2] }
26
+
27
+ # Maps Post including all nested data
28
+ post = Post.new(post_params)
29
+ puts JSON.pretty_generate post.to_h
data/examples/poro.rb ADDED
@@ -0,0 +1,23 @@
1
+ require "mimi/struct"
2
+
3
+ #
4
+ # Mapping a PORO
5
+ #
6
+
7
+ class User < Mimi::Struct
8
+ attribute :id
9
+ attribute :name, from: :username
10
+ end
11
+
12
+ class UserData
13
+ attr_reader :id, :username
14
+
15
+ def initialize(username)
16
+ @id = rand(1000)
17
+ @username = username
18
+ end
19
+ end
20
+
21
+ user_data = UserData.new("John")
22
+
23
+ puts User.new(user_data).to_h
@@ -0,0 +1,13 @@
1
+ require "mimi/struct"
2
+
3
+ # Simple data mapping
4
+ #
5
+ class User < Mimi::Struct
6
+ attribute :id
7
+ attribute :name, from: :username
8
+ end
9
+
10
+ # Maps defined attributes, filters out all the extra attributes:
11
+ user = User.new(id: 1, username: "John", email: "john@gmail.com")
12
+
13
+ puts user.to_h
data/lib/mimi/struct.rb CHANGED
@@ -1,14 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "mimi/core"
4
+
3
5
  module Mimi
4
6
  #
5
- # A Struct that can be initialized from a Hash or another Struct.
7
+ # A Struct that can be initialized from a Hash or a PORO.
6
8
  #
7
- # A Struct declares its attributes and rules, which define how its attrubutes
9
+ # A Struct declares its attributes and rules, which define how its attributes
8
10
  # are mapped from input data.
9
11
  #
10
- class Struct < ::Struct
11
-
12
+ class Struct < Mimi::Core::Struct
13
+ #
12
14
  # Default attribute mapper
13
15
  #
14
16
  # Maps value of the source attribute to the target attribute.
@@ -16,9 +18,9 @@ module Mimi
16
18
  #
17
19
  DEFAULT_ATTRIBUTE_MAPPER = -> (o, params) do
18
20
  if params.key?(:default)
19
- o.to_h.key?(params[:from]) || call_as_proc(params[:default], o, params)
21
+ o.respond_to?(params[:from]) || call_as_proc(params[:default], o, params)
20
22
  else
21
- o[params[:from]]
23
+ o.send(params[:from])
22
24
  end
23
25
  end
24
26
 
@@ -27,7 +29,27 @@ module Mimi
27
29
  # Skips the attribute if the source attribute is not set.
28
30
  #
29
31
  DEFAULT_IF_FOR_OPTIONAL = -> (o, params) do
30
- o.to_h.key?(params[:from])
32
+ o.respond_to?(params[:from])
33
+ end
34
+
35
+ # Creates a mapped Struct object from another object
36
+ #
37
+ # @param source [Hash,Object]
38
+ #
39
+ def initialize(source)
40
+ source = Mimi::Core::Struct.new(source) if source.is_a?(Hash)
41
+ attributes = self.class.transform_attributes(source)
42
+ super(attributes)
43
+ rescue StandardError => e
44
+ raise e.class, "Failed to construct #{self.class}: #{e}", e.backtrace
45
+ end
46
+
47
+ # Fetches an attribute with given name
48
+ #
49
+ # @param name [Symbol]
50
+ #
51
+ def [](name)
52
+ @attributes[name.to_sym]
31
53
  end
32
54
 
33
55
  # Presents this Struct as a Hash, deeply converting nested Structs
@@ -35,7 +57,7 @@ module Mimi
35
57
  # @return [Hash]
36
58
  #
37
59
  def to_h
38
- super.map do |k, v|
60
+ attributes.map do |k, v|
39
61
  [k, self.class.value_to_h(v)]
40
62
  end.to_h
41
63
  end
@@ -45,7 +67,7 @@ module Mimi
45
67
  # @return [Hash]
46
68
  #
47
69
  def attributes
48
- to_h
70
+ @attributes
49
71
  end
50
72
 
51
73
  # An attribute definition
@@ -109,7 +131,7 @@ module Mimi
109
131
  if obj_or_collection.is_a?(Array)
110
132
  obj_or_collection.map { |o| self << o }
111
133
  else
112
- transform(obj_or_collection)
134
+ new(obj_or_collection)
113
135
  end
114
136
  end
115
137
 
@@ -141,36 +163,19 @@ module Mimi
141
163
  @group_params ||= [{}]
142
164
  end
143
165
 
144
- # Creates a Struct instance from given parameters
145
- #
146
- # @param source [Struct,Hash]
147
- #
148
- private_class_method def self.transform(source)
149
- if source.is_a?(Struct)
150
- # do nothing
151
- elsif source.is_a?(Hash)
152
- source = Struct.new(*source.to_h.keys).new(*source.to_h.values)
153
- else
154
- raise ArgumentError, "Struct or Hash is expected as source"
155
- end
156
- attributes = transform_attributes(source)
157
- new(*attributes.keys).new(*attributes.values)
158
- rescue StandardError => e
159
- raise "Failed to construct #{self}: #{e}"
160
- end
161
-
162
166
  # Transform attributes according to rules
163
167
  #
164
168
  # @param source [Struct]
165
169
  # @return [Hash] map of attribute name -> value
166
170
  #
167
- private_class_method def self.transform_attributes(source)
168
- attribute_definitions.map do |k, params|
171
+ def self.transform_attributes(source)
172
+ result = attribute_definitions.map do |k, params|
169
173
  if params[:if].is_a?(Proc)
170
174
  next unless call_as_proc(params[:if], source, params)
171
175
  end
172
176
  [k, transform_single_attribute(source, k, params)]
173
177
  end.compact.to_h
178
+ result
174
179
  end
175
180
 
176
181
  # Transforms a single attribute value according to rules passed as params
@@ -183,7 +188,7 @@ module Mimi
183
188
  private_class_method def self.transform_single_attribute(source, key, params)
184
189
  return call_as_proc(params[:using], source, params) if params[:using].is_a?(Proc)
185
190
  if params[:using].is_a?(Class) && params[:using] < Mimi::Struct
186
- return params[:using] << source[params[:from]]
191
+ return params[:using] << source.send(params[:from])
187
192
  end
188
193
  raise "unexpected :using type: #{params[:using].class}"
189
194
  rescue StandardError => e
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "mimi/struct"
4
-
5
3
  module Mimi
6
4
  class Struct
7
- VERSION = "0.1.0"
5
+ VERSION = "1.0.0"
8
6
  end
9
7
  end
data/mimi-struct.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  lib = File.expand_path("lib", __dir__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require "mimi/struct/version"
3
+ require "mimi/struct"
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "mimi-struct"
@@ -30,9 +30,10 @@ Gem::Specification.new do |spec|
30
30
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
31
  spec.require_paths = ["lib"]
32
32
 
33
- spec.add_dependency "mimi-core", "~> 1.0"
33
+ spec.add_dependency "mimi-core", "~> 1.1"
34
34
 
35
35
  spec.add_development_dependency "bundler", "~> 2.0"
36
+ spec.add_development_dependency "pry", "~> 0.12"
36
37
  spec.add_development_dependency "rake", "~> 10.0"
37
38
  spec.add_development_dependency "rspec", "~> 3.0"
38
39
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mimi-struct
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Kukushkin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-06-23 00:00:00.000000000 Z
11
+ date: 2019-06-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mimi-core
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.0'
19
+ version: '1.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.0'
26
+ version: '1.1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.12'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.12'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rake
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -78,13 +92,15 @@ files:
78
92
  - ".travis.yml"
79
93
  - CODE_OF_CONDUCT.md
80
94
  - Gemfile
81
- - Gemfile.lock
82
95
  - LICENSE.txt
83
96
  - README.md
84
97
  - Rakefile
85
98
  - bin/console
86
99
  - bin/setup
87
100
  - examples/customer.rb
101
+ - examples/nested.rb
102
+ - examples/poro.rb
103
+ - examples/simple.rb
88
104
  - lib/mimi/struct.rb
89
105
  - lib/mimi/struct/version.rb
90
106
  - mimi-struct.gemspec
data/Gemfile.lock DELETED
@@ -1,39 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- mimi-struct (0.1.0)
5
- mimi-core (~> 1.0)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- diff-lcs (1.3)
11
- hashie (3.6.0)
12
- mimi-core (1.0.0)
13
- hashie (~> 3.6)
14
- rake (10.5.0)
15
- rspec (3.8.0)
16
- rspec-core (~> 3.8.0)
17
- rspec-expectations (~> 3.8.0)
18
- rspec-mocks (~> 3.8.0)
19
- rspec-core (3.8.1)
20
- rspec-support (~> 3.8.0)
21
- rspec-expectations (3.8.4)
22
- diff-lcs (>= 1.2.0, < 2.0)
23
- rspec-support (~> 3.8.0)
24
- rspec-mocks (3.8.1)
25
- diff-lcs (>= 1.2.0, < 2.0)
26
- rspec-support (~> 3.8.0)
27
- rspec-support (3.8.2)
28
-
29
- PLATFORMS
30
- ruby
31
-
32
- DEPENDENCIES
33
- bundler (~> 2.0)
34
- mimi-struct!
35
- rake (~> 10.0)
36
- rspec (~> 3.0)
37
-
38
- BUNDLED WITH
39
- 2.0.2