hash_cast 0.4.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -0
  3. data/Gemfile.lock +1 -1
  4. data/README.md +5 -5
  5. data/{hcast.gemspec → hash_cast.gemspec} +2 -2
  6. data/lib/{hcast → hash_cast}/attributes_caster.rb +6 -6
  7. data/lib/{hcast → hash_cast}/attributes_parser.rb +9 -9
  8. data/lib/{hcast → hash_cast}/caster.rb +12 -12
  9. data/lib/{hcast → hash_cast}/casters/array_caster.rb +4 -4
  10. data/lib/{hcast → hash_cast}/casters/boolean_caster.rb +2 -2
  11. data/lib/{hcast → hash_cast}/casters/date_caster.rb +3 -3
  12. data/lib/{hcast → hash_cast}/casters/datetime_caster.rb +3 -3
  13. data/lib/{hcast → hash_cast}/casters/float_caster.rb +3 -3
  14. data/lib/{hcast → hash_cast}/casters/hash_caster.rb +2 -2
  15. data/lib/{hcast → hash_cast}/casters/integer_caster.rb +3 -3
  16. data/lib/hash_cast/casters/string_caster.rb +26 -0
  17. data/lib/{hcast → hash_cast}/casters/symbol_caster.rb +3 -3
  18. data/lib/{hcast → hash_cast}/casters/time_caster.rb +3 -3
  19. data/lib/hash_cast/casters.rb +13 -0
  20. data/lib/{hcast → hash_cast}/concern.rb +1 -1
  21. data/lib/hash_cast/config.rb +17 -0
  22. data/lib/{hcast → hash_cast}/errors.rb +8 -8
  23. data/lib/{hcast → hash_cast}/metadata/attribute.rb +1 -1
  24. data/lib/hash_cast/version.rb +3 -0
  25. data/lib/hash_cast.rb +46 -0
  26. data/spec/{hcast → hash_cast}/caster_spec.rb +42 -17
  27. data/spec/{hcast/hcast_spec.rb → hash_cast/hash_cast_spec.rb} +2 -2
  28. data/spec/spec_helper.rb +1 -1
  29. metadata +28 -27
  30. data/lib/hcast/casters/string_caster.rb +0 -13
  31. data/lib/hcast/casters.rb +0 -13
  32. data/lib/hcast/config.rb +0 -11
  33. data/lib/hcast/version.rb +0 -3
  34. data/lib/hcast.rb +0 -46
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 71b3bcf7f98727c99228d5fb0ceaba02b87767721c251ba69d5c91079f936b5a
4
- data.tar.gz: 1cd37fcce0009d5895dc72a4af32bd0c2dd2ea6ce5abee97b7e6b190a33c1655
3
+ metadata.gz: 68e050b609ffe18b09ada29f3606534113be56827b161bae6e917cbeadc82a57
4
+ data.tar.gz: 76b1ba697a03d6edcccb6f5196d3411d8af423ff5e0e0b1661b81db3e02846e6
5
5
  SHA512:
