serdee 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d32e12c6af56fcee2b79e0d1c3390410459d5c23
4
+ data.tar.gz: 0e8003cbd25ad282db4749c35119326c3cb23f0e
5
+ SHA512:
6
+ metadata.gz: 97c96e37529521be72bd5ffe824a6f0cc11f07e64e6c838ae7719c32989cfe2b12be649d11b52a4f8144eee88f33dfe8620051d7b8ccff352a5b128d8598f7fe
7
+ data.tar.gz: '0818da033b2801fcf157d2be3f753c5bb61b87385131694c4ae3ba734086d54063bf9a7ac56793a5c68bb9beb7c95809e16255607a8a5ac56f2810db18ad02fb'
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.1
5
+ before_install: gem install bundler -v 1.16.0
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in serdee.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,54 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ serdee (0.1.0)
5
+ activesupport
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activesupport (5.2.1)
11
+ concurrent-ruby (~> 1.0, >= 1.0.2)
12
+ i18n (>= 0.7, < 2)
13
+ minitest (~> 5.1)
14
+ tzinfo (~> 1.1)
15
+ coderay (1.1.2)
16
+ concurrent-ruby (1.0.5)
17
+ diff-lcs (1.3)
18
+ i18n (1.1.0)
19
+ concurrent-ruby (~> 1.0)
20
+ method_source (0.9.0)
21
+ minitest (5.11.3)
22
+ pry (0.11.2)
23
+ coderay (~> 1.1.0)
24
+ method_source (~> 0.9.0)
25
+ rake (10.5.0)
26
+ rspec (3.8.0)
27
+ rspec-core (~> 3.8.0)
28
+ rspec-expectations (~> 3.8.0)
29
+ rspec-mocks (~> 3.8.0)
30
+ rspec-core (3.8.0)
31
+ rspec-support (~> 3.8.0)
32
+ rspec-expectations (3.8.1)
33
+ diff-lcs (>= 1.2.0, < 2.0)
34
+ rspec-support (~> 3.8.0)
35
+ rspec-mocks (3.8.0)
36
+ diff-lcs (>= 1.2.0, < 2.0)
37
+ rspec-support (~> 3.8.0)
38
+ rspec-support (3.8.0)
39
+ thread_safe (0.3.6)
40
+ tzinfo (1.2.5)
41
+ thread_safe (~> 0.1)
42
+
43
+ PLATFORMS
44
+ ruby
45
+
46
+ DEPENDENCIES
47
+ bundler (~> 1.16)
48
+ pry
49
+ rake (~> 10.0)
50
+ rspec (~> 3.0)
51
+ serdee!
52
+
53
+ BUNDLED WITH
54
+ 1.16.0
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # Serdee
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/serdee`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'serdee'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install serdee
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/serdee.
data/Rakefile ADDED
@@ -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
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "serdee"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
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__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+ class Address
3
+ BYTES = {
4
+ address: 22,
5
+ city: 13,
6
+ state: 3,
7
+ country: 2
8
+ }.freeze
9
+ attr_accessor :address, :city, :state, :country
10
+ def initialize(address:, city:, state:, country:)
11
+ @address = address
12
+ @city = city
13
+ @state = state
14
+ @country = country
15
+ end
16
+
17
+ def self.serialize(address)
18
+ return if address.nil?
19
+ BYTES.map do |field, bytes|
20
+ address.send(field)[0...bytes].ljust(bytes, " ")
21
+ end.join
22
+ end
23
+
24
+ def self.deserialize(string)
25
+ return if string.nil?
26
+ string = string.dup
27
+ new(
28
+ BYTES.transform_values { |bytes| string.slice!(0...bytes) }
29
+ )
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ {
2
+ "request":{
3
+ "header":{
4
+ "signature":"BHNUMS",
5
+ "details":{
6
+ "productCategoryCode":"01",
7
+ "specVersion":"04"
8
+ }
9
+ },
10
+ "transaction":{
11
+ "primaryAccountNumber":"9877890000000000",
12
+ "processingCode":"315400",
13
+ "transactionAmount":"000000000000",
14
+ "transmissionDateTime":"131121105414",
15
+ "systemTraceAuditNumber":"000110",
16
+ "localTransactionTime":"105414",
17
+ "localTransactionDate":"131121",
18
+ "merchantCategoryCode":"5411",
19
+ "pointOfServiceEntryMode":"011",
20
+ "acquiringInstitutionIdentifier":"60300000063",
21
+ "retrievalReferenceNumber":"000000002962",
22
+ "merchantTerminalId":"06220 600 ",
23
+ "merchantIdentifier":"60300000063 ",
24
+ "merchantLocation":"BLACKHAWK SIMULATOR PLEASANTON CA US",
25
+ "transactionCurrencyCode":"840",
26
+ "additionalTxnFields":{
27
+ "productId":"07675004390"
28
+ }
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+ require_relative "./unified_message"
3
+
4
+ class RequestMessage
5
+ include Serdee::Attributes
6
+ set_key_transform :camel_lower
7
+
8
+ nested :request, UnifiedMessage
9
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+ class ResponseCode
3
+ attr_reader :code, :type, :message
4
+ def initialize(code:, type:, message:)
5
+ @code = code
6
+ @type = type
7
+ @message = message
8
+ end
9
+
10
+ def approved?
11
+ type == :approved
12
+ end
13
+
14
+ def soft_declined?
15
+ type == :soft_declined
16
+ end
17
+
18
+ def hard_declined?
19
+ type == :hard_declined
20
+ end
21
+
22
+ def self.find(code)
23
+ response = CODES.fetch(code)
24
+ new(
25
+ code: code,
26
+ type: response[0],
27
+ message: response[1]
28
+ )
29
+ end
30
+
31
+ CODES = {
32
+ "00" => [:approved, "Approved – balance available"],
33
+ "01" => [:approved, "Approved – balance unavailable"],
34
+ "03" => [:approved, "Approved – balance unavailable on external account number"],
35
+ "74" => [:soft_declined, "Unable to route / System Error"],
36
+ "15" => [:soft_declined, "Time Out occurred- Auth Server not available /responding"],
37
+ "02" => [:hard_declined, "Refer to card issuer"],
38
+ "04" => [:hard_declined, "Already Redeemed"],
39
+ "05" => [:hard_declined, "Error account problem"],
40
+ "06" => [:hard_declined, "Invalid expiration date"],
41
+ "07" => [:hard_declined, "Unable to process"],
42
+ "08" => [:hard_declined, "Card not found"],
43
+ "12" => [:hard_declined, "Invalid transaction"],
44
+ "13" => [:hard_declined, "Invalid amount"],
45
+ "14" => [:hard_declined, "Invalid Product"],
46
+ "16" => [:hard_declined, "Invalid status change"],
47
+ "17" => [:hard_declined, "Invalid merchant"],
48
+ "18" => [:hard_declined, "Invalid Phone Number"],
49
+ "20" => [:hard_declined, "Invalid Pin"],
50
+ "21" => [:hard_declined, "Card already active"],
51
+ "22" => [:hard_declined, "Card Already Associated"],
52
+ "30" => [:hard_declined, "Bad track2 – format error"],
53
+ "33" => [:hard_declined, "Expired card"],
54
+ "34" => [:hard_declined, "Already reversed"],
55
+ "35" => [:hard_declined, "Already voided"],
56
+ "36" => [:hard_declined, "Restricted card"],
57
+ "37" => [:hard_declined, "Restricted External Account"],
58
+ "38" => [:hard_declined, "Restricted Merchant"],
59
+ "41" => [:hard_declined, "Lost card"],
60
+ "42" => [:hard_declined, "Lost External Account"],
61
+ "43" => [:hard_declined, "Stolen card"],
62
+ "44" => [:hard_declined, "Stolen External Account"],
63
+ "51" => [:hard_declined, "Insufficient funds"],
64
+ "54" => [:hard_declined, "Expired External Account"],
65
+ "55" => [:hard_declined, "Max recharge reached"],
66
+ "56" => [:hard_declined, "Advance less amount / enter lesser amount"],
67
+ "58" => [:hard_declined, "Request not permitted by merchant location"],
68
+ "59" => [:hard_declined, "Request not permitted by processor"],
69
+ "61" => [:hard_declined, "Exceeds withdrawal amt / over limit"],
70
+ "62" => [:hard_declined, "Exceeds financial limit"],
71
+ "65" => [:hard_declined, "Exceeds withdrawal frequency limit"],
72
+ "66" => [:hard_declined, "Exceeds transaction count limit"],
73
+ "69" => [:hard_declined, "Format error –bad data"],
74
+ "71" => [:hard_declined, "Invalid External Account number"],
75
+ "94" => [:hard_declined, "Duplicate transaction"],
76
+ "95" => [:hard_declined, "Cannot Reverse the Original Transaction"],
77
+ "99" => [:hard_declined, "General decline"],
78
+ }.freeze
79
+ end
@@ -0,0 +1,36 @@
1
+ {
2
+ "response":{
3
+ "header":{
4
+ "signature":"BHNUMS",
5
+ "details":{
6
+ "productCategoryCode":"01",
7
+ "statusCode":"00",
8
+ "specVersion":"04"
9
+ }
10
+ },
11
+ "transaction":{
12
+ "primaryAccountNumber":"9877890000000000",
13
+ "processingCode":"315400",
14
+ "transactionAmount":"000000000000",
15
+ "transmissionDateTime":"131121105414",
16
+ "systemTraceAuditNumber":"000110",
17
+ "localTransactionTime":"105414",
18
+ "localTransactionDate":"131121",
19
+ "merchantCategoryCode":"5411",
20
+ "pointOfServiceEntryMode":"011",
21
+ "acquiringInstitutionIdentifier":"60300000063",
22
+ "authidentificationResponse":"123456",
23
+ "responseCode":"00",
24
+ "retrievalReferenceNumber":"000000002962",
25
+ "merchantTerminalId":"06220 600 ",
26
+ "merchantIdentifier":"60300000063 ",
27
+ "transactionCurrencyCode":"840",
28
+ "additionalTxnFields":{
29
+ "productId":"07675004390",
30
+ "balanceAmount":"C000000002500",
31
+ "transactionUniqueId": "0JPKA8FKHT2H011784WA0524PM",
32
+ "correlatedTransactionUniqueId": "0JPKA8FKHT2H011784WA0524PM"
33
+ }
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+ require_relative "./unified_message"
3
+ require_relative "./response_code"
4
+ class ResponseMessage
5
+ include Serdee::Attributes
6
+ set_key_transform :camel_lower
7
+
8
+ attr_accessor :request_id
9
+
10
+ nested :response, UnifiedMessage
11
+
12
+ def parsed_message?
13
+ status_code == "00" if status_code
14
+ end
15
+
16
+ def status
17
+ return unless response_code
18
+ @status ||= ResponseCode.find(response_code)
19
+ end
20
+
21
+ def approved?
22
+ status&.approved?
23
+ end
24
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+ require_relative "./address"
3
+ require_relative "./response_code"
4
+
5
+ class UnifiedMessage
6
+ include Serdee::Attributes
7
+ set_key_transform :camel_lower
8
+
9
+ PROCESSING_CODES = {
10
+ balance_inquiry: "315400",
11
+ redemption: "615400"
12
+ }.freeze
13
+
14
+ nested :header do
15
+ attribute :signature, default: "BHNUMS"
16
+ nested :details do
17
+ attribute :product_category_code, default: "01"
18
+ attribute :spec_version, default: "43"
19
+ attribute :status_code
20
+ end
21
+ end
22
+
23
+ nested :transaction do
24
+ attribute :local_transaction_at do
25
+ insert do |time, hash|
26
+ if time
27
+ hash[:local_transaction_time] = time.strftime("%H%M%S")
28
+ hash[:local_transaction_date] = time.strftime("%y%m%d")
29
+ end
30
+ end
31
+
32
+ extract do |data|
33
+ if data[:local_transaction_date] && data[:local_transaction_time]
34
+ time_string = "#{data[:local_transaction_date]}-#{data[:local_transaction_time]}"
35
+ DateTime.strptime(time_string, "%y%m%d-%H%M%S")
36
+ end
37
+ end
38
+ end
39
+ attribute :retrieval_reference_number do
40
+ serialize { |int| format("%012d", int) }
41
+ deserialize { |string| string&.to_i }
42
+ end
43
+ attribute :system_trace_audit_number do
44
+ serialize { |int| format("%06d", int) }
45
+ deserialize { |string| string&.to_i }
46
+ end
47
+ attribute :transaction_amount do
48
+ serialize { |int| format("%012d", int) }
49
+ deserialize { |string| string&.to_i }
50
+ end
51
+ attribute :transmission_date_time do
52
+ serialize { |time| time&.strftime("%y%m%d%H%M%S") }
53
+ deserialize { |time_string| DateTime.strptime(time_string, "%y%m%d%H%M%S") if time_string }
54
+ end
55
+ attribute :merchant_identifier do
56
+ serialize { |id| id&.ljust(15, " ") }
57
+ deserialize { |id| id&.strip }
58
+ end
59
+ attribute :action, as: :processing_code do
60
+ serialize { |action| PROCESSING_CODES.fetch(action) }
61
+ deserialize { |code| PROCESSING_CODES.key(code) }
62
+ end
63
+ attribute :merchant_location, serializer: Address
64
+
65
+ attribute :authidentification_response
66
+ attribute :acquiring_institution_identifier
67
+ attribute :merchant_category_code
68
+ attribute :merchant_terminal_id
69
+ attribute :point_of_service_entry_mode
70
+ attribute :primary_account_number
71
+ attribute :response_code
72
+ attribute :transaction_currency_code
73
+
74
+ nested :additional_txn_fields do
75
+ attribute :balance_amount do
76
+ serialize do |int|
77
+ return if int.nil?
78
+ (int >= 0 ? "C" : "D") + int.abs.to_s.rjust(12, "0")
79
+ end
80
+ deserialize do |string|
81
+ return if string.nil?
82
+ int = string[1..-1].to_i
83
+ return -int if string[0] == "D"
84
+ int
85
+ end
86
+ end
87
+ attribute :correlated_transaction_unique_id
88
+ attribute :product_id
89
+ attribute :transaction_unique_id
90
+ attribute :redemption_pin do
91
+ serialize { |pin| pin&.ljust(16, " ") }
92
+ deserialize { |pin| pin&.strip }
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+ module Serdee
3
+ class Attribute
4
+ attr_reader :key, :default
5
+ attr_writer :as
6
+ attr_accessor :default, :allow_blank, :serializer, :optional
7
+
8
+ def initialize(key, **options, &block)
9
+ @key = key
10
+ { allow_blank: false }.merge(options).each do |option, setting|
11
+ config.public_send(option, setting)
12
+ end
13
+ config.instance_eval(&block) if block_given?
14
+ end
15
+
16
+ def config
17
+ @config ||= Config.new(self)
18
+ end
19
+
20
+ def as
21
+ @as || key
22
+ end
23
+
24
+ def default=(val)
25
+ @optional = true
26
+ @default = val
27
+ end
28
+
29
+ def insert(value, hash)
30
+ new_value = serialize(value)
31
+ hash[as] = new_value if new_value.present? || allow_blank
32
+ end
33
+
34
+ def insert_to(obj, hash)
35
+ insert(obj.send(key), hash)
36
+ hash
37
+ end
38
+
39
+ def extract_to(data, obj)
40
+ obj.send("#{key}=", extract(data))
41
+ obj
42
+ end
43
+
44
+ def extract(hash)
45
+ deserialize(hash[as])
46
+ end
47
+
48
+ def serialize(value)
49
+ value
50
+ end
51
+
52
+ def deserialize(value)
53
+ value
54
+ end
55
+
56
+ class Config
57
+ attr_reader :attribute
58
+ def initialize(attribute)
59
+ @attribute = attribute
60
+ end
61
+
62
+ def serializer(obj)
63
+ return unless obj
64
+
65
+ attribute.serializer = obj
66
+ serialize { |value| obj.serialize(value) }
67
+ deserialize { |value| obj.deserialize(value) }
68
+ end
69
+
70
+ [
71
+ :optional,
72
+ :default,
73
+ :allow_blank,
74
+ :as
75
+ ].each do |key|
76
+ define_method(key) do |value|
77
+ attribute.send("#{key}=", value)
78
+ end
79
+ end
80
+
81
+ [
82
+ :extract_to,
83
+ :insert_to,
84
+ :extract,
85
+ :insert,
86
+ :serialize,
87
+ :deserialize
88
+ ].each do |key|
89
+ expected_arg_size = Attribute.instance_method(key).parameters.size
90
+ define_method(key) do |&block|
91
+ if block.parameters.size > expected_arg_size || block.parameters.any? { |type, _key| type == :keyreq }
92
+ raise ArgumentError,
93
+ "wrong number of arguments defined for ##{key} (given #{block.parameters}, expected #{args})"
94
+ end
95
+ attribute.singleton_class.send(:define_method, key, &block)
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,154 @@
1
+ # frozen_string_literal: true
2
+ require "active_support/core_ext/hash"
3
+
4
+ module Serdee
5
+ module Attributes
6
+ def self.included(base)
7
+ base.extend ClassMethods
8
+ end
9
+
10
+ attr_accessor :deserialized_from
11
+
12
+ def initialize(**values)
13
+ self.class.attributes.each do |key, attribute|
14
+ if !attribute.optional && !values.key?(key)
15
+ raise ArgumentError, "#{key} is required parameter"
16
+ end
17
+
18
+ if values.key?(key)
19
+ send("#{key}=", values[key])
20
+ elsif attribute.default
21
+ send("#{key}=", attribute.default)
22
+ end
23
+ end
24
+ end
25
+
26
+ def attributes
27
+ self.class.attributes.keys.each_with_object({}) do |key, hash|
28
+ value = send(key)
29
+ hash[key] = value if value
30
+ end
31
+ end
32
+
33
+ def as_json
34
+ self.class.insert_to(self, {}).deep_transform_keys! do |key|
35
+ if self.class.key_transform
36
+ self.class.key_transform.call(key.to_s)
37
+ else
38
+ key.to_s
39
+ end
40
+ end
41
+ end
42
+
43
+ def to_json
44
+ as_json.to_json
45
+ end
46
+
47
+ module ClassMethods
48
+ def attributes
49
+ @attributes ||= {}
50
+ end
51
+
52
+ def serializers
53
+ @serializers ||= {}
54
+ end
55
+
56
+ def set_key_transform(transform_name = nil, &block)
57
+ if transform_name
58
+ mapping = {
59
+ camel: :camelize.to_proc,
60
+ camel_lower: ->(key) { key.camelize(:lower) },
61
+ dash: :dasherize.to_proc,
62
+ underscore: :underscore.to_proc
63
+ }
64
+
65
+ @key_transform = mapping[transform_name.to_sym]
66
+ elsif block
67
+ @key_transform = block
68
+ else
69
+ raise ArgumentError, "must supply at least transform_name or block"
70
+ end
71
+ end
72
+
73
+ def key_transform
74
+ @key_transform || Serdee.default_key_transform
75
+ end
76
+
77
+ def attributes_class
78
+ self
79
+ end
80
+
81
+ def attribute(key, *args, &block)
82
+ attributes_class.attributes[key] = serializers[key] =
83
+ Attribute.new(key, *args, &block)
84
+
85
+ attributes_class.send(:attr_accessor, key)
86
+ end
87
+
88
+ def nested(key, nested_class = nil, &block)
89
+ serializers[key] = Nested.new(
90
+ attributes_class,
91
+ key,
92
+ nested_class&.serializers,
93
+ &block
94
+ )
95
+
96
+ return unless nested_class
97
+
98
+ attributes_class.attributes.merge!(nested_class.attributes)
99
+ attributes_class.send(:attr_accessor, *nested_class.attributes.keys)
100
+ end
101
+
102
+ def from_json(json)
103
+ of_json(JSON.parse(json))
104
+ end
105
+
106
+ def of_json(json)
107
+ allocate.tap do |obj|
108
+ data = json.deep_transform_keys do |key|
109
+ key.underscore.to_sym
110
+ end
111
+ extract_to(data, obj)
112
+ obj.deserialized_from = json
113
+ end
114
+ end
115
+
116
+ def extract_to(data, obj)
117
+ return if obj.nil?
118
+ serializers.each do |_key, attribute|
119
+ attribute.extract_to(data, obj)
120
+ end
121
+ obj
122
+ end
123
+
124
+ def insert_to(obj, data)
125
+ serializers.each do |_key, attribute|
126
+ attribute.insert_to(obj, data)
127
+ end
128
+ data
129
+ end
130
+ end
131
+
132
+ class Nested
133
+ include Attributes::ClassMethods
134
+
135
+ attr_reader :key, :attributes_class
136
+ def initialize(attributes_class, key, serializers, &block)
137
+ @attributes_class = attributes_class
138
+ @key = key
139
+ @serializers = serializers
140
+ instance_eval(&block) if block_given?
141
+ end
142
+
143
+ def extract_to(data, obj)
144
+ return if data.nil? || data[key].nil?
145
+ super(data[key], obj)
146
+ end
147
+
148
+ def insert_to(obj, data)
149
+ data[key] = {}
150
+ super(obj, data[key])
151
+ end
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,3 @@
1
+ module Serdee
2
+ VERSION = "0.1.0"
3
+ end
data/lib/serdee.rb ADDED
@@ -0,0 +1,10 @@
1
+ require "json"
2
+ require "serdee/version"
3
+ require "serdee/attribute"
4
+ require "serdee/attributes"
5
+
6
+ module Serdee
7
+ class << self
8
+ attr_accessor :default_key_transform
9
+ end
10
+ end
data/serdee.gemspec ADDED
@@ -0,0 +1,30 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "serdee/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "serdee"
8
+ spec.version = Serdee::VERSION
9
+ spec.authors = ["Ryan Ong"]
10
+ spec.email = ["ryanong@gmail.com"]
11
+
12
+ spec.summary = %q{Serdee is a serialization/deserialization library for mostly json}
13
+ spec.description = %q{Serdee is a highly customizable serialization and deserialization library that is strict by default.}
14
+ spec.homepage = "https://github.com/ryanong/serdee"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+
24
+ spec.add_dependency "activesupport"
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.16"
27
+ spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_development_dependency "rspec", "~> 3.0"
29
+ spec.add_development_dependency "pry"
30
+ end
metadata ADDED
@@ -0,0 +1,135 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: serdee
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Ong
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-09-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.16'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.16'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Serdee is a highly customizable serialization and deserialization library
84
+ that is strict by default.
85
+ email:
86
+ - ryanong@gmail.com
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - ".rspec"
93
+ - ".travis.yml"
94
+ - Gemfile
95
+ - Gemfile.lock
96
+ - README.md
97
+ - Rakefile
98
+ - bin/console
99
+ - bin/setup
100
+ - examples/address.rb
101
+ - examples/request_message.json
102
+ - examples/request_message.rb
103
+ - examples/response_code.rb
104
+ - examples/response_message.json
105
+ - examples/response_message.rb
106
+ - examples/unified_message.rb
107
+ - lib/serdee.rb
108
+ - lib/serdee/attribute.rb
109
+ - lib/serdee/attributes.rb
110
+ - lib/serdee/version.rb
111
+ - serdee.gemspec
112
+ homepage: https://github.com/ryanong/serdee
113
+ licenses: []
114
+ metadata: {}
115
+ post_install_message:
116
+ rdoc_options: []
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ requirements: []
130
+ rubyforge_project:
131
+ rubygems_version: 2.6.11
132
+ signing_key:
133
+ specification_version: 4
134
+ summary: Serdee is a serialization/deserialization library for mostly json
135
+ test_files: []