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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/bin/console +4 -3
  3. data/lib/decanter.rb +10 -18
  4. data/lib/decanter/base.rb +2 -0
  5. data/lib/decanter/configuration.rb +2 -1
  6. data/lib/decanter/core.rb +121 -140
  7. data/lib/decanter/decant.rb +11 -0
  8. data/lib/decanter/exceptions.rb +2 -0
  9. data/lib/decanter/extensions.rb +11 -11
  10. data/lib/decanter/parser.rb +5 -3
  11. data/lib/decanter/parser/base.rb +2 -1
  12. data/lib/decanter/parser/boolean_parser.rb +3 -2
  13. data/lib/decanter/parser/core.rb +9 -10
  14. data/lib/decanter/parser/date_parser.rb +7 -4
  15. data/lib/decanter/parser/date_time_parser.rb +21 -0
  16. data/lib/decanter/parser/float_parser.rb +5 -5
  17. data/lib/decanter/parser/hash_parser.rb +9 -6
  18. data/lib/decanter/parser/integer_parser.rb +4 -6
  19. data/lib/decanter/parser/join_parser.rb +4 -3
  20. data/lib/decanter/parser/key_value_splitter_parser.rb +6 -3
  21. data/lib/decanter/parser/pass_parser.rb +2 -1
  22. data/lib/decanter/parser/phone_parser.rb +3 -1
  23. data/lib/decanter/parser/string_parser.rb +3 -2
  24. data/lib/decanter/parser/time_parser.rb +19 -0
  25. data/lib/decanter/parser/utils.rb +3 -1
  26. data/lib/decanter/parser/value_parser.rb +4 -3
  27. data/lib/decanter/railtie.rb +11 -15
  28. data/lib/decanter/version.rb +3 -1
  29. data/lib/generators/decanter/install_generator.rb +5 -3
  30. data/lib/generators/decanter/templates/initializer.rb +2 -0
  31. data/lib/generators/rails/decanter_generator.rb +7 -5
  32. data/lib/generators/rails/parser_generator.rb +5 -3
  33. data/lib/generators/rails/resource_override.rb +2 -0
  34. metadata +19 -38
  35. data/.codeclimate.yml +0 -38
  36. data/.gitignore +0 -3
  37. data/.rspec +0 -2
  38. data/.ruby-version +0 -1
  39. data/Gemfile +0 -4
  40. data/Gemfile.lock +0 -102
  41. data/LICENSE.txt +0 -21
  42. data/README.md +0 -516
  43. data/Rakefile +0 -1
  44. data/decanter.gemspec +0 -39
  45. data/lib/decanter/parser/datetime_parser.rb +0 -13
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Decanter
2
4
  module Core
3
5
  class Error < StandardError; end
@@ -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
- self.save(context: options[:context])
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
- self.save!(context: options[:context])
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
- self.new(decant(args, options))
26
- .save(context: options[:context])
25
+ new(decant(args, options))
26
+ .save(context: options[:context])
27
27
  end
28
28
 
29
29
  def decant_new(args, **options)
30
- self.new(decant(args, options))
30
+ new(decant(args, options))
31
31
  end
32
32
 
33
33
  def decant_create!(args, **options)
34
- self.new(decant(args, options))
35
- .save!(context: options[:context])
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)
@@ -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.new("cannot lookup parser for #{klass_or_sym} with class #{klass_or_sym.class}")
25
- end.concat('Parser')
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.new("cannot find parser #{parser_str}"))
35
+ raise(NameError, "cannot find parser #{parser_str}")
34
36
  end
35
37
 
36
38
  # expand to include preparsers
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'core'
2
4
 
3
5
  module Decanter
@@ -7,4 +9,3 @@ module Decanter
7
9
  end
8
10
  end
9
11
  end
10
-
@@ -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, options|
8
+ parser do |val, _options|
8
9
  [1, '1'].include?(val) || !!/true/i.match(val.to_s)
9
10
  end
10
11
  end
@@ -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(name, values, options={})
13
- case
14
- when empty_values?(values)
15
- { name => nil }
16
- when allowed?(values)
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(name, values, options)
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.fetch(:parse_format, '%m/%d/%Y')
9
- ::Date.strptime(val, parse_format)
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
- REGEX = /(\d|[.])/
5
-
6
- allow Float, Integer
6
+ allow Float
7
7
 
8
- parser do |val, options|
9
- val.scan(REGEX).join.try(:to_f)
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(name, values, options={})
7
- validate_hash(@parser.call(name, values, options))
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) ? parsed :
13
- raise(ArgumentError.new("Result of HashParser #{self.name} was #{parsed} when it must be a hash."))
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, options|
9
- val.is_a?(Float) ?
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
- DELIM = ','
6
+ ITEM_DELIM = ','
5
7
 
6
8
  parser do |val, options|
7
9
  delimiter = options.fetch(:delimiter, ITEM_DELIM)
8
- val.join(DELIM)
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 |name, val, options|
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({}) { |memo, pair| memo.merge( Hash[ *pair.split(pair_delimiter) ] ) }
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
-
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Decanter
2
4
  module Parser
3
5
  class PassParser < ValueParser
4
-
5
6
  allow Object
6
7
  end
7
8
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Decanter
2
4
  module Parser
3
5
  class PhoneParser < ValueParser
@@ -5,7 +7,7 @@ module Decanter
5
7
 
6
8
  allow Integer
7
9
 
8
- parser do |val, options|
10
+ parser do |val, _options|
9
11
  val.scan(REGEX).join.to_s
10
12
  end
11
13
  end
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Decanter
2
4
  module Parser
3
5
  class StringParser < ValueParser
4
-
5
6
  allow String
6
7
 
7
- parser do |val, options|
8
+ parser do |val, _options|
8
9
  val.to_s
9
10
  end
10
11
  end
@@ -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::'.concat(parser_str)
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(name, values, options={})
7
- { name => @parser.call(values, options) }
8
+ def self._parse(values, options = {})
9
+ @parser.call(values, options)
8
10
  end
9
11
  end
10
12
  end
11
13
  end
12
-
@@ -1,21 +1,17 @@
1
- require 'decanter'
1
+ # frozen_string_literal: true
2
2
 
3
- class Decanter::Railtie < Rails::Railtie
3
+ require 'decanter'
4
4
 
5
- initializer 'decanter.active_record' do
6
- ActiveSupport.on_load :active_record do
7
- require 'decanter/extensions'
8
- Decanter::Extensions::ActiveRecordExtensions.enable!
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
- initializer 'decanter.parser.autoload', :before => :set_autoload_paths do |app|
13
- app.config.autoload_paths << Rails.root.join("lib/decanter/parsers")
14
- end
15
-
16
- generators do |app|
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Decanter
2
- VERSION = '1.1.10'.freeze
4
+ VERSION = '2.1.0'.freeze
3
5
  end
@@ -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('../templates', __FILE__)
6
+ source_root File.expand_path('templates', __dir__)
5
7
 
6
- desc "Creates a Decanter initializer in your application."
8
+ desc 'Creates a Decanter initializer in your application.'
7
9
 
8
10
  def copy_initializer
9
- copy_file "initializer.rb", "config/initializers/decanter.rb"
11
+ copy_file 'initializer.rb', 'config/initializers/decanter.rb'
10
12
  end
11
13
  end
12
14
  end