cartograph 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 75a2908b56243cc37194669f69b38f4b98b98674
4
+ data.tar.gz: d6ef9fc6b4ada540498ba187594fdff5234767aa
5
+ SHA512:
6
+ metadata.gz: 46424d9ba2555a11ea4acac0ad660259b5b46d47b9a1da40226c9dd8695cb7df22a6f82d4c02c2c9a5339b15290c5ffacaec91e6329c1d210b2d0939dd71a8ea
7
+ data.tar.gz: 4bc57fb275ea7f6f3f349af9e08f34ca20c9d302b7612ae1575c1d942b86d05dc6a624170df72bed91b4d0d334d4b933be59df0dffb023d8a6fe6058928db307
@@ -0,0 +1,23 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+ .pairs
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.1
4
+ - 2.0.0
@@ -0,0 +1,11 @@
1
+ Cartograph Changelog
2
+ ====================
3
+
4
+ ### master
5
+
6
+ ### [v1.0.0][v1.0.0] (September 7, 2017)
7
+
8
+ * Added support for dry-struct
9
+ ([#3](https://github.com/kyrylo/cartograph/pull/3))
10
+
11
+ [v1.0.0]: https://github.com/kyrylo/cartograph/releases/tag/v1.0.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cartograph.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Robert Ross
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,211 @@
1
+ # Cartograph
2
+
3
+ A Serialization / Deserialization library.
4
+
5
+ [![Build Status](https://travis-ci.org/kyrylo/cartograph.svg?branch=master)](https://travis-ci.org/kyrylo/cartograph)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'cartograph'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ ## Usage
18
+
19
+ Cartograph makes it easy to generate and convert JSON. It's intention is to be used for API clients.
20
+
21
+ For example, if you have an object that you would like to convert to JSON for a create request to an API. You would have something similar to this:
22
+
23
+ ```ruby
24
+ class UserMapping
25
+ include Cartograph::DSL
26
+
27
+ cartograph do
28
+ mapping User # The object we're mapping
29
+
30
+ property :name, :email, scopes: [:create, :update]
31
+ property :id, scopes: :read
32
+ end
33
+ end
34
+
35
+ user = User.new(name: 'Bobby Tables')
36
+ json_for_create = UserMapping.representation_for(:create, user)
37
+ ```
38
+
39
+ ### Rendering Objects or Collections as Hashes
40
+
41
+ ```ruby
42
+ user = User.new(name: 'PB Jelly')
43
+ users = [user]
44
+
45
+ hash = UserMapping.hash_for(:read, user)
46
+ hash_collection = UserMapping.hash_collection_for(:read, user)
47
+ ```
48
+
49
+ ### Rendering Collections as JSON
50
+
51
+ ```ruby
52
+ user = User.new(name: 'Bobby Tables')
53
+ users = Array.new(10, user)
54
+
55
+ json = UserMapping.represent_collection_for(:read, users)
56
+ ```
57
+
58
+ ---
59
+
60
+ Some API's will give you the created resource back as JSON as well on a successful create. For that, you may do something like this:
61
+
62
+ ```ruby
63
+ response = HTTPClient.post("http://something.com/api/users", body: json_for_create)
64
+ created_user = UserMapping.extract_single(response.body, :read)
65
+ ```
66
+
67
+ Most API's will have a way of retrieving an entire resource collection. For this you can instruct Cartograph to convert a collection.
68
+
69
+ ```ruby
70
+ response = HTTPClient.get("http://something.com/api/users")
71
+ users = UserMapping.extract_collection(response.body, :read)
72
+ # => [ User, User, User ]
73
+ ```
74
+
75
+ ### Getting Harder
76
+
77
+ Sometimes resources will nest other properties under a key. Cartograph can handle this as well.
78
+
79
+ ```ruby
80
+ class UserMapping
81
+ include Cartograph::DSL
82
+
83
+ cartograph do
84
+ mapping User # The object we're mapping
85
+
86
+ property :name, scopes: [:read]
87
+
88
+ property :comments do
89
+ mapping Comment # The nested object we're mapping
90
+
91
+ property :text, scopes: [:read]
92
+ property :author, scopes: [:read]
93
+ end
94
+ end
95
+ end
96
+ ```
97
+
98
+ Just like the previous examples, when you serialize this. It will include the comment block for the scope defined.
99
+
100
+ ### Root Keys
101
+
102
+ Cartograph can also handle the event of root keys in response bodies. For example, if you receive a response with:
103
+
104
+ ```json
105
+ { "user": { "id": 123 } }
106
+ ```
107
+
108
+ You could define a mapping like this:
109
+
110
+
111
+ ```ruby
112
+ class UserMapping
113
+ include Cartograph::DSL
114
+
115
+ cartograph do
116
+ mapping User
117
+ root_key singular: 'user', plural: 'users', scopes: [:read]
118
+ property :id, scopes: [:read]
119
+ end
120
+ end
121
+ ```
122
+
123
+ This means that when you call the same thing:
124
+
125
+ ```ruby
126
+ response = HTTPClient.get("http://something.com/api/users")
127
+ users = UserMapping.extract_collection(response.body, :read)
128
+ ```
129
+
130
+ It will look for the root key before trying to deserialize the JSON response.
131
+ The advantage of this is it will only use the root key if there is a scope defined for it.
132
+
133
+
134
+ ### Including other definitions within eachother
135
+
136
+ Sometimes you might have models that are nested within eachother on responses. Or you simply want to cleanup definitions by separating concerns. Cartograph lets you do this with includes.
137
+
138
+ ```ruby
139
+ class UserMapping
140
+ include Cartograph::DSL
141
+
142
+ cartograph do
143
+ mapping User
144
+ property :id, scopes: [:read]
145
+ property :comments, plural: true, include: CommentMapping
146
+ end
147
+ end
148
+
149
+ class CommentMapping
150
+ include Cartograph::DSL
151
+
152
+ cartograph do
153
+ mapping Comment
154
+ property :id, scopes: [:read]
155
+ property :text, scopes: [:read]
156
+ end
157
+ end
158
+ ```
159
+
160
+
161
+ ### Scope blocks
162
+
163
+ Sometimes adding scopes to all properties can be tedious, to avoid that, you can define properties within a scope block.
164
+
165
+ ```ruby
166
+ class UserMapping
167
+ include Cartograph::DSL
168
+
169
+ cartograph do
170
+ scoped :read do
171
+ property :name
172
+ property :id
173
+ property :email, key: 'email_address' # The JSON returned has the key of email_address, our property is called email however.
174
+ end
175
+
176
+ scoped :update, :create do
177
+ property :name
178
+ property :email, key: 'email_address'
179
+ end
180
+ end
181
+ end
182
+ ```
183
+
184
+ Now when JSON includes comments for a user, it will know how to map the comments using the provided Cartograph definition.
185
+
186
+ ---
187
+
188
+ ### Caching
189
+
190
+ Cartograph has the option to cache certain serializations, determined by the way you setup the key.
191
+
192
+ ```ruby
193
+ class UserMapping
194
+ include Cartograph::DSL
195
+
196
+ cartograph do
197
+ cache { Rails.cache } # As long as this respond to #fetch(key_name, options = {}, &block) it will work
198
+ cache_key { |object| object.cache_key }
199
+
200
+ end
201
+ end
202
+ end
203
+ ```
204
+
205
+ ## Contributing
206
+
207
+ 1. Fork it ( https://github.com/kyrylo/cartograph/fork )
208
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
209
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
210
+ 4. Push to the branch (`git push origin my-new-feature`)
211
+ 5. Create a new Pull Request
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cartograph/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "cartograph"
8
+ spec.version = Cartograph::VERSION
9
+ spec.authors = ["Robert Ross", "Kyrylo Silin"]
10
+ spec.email = ["silin@kyrylo.org"]
11
+ spec.summary = %q{Cartograph makes it easy to generate and convert JSON. It's intention is to be used for API clients.}
12
+ spec.description = %q{Cartograph makes it easy to generate and convert JSON. It's intention is to be used for API clients.}
13
+ spec.homepage = "https://github.com/kyrylo/cartograph"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency 'rake', '~> 12.0'
22
+ spec.add_development_dependency 'rspec', '~> 3.6'
23
+ spec.add_development_dependency 'pry', '~> 0'
24
+ end
@@ -0,0 +1,41 @@
1
+ require 'cartograph'
2
+ require 'pp'
3
+
4
+ class User < Struct.new(:id, :name, :comments)
5
+ end
6
+
7
+ class Comment < Struct.new(:id, :text)
8
+ end
9
+
10
+ class UserMapping
11
+ include Cartograph::DSL
12
+
13
+ cartograph do
14
+ mapping User
15
+
16
+ property :id, scopes: [:read]
17
+ property :name, scopes: [:read, :create]
18
+
19
+ property :comments, plural: true, scopes: [:read] do
20
+ mapping Comment
21
+
22
+ property :id, scopes: [:read]
23
+ property :text, scopes: [:read, :create]
24
+ end
25
+ end
26
+ end
27
+
28
+ user = User.new(1, 'he@he.com')
29
+ comment = Comment.new(12, 'aksjdfhasjkdfh')
30
+
31
+ user.comments = Array.new(3, comment)
32
+ users = Array.new(4, user)
33
+
34
+ json = UserMapping.represent_collection_for(:read, users)
35
+ puts "The JSON generated from that collection:"
36
+ puts json
37
+
38
+ users_again = UserMapping.extract_collection(json, :read)
39
+ puts "\n"
40
+ puts "And the JSON slurped back into an array:"
41
+ pp users_again
@@ -0,0 +1,54 @@
1
+ require 'cartograph'
2
+
3
+ json = '{
4
+ "domains": [
5
+ {
6
+ "name": "example.com",
7
+ "ttl": 1800,
8
+ "zone_file": "Example zone file text..."
9
+ }
10
+ ],
11
+ "meta": {
12
+ "total": 1
13
+ }
14
+ }'
15
+
16
+ class Domain
17
+ attr_accessor :name, :ttl, :zone_file
18
+ end
19
+
20
+ class MetaInformation
21
+ attr_accessor :total
22
+ end
23
+
24
+ class DomainMapper
25
+ include Cartograph::DSL
26
+
27
+ cartograph do
28
+ mapping Domain
29
+ root_key singular: 'domain', plural: 'domains', scopes: [:read]
30
+
31
+ property :name, scopes: [:read]
32
+ property :ttl, scopes: [:read]
33
+ property :zone_file, scopes: [:read]
34
+ end
35
+ end
36
+
37
+ class MetaInformationMapper
38
+ include Cartograph::DSL
39
+
40
+ cartograph do
41
+ mapping MetaInformation
42
+
43
+ root_key singular: 'meta', scopes: [:read]
44
+ property :total, scopes: [:read]
45
+ end
46
+ end
47
+
48
+ domains = DomainMapper.extract_collection(json, :read)
49
+ meta = MetaInformationMapper.extract_single(json, :read)
50
+
51
+ puts "Total Domains: #{domains.size}"
52
+ puts domains.map(&:name)
53
+ puts
54
+ puts "Total pages: #{meta.total}"
@@ -0,0 +1,24 @@
1
+ class Domain
2
+ attr_accessor :name, :ttl, :zone_file
3
+ end
4
+
5
+ class DomainMapper
6
+ include Cartograph::DSL
7
+
8
+ cartograph do
9
+ mapping Domain
10
+ root_key singular: 'domain', plural: 'domains', scopes: [:read]
11
+
12
+ property :name, scopes: [:read, :create]
13
+ property :ttl, scopes: [:read, :create]
14
+ property :zone_file, scopes: [:read]
15
+ end
16
+ end
17
+
18
+ domain = Domain.new
19
+ domain.name = 'example.com'
20
+ domain.ttl = 3600
21
+ domain.zone_file = "this wont be represented for create"
22
+
23
+ puts DomainMapper.representation_for(:create, domain)
24
+ #=> {"name":"example.com","ttl":3600}