acts_as_sanitizable 0.3.1 → 0.4.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/README.md +52 -7
- data/VERSION +1 -1
- data/acts_as_sanitizable.gemspec +3 -3
- data/lib/sanitizable/attribute_sanitizer.rb +9 -2
- data/lib/sanitizable/macro.rb +21 -15
- data/lib/sanitizable/model.rb +12 -13
- data/spec/models/sanitizable_spec.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e4317192c5b23b320ebbce26cf6e9ba1962a66e
|
4
|
+
data.tar.gz: 3b676779bf3852f8a05d9e178396497dd17fb779
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce11693621154504f735c5ab69cd64fa03954e2bf003a5e9dbfbeb1efda2e55b9bfcccf30851afd3bf3814ce6082da86f7e4dda41f710566fac4576cabdf0289
|
7
|
+
data.tar.gz: 1f42baef78fa388c8f0925ede8bdeac70b005b2d71856a8318bc22bc16767ab031e45f5588e34574237c4598631a8182638b767738bd7e3bec0732e2db8b1b73
|
data/README.md
CHANGED
@@ -16,19 +16,64 @@ Download and install by running:
|
|
16
16
|
bundle install
|
17
17
|
```
|
18
18
|
|
19
|
-
|
19
|
+
## Usage
|
20
20
|
|
21
|
-
|
21
|
+
Add the `sanitizes` method to your model to perform sanitization on specific attributes. You can define what type of sanitization you want to do by specifing a `:with` option or a block.
|
22
|
+
|
23
|
+
```ruby
|
22
24
|
class User < ActiveRecord::Base
|
23
|
-
sanitizes :
|
24
|
-
sanitizes :
|
25
|
-
sanitizes :
|
26
|
-
|
25
|
+
sanitizes :first_name, :last_name, with: :strip
|
26
|
+
sanitizes :email, with: [:strip, :downcase]
|
27
|
+
sanitizes :biography, with: ->(biography) { biography.squish }
|
28
|
+
sanitizes :username do |username|
|
29
|
+
# strip leading "@" characters as used in Twitter usernames
|
30
|
+
username.strip.downcase.sub(/\A@/, '')
|
27
31
|
end
|
28
|
-
sanitizes :content, with: ->(content) { content.squish.downcase }
|
29
32
|
end
|
30
33
|
```
|
31
34
|
|
35
|
+
The `sanitizes` method is aliased as `acts_as_sanitizable`.
|
36
|
+
|
37
|
+
Sanitization is performed `before_validation` so the sanitized content will only be visible after calling the `valid?` or `save` methods on your instance of the model.
|
38
|
+
|
39
|
+
### Contexts
|
40
|
+
|
41
|
+
You can define when sanitization should be performed via `:on`. If no `:on` parameter is specified acts_as_sanitizable will sanitize on both, create and update.
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
class User < ActiveRecord::Base
|
45
|
+
sanitizes :first_name, with: :strip, on: :create
|
46
|
+
sanitizes :last_name, with: :strip, on: :update
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
### Inheritance
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
class User < ActiveRecord::Base
|
54
|
+
sanitizes :first_name, :last_name, with: :strip
|
55
|
+
sanitizes :email, with: [:strip, :downcase], on: :create
|
56
|
+
end
|
57
|
+
```
|
58
|
+
|
59
|
+
If you wish to not sanitize specific attributes on an inherited model you can call `skip_sanitization_on`. When you have been using a context in the sanitizer definition be sure to specify the same one when using `skip_sanitization_on`.
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
class Admin < User
|
63
|
+
skip_sanitization_on :first_name
|
64
|
+
skip_sanitization_on :email, on: :create
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
### Reflection
|
69
|
+
|
70
|
+
You can return a list of all sanitized attributes by calling:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
User.sanitizable_attributes # => [#<Sanitizable::AttributeSanitizer name: :first_name, ...>, ...]
|
74
|
+
|
75
|
+
User.sanitizable_attribute_names # => [:first_name, :last_name, ...]
|
76
|
+
```
|
32
77
|
|
33
78
|
## Contributing to acts_as_sanitizable
|
34
79
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/acts_as_sanitizable.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: acts_as_sanitizable 0.
|
5
|
+
# stub: acts_as_sanitizable 0.4.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "acts_as_sanitizable"
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.4.0"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Christoph Chilian"]
|
14
|
-
s.date = "2014-04-
|
14
|
+
s.date = "2014-04-22"
|
15
15
|
s.description = "Sanitizable concern to sanitize attributes the way you like"
|
16
16
|
s.email = "christoph@chilian.de"
|
17
17
|
s.extra_rdoc_files = [
|
@@ -1,15 +1,22 @@
|
|
1
1
|
module Sanitizable
|
2
2
|
class AttributeSanitizer
|
3
|
-
attr_reader :name, :sanitizers, :context
|
3
|
+
attr_reader :name, :sanitizers, :sanitizer_procs, :context
|
4
4
|
|
5
5
|
def initialize(name, options = {})
|
6
6
|
@name = name
|
7
|
-
@sanitizers = Array(options[:with])
|
7
|
+
@sanitizers = Array(options[:with])
|
8
|
+
@sanitizer_procs = @sanitizers.map(&:to_proc)
|
8
9
|
@context = options[:on]
|
9
10
|
end
|
10
11
|
|
11
12
|
def inspect
|
12
13
|
"#<#{self.class.name} name: #{name.inspect}, sanitizers: #{sanitizers.inspect}, context: #{context.inspect}>"
|
13
14
|
end
|
15
|
+
|
16
|
+
def sanitize(value)
|
17
|
+
@sanitizer_procs.inject(value) do |prev_value, sanitizer_proc|
|
18
|
+
sanitizer_proc.call(prev_value)
|
19
|
+
end
|
20
|
+
end
|
14
21
|
end
|
15
22
|
end
|
data/lib/sanitizable/macro.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
|
-
require 'active_support/concern'
|
2
|
-
|
3
1
|
module Sanitizable
|
4
2
|
module Macro
|
5
3
|
# Defines one or multiple columns that should be sanitized. The method used
|
6
|
-
# for sanitizing can be defined via the :
|
4
|
+
# for sanitizing can be defined via the :with key and can either contain the name
|
7
5
|
# of any method that is implemented on the particular class or a custom Proc.
|
8
6
|
# Additionally, an Array of Symbols or Procs can be speficied. Alternatively a block
|
9
7
|
# can be supplied as sanitizer.
|
@@ -12,43 +10,51 @@ module Sanitizable
|
|
12
10
|
#
|
13
11
|
# === Example:
|
14
12
|
# class User < ActiveRecord::Base
|
15
|
-
# sanitizes :
|
16
|
-
# sanitizes :
|
17
|
-
# sanitizes :
|
18
|
-
#
|
13
|
+
# sanitizes :first_name, :last_name, with: :strip
|
14
|
+
# sanitizes :email, with: [:strip, :downcase]
|
15
|
+
# sanitizes :biography, with: ->(biography) { biography.squish }
|
16
|
+
# sanitizes :username do |username|
|
17
|
+
# # strip leading "@" characters as used in Twitter usernames
|
18
|
+
# username.strip.downcase.sub(/\A@/, '')
|
19
19
|
# end
|
20
|
-
# sanitizes :content, with: ->(content) { content.squish.downcase }
|
21
20
|
# end
|
22
21
|
def sanitizes(*attribute_names, &block)
|
23
22
|
include Model unless self.include?(Model)
|
24
23
|
|
25
24
|
options = attribute_names.extract_options!.assert_valid_keys(:with, :on)
|
26
25
|
options[:with] = block || options[:with]
|
27
|
-
raise ArgumentError, "#{self.name}#sanitizes must define a :with option or have block" unless options[:with]
|
26
|
+
raise ArgumentError, "#{self.name}#sanitizes must define a :with option or have a block" unless options[:with]
|
28
27
|
raise ArgumentError, "#{self.name}#sanitizes must define at least one attribute" if attribute_names.empty?
|
29
28
|
|
30
|
-
|
31
|
-
@sanitizable_attributes += attribute_names.map do |attribute_name|
|
29
|
+
self.sanitizable_attributes += attribute_names.map do |attribute_name|
|
32
30
|
AttributeSanitizer.new(attribute_name.to_s, options.dup)
|
33
31
|
end
|
34
|
-
|
32
|
+
self.sanitizable_attributes.uniq!
|
35
33
|
end
|
36
34
|
|
37
35
|
def acts_as_sanitizable(*attribute_names, &block)
|
38
36
|
sanitizes(*attribute_names, &block)
|
39
37
|
end
|
40
38
|
|
41
|
-
def
|
39
|
+
def acts_as_sanitizable_on(*attribute_names, &block)
|
40
|
+
sanitizes(*attribute_names, &block)
|
41
|
+
end
|
42
|
+
|
43
|
+
def skip_sanitization_of(*attribute_names)
|
42
44
|
if self.include?(Model)
|
43
45
|
options = attribute_names.extract_options!.assert_valid_keys(:on)
|
44
46
|
attribute_names = attribute_names.map(&:to_s)
|
45
47
|
context = options[:on]
|
46
|
-
|
48
|
+
sanitizable_attributes.delete_if do |attribute|
|
47
49
|
attribute_names.include?(attribute.name) and context == attribute.context
|
48
50
|
end
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
54
|
+
def skip_sanitization_on(*attribute_names)
|
55
|
+
skip_sanitization_of(*attribute_names)
|
56
|
+
end
|
57
|
+
|
52
58
|
def reset_sanitization
|
53
59
|
sanitizable_attributes.clear if self.include?(Model)
|
54
60
|
end
|
@@ -57,4 +63,4 @@ end
|
|
57
63
|
|
58
64
|
ActiveSupport.on_load(:active_record) do
|
59
65
|
ActiveRecord::Base.extend(Sanitizable::Macro)
|
60
|
-
end
|
66
|
+
end
|
data/lib/sanitizable/model.rb
CHANGED
@@ -1,20 +1,17 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
1
3
|
module Sanitizable
|
2
4
|
module Model
|
3
5
|
extend ActiveSupport::Concern
|
4
6
|
|
5
7
|
included do
|
8
|
+
class_attribute :sanitizable_attributes
|
9
|
+
self.sanitizable_attributes = []
|
10
|
+
|
6
11
|
before_validation :_sanitize_attributes
|
7
12
|
end
|
8
13
|
|
9
14
|
module ClassMethods
|
10
|
-
def inherited(base)
|
11
|
-
base.instance_variable_set(:@sanitizable_attributes, sanitizable_attributes.dup)
|
12
|
-
end
|
13
|
-
|
14
|
-
def sanitizable_attributes
|
15
|
-
@sanitizable_attributes ||= []
|
16
|
-
end
|
17
|
-
|
18
15
|
def sanitizable_attribute_names
|
19
16
|
sanitizable_attributes.collect(&:name).uniq.freeze
|
20
17
|
end
|
@@ -22,18 +19,20 @@ module Sanitizable
|
|
22
19
|
|
23
20
|
private
|
24
21
|
def _sanitize_attributes
|
25
|
-
context = new_record? ? :create : :update
|
26
22
|
self.class.sanitizable_attributes.each do |attribute|
|
27
|
-
if
|
23
|
+
if _sanitizable_in_context?(attribute.context)
|
28
24
|
original_value = self.send(attribute.name)
|
29
25
|
unless original_value.nil?
|
30
|
-
sanitized_value = attribute.
|
31
|
-
sanitizer_proc.call(prev_value)
|
32
|
-
end
|
26
|
+
sanitized_value = attribute.sanitize(original_value)
|
33
27
|
self.send("#{attribute.name}=", sanitized_value)
|
34
28
|
end
|
35
29
|
end
|
36
30
|
end
|
37
31
|
end
|
32
|
+
|
33
|
+
def _sanitizable_in_context?(context)
|
34
|
+
actual_context = new_record? ? :create : :update
|
35
|
+
context.nil? or (!context.nil? and context == actual_context)
|
36
|
+
end
|
38
37
|
end
|
39
38
|
end
|
@@ -21,7 +21,7 @@ describe Sanitizable do
|
|
21
21
|
it 'must be defined through :with or a block' do
|
22
22
|
expect {
|
23
23
|
User.sanitizes :first_name
|
24
|
-
}.to raise_error ArgumentError, 'User#sanitizes must define a :with option or have block'
|
24
|
+
}.to raise_error ArgumentError, 'User#sanitizes must define a :with option or have a block'
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'prefers block sanitizer over :with sanitizer' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_sanitizable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christoph Chilian
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-04-
|
11
|
+
date: 2014-04-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|