decanter 1.1.10 → 2.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 +4 -4
- data/bin/console +4 -3
- data/lib/decanter.rb +10 -18
- data/lib/decanter/base.rb +2 -0
- data/lib/decanter/configuration.rb +2 -1
- data/lib/decanter/core.rb +121 -140
- data/lib/decanter/decant.rb +11 -0
- data/lib/decanter/exceptions.rb +2 -0
- data/lib/decanter/extensions.rb +11 -11
- data/lib/decanter/parser.rb +5 -3
- data/lib/decanter/parser/base.rb +2 -1
- data/lib/decanter/parser/boolean_parser.rb +3 -2
- data/lib/decanter/parser/core.rb +9 -10
- data/lib/decanter/parser/date_parser.rb +7 -4
- data/lib/decanter/parser/date_time_parser.rb +21 -0
- data/lib/decanter/parser/float_parser.rb +5 -5
- data/lib/decanter/parser/hash_parser.rb +9 -6
- data/lib/decanter/parser/integer_parser.rb +4 -6
- data/lib/decanter/parser/join_parser.rb +4 -3
- data/lib/decanter/parser/key_value_splitter_parser.rb +6 -3
- data/lib/decanter/parser/pass_parser.rb +2 -1
- data/lib/decanter/parser/phone_parser.rb +3 -1
- data/lib/decanter/parser/string_parser.rb +3 -2
- data/lib/decanter/parser/time_parser.rb +19 -0
- data/lib/decanter/parser/utils.rb +3 -1
- data/lib/decanter/parser/value_parser.rb +4 -3
- data/lib/decanter/railtie.rb +11 -15
- data/lib/decanter/version.rb +3 -1
- data/lib/generators/decanter/install_generator.rb +5 -3
- data/lib/generators/decanter/templates/initializer.rb +2 -0
- data/lib/generators/rails/decanter_generator.rb +7 -5
- data/lib/generators/rails/parser_generator.rb +5 -3
- data/lib/generators/rails/resource_override.rb +2 -0
- metadata +19 -38
- data/.codeclimate.yml +0 -38
- data/.gitignore +0 -3
- data/.rspec +0 -2
- data/.ruby-version +0 -1
- data/Gemfile +0 -4
- data/Gemfile.lock +0 -102
- data/LICENSE.txt +0 -21
- data/README.md +0 -516
- data/Rakefile +0 -1
- data/decanter.gemspec +0 -39
- data/lib/decanter/parser/datetime_parser.rb +0 -13
data/lib/decanter/exceptions.rb
CHANGED
data/lib/decanter/extensions.rb
CHANGED
@@ -1,18 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Decanter
|
2
4
|
module Extensions
|
3
|
-
|
4
5
|
def self.included(base)
|
5
6
|
base.extend(ClassMethods)
|
6
7
|
end
|
7
8
|
|
8
9
|
def decant_update(args, **options)
|
9
10
|
self.attributes = self.class.decant(args, options)
|
10
|
-
|
11
|
+
save(context: options[:context])
|
11
12
|
end
|
12
13
|
|
13
14
|
def decant_update!(args, **options)
|
14
15
|
self.attributes = self.class.decant(args, options)
|
15
|
-
|
16
|
+
save!(context: options[:context])
|
16
17
|
end
|
17
18
|
|
18
19
|
def decant(args, **options)
|
@@ -20,23 +21,22 @@ module Decanter
|
|
20
21
|
end
|
21
22
|
|
22
23
|
module ClassMethods
|
23
|
-
|
24
24
|
def decant_create(args, **options)
|
25
|
-
|
26
|
-
|
25
|
+
new(decant(args, options))
|
26
|
+
.save(context: options[:context])
|
27
27
|
end
|
28
28
|
|
29
29
|
def decant_new(args, **options)
|
30
|
-
|
30
|
+
new(decant(args, options))
|
31
31
|
end
|
32
32
|
|
33
33
|
def decant_create!(args, **options)
|
34
|
-
|
35
|
-
|
34
|
+
new(decant(args, options))
|
35
|
+
.save!(context: options[:context])
|
36
36
|
end
|
37
37
|
|
38
|
-
def decant(args, options={})
|
39
|
-
if specified_decanter = options[:decanter]
|
38
|
+
def decant(args, options = {})
|
39
|
+
if (specified_decanter = options[:decanter])
|
40
40
|
Decanter.decanter_from(specified_decanter)
|
41
41
|
else
|
42
42
|
Decanter.decanter_for(self)
|
data/lib/decanter/parser.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'parser/utils'
|
2
4
|
|
3
5
|
module Decanter
|
@@ -21,8 +23,8 @@ module Decanter
|
|
21
23
|
when Symbol
|
22
24
|
symbol_to_string(klass_or_sym)
|
23
25
|
else
|
24
|
-
raise ArgumentError
|
25
|
-
end
|
26
|
+
raise ArgumentError, "cannot lookup parser for #{klass_or_sym} with class #{klass_or_sym.class}"
|
27
|
+
end + 'Parser'
|
26
28
|
end
|
27
29
|
|
28
30
|
# convert from a string to a constant
|
@@ -30,7 +32,7 @@ module Decanter
|
|
30
32
|
# safe_constantize returns nil if match not found
|
31
33
|
parser_str.safe_constantize ||
|
32
34
|
concat_str(parser_str).safe_constantize ||
|
33
|
-
raise(NameError
|
35
|
+
raise(NameError, "cannot find parser #{parser_str}")
|
34
36
|
end
|
35
37
|
|
36
38
|
# expand to include preparsers
|
data/lib/decanter/parser/base.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Decanter
|
2
4
|
module Parser
|
3
5
|
class BooleanParser < ValueParser
|
4
|
-
|
5
6
|
allow TrueClass, FalseClass
|
6
7
|
|
7
|
-
parser do |val,
|
8
|
+
parser do |val, _options|
|
8
9
|
[1, '1'].include?(val) || !!/true/i.match(val.to_s)
|
9
10
|
end
|
10
11
|
end
|
data/lib/decanter/parser/core.rb
CHANGED
@@ -1,22 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Decanter
|
2
4
|
module Parser
|
3
5
|
module Core
|
4
|
-
|
5
6
|
def self.included(base)
|
6
7
|
base.extend(ClassMethods)
|
7
8
|
end
|
8
9
|
|
9
10
|
module ClassMethods
|
10
|
-
|
11
11
|
# Check if allowed, parse if not
|
12
|
-
def parse(
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
{ name => values }
|
12
|
+
def parse(values, options = {})
|
13
|
+
if empty_values?(values)
|
14
|
+
nil
|
15
|
+
elsif allowed?(values)
|
16
|
+
values
|
18
17
|
else
|
19
|
-
_parse(
|
18
|
+
_parse(values, options)
|
20
19
|
end
|
21
20
|
end
|
22
21
|
|
@@ -48,7 +47,7 @@ module Decanter
|
|
48
47
|
end
|
49
48
|
|
50
49
|
def empty_values?(values)
|
51
|
-
return true if Array.wrap(values).all? { |value| value.nil? || value ==
|
50
|
+
return true if Array.wrap(values).all? { |value| value.nil? || value == '' }
|
52
51
|
end
|
53
52
|
end
|
54
53
|
end
|
@@ -1,14 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Decanter
|
2
4
|
module Parser
|
3
5
|
class DateParser < ValueParser
|
4
|
-
|
5
6
|
allow Date
|
6
7
|
|
7
8
|
parser do |val, options|
|
8
|
-
parse_format = options
|
9
|
-
|
9
|
+
if (parse_format = options[:parse_format])
|
10
|
+
::Date.strptime(val, parse_format)
|
11
|
+
else
|
12
|
+
::Date.parse(val)
|
13
|
+
end
|
10
14
|
end
|
11
15
|
end
|
12
16
|
end
|
13
17
|
end
|
14
|
-
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decanter
|
4
|
+
module Parser
|
5
|
+
# rubocop:disable Style/DateTime
|
6
|
+
class DateTimeParser < ValueParser
|
7
|
+
allow DateTime
|
8
|
+
|
9
|
+
parser do |val, options|
|
10
|
+
if val.is_a?(Time)
|
11
|
+
val.to_datetime
|
12
|
+
elsif (parse_format = options[:parse_format])
|
13
|
+
::DateTime.strptime(val, parse_format)
|
14
|
+
else
|
15
|
+
::DateTime.parse(val)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
# rubocop:enable Style/DateTime
|
20
|
+
end
|
21
|
+
end
|
@@ -1,12 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Decanter
|
2
4
|
module Parser
|
3
5
|
class FloatParser < ValueParser
|
4
|
-
|
5
|
-
|
6
|
-
allow Float, Integer
|
6
|
+
allow Float
|
7
7
|
|
8
|
-
parser do |val,
|
9
|
-
val
|
8
|
+
parser do |val, _options|
|
9
|
+
Float(val)
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -1,18 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'core'
|
2
4
|
|
3
5
|
module Decanter
|
4
6
|
module Parser
|
5
7
|
class HashParser < Base
|
6
|
-
def self._parse(
|
7
|
-
validate_hash(@parser.call(
|
8
|
+
def self._parse(values, options = {})
|
9
|
+
validate_hash(@parser.call(values, options))
|
8
10
|
end
|
9
11
|
|
10
|
-
private
|
11
12
|
def self.validate_hash(parsed)
|
12
|
-
parsed.is_a?(Hash)
|
13
|
-
|
13
|
+
return parsed if parsed.is_a?(Hash)
|
14
|
+
|
15
|
+
raise(ArgumentError, "Result of HashParser was #{parsed} when it must be a hash.")
|
14
16
|
end
|
17
|
+
|
18
|
+
private_class_method :validate_hash
|
15
19
|
end
|
16
20
|
end
|
17
21
|
end
|
18
|
-
|
@@ -1,14 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Decanter
|
2
4
|
module Parser
|
3
5
|
class IntegerParser < ValueParser
|
4
|
-
REGEX = /(\d|[.])/
|
5
|
-
|
6
6
|
allow Integer
|
7
7
|
|
8
|
-
parser do |val,
|
9
|
-
val
|
10
|
-
val.to_i :
|
11
|
-
val.scan(REGEX).join.try(:to_i)
|
8
|
+
parser do |val, _options|
|
9
|
+
Integer(val)
|
12
10
|
end
|
13
11
|
end
|
14
12
|
end
|
@@ -1,13 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Decanter
|
2
4
|
module Parser
|
3
5
|
class JoinParser < ValueParser
|
4
|
-
|
6
|
+
ITEM_DELIM = ','
|
5
7
|
|
6
8
|
parser do |val, options|
|
7
9
|
delimiter = options.fetch(:delimiter, ITEM_DELIM)
|
8
|
-
val.join(
|
10
|
+
val.join(delimiter)
|
9
11
|
end
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|
13
|
-
|
@@ -1,15 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Decanter
|
2
4
|
module Parser
|
3
5
|
class KeyValueSplitterParser < HashParser
|
4
6
|
ITEM_DELIM = ','
|
5
7
|
PAIR_DELIM = ':'
|
6
8
|
|
7
|
-
parser do |
|
9
|
+
parser do |val, options|
|
8
10
|
item_delimiter = options.fetch(:item_delimiter, ITEM_DELIM)
|
9
11
|
pair_delimiter = options.fetch(:pair_delimiter, PAIR_DELIM)
|
10
|
-
val.split(item_delimiter).reduce({})
|
12
|
+
val.split(item_delimiter).reduce({}) do |memo, pair|
|
13
|
+
memo.merge(Hash[*pair.split(pair_delimiter)])
|
14
|
+
end
|
11
15
|
end
|
12
16
|
end
|
13
17
|
end
|
14
18
|
end
|
15
|
-
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decanter
|
4
|
+
module Parser
|
5
|
+
class TimeParser < ValueParser
|
6
|
+
allow Time
|
7
|
+
|
8
|
+
parser do |val, options|
|
9
|
+
if val.is_a?(DateTime)
|
10
|
+
val.to_time
|
11
|
+
elsif (parse_format = options[:parse_format])
|
12
|
+
::Time.strptime(val, parse_format)
|
13
|
+
else
|
14
|
+
::Time.parse(val)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Decanter
|
2
4
|
module Parser
|
3
5
|
module Utils
|
@@ -24,7 +26,7 @@ module Decanter
|
|
24
26
|
end
|
25
27
|
|
26
28
|
def concat_str(parser_str)
|
27
|
-
'Decanter::Parser::'
|
29
|
+
'Decanter::Parser::' + parser_str
|
28
30
|
end
|
29
31
|
end
|
30
32
|
end
|
@@ -1,12 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'core'
|
2
4
|
|
3
5
|
module Decanter
|
4
6
|
module Parser
|
5
7
|
class ValueParser < Base
|
6
|
-
def self._parse(
|
7
|
-
|
8
|
+
def self._parse(values, options = {})
|
9
|
+
@parser.call(values, options)
|
8
10
|
end
|
9
11
|
end
|
10
12
|
end
|
11
13
|
end
|
12
|
-
|
data/lib/decanter/railtie.rb
CHANGED
@@ -1,21 +1,17 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require 'decanter'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
module Decanter
|
6
|
+
class Railtie < Rails::Railtie
|
7
|
+
initializer 'decanter.parser.autoload', before: :set_autoload_paths do |app|
|
8
|
+
app.config.autoload_paths << Rails.root.join('lib/decanter/parsers')
|
9
9
|
end
|
10
|
-
end
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
Rails::Generators.configure!(app.config.generators)
|
18
|
-
Rails::Generators.hidden_namespaces.uniq!
|
19
|
-
require 'generators/rails/resource_override'
|
11
|
+
generators do |app|
|
12
|
+
Rails::Generators.configure!(app.config.generators)
|
13
|
+
Rails::Generators.hidden_namespaces.uniq!
|
14
|
+
require 'generators/rails/resource_override'
|
15
|
+
end
|
20
16
|
end
|
21
17
|
end
|
data/lib/decanter/version.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Decanter
|
2
4
|
module Generators
|
3
5
|
class InstallGenerator < Rails::Generators::Base
|
4
|
-
source_root File.expand_path('
|
6
|
+
source_root File.expand_path('templates', __dir__)
|
5
7
|
|
6
|
-
desc
|
8
|
+
desc 'Creates a Decanter initializer in your application.'
|
7
9
|
|
8
10
|
def copy_initializer
|
9
|
-
copy_file
|
11
|
+
copy_file 'initializer.rb', 'config/initializers/decanter.rb'
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|