6
- metadata.gz: e607f921e463af6ff705ad3cfd86c9ca5532d7813913f6c795bfec73879b02cc4a8101b44ab9f475f45576ccbadd8b47d5d71e57ca3565b98813e4a3e5c6427c
7
- data.tar.gz: a7297e7a81c4165dcda83135131e68817e29c043fd20594f5ce3ec9ab8b37eef07afd16bd9d606bf2a6ab0a8bb041e0cf17067ddc0b46212749e56b2a55afe34
6
+ metadata.gz: e7fc1162f788fd180c0cd1a080bb2dbbcaaeb7b28fa1d59b3d490a0bd3f744a3457998d65fc1ce6d2e9819ce898416d6832c658d8bd5e3d47486980d6a4a1db3
7
+ data.tar.gz: 1d9d02707117f5619902867966c4e0a1f542e0e9aedd2b183557aaf25c6fc85704d488db2c52c22534a377779a68b1bc9d09b31420ad77af54576d701358f9fe
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ **Version 0.5.1**
2
+ - String caster should validate for null byte by default
3
+ - skip_unexpected_attributes option is true by default
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hash_cast (0.4.0)
4
+ hash_cast (0.5.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,14 +1,14 @@
1
- # HCast
2
- [![Rspec](https://github.com/droidlabs/hcast/workflows/Rspec/badge.svg)](https://github.com/droidlabs/hcast/actions?query=workflow%3ARspec)
1
+ # HashCast
2
+ [![Rspec](https://github.com/droidlabs/hash_cast/workflows/Rspec/badge.svg)](https://github.com/droidlabs/hash_cast/actions?query=workflow%3ARspec)
3
3
 
4
- HCast is a library for casting hash attributes
4
+ HashCast is a library for casting hash attributes
5
5
 
6
6
  ### Usage
7
7
 
8
8
  Create caster class and declare hash attributes inside:
9
9
  ```ruby
10
10
  class ContactCaster
11
- include HCast::Caster
11
+ include HashCast::Caster
12
12
 
13
13
  attributes do
14
14
  hash :contact do
@@ -86,7 +86,7 @@ The caster will cast your hash attributes to:
86
86
  }
87
87
  ```
88
88
 
89
- if some of the attributes can't be casted the HCast::Errors::CastingError is raised
89
+ if some of the attributes can't be casted the HashCast::Errors::CastingError is raised
90
90
 
91
91
 
92
92
  ## Author
@@ -1,11 +1,11 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'hcast/version'
4
+ require 'hash_cast/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "hash_cast"
8
- spec.version = HCast::VERSION
8
+ spec.version = HashCast::VERSION
9
9
  spec.authors = ["Albert Gazizov"]
10
10
  spec.email = ["deeper4k@gmail.com"]
11
11
  spec.description = %q{Declarative Hash Caster}
@@ -1,4 +1,4 @@
1
- class HCast::AttributesCaster
1
+ class HashCast::AttributesCaster
2
2
  attr_reader :attributes, :options
3
3
 
4
4
  def initialize(attributes, options)
@@ -15,15 +15,15 @@ class HCast::AttributesCaster
15
15
  begin
16
16
  casted_value = cast_attribute(attribute, input_hash)
17
17
  casted_hash[attribute.name] = casted_value
18
- rescue HCast::Errors::AttributeError => e
18
+ rescue HashCast::Errors::AttributeError => e
19
19
  handle_attribute_error(e, attribute)
20
20
  end
21
21
  else
22
- raise HCast::Errors::MissingAttributeError.new("should be given", attribute.name)if attribute.required?
22
+ raise HashCast::Errors::MissingAttributeError.new("should be given", attribute.name)if attribute.required?
23
23
  end
24
24
  end
25
25
 
26
- if !options[:skip_unexpected_attributes]
26
+ if options.has_key?(:skip_unexpected_attributes) && !options[:skip_unexpected_attributes]
27
27
  check_unexpected_attributes_not_given!(hash_keys, casted_hash.keys)
28
28
  end
29
29
 
@@ -59,7 +59,7 @@ class HCast::AttributesCaster
59
59
  end
60
60
 
61
61
  def cast_children_with_caster(value, attribute, caster)
62
- if attribute.caster == HCast::Casters::ArrayCaster
62
+ if attribute.caster == HashCast::Casters::ArrayCaster
63
63
  value.map do |val|
64
64
  caster.cast(val)
65
65
  end
@@ -95,7 +95,7 @@ class HCast::AttributesCaster
95
95
  def check_unexpected_attributes_not_given!(input_hash_keys, casted_hash_keys)
96
96
  unexpected_keys = input_hash_keys - casted_hash_keys
97
97
  unless unexpected_keys.empty?
98
- raise HCast::Errors::UnexpectedAttributeError.new("is not valid attribute name", unexpected_keys.first)
98
+ raise HashCast::Errors::UnexpectedAttributeError.new("is not valid attribute name", unexpected_keys.first)
99
99
  end
100
100
  end
101
101
 
@@ -1,11 +1,11 @@
1
1
  # Parses caster rules
2
- # and returns list of HCast::Metadata::Attribute instances
2
+ # and returns list of HashCast::Metadata::Attribute instances
3
3
  # which contains casting rules
4
- class HCast::AttributesParser
4
+ class HashCast::AttributesParser
5
5
 
6
6
  # Performs casting
7
7
  # @param block [Proc] block with casting rules
8
- # @return Array(HCast::Metadata::Attribute) list of casting rules
8
+ # @return Array(HashCast::Metadata::Attribute) list of casting rules
9
9
  def self.parse(&block)
10
10
  dsl = DSL.new
11
11
  dsl.instance_exec(&block)
@@ -27,15 +27,15 @@ class HCast::AttributesParser
27
27
  def method_missing(caster_name, *args, &block)
28
28
  attr_name = args[0]
29
29
  options = args[1] || {}
30
- caster = HCast.casters[caster_name]
30
+ caster = HashCast.casters[caster_name]
31
31
 
32
32
  check_caster_exists!(caster, caster_name)
33
33
  check_attr_name_valid!(attr_name)
34
34
  check_options_is_hash!(options)
35
35
 
36
- attribute = HCast::Metadata::Attribute.new(attr_name, caster, options)
36
+ attribute = HashCast::Metadata::Attribute.new(attr_name, caster, options)
37
37
  if block_given?
38
- attribute.children = HCast::AttributesParser.parse(&block)
38
+ attribute.children = HashCast::AttributesParser.parse(&block)
39
39
  end
40
40
  attributes << attribute
41
41
  end
@@ -44,19 +44,19 @@ class HCast::AttributesParser
44
44
 
45
45
  def check_caster_exists!(caster, caster_name)
46
46
  if !caster
47
- raise HCast::Errors::CasterNotFoundError, "caster with name '#{caster_name}' is not found"
47
+ raise HashCast::Errors::CasterNotFoundError, "caster with name '#{caster_name}' is not found"
48
48
  end
49
49
  end
50
50
 
51
51
  def check_attr_name_valid!(attr_name)
52
52
  if !attr_name.is_a?(Symbol) && !attr_name.is_a?(String)
53
- raise HCast::Errors::ArgumentError, "attribute name should be a symbol or string"
53
+ raise HashCast::Errors::ArgumentError, "attribute name should be a symbol or string"
54
54
  end
55
55
  end
56
56
 
57
57
  def check_options_is_hash!(options)
58
58
  if !options.is_a?(Hash)
59
- raise HCast::Errors::ArgumentError, "attribute options should be a Hash"
59
+ raise HashCast::Errors::ArgumentError, "attribute options should be a Hash"
60
60
  end
61
61
  end
62
62
  end
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Example caster:
4
4
  # class ContactCaster
5
- # include HCast::Caster
5
+ # include HashCast::Caster
6
6
  #
7
7
  # attributes do
8
8
  # hash :contact do
@@ -76,8 +76,8 @@
76
76
  # ]
77
77
  # }
78
78
  # }
79
- module HCast::Caster
80
- extend HCast::Concern
79
+ module HashCast::Caster
80
+ extend HashCast::Concern
81
81
 
82
82
  module ClassMethods
83
83
 
@@ -91,7 +91,7 @@ module HCast::Caster
91
91
  def attributes(&block)
92
92
  raise ArgumentError, "You should provide block" unless block_given?
93
93
 
94
- attributes = HCast::AttributesParser.parse(&block)
94
+ attributes = HashCast::AttributesParser.parse(&block)
95
95
  self.class_variable_set(:@@attributes, attributes)
96
96
  end
97
97
 
@@ -104,7 +104,7 @@ module HCast::Caster
104
104
  check_options!(options)
105
105
  set_default_options(options)
106
106
 
107
- attributes_caster = HCast::AttributesCaster.new(class_variable_get(:@@attributes), options)
107
+ attributes_caster = HashCast::AttributesCaster.new(class_variable_get(:@@attributes), options)
108
108
  attributes_caster.cast(hash)
109
109
  end
110
110
 
@@ -112,31 +112,31 @@ module HCast::Caster
112
112
 
113
113
  def check_attributes_defined!
114
114
  unless class_variable_defined?(:@@attributes)
115
- raise HCast::Errors::ArgumentError, "Attributes block should be defined"
115
+ raise HashCast::Errors::ArgumentError, "Attributes block should be defined"
116
116
  end
117
117
  end
118
118
 
119
119
  def check_options!(options)
120
120
  unless options.is_a?(Hash)
121
- raise HCast::Errors::ArgumentError, "Options should be a hash"
121
+ raise HashCast::Errors::ArgumentError, "Options should be a hash"
122
122
  end
123
123
  if options[:input_keys] && ![:string, :symbol].include?(options[:input_keys])
124
- raise HCast::Errors::ArgumentError, "input_keys should be :string or :symbol"
124
+ raise HashCast::Errors::ArgumentError, "input_keys should be :string or :symbol"
125
125
  end
126
126
  if options[:output_keys] && ![:string, :symbol].include?(options[:output_keys])
127
- raise HCast::Errors::ArgumentError, "output_keys should be :string or :symbol"
127
+ raise HashCast::Errors::ArgumentError, "output_keys should be :string or :symbol"
128
128
  end
129
129
  end
130
130
 
131
131
  def check_hash_given!(hash)
132
132
  unless hash.is_a?(Hash)
133
- raise HCast::Errors::ArgumentError, "Hash should be given"
133
+ raise HashCast::Errors::ArgumentError, "Hash should be given"
134
134
  end
135
135
  end
136
136
 
137
137
  def set_default_options(options)
138
- options[:input_keys] ||= HCast.config.input_keys
139
- options[:output_keys] ||= HCast.config.output_keys
138
+ options[:input_keys] ||= HashCast.config.input_keys
139
+ options[:output_keys] ||= HashCast.config.output_keys
140
140
  end
141
141
  end
142
142
  end
@@ -1,4 +1,4 @@
1
- class HCast::Casters::ArrayCaster
1
+ class HashCast::Casters::ArrayCaster
2
2
 
3
3
  def self.cast(value, attr_name, options = {})
4
4
  if value.is_a?(Array)
@@ -8,7 +8,7 @@ class HCast::Casters::ArrayCaster
8
8
  value
9
9
  end
10
10
  else
11
- raise HCast::Errors::CastingError, "should be an array"
11
+ raise HashCast::Errors::CastingError, "should be an array"
12
12
  end
13
13
  end
14
14
 
@@ -16,7 +16,7 @@ class HCast::Casters::ArrayCaster
16
16
 
17
17
  def self.cast_array_items(array, attr_name, options)
18
18
  caster_name = options[:each]
19
- caster = HCast.casters[caster_name]
19
+ caster = HashCast.casters[caster_name]
20
20
  check_caster_exists!(caster, caster_name)
21
21
  array.map do |item|
22
22
  caster.cast(item, "#{attr_name} item", options)
@@ -25,7 +25,7 @@ class HCast::Casters::ArrayCaster
25
25
 
26
26
  def self.check_caster_exists!(caster, caster_name)
27
27
  unless caster
28
- raise HCast::Errors::CasterNotFoundError, "caster with name #{caster_name} is not found"
28
+ raise HashCast::Errors::CasterNotFoundError, "caster with name #{caster_name} is not found"
29
29
  end
30
30
  end
31
31
 
@@ -1,4 +1,4 @@
1
- class HCast::Casters::BooleanCaster
1
+ class HashCast::Casters::BooleanCaster
2
2
 
3
3
  def self.cast(value, attr_name, options = {})
4
4
  if [TrueClass, FalseClass].include?(value.class)
@@ -8,7 +8,7 @@ class HCast::Casters::BooleanCaster
8
8
  elsif ['0', 'false', 'off', 0].include?(value)
9
9
  false
10
10
  else
11
- raise HCast::Errors::CastingError, "should be a boolean"
11
+ raise HashCast::Errors::CastingError, "should be a boolean"
12
12
  end
13
13
  end
14
14
 
@@ -1,6 +1,6 @@
1
1
  require 'date'
2
2
 
3
- class HCast::Casters::DateCaster
3
+ class HashCast::Casters::DateCaster
4
4
 
5
5
  def self.cast(value, attr_name, options = {})
6
6
  if value.is_a?(Date)
@@ -9,10 +9,10 @@ class HCast::Casters::DateCaster
9
9
  begin
10
10
  Date.parse(value)
11
11
  rescue ArgumentError => e
12
- raise HCast::Errors::CastingError, "is invalid date"
12
+ raise HashCast::Errors::CastingError, "is invalid date"
13
13
  end
14
14
  else
15
- raise HCast::Errors::CastingError, "should be a date"
15
+ raise HashCast::Errors::CastingError, "should be a date"
16
16
  end
17
17
  end
18
18
 
@@ -1,4 +1,4 @@
1
- class HCast::Casters::DateTimeCaster
1
+ class HashCast::Casters::DateTimeCaster
2
2
 
3
3
  def self.cast(value, attr_name, options = {})
4
4
  if value.is_a?(DateTime)
@@ -9,10 +9,10 @@ class HCast::Casters::DateTimeCaster
9
9
  begin
10
10
  DateTime.parse(value)
11
11
  rescue ArgumentError => e
12
- raise HCast::Errors::CastingError, "is invalid datetime"
12
+ raise HashCast::Errors::CastingError, "is invalid datetime"
13
13
  end
14
14
  else
15
- raise HCast::Errors::CastingError, "should be a datetime"
15
+ raise HashCast::Errors::CastingError, "should be a datetime"
16
16
  end
17
17
  end
18
18
 
@@ -1,4 +1,4 @@
1
- class HCast::Casters::FloatCaster
1
+ class HashCast::Casters::FloatCaster
2
2
 
3
3
  def self.cast(value, attr_name, options = {})
4
4
  if value.is_a?(Float)
@@ -7,10 +7,10 @@ class HCast::Casters::FloatCaster
7
7
  begin
8
8
  Float(value)
9
9
  rescue ArgumentError => e
10
- raise HCast::Errors::CastingError, "is invalid float"
10
+ raise HashCast::Errors::CastingError, "is invalid float"
11
11
  end
12
12
  else
13
- raise HCast::Errors::CastingError, "should be a float"
13
+ raise HashCast::Errors::CastingError, "should be a float"
14
14
  end
15
15
  end
16
16
 
@@ -1,10 +1,10 @@
1
- class HCast::Casters::HashCaster
1
+ class HashCast::Casters::HashCaster
2
2
 
3
3
  def self.cast(value, attr_name, options = {})
4
4
  if value.is_a?(Hash)
5
5
  value
6
6
  else
7
- raise HCast::Errors::CastingError, "should be a hash"
7
+ raise HashCast::Errors::CastingError, "should be a hash"
8
8
  end
9
9
  end
10
10
 
@@ -1,4 +1,4 @@
1
- class HCast::Casters::IntegerCaster
1
+ class HashCast::Casters::IntegerCaster
2
2
 
3
3
  def self.cast(value, attr_name, options = {})
4
4
  if value.is_a?(Integer)
@@ -7,10 +7,10 @@ class HCast::Casters::IntegerCaster
7
7
  begin
8
8
  Integer(value)
9
9
  rescue ArgumentError => e
10
- raise HCast::Errors::CastingError, "is invalid integer"
10
+ raise HashCast::Errors::CastingError, "is invalid integer"
11
11
  end
12
12
  else
13
- raise HCast::Errors::CastingError, "should be a integer"
13
+ raise HashCast::Errors::CastingError, "should be a integer"
14
14
  end
15
15
  end
16
16
 
@@ -0,0 +1,26 @@
1
+ class HashCast::Casters::StringCaster
2
+ NULL_BYTE_CHARACTER = "\u0000".freeze
3
+
4
+ def self.cast(value, attr_name, options = {})
5
+ casted_value = cast_string(value, attr_name, options)
6
+
7
+ if HashCast.config.validate_string_null_byte && casted_value.match?(NULL_BYTE_CHARACTER)
8
+ raise HashCast::Errors::CastingError, 'contains invalid characters'
9
+ end
10
+
11
+ casted_value
12
+ end
13
+
14
+ private
15
+
16
+ def self.cast_string(value, attr_name, options = {})
17
+ if value.is_a?(String)
18
+ value
19
+ elsif value.is_a?(Symbol)
20
+ value.to_s
21
+ else
22
+ raise HashCast::Errors::CastingError, "should be a string"
23
+ end
24
+ end
25
+
26
+ end
@@ -1,4 +1,4 @@
1
- class HCast::Casters::SymbolCaster
1
+ class HashCast::Casters::SymbolCaster
2
2
  MAX_SYMBOL_LENGTH = 1000
3
3
 
4
4
  def self.cast(value, attr_name, options = {})
@@ -6,12 +6,12 @@ class HCast::Casters::SymbolCaster
6
6
  value
7
7
  elsif value.is_a?(String)
8
8
  if value.length > MAX_SYMBOL_LENGTH
9
- raise HCast::Errors::CastingError, "is too long to be a symbol"
9
+ raise HashCast::Errors::CastingError, "is too long to be a symbol"
10
10
  else
11
11
  value.to_sym
12
12
  end
13
13
  else
14
- raise HCast::Errors::CastingError, "should be a symbol"
14
+ raise HashCast::Errors::CastingError, "should be a symbol"
15
15
  end
16
16
  end
17
17
 
@@ -1,6 +1,6 @@
1
1
  require 'time'
2
2
 
3
- class HCast::Casters::TimeCaster
3
+ class HashCast::Casters::TimeCaster
4
4
 
5
5
  def self.cast(value, attr_name, options = {})
6
6
  if value.is_a?(Time)
@@ -9,10 +9,10 @@ class HCast::Casters::TimeCaster
9
9
  begin
10
10
  Time.parse(value)
11
11
  rescue ArgumentError => e
12
- raise HCast::Errors::CastingError, "is invalid time"
12
+ raise HashCast::Errors::CastingError, "is invalid time"
13
13
  end
14
14
  else
15
- raise HCast::Errors::CastingError, "should be a time"
15
+ raise HashCast::Errors::CastingError, "should be a time"
16
16
  end
17
17
  end
18
18
 
@@ -0,0 +1,13 @@
1
+ # List of build in casters
2
+ module HashCast::Casters
3
+ require 'hash_cast/casters/array_caster'
4
+ require 'hash_cast/casters/boolean_caster'
5
+ require 'hash_cast/casters/date_caster'
6
+ require 'hash_cast/casters/datetime_caster'
7
+ require 'hash_cast/casters/float_caster'
8
+ require 'hash_cast/casters/hash_caster'
9
+ require 'hash_cast/casters/integer_caster'
10
+ require 'hash_cast/casters/string_caster'
11
+ require 'hash_cast/casters/symbol_caster'
12
+ require 'hash_cast/casters/time_caster'
13
+ end
@@ -1,4 +1,4 @@
1
- module HCast
1
+ module HashCast
2
2
  # Copied from here https://github.com/rails/rails/blob/master/activesupport/lib/active_support/concern.rb
3
3
  #
4
4
  # A typical module looks like this:
@@ -0,0 +1,17 @@
1
+ class HashCast::Config
2
+ attr_accessor :input_keys, :output_keys, :validate_string_null_byte
3
+
4
+ def input_keys
5
+ @input_keys || :symbol
6
+ end
7
+
8
+ def output_keys
9
+ @output_keys || :symbol
10
+ end
11
+
12
+ def validate_string_null_byte
13
+ return true if @validate_string_null_byte.nil?
14
+
15
+ @validate_string_null_byte
16
+ end
17
+ end
@@ -1,15 +1,15 @@
1
- module HCast::Errors
1
+ module HashCast::Errors
2
2
 
3
- # Base error class for all HCast errors
4
- class HCastError < StandardError; end
3
+ # Base error class for all HashCast errors
4
+ class HashCastError < StandardError; end
5
5
 
6
- # Raised when caster with given name is not registered in HCast
7
- class CasterNotFoundError < HCastError; end
6
+ # Raised when caster with given name is not registered in HashCast
7
+ class CasterNotFoundError < HashCastError; end
8
8
 
9
- # Raised when some of the given to HCast argument is not valid
10
- class ArgumentError < HCastError; end
9
+ # Raised when some of the given to HashCast argument is not valid
10
+ class ArgumentError < HashCastError; end
11
11
 
12
- class AttributeError < HCastError
12
+ class AttributeError < HashCastError
13
13
  attr_reader :namespaces
14
14
 
15
15
  def initialize(message, namespace = nil)
@@ -1,4 +1,4 @@
1
- module HCast::Metadata
1
+ module HashCast::Metadata
2
2
  class Attribute
3
3
  attr_reader :name, :caster, :options
4
4
  attr_accessor :children
@@ -0,0 +1,3 @@
1
+ module HashCast
2
+ VERSION = "0.5.1"
3
+ end
data/lib/hash_cast.rb ADDED
@@ -0,0 +1,46 @@
1
+ require 'hash_cast/version'
2
+ require 'hash_cast/errors'
3
+ require 'hash_cast/config'
4
+ require 'hash_cast/casters'
5
+ require 'hash_cast/concern.rb'
6
+ require 'hash_cast/metadata/attribute'
7
+ require 'hash_cast/attributes_parser'
8
+ require 'hash_cast/attributes_caster'
9
+ require 'hash_cast/caster'
10
+
11
+ module HashCast
12
+ @@casters = {}
13
+
14
+ # Defines caster without adding own class
15
+ # @note Not yet implemented
16
+ def self.create(&block)
17
+ end
18
+
19
+ # Returns list of defined casters
20
+ def self.casters
21
+ @@casters
22
+ end
23
+
24
+ # Adds new casters to HashCast
25
+ # Allow extend HashCast with your own casters
26
+ # @param caster_name [Symbol] caster name
27
+ # @param caster [Class] caster
28
+ def self.add_caster(caster_name, caster)
29
+ @@casters[caster_name] = caster
30
+ end
31
+
32
+ def self.config
33
+ @@config ||= HashCast::Config.new
34
+ end
35
+ end
36
+
37
+ HashCast.add_caster(:array, HashCast::Casters::ArrayCaster)
38
+ HashCast.add_caster(:boolean, HashCast::Casters::BooleanCaster)
39
+ HashCast.add_caster(:date, HashCast::Casters::DateCaster)
40
+ HashCast.add_caster(:datetime, HashCast::Casters::DateTimeCaster)
41
+ HashCast.add_caster(:float, HashCast::Casters::FloatCaster)
42
+ HashCast.add_caster(:hash, HashCast::Casters::HashCaster)
43
+ HashCast.add_caster(:integer, HashCast::Casters::IntegerCaster)
44
+ HashCast.add_caster(:string, HashCast::Casters::StringCaster)
45
+ HashCast.add_caster(:symbol, HashCast::Casters::SymbolCaster)
46
+ HashCast.add_caster(:time, HashCast::Casters::TimeCaster)
@@ -1,10 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe HCast::Caster do
3
+ describe HashCast::Caster do
4
4
  describe "#cast" do
5
5
 
6
6
  class ContactCaster
7
- include HCast::Caster
7
+ include HashCast::Caster
8
8
 
9
9
  attributes do
10
10
  hash :contact do
@@ -82,7 +82,7 @@ describe HCast::Caster do
82
82
 
83
83
  describe "Custom casters" do
84
84
  class SettingsCaster
85
- include HCast::Caster
85
+ include HashCast::Caster
86
86
 
87
87
  attributes do
88
88
  string :account
@@ -90,7 +90,7 @@ describe HCast::Caster do
90
90
  end
91
91
 
92
92
  class EmailCaster
93
- include HCast::Caster
93
+ include HashCast::Caster
94
94
 
95
95
  attributes do
96
96
  string :address
@@ -98,7 +98,7 @@ describe HCast::Caster do
98
98
  end
99
99
 
100
100
  class CompanyCaster
101
- include HCast::Caster
101
+ include HashCast::Caster
102
102
 
103
103
  attributes do
104
104
  string :name
@@ -158,7 +158,7 @@ describe HCast::Caster do
158
158
 
159
159
  expect do
160
160
  ContactCaster.cast(input_hash)
161
- end.to raise_error(HCast::Errors::CastingError, "contact[name] should be a string")
161
+ end.to raise_error(HashCast::Errors::CastingError, "contact[name] should be a string")
162
162
  end
163
163
 
164
164
  it "should raise error if some attribute wasn't given" do
@@ -188,7 +188,7 @@ describe HCast::Caster do
188
188
 
189
189
  expect do
190
190
  ContactCaster.cast(input_hash)
191
- end.to raise_error(HCast::Errors::MissingAttributeError, "contact[name] should be given")
191
+ end.to raise_error(HashCast::Errors::MissingAttributeError, "contact[name] should be given")
192
192
  end
193
193
 
194
194
  it "should not raise error if attribute is optional" do
@@ -221,7 +221,7 @@ describe HCast::Caster do
221
221
  end.to_not raise_error
222
222
  end
223
223
 
224
- it "should raise error if unexpected attribute was given" do
224
+ it "raises error if skip_unexpected_attributes=false and unexpected attribute was given" do
225
225
  input_hash = {
226
226
  contact: {
227
227
  wrong_attribute: 'foo',
@@ -248,11 +248,11 @@ describe HCast::Caster do
248
248
  }
249
249
 
250
250
  expect do
251
- ContactCaster.cast(input_hash)
252
- end.to raise_error(HCast::Errors::UnexpectedAttributeError, "contact[wrong_attribute] is not valid attribute name")
251
+ ContactCaster.cast(input_hash, skip_unexpected_attributes: false)
252
+ end.to raise_error(HashCast::Errors::UnexpectedAttributeError, "contact[wrong_attribute] is not valid attribute name")
253
253
  end
254
254
 
255
- it "shouldn't unexpected attributes error if skip_unexpected_attributes flag is set to true" do
255
+ it "doesn't raise unexpected attributes error by default" do
256
256
  input_hash = {
257
257
  contact: {
258
258
  wrong_attribute: 'foo',
@@ -279,8 +279,8 @@ describe HCast::Caster do
279
279
  }
280
280
 
281
281
  expect do
282
- ContactCaster.cast(input_hash, skip_unexpected_attributes: true)
283
- end.not_to raise_error(HCast::Errors::UnexpectedAttributeError)
282
+ ContactCaster.cast(input_hash)
283
+ end.not_to raise_error(HashCast::Errors::UnexpectedAttributeError)
284
284
 
285
285
  end
286
286
 
@@ -343,20 +343,20 @@ describe HCast::Caster do
343
343
  it "should raise CaterNotFound exception if caster name is invalid" do
344
344
  expect do
345
345
  class WrongCaster
346
- include HCast::Caster
346
+ include HashCast::Caster
347
347
 
348
348
  attributes do
349
349
  integr :name
350
350
  end
351
351
  end
352
- end.to raise_error(HCast::Errors::CasterNotFoundError)
352
+ end.to raise_error(HashCast::Errors::CasterNotFoundError)
353
353
  end
354
354
  end
355
355
 
356
356
  context "allow nil values" do
357
357
  before(:all) do
358
358
  class HomeCaster
359
- include HCast::Caster
359
+ include HashCast::Caster
360
360
 
361
361
  attributes do
362
362
  string :city
@@ -378,7 +378,32 @@ describe HCast::Caster do
378
378
  city: nil,
379
379
  zip: nil
380
380
  )
381
- end.to raise_error(HCast::Errors::CastingError, "city should be a string")
381
+ end.to raise_error(HashCast::Errors::CastingError, "city should be a string")
382
+ end
383
+ end
384
+
385
+ context "string caster" do
386
+ before(:all) do
387
+ class HomeCaster
388
+ include HashCast::Caster
389
+
390
+ attributes do
391
+ string :city
392
+ end
393
+ end
394
+ end
395
+
396
+ after{ HashCast.config.validate_string_null_byte = nil }
397
+
398
+ it "should allow null byte if validate_string_null_byte config is set to false" do
399
+ HashCast.config.validate_string_null_byte = false
400
+ HomeCaster.cast(city: "\u0000")
401
+ end
402
+
403
+ it "should not allow null byte if validate_string_null_byte config by default" do
404
+ expect do
405
+ HomeCaster.cast(city: "\u0000")
406
+ end.to raise_error(HashCast::Errors::CastingError, "city contains invalid characters")
382
407
  end
383
408
  end
384
409
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe HCast do
3
+ describe HashCast do
4
4
 
5
5
  describe ".create" do
6
6
  it "should cast hash attributes" do
@@ -15,7 +15,7 @@ describe HCast do
15
15
  }
16
16
  }
17
17
 
18
- caster = HCast.create do
18
+ caster = HashCast.create do
19
19
  hash :contact do
20
20
  string :name
21
21
  integer :age
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'bundler/setup'
3
- require 'hcast'
3
+ require 'hash_cast'
4
4
 
5
5
  RSpec.configure do |config|
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hash_cast
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Albert Gazizov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-28 00:00:00.000000000 Z
11
+ date: 2024-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -50,34 +50,35 @@ files:
50
50
  - ".rspec"
51
51
  - ".ruby-gemset"
52
52
  - ".ruby-version"
53
+ - CHANGELOG.md
53
54
  - Gemfile
54
55
  - Gemfile.lock
55
56
  - LICENSE.txt
56
57
  - README.md
57
58
  - Rakefile
58
- - hcast.gemspec
59
- - lib/hcast.rb
60
- - lib/hcast/attributes_caster.rb
61
- - lib/hcast/attributes_parser.rb
62
- - lib/hcast/caster.rb
63
- - lib/hcast/casters.rb
64
- - lib/hcast/casters/array_caster.rb
65
- - lib/hcast/casters/boolean_caster.rb
66
- - lib/hcast/casters/date_caster.rb
67
- - lib/hcast/casters/datetime_caster.rb
68
- - lib/hcast/casters/float_caster.rb
69
- - lib/hcast/casters/hash_caster.rb
70
- - lib/hcast/casters/integer_caster.rb
71
- - lib/hcast/casters/string_caster.rb
72
- - lib/hcast/casters/symbol_caster.rb
73
- - lib/hcast/casters/time_caster.rb
74
- - lib/hcast/concern.rb
75
- - lib/hcast/config.rb
76
- - lib/hcast/errors.rb
77
- - lib/hcast/metadata/attribute.rb
78
- - lib/hcast/version.rb
79
- - spec/hcast/caster_spec.rb
80
- - spec/hcast/hcast_spec.rb
59
+ - hash_cast.gemspec
60
+ - lib/hash_cast.rb
61
+ - lib/hash_cast/attributes_caster.rb
62
+ - lib/hash_cast/attributes_parser.rb
63
+ - lib/hash_cast/caster.rb
64
+ - lib/hash_cast/casters.rb
65
+ - lib/hash_cast/casters/array_caster.rb
66
+ - lib/hash_cast/casters/boolean_caster.rb
67
+ - lib/hash_cast/casters/date_caster.rb
68
+ - lib/hash_cast/casters/datetime_caster.rb
69
+ - lib/hash_cast/casters/float_caster.rb
70
+ - lib/hash_cast/casters/hash_caster.rb
71
+ - lib/hash_cast/casters/integer_caster.rb
72
+ - lib/hash_cast/casters/string_caster.rb
73
+ - lib/hash_cast/casters/symbol_caster.rb
74
+ - lib/hash_cast/casters/time_caster.rb
75
+ - lib/hash_cast/concern.rb
76
+ - lib/hash_cast/config.rb
77
+ - lib/hash_cast/errors.rb
78
+ - lib/hash_cast/metadata/attribute.rb
79
+ - lib/hash_cast/version.rb
80
+ - spec/hash_cast/caster_spec.rb
81
+ - spec/hash_cast/hash_cast_spec.rb
81
82
  - spec/spec_helper.rb
82
83
  homepage: http://github.com/droidlabs/hash_cast
83
84
  licenses:
@@ -103,6 +104,6 @@ signing_key:
103
104
  specification_version: 4
104
105
  summary: Declarative Hash Caster
105
106
  test_files:
106
- - spec/hcast/caster_spec.rb
107
- - spec/hcast/hcast_spec.rb
107
+ - spec/hash_cast/caster_spec.rb
108
+ - spec/hash_cast/hash_cast_spec.rb
108
109
  - spec/spec_helper.rb
@@ -1,13 +0,0 @@
1
- class HCast::Casters::StringCaster
2
-
3
- def self.cast(value, attr_name, options = {})
4
- if value.is_a?(String)
5
- value
6
- elsif value.is_a?(Symbol)
7
- value.to_s
8
- else
9
- raise HCast::Errors::CastingError, "should be a string"
10
- end
11
- end
12
-
13
- end
data/lib/hcast/casters.rb DELETED
@@ -1,13 +0,0 @@
1
- # List of build in casters
2
- module HCast::Casters
3
- require 'hcast/casters/array_caster'
4
- require 'hcast/casters/boolean_caster'
5
- require 'hcast/casters/date_caster'
6
- require 'hcast/casters/datetime_caster'
7
- require 'hcast/casters/float_caster'
8
- require 'hcast/casters/hash_caster'
9
- require 'hcast/casters/integer_caster'
10
- require 'hcast/casters/string_caster'
11
- require 'hcast/casters/symbol_caster'
12
- require 'hcast/casters/time_caster'
13
- end
data/lib/hcast/config.rb DELETED
@@ -1,11 +0,0 @@
1
- class HCast::Config
2
- attr_accessor :input_keys, :output_keys
3
-
4
- def input_keys
5
- @input_keys || :symbol
6
- end
7
-
8
- def output_keys
9
- @output_keys || :symbol
10
- end
11
- end
data/lib/hcast/version.rb DELETED
@@ -1,3 +0,0 @@
1
- module HCast
2
- VERSION = "0.4.0"
3
- end
data/lib/hcast.rb DELETED
@@ -1,46 +0,0 @@
1
- require 'hcast/version'
2
- require 'hcast/errors'
3
- require 'hcast/config'
4
- require 'hcast/casters'
5
- require 'hcast/concern.rb'
6
- require 'hcast/metadata/attribute'
7
- require 'hcast/attributes_parser'
8
- require 'hcast/attributes_caster'
9
- require 'hcast/caster'
10
-
11
- module HCast
12
- @@casters = {}
13
-
14
- # Defines caster without adding own class
15
- # @note Not yet implemented
16
- def self.create(&block)
17
- end
18
-
19
- # Returns list of defined casters
20
- def self.casters
21
- @@casters
22
- end
23
-
24
- # Adds new casters to HCast
25
- # Allow extend HCast with your own casters
26
- # @param caster_name [Symbol] caster name
27
- # @param caster [Class] caster
28
- def self.add_caster(caster_name, caster)
29
- @@casters[caster_name] = caster
30
- end
31
-
32
- def self.config
33
- @@config ||= HCast::Config.new
34
- end
35
- end
36
-
37
- HCast.add_caster(:array, HCast::Casters::ArrayCaster)
38
- HCast.add_caster(:boolean, HCast::Casters::BooleanCaster)
39
- HCast.add_caster(:date, HCast::Casters::DateCaster)
40
- HCast.add_caster(:datetime, HCast::Casters::DateTimeCaster)
41
- HCast.add_caster(:float, HCast::Casters::FloatCaster)
42
- HCast.add_caster(:hash, HCast::Casters::HashCaster)
43
- HCast.add_caster(:integer, HCast::Casters::IntegerCaster)
44
- HCast.add_caster(:string, HCast::Casters::StringCaster)
45
- HCast.add_caster(:symbol, HCast::Casters::SymbolCaster)
46
- HCast.add_caster(:time, HCast::Casters::TimeCaster)