simple_params 1.1.2 → 1.2.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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZGYzNDdhM2YxYjQzNzI3NWEzOTlkMGRjNDA2M2NiN2NmZjA2ZGFjOQ==
4
+ NjYyNWJhNWU2ZmNkMGMxZWFjMmEzMjM3OWQyNWY0ZWZhNzY2N2ZhNw==
5
5
  data.tar.gz: !binary |-
6
- OGM2ODA5ZWI2ZTVjMDFlY2EwMzhmY2Y2ODM0ZTY5MmY5YjFmYTA0MA==
6
+ NzllYWUzNDJjMDRkNTM5YzIwODMyYWRiYzhmOTU4M2NkNTczNGE0NA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- YWQzNjllOTcyYjAxNDM5NWNhYmI0ZjM0ZmVlMjFlMGE4MWU0ZjIwMDIzNmFi
10
- ZmNmZjY1NDYyMTg5MDYyYjhjZDI5ZjE0MDU5MmI2YjUwYzBjMjg3M2Q1NzVi
11
- MzcxMDFlOWY3MDAwZjM1MGNhMGI3ZDJjZWFjOTg2YmYyMGVjYTE=
9
+ ZTNkMzU1YjhkMjdjNzg0MWFkZDhmNTUzYmU3OGVhZmNlOTBiYjM0NWRiMjRl
10
+ YWRiMTkzNTBiNjY3MDBiODAzOGUxYzk0MDY0YzJiNTUwNGRlNThmMTM0ODg0
11
+ MDc5MGU5MTgxNjQzMWY4ZjQ0MTc2OWQ5MTI3ZjUyNmVjM2ZiZTk=
12
12
  data.tar.gz: !binary |-
13
- YTRmNmQ0YzdmMmRjYWNlOTU5ZGNmZDJjZWNjOTRkZDEyZGNkOGUzOGNjZTRk
14
- MTAyMGE0ZjlmNWU2MDJjOGNjOGVkOTFhMjc4MjM2NGY3NmZhY2JlNzc3OWM5
15
- MWJjZTgwNThjMTg3NjBmNzFjN2ViOGIzYTI5M2VlYzc5MTQzYjk=
13
+ N2ExNzhkZjk0MmM4YTM4ZWQ2YjYwZGVjZTJlMDBiNjVmMGVkYzE1NWVlMDA0
14
+ Y2IwMWFjNjAyMjE1MWE2MDk5ZDY4NWNlODAxMDEyOGNiZjgxMTJlYzg4ZWZk
15
+ ZTE5N2E2ZTFhZTcxZDY0OWJiZjViNzZiOGE0NTNjMTZmNWZlNzY=
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- simple_params (1.1.1)
4
+ simple_params (1.1.2)
5
5
  activemodel (>= 3.0, < 5.0)
6
6
  shoulda-matchers (~> 2.8)
7
7
  virtus (>= 1.0.0)
@@ -19,9 +19,16 @@ module SimpleParams
19
19
  end
20
20
 
21
21
  private
22
+ def nested_type
23
+ if options[:type].present? && options[:type].to_sym == :array
24
+ 'Array'
25
+ else
26
+ 'Hash'
27
+ end
28
+ end
22
29
 
23
30
  def nested_description
24
- start = "param :#{name}, Hash, #{description}, #{requirement_description} do"
31
+ start = "param :#{name}, #{nested_type}, #{description}, #{requirement_description} do"
25
32
  attribute_descriptors = []
26
33
  attributes.each { |attribute| attribute_descriptors << attribute.to_s }
27
34
  finish = "end"
@@ -2,22 +2,17 @@ module SimpleParams
2
2
  class ApiPieDoc
3
3
 
4
4
  attr_accessor :base_attributes,
5
- :nested_hashes,
6
- :nested_arrays,
5
+ :nested_classes,
7
6
  :nested_attributes,
8
- :nested_array_attributes,
9
7
  :docs
10
8
 
11
9
  def initialize(simple_params)
12
10
  self.base_attributes = simple_params.defined_attributes
13
- self.nested_hashes = simple_params.nested_hashes
14
- self.nested_arrays = simple_params.nested_arrays
11
+ self.nested_classes = simple_params.nested_classes
15
12
  self.nested_attributes = []
16
- self.nested_array_attributes = []
17
13
  self.docs = []
18
14
 
19
- build_nested_attributes
20
- build_nested_array_attributes
15
+ build_nested_classes
21
16
  end
22
17
 
23
18
  def build
@@ -25,12 +20,8 @@ module SimpleParams
25
20
  docs << Attribute.new(attribute).to_s
26
21
  end
27
22
 
28
- nested_attributes.each do |nested_attribute|
29
- docs << NestedAttribute.new(nested_attribute).to_s
30
- end
31
-
32
- nested_array_attributes.each do |nested_attribute|
33
- docs << NestedArray.new(nested_attribute).to_s
23
+ nested_attributes.each do |nested_class|
24
+ docs << NestedAttribute.new(nested_class).to_s
34
25
  end
35
26
 
36
27
  docs.join("\n")
@@ -38,16 +29,10 @@ module SimpleParams
38
29
 
39
30
  private
40
31
 
41
- def build_nested_attributes
42
- nested_hashes.each do |name, parameter_set|
32
+ def build_nested_classes
33
+ nested_classes.each do |name, parameter_set|
43
34
  nested_attributes << { name => parameter_set.defined_attributes, options: parameter_set.options }
44
35
  end
45
36
  end
46
-
47
- def build_nested_array_attributes
48
- nested_arrays.each do |name, parameter_set|
49
- nested_array_attributes << { name => parameter_set.defined_attributes, options: parameter_set.options }
50
- end
51
- end
52
37
  end
53
38
  end
@@ -3,12 +3,8 @@ require "virtus"
3
3
 
4
4
  module SimpleParams
5
5
  class Attribute
6
- attr_reader :parent
7
- attr_reader :name
8
- attr_reader :type
9
- attr_reader :default
10
- attr_reader :validations
11
- attr_reader :formatter
6
+ attr_reader :parent, :name, :type, :default,
7
+ :validations, :formatter
12
8
 
13
9
  def initialize(parent, name, opts={})
14
10
  @parent = parent
@@ -0,0 +1,68 @@
1
+ module SimpleParams
2
+ module DateTimeHelpers
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ end
7
+
8
+ module ClassMethods
9
+ def define_date_helper_methods(name)
10
+ define_method("#{name}(3i)=") do |day|
11
+ attribute = send("#{name}_attribute")
12
+ value = attribute.send("value") || Date.today
13
+ attribute.send("value=", Date.new(value.year, value.month, day.to_i))
14
+ end
15
+
16
+ define_method("#{name}(2i)=") do |month|
17
+ attribute = send("#{name}_attribute")
18
+ value = attribute.send("value") || Date.today
19
+ attribute.send("value=", Date.new(value.year, month.to_i, value.day))
20
+ end
21
+
22
+ define_method("#{name}(1i)=") do |year|
23
+ attribute = send("#{name}_attribute")
24
+ value = attribute.send("value") || Date.today
25
+ attribute.send("value=", Date.new(year.to_i, value.month, value.day))
26
+ end
27
+ end
28
+
29
+ def define_datetime_helper_methods(name)
30
+ define_method("#{name}(6i)=") do |sec|
31
+ attribute = send("#{name}_attribute")
32
+ value = attribute.send("value") || Time.now.utc
33
+ attribute.send("value=", Time.new(value.year, value.month, value.day, value.hour, value.min, sec.to_i, value.utc_offset))
34
+ end
35
+
36
+ define_method("#{name}(5i)=") do |minute|
37
+ attribute = send("#{name}_attribute")
38
+ value = attribute.send("value") || Time.now.utc
39
+ attribute.send("value=", Time.new(value.year, value.month, value.day, value.hour, minute.to_i, value.sec, value.utc_offset))
40
+ end
41
+
42
+ define_method("#{name}(4i)=") do |hour|
43
+ attribute = send("#{name}_attribute")
44
+ value = attribute.send("value") || Time.now.utc
45
+ attribute.send("value=", Time.new(value.year, value.month, value.day, hour.to_i, value.min, value.sec, value.utc_offset))
46
+ end
47
+
48
+ define_method("#{name}(3i)=") do |day|
49
+ attribute = send("#{name}_attribute")
50
+ value = attribute.send("value") || Time.now.utc
51
+ attribute.send("value=", Time.new(value.year, value.month, day.to_i, value.hour, value.min, value.sec, value.utc_offset))
52
+ end
53
+
54
+ define_method("#{name}(2i)=") do |month|
55
+ attribute = send("#{name}_attribute")
56
+ value = attribute.send("value") || Time.now.utc
57
+ attribute.send("value=", Time.new(value.year, month.to_i, value.day, value.hour, value.min, value.sec, value.utc_offset))
58
+ end
59
+
60
+ define_method("#{name}(1i)=") do |year|
61
+ attribute = send("#{name}_attribute")
62
+ value = attribute.send("value") || Time.now.utc
63
+ attribute.send("value=", Time.new(year.to_i, value.month, value.day, value.hour, value.min, value.sec, value.utc_offset))
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,68 @@
1
+ module SimpleParams
2
+ module HasAttributes
3
+ extend ActiveSupport::Concern
4
+ included do
5
+ def define_attributes(params)
6
+ self.class.defined_attributes.each_pair do |key, opts|
7
+ send("#{key}_attribute=", Attribute.new(self, key, opts))
8
+ end
9
+ end
10
+
11
+ def attributes
12
+ (defined_attributes.keys + nested_classes.keys).flatten
13
+ end
14
+ end
15
+
16
+ module ClassMethods
17
+ def defined_attributes
18
+ @define_attributes ||= {}
19
+ end
20
+
21
+ private
22
+ def define_attribute(name, opts = {})
23
+ opts[:type] ||= :string
24
+ defined_attributes[name.to_sym] = opts
25
+ attr_accessor "#{name}_attribute"
26
+
27
+ define_method("#{name}") do
28
+ attribute = send("#{name}_attribute")
29
+ attribute.send("value")
30
+ end
31
+
32
+ define_method("raw_#{name}") do
33
+ attribute = send("#{name}_attribute")
34
+ attribute.send("raw_value")
35
+ end
36
+
37
+ define_method("#{name}=") do |val|
38
+ attribute = send("#{name}_attribute")
39
+ attribute.send("value=", val)
40
+ end
41
+
42
+ if [Date, 'Date', :date].include?(opts[:type])
43
+ define_date_helper_methods(name)
44
+ elsif [DateTime, 'DateTime', :datetime, Time, 'Time', :time].include?(opts[:type])
45
+ define_datetime_helper_methods(name)
46
+ end
47
+ end
48
+
49
+ def add_validations(name, opts = {})
50
+ validations = opts[:validations] || {}
51
+ has_default = opts.has_key?(:default) # checking has_key? because :default may be nil
52
+ optional = opts[:optional]
53
+ if !validations.empty?
54
+ if optional || has_default
55
+ validations.merge!(allow_nil: true)
56
+ else
57
+ validations.merge!(presence: true)
58
+ end
59
+ else
60
+ if !optional && !has_default
61
+ validations.merge!(presence: true)
62
+ end
63
+ end
64
+ validates name, validations unless validations.empty?
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,30 @@
1
+ module SimpleParams
2
+ module HasTypedParams
3
+ extend ActiveSupport::Concern
4
+
5
+ TYPES = [
6
+ :integer,
7
+ :string,
8
+ :decimal,
9
+ :datetime,
10
+ :date,
11
+ :time,
12
+ :float,
13
+ :boolean,
14
+ :array,
15
+ :hash,
16
+ :object
17
+ ]
18
+
19
+ included do
20
+ end
21
+
22
+ module ClassMethods
23
+ TYPES.each do |sym|
24
+ define_method("#{sym}_param") do |name, opts={}|
25
+ param(name, opts.merge(type: sym))
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,27 @@
1
+ module SimpleParams
2
+ module HashHelpers
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+
7
+ private
8
+ def hash_to_symbolized_hash(hash)
9
+ hash.inject({}){|result, (key, value)|
10
+ new_key = case key
11
+ when String then key.to_sym
12
+ else key
13
+ end
14
+ new_value = case value
15
+ when Hash then hash_to_symbolized_hash(value)
16
+ else value
17
+ end
18
+ result[new_key] = new_value
19
+ result
20
+ }
21
+ end
22
+ end
23
+
24
+ module ClassMethods
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ require 'active_support/core_ext/string'
2
+
3
+ module SimpleParams
4
+ module RailsHelpers
5
+ extend ActiveSupport::Concern
6
+ included do
7
+ # Required for ActiveModel
8
+ def persisted?; false end
9
+ end
10
+
11
+ module ClassMethods
12
+ def define_rails_helpers(name, klass)
13
+ # E.g. if we have a nested_class named :phones, then we need:
14
+ # - a method called :phones_attributes that also sets :phones
15
+ # - a method called :build_phone
16
+
17
+ define_method("#{name}_attributes=") do |value|
18
+ send("#{name}=", value)
19
+ end
20
+
21
+ singular_key = singularized_key(name)
22
+ define_method("build_#{singular_key}") do |value={}|
23
+ klass.new(value, self)
24
+ end
25
+ end
26
+
27
+ private
28
+ def singularized_key(key)
29
+ key.to_s.singularize
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,68 @@
1
+ module SimpleParams
2
+ module StrictParams
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ def set_strictness
7
+ if self.class.strict_enforcement.nil?
8
+ self.class.strict_enforcement = true
9
+ end
10
+ end
11
+
12
+ # Overriding this method to allow for non-strict enforcement!
13
+ def method_missing(method_name, *arguments, &block)
14
+ if strict_enforcement?
15
+ raise SimpleParamsError, "parameter #{method_name} is not defined."
16
+ else
17
+ if @original_params.include?(method_name.to_sym)
18
+ value = @original_params[method_name.to_sym]
19
+ if value.is_a?(Hash)
20
+ define_anonymous_class(method_name, value)
21
+ else
22
+ Attribute.new(self, method_name).value = value
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def respond_to?(method_name, include_private = false)
29
+ if strict_enforcement?
30
+ super
31
+ else
32
+ @original_params.include?(method_name.to_sym) || super
33
+ end
34
+ end
35
+
36
+ def define_anonymous_class(name, hash)
37
+ klass_name = name.to_s.split('_').collect(&:capitalize).join
38
+ anonymous_klass = Class.new(Params).tap do |klass|
39
+ if self.class.const_defined?(klass_name)
40
+ begin
41
+ self.class.send(:remove_const, klass_name)
42
+ rescue NameError
43
+ end
44
+ end
45
+ self.class.const_set(klass_name, klass)
46
+ end
47
+ anonymous_klass.allow_undefined_params
48
+ anonymous_klass.new(hash)
49
+ end
50
+
51
+ def strict_enforcement?
52
+ self.class.strict_enforcement
53
+ end
54
+ end
55
+
56
+ module ClassMethods
57
+ attr_accessor :strict_enforcement
58
+
59
+ def strict
60
+ @strict_enforcement = true
61
+ end
62
+
63
+ def allow_undefined_params
64
+ @strict_enforcement = false
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,41 @@
1
+ require "active_model"
2
+
3
+ module SimpleParams
4
+ module Validations
5
+ extend ActiveModel::Validations
6
+
7
+ def valid?(context = nil)
8
+ current_context, self.validation_context = validation_context, context
9
+ errors.clear
10
+ run_validations!
11
+
12
+ # Make sure that nested classes are also valid
13
+ nested_classes_valid? && errors.empty?
14
+ ensure
15
+ self.validation_context = current_context
16
+ end
17
+
18
+ def validate!
19
+ unless valid?
20
+ raise SimpleParamsError, self.errors.to_hash.to_s
21
+ end
22
+ end
23
+
24
+ private
25
+ def nested_classes_valid?
26
+ nested_classes.map do |key, array|
27
+ nested_class_valid?(send("#{key}") )
28
+ end.all?
29
+ end
30
+
31
+ def nested_class_valid?(nested_class)
32
+ if nested_class.is_a?(Array)
33
+ # Have to map? & THEN all?, or else it won't
34
+ # necessarily call valid? on every object
35
+ nested_class.map(&:valid?).all?
36
+ else
37
+ nested_class.valid?
38
+ end
39
+ end
40
+ end
41
+ end