custom_fields 2.5.0 → 2.8.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,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a2d0f1cab5f7e3c7153f38202b4a77b8f466e04d
4
- data.tar.gz: eb6e1f46553f3a565939c16ecd15ae5ab6613d87
3
+ metadata.gz: 88e261b104e415fe6b64700e80b1f69e8e2448b7
4
+ data.tar.gz: 5dd052af6575958e56d77eac8ea79186833503fb
5
5
  SHA512:
6
- metadata.gz: bef098cd02a0e26ef093432d3dd3233d361b8e4cec1d32c88f94928c7644e9653974e8789bbed6609f5e550c54225997de3130da7f16605fdb607cce56efd3a6
7
- data.tar.gz: dd15ddff7b81739385881fbd93e3897ca511db4a6fce1b8aa1eb1df3770848280077eb176e041e0e2c54006d04d724075d685db00c58ea1b7c7fb92752028896
6
+ metadata.gz: 3f4d7290c9222c0ed84170942c6143a27a469aca8068bc556caeb5fb9c8f9967acb9b7cfcb04796c5785e9078ccad8ba92d7aab7cd9715319ae33912cca20fb1
7
+ data.tar.gz: 3576971a4a8f027036499520b95002ca27c7520db9418a7862aba0013b69d8bd8e61d86b21151a7dad820d37252cde870e075ef18babaa70c0d076390371f716
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013-2015, Didier Lafforgue
1
+ Copyright (c) 2017, NoCoffee
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy of
4
4
  this software and associated documentation files (the "Software"), to deal in
@@ -15,4 +15,4 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
15
  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
16
  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
17
  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -93,7 +93,7 @@ Feel free to contact me at did at locomotivecms dot com.
93
93
  License
94
94
  -------
95
95
 
96
- Copyright (c) 2013-2016 NoCoffee, released under the [MIT License (MIT)], see [LICENSE].
96
+ Copyright (c) 2017 NoCoffee, released under the [MIT License (MIT)], see [LICENSE].
97
97
 
98
98
  [CustomFields]: https://github.com/locomotivecms/custom_fields "Custom fields extension for Mongoid."
99
99
  [Gemnasium]: https://gemnasium.com/locomotivecms/custom_fields "CustomFields at Gemnasium"
@@ -35,7 +35,7 @@ module Mongoid #:nodoc
35
35
  end
36
36
 
37
37
  def self.fallbacks?
38
- !self.instance.fallbacks.blank? || ::I18n.respond_to?(:fallbacks)
38
+ !self.instance.fallbacks.blank? || (::I18n.respond_to?(:fallbacks) && !::I18n.fallbacks.blank?)
39
39
  end
40
40
 
41
41
  def self.clear_fallbacks
@@ -6,7 +6,7 @@ module CustomFields
6
6
  include ::Mongoid::Timestamps
7
7
 
8
8
  AVAILABLE_TYPES = %w(default string text email date date_time boolean file select float integer
9
- money tags color relationship_default belongs_to has_many many_to_many)
9
+ money tags color relationship_default belongs_to has_many many_to_many password json)
10
10
 
11
11
  ## types ##
12
12
  AVAILABLE_TYPES.each do |type|
@@ -22,6 +22,7 @@ module CustomFields
22
22
  field :required, type: ::Boolean, default: false
23
23
  field :unique, type: ::Boolean, default: false
24
24
  field :localized, type: ::Boolean, default: false
25
+ field :default
25
26
 
26
27
  ## validations ##
27
28
  validates_presence_of :label, :type
@@ -67,7 +68,8 @@ module CustomFields
67
68
  'type' => self.type,
68
69
  'required' => self.required?,
69
70
  'unique' => self.unique?,
70
- 'localized' => self.localized? }.merge(custom_to_recipe)
71
+ 'localized' => self.localized?,
72
+ 'default' => self.default }.merge(custom_to_recipe)
71
73
  end
72
74
 
73
75
  def as_json(options = {})
@@ -8,7 +8,8 @@ module CustomFields
8
8
 
9
9
  ## types ##
10
10
  %w(default string text email date date_time boolean file select
11
- float integer money color belongs_to has_many many_to_many tags).each do |type|
11
+ float integer money color belongs_to has_many many_to_many
12
+ tags password json).each do |type|
12
13
  include "CustomFields::Types::#{type.camelize}::Target".constantize
13
14
  end
14
15
 
@@ -18,7 +18,7 @@ module CustomFields
18
18
  # @param [ Hash ] rule It contains the name of the field.
19
19
  #
20
20
  def apply_boolean_custom_field(klass, rule)
21
- klass.field rule['name'], type: ::Boolean, localize: rule['localized'] || false, default: false
21
+ klass.field rule['name'], type: ::Boolean, localize: rule['localized'] || false, default: rule['default'].nil? ? false : rule['default']
22
22
  end
23
23
 
24
24
  # Build a hash storing the boolean value (true / false) for
@@ -52,4 +52,4 @@ module CustomFields
52
52
 
53
53
  end
54
54
 
55
- end
55
+ end
@@ -47,7 +47,7 @@ module CustomFields
47
47
  # @param [ Hash ] rule It contains the name of the field and if it is required or not
48
48
  #
49
49
  def apply_custom_field(klass, rule)
50
- klass.field rule['name'], localize: rule['localized'] || false
50
+ klass.field rule['name'], localize: rule['localized'] || false, default: rule['default']
51
51
 
52
52
  klass.validates_presence_of rule['name'] if rule['required']
53
53
  klass.validates_uniqueness_of rule['name'], scope: :_type if rule['unique']
@@ -100,4 +100,4 @@ module CustomFields
100
100
 
101
101
  end
102
102
 
103
- end
103
+ end
@@ -20,7 +20,7 @@ module CustomFields
20
20
  def apply_email_custom_field(klass, rule)
21
21
  name = rule['name']
22
22
 
23
- klass.field name, type: ::String, localize: rule['localized'] || false
23
+ klass.field name, type: ::String, localize: rule['localized'] || false, default: rule['default']
24
24
  klass.validates_presence_of name if rule['required']
25
25
  klass.validates_format_of name, with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/, allow_blank: !rule['required']
26
26
  klass.validates_uniqueness_of rule['name'], scope: :_type if rule['unique']
@@ -57,4 +57,4 @@ module CustomFields
57
57
 
58
58
  end
59
59
 
60
- end
60
+ end
@@ -21,6 +21,7 @@ module CustomFields
21
21
  name = rule['name']
22
22
 
23
23
  klass.mount_uploader name, FileUploader
24
+ klass.field :"#{name}_size", type: ::Hash, default: {}
24
25
 
25
26
  if rule['localized'] == true
26
27
  klass.replace_field name, ::String, true
@@ -83,6 +84,21 @@ module CustomFields
83
84
  end
84
85
 
85
86
  class FileUploader < ::CarrierWave::Uploader::Base
87
+
88
+ process :set_size_in_model
89
+
90
+ def set_size_in_model
91
+ size_field_name = :"#{mounted_as}_size"
92
+
93
+ if model.respond_to?(size_field_name)
94
+ is_localized = model.fields[mounted_as.to_s].options[:localize]
95
+ key = is_localized ? ::Mongoid::Fields::I18n.locale.to_s : 'default'
96
+ values = model.send(size_field_name)
97
+
98
+ values[key] = file.size
99
+ end
100
+ end
101
+
86
102
  end
87
103
 
88
104
  end
@@ -15,7 +15,7 @@ module CustomFields
15
15
  # @param [ Hash ] rule It contains the name of the field and if it is required or not
16
16
  #
17
17
  def apply_float_custom_field(klass, rule)
18
- klass.field rule['name'], type: ::Float, localize: rule['localized'] || false
18
+ klass.field rule['name'], type: ::Float, localize: rule['localized'] || false, default: rule['default']
19
19
  klass.validates_presence_of rule['name'] if rule['required']
20
20
  klass.validates rule['name'], numericality: true, if: ->(x){ rule['required'] }
21
21
  end
@@ -17,7 +17,7 @@ module CustomFields
17
17
  def apply_integer_custom_field(klass, rule)
18
18
  name = rule['name']
19
19
 
20
- klass.field name, type: ::Integer, localize: rule['localized'] || false
20
+ klass.field name, type: ::Integer, localize: rule['localized'] || false, default: rule['default']
21
21
  klass.validates_presence_of name if rule['required']
22
22
  klass.validates name, numericality: { only_integer: true }, if: ->(x){ rule['required'] }
23
23
  end
@@ -0,0 +1,93 @@
1
+ module CustomFields
2
+
3
+ module Types
4
+
5
+ module Json
6
+
7
+ module Field; end
8
+
9
+ module Target
10
+
11
+ extend ActiveSupport::Concern
12
+
13
+ module ClassMethods
14
+
15
+ # Adds a json field
16
+ #
17
+ # @param [ Class ] klass The class to modify
18
+ # @param [ Hash ] rule It contains the name of the field and if it is required or not
19
+ #
20
+ def apply_json_custom_field(klass, rule)
21
+ name = rule['name']
22
+
23
+ klass.field name, type: Hash, localize: rule['localized'] || false
24
+ klass.validates_presence_of name if rule['required']
25
+
26
+ klass.before_validation { |record| record.send(:add_json_parsing_error, name) }
27
+
28
+ klass.send(:define_method, :"#{name}=") do |json|
29
+ super(decode_json(name, json))
30
+ end
31
+ end
32
+
33
+ # Build a hash storing the formatted value for
34
+ # a JSON custom field of an instance.
35
+ #
36
+ # @param [ Object ] instance An instance of the class enhanced by the custom_fields
37
+ # @param [ String ] name The name of the json custom field
38
+ #
39
+ # @return [ Hash ] field name => JSON
40
+ #
41
+ def json_attribute_get(instance, name)
42
+ self.default_attribute_get(instance, name)
43
+ end
44
+
45
+ # Set the value for the instance and the date field specified by
46
+ # the 2 params.
47
+ #
48
+ # @param [ Object ] instance An instance of the class enhanced by the custom_fields
49
+ # @param [ String ] name The name of the date custom field
50
+ # @param [ Hash ] attributes The attributes used to fetch the values
51
+ #
52
+ def json_attribute_set(instance, name, attributes)
53
+ self.default_attribute_set(instance, name, attributes)
54
+ end
55
+
56
+ end
57
+
58
+ protected
59
+
60
+ def decode_json(name, json)
61
+ begin
62
+ value = json.respond_to?(:to_str) && !json.blank? ? ActiveSupport::JSON.decode(URI.unescape(json)) : json
63
+ value = nil if json.blank?
64
+
65
+ # Only hashes are accepted
66
+ if value && !value.is_a?(Hash)
67
+ raise ActiveSupport::JSON.parse_error.new('Only a Hash object is accepted')
68
+ end
69
+
70
+ instance_variable_set(:"@#{name}_json_parsing_error", nil)
71
+ value
72
+ rescue ActiveSupport::JSON.parse_error
73
+ instance_variable_set(:"@#{name}_json_parsing_error", $!.message)
74
+ nil
75
+ end
76
+ end
77
+
78
+ def add_json_parsing_error(name)
79
+ error = instance_variable_get(:"@#{name}_json_parsing_error")
80
+
81
+ if error
82
+ msg = "Invalid #{name}: \"#{error}\". Check it out on http://jsonlint.com"
83
+ self.errors.add(name, msg)
84
+ end
85
+ end
86
+
87
+ end
88
+
89
+ end
90
+
91
+ end
92
+
93
+ end
@@ -81,7 +81,7 @@ module CustomFields
81
81
  klass.send(:define_method, names[:default_currency]) { rule['default_currency'] }
82
82
 
83
83
  # validations
84
- klass.validate { _check_money(names) } if rule['required']
84
+ klass.validate { _check_money(names) } if rule['required']
85
85
  klass.validates_presence_of(names[:cents_field], names[:currency_field]) if rule['required']
86
86
  klass.validates_numericality_of names[:cents_field], only_integer: true, if: names[:cents_field]
87
87
 
@@ -0,0 +1,79 @@
1
+ module CustomFields
2
+ module Types
3
+ module Password
4
+
5
+ module Field
6
+
7
+ MIN_PASSWORD_LENGTH = 6
8
+
9
+ end
10
+
11
+ module Target
12
+ extend ActiveSupport::Concern
13
+
14
+ module ClassMethods
15
+
16
+ # Add a password field
17
+ #
18
+ # @param [ Class ] klass The class to modify
19
+ # @param [ Hash ] rule It contains the name of the field and if it is required or not
20
+ #
21
+ def apply_password_custom_field(klass, rule)
22
+ name = rule['name']
23
+
24
+ klass.field :"#{name}_hash"
25
+
26
+ klass.send(:define_method, name.to_sym) { '' }
27
+ klass.send(:define_method, :"#{name}=") { |value| _encrypt_password(name, value) }
28
+
29
+ klass.validate { _check_password(name) }
30
+ end
31
+
32
+ # Build a hash storing the raw value for
33
+ # a string custom field of an instance.
34
+ #
35
+ # @param [ Object ] instance An instance of the class enhanced by the custom_fields
36
+ # @param [ String ] name The name of the string custom field
37
+ #
38
+ # @return [ Hash ] field name => raw value
39
+ #
40
+ def password_attribute_get(instance, name)
41
+ {}
42
+ end
43
+
44
+ # Set the value for the instance and the string field specified by
45
+ # the 2 params.
46
+ #
47
+ # @param [ Object ] instance An instance of the class enhanced by the custom_fields
48
+ # @param [ String ] name The name of the string custom field
49
+ # @param [ Hash ] attributes The attributes used to fetch the values
50
+ #
51
+ def password_attribute_set(instance, name, attributes)
52
+ instance._encrypt_password(name, attributes[name])
53
+ end
54
+
55
+ end # ClassMethods
56
+
57
+ def _encrypt_password(name, new_password)
58
+ return if new_password.blank?
59
+
60
+ self.instance_variable_set(:"@#{name}", new_password)
61
+
62
+ self.send(:"#{name}_hash=", BCrypt::Password.create(new_password))
63
+ end
64
+
65
+ def _check_password(name)
66
+ new_password = self.instance_variable_get(:"@#{name}")
67
+
68
+ return if new_password.blank?
69
+
70
+ if new_password.size < CustomFields::Types::Password::Field::MIN_PASSWORD_LENGTH
71
+ self.errors.add(name, :too_short, count: 6)
72
+ end
73
+ end
74
+
75
+ end # Target
76
+
77
+ end # Password
78
+ end # Types
79
+ end # CustomFields
@@ -67,7 +67,7 @@ module CustomFields
67
67
  def apply_select_custom_field(klass, rule)
68
68
  name, base_collection_name = rule['name'], "#{rule['name']}_options".to_sym
69
69
 
70
- klass.field :"#{name}_id", type: BSON::ObjectId, localize: rule['localized'] || false
70
+ klass.field :"#{name}_id", type: BSON::ObjectId, localize: rule['localized'] || false, default: ->{ _set_select_option(name, rule['default']) }
71
71
 
72
72
  klass.cattr_accessor "_raw_#{base_collection_name}"
73
73
  klass.send :"_raw_#{base_collection_name}=", rule['select_options'].sort { |a, b| a['position'] <=> b['position'] }
@@ -164,10 +164,12 @@ module CustomFields
164
164
 
165
165
  name = if !option['name'].respond_to?(:merge)
166
166
  option['name']
167
+ elsif option['name'].has_key?(locale)
168
+ option['name'][locale.to_s]
167
169
  elsif Mongoid::Fields::I18n.fallbacks?
168
170
  option['name'][Mongoid::Fields::I18n.fallbacks[locale.to_sym].map(&:to_s).find { |loc| !option['name'][loc].nil? }]
169
171
  else
170
- option['name'][locale.to_s]
172
+ nil
171
173
  end
172
174
 
173
175
  { '_id' => option['_id'], 'name' => name }
@@ -1,5 +1,5 @@
1
1
  module CustomFields #:nodoc
2
2
 
3
- VERSION = '2.5.0'
3
+ VERSION = '2.8.0'
4
4
 
5
5
  end
data/lib/custom_fields.rb CHANGED
@@ -3,6 +3,7 @@ $:.unshift File.expand_path(File.dirname(__FILE__))
3
3
  require 'active_support'
4
4
  require 'carrierwave/mongoid'
5
5
  require 'monetize'
6
+ require 'bcrypt'
6
7
 
7
8
  Money.use_i18n = false
8
9
 
@@ -55,6 +56,8 @@ end
55
56
  types/has_many
56
57
  types/many_to_many
57
58
  types/tags
59
+ types/password
60
+ types/json
58
61
  field
59
62
  source
60
63
  target_helpers
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: custom_fields
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 2.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Didier Lafforgue
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-12 00:00:00.000000000 Z
11
+ date: 2017-03-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mongoid
@@ -16,56 +16,70 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 5.0.2
19
+ version: 5.2.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 5.0.2
26
+ version: 5.2.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: carrierwave-mongoid
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.8.1
33
+ version: 0.10.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.8.1
40
+ version: 0.10.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: activesupport
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 4.2.5
47
+ version: 4.2.7
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 4.2.5
54
+ version: 4.2.7
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: monetize
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 1.3.1
61
+ version: 1.6.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 1.3.1
68
+ version: 1.6.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: bcrypt
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 3.1.11
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 3.1.11
69
83
  description: Manage custom fields to a Mongoid document or a collection. This module
70
84
  is one of the core features we implemented in our custom CMS, named LocomotiveCMS.
71
85
  email: didier@nocoffee.fr
@@ -111,8 +125,10 @@ files:
111
125
  - lib/custom_fields/types/float.rb
112
126
  - lib/custom_fields/types/has_many.rb
113
127
  - lib/custom_fields/types/integer.rb
128
+ - lib/custom_fields/types/json.rb
114
129
  - lib/custom_fields/types/many_to_many.rb
115
130
  - lib/custom_fields/types/money.rb
131
+ - lib/custom_fields/types/password.rb
116
132
  - lib/custom_fields/types/relationship_default.rb
117
133
  - lib/custom_fields/types/select.rb
118
134
  - lib/custom_fields/types/string.rb
@@ -139,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
155
  version: '2.4'
140
156
  requirements: []
141
157
  rubyforge_project:
142
- rubygems_version: 2.4.5.1
158
+ rubygems_version: 2.5.2
143
159
  signing_key:
144
160
  specification_version: 4
145
161
  summary: Custom fields extension for Mongoid.