mapping 0.1.0 → 0.2.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: 62eeea4a078392af4033ea474e602e46380f292a
4
- data.tar.gz: d42f4dbec45ba55de098a4d9460f56fb7fbf8bf3
3
+ metadata.gz: ff5729eb2b5ed25394691d7b0eddbc6083ec181e
4
+ data.tar.gz: a9a4b1ba4d65cd2851dd31459a89c603d4118c52
5
5
  SHA512:
6
- metadata.gz: 48aebf04842380c3fab0f9074aeec5b095d4c1c992c278f7f3e7e148c447a052c5d18f5e4139344fd9e15647160667c71e9c65dfad7ffe8c8cfb0d1bfb766b0a
7
- data.tar.gz: fd36ade69b67a8bb2b2c78be72eb490e3b75cc2cc62a5dfb55875f6df343995ca44561454175530d6087897f0dee5a0b9c78032752bb600102322d8fdd2d82bb
6
+ metadata.gz: 875e03d2ddf007893fbc87e4cfcc6f6decc4bc5e96730da64b7a858997856674a5d739d1620ba4e6eef7250bf5b6c230f4e83782e9844d2230643cd337636da1
7
+ data.tar.gz: e15c06f44348dad4378319aef715303ac4c0027469fe6bb3fdbbf266d6ca24309f2d1021996eaf1a0a0f239cf8fb3d18c3d4847ae3c842d7cd42f7576c682f24
data/README.md CHANGED
@@ -6,6 +6,35 @@ The mapping gem is a structured system for mapping one model to another, using a
6
6
  [![Code Climate](https://codeclimate.com/github/ioquatix/mapping.svg)](https://codeclimate.com/github/ioquatix/mapping)
7
7
  [![Coverage Status](https://coveralls.io/repos/ioquatix/mapping/badge.svg)](https://coveralls.io/r/ioquatix/mapping)
8
8
 
9
+ ## Motivation
10
+
11
+ I've been thinking (and designing) versioned APIs which serve their data primarily from `ActiveRecord` models. Initially we have been using `as_json/serializable_hash/to_json` where it made sense.
12
+
13
+ records.as_json
14
+
15
+ This was fine for really simple models and APIs. However, as things get more complex, this approach gets cumbersome:
16
+
17
+ records.as_json(
18
+ only: [:id, :name, :image, :longitude, :latitude],
19
+ include: [:major_category, :categories],
20
+ )
21
+
22
+ We need versioned, internationalized APIs which don't always directly match up to the underlying database models, or in some cases the underlying models change but the API should remain stable (e.g. column renamed, tables changed).
23
+
24
+ # image attribute was renamed to image_url, how do we version the response?
25
+ records.as_json(
26
+ only: [:id, :name, :image_url, :longitude, :latitude],
27
+ include: [:major_category, :categories],
28
+ )
29
+
30
+ It's also not obvious how to inject methods that take arguments, or even handle per-request state (e.g. `Accept-Language`). Even if it is possible (e.g. using a lambda) I'm not sure that this approach is really desirable - the argument list is becoming impossibly complex: Possibly buggy, hard to reuse, test and difficult to document.
31
+
32
+ [ActiveModel::Serializers](https://github.com/rails-api/active_model_serializers) looks awesome at first but ultimately seems like an over-engineered version of `as_json`. It **directly** depends on globally defined models which makes versioning hard and doesn't provide any obvious way to inject per-request state (e.g. language). It [clutters up existing models and splits serialization concerns over multiple classes](http://programmingisterrible.com/post/139222674273/write-code-that-is-easy-to-delete-not-easy-to-extend). It's implementation is difficult to understand, it has a large surface area, and it doesn't really address the major concerns regarding versioning, stability and (per-request) state.
33
+
34
+ I've implemented a [framework for Objective-C many years ago](https://github.com/oriontransfer/SWXMLMapping) which exposes a single primary concept: a mapping model. A mapping model is an object which describes the process mapping an input model (e.g. an `ActiveRecord` model) to an output model (e.g. a hash suitable for `JSON::generate`). A mapping model is entirely isolated from state which is not directly related to the mapping process itself. Because of this, multiple models can co-exist, and the models themselves can be versioned, localized, or whatever else necessary to perform a suitable mapping. It's easy to remove a model if it's no longer being used as all the code is in one place. It's easy to test a mapping model in isolation. Models can be documented like normal code. They can be reused and composed together easily.
35
+
36
+ The design of this library is centered around being explicit where being explicit makes life easier in the long term.
37
+
9
38
  ## Installation
10
39
 
11
40
  Add this line to your application's Gemfile:
@@ -41,7 +70,7 @@ class APIv1 < Mapping::Model
41
70
  end
42
71
  end
43
72
 
44
- class APIv2 < MappingModelV1
73
+ class APIv2 < APIv1
45
74
  map(Human::Person) do |object|
46
75
  super.merge(
47
76
  posessions: self.map(object.posessions)
@@ -27,8 +27,8 @@ module Mapping
27
27
  PREFIX + klass.name.gsub(/::/, '_')
28
28
  end
29
29
 
30
- def method_for_mapping(klass)
31
- self.class.method_for_mapping(klass)
30
+ def method_for_mapping(object)
31
+ self.class.method_for_mapping(object.class)
32
32
  end
33
33
 
34
34
  def self.map(klass, &block)
@@ -36,6 +36,18 @@ module Mapping
36
36
  define_method(method_name, &block)
37
37
  end
38
38
 
39
+ map(NilClass) do |object|
40
+ nil
41
+ end
42
+
43
+ map(TrueClass) do |object|
44
+ true
45
+ end
46
+
47
+ map(FalseClass) do |object|
48
+ false
49
+ end
50
+
39
51
  map(Array) do |items|
40
52
  items.collect{|object| map(object)}
41
53
  end
@@ -44,10 +56,10 @@ module Mapping
44
56
  hash
45
57
  end
46
58
 
47
- def map(root)
48
- method_name = self.method_for_mapping(root.class)
59
+ def map(root, *args)
60
+ method_name = self.method_for_mapping(root)
49
61
 
50
- self.send(method_name, root)
62
+ self.send(method_name, root, *args)
51
63
  end
52
64
  end
53
65
  end
@@ -19,5 +19,5 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  module Mapping
22
- VERSION = "0.1.0"
22
+ VERSION = "0.2.0"
23
23
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mapping
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-03-01 00:00:00.000000000 Z
11
+ date: 2016-03-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler