activecleaner 0.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.
- data/LICENSE +21 -0
- data/README.md +96 -0
- data/lib/active_cleaner/base_cleaner.rb +48 -0
- data/lib/active_cleaner/helper_methods.rb +24 -0
- data/lib/active_cleaner/markdown_cleaner.rb +32 -0
- data/lib/active_cleaner/string_cleaner.rb +18 -0
- data/lib/active_cleaner/text_cleaner.rb +30 -0
- data/lib/active_cleaner/version.rb +8 -0
- data/lib/active_cleaner.rb +64 -0
- data/lib/activecleaner.rb +3 -0
- data/spec/cases/inherit_spec.rb +122 -0
- data/spec/cases/nilify_spec.rb +101 -0
- data/spec/cases/simple_spec.rb +101 -0
- data/spec/lib/active_cleaner/markdown_cleaner_spec.rb +67 -0
- data/spec/lib/active_cleaner/string_cleaner_spec.rb +45 -0
- data/spec/lib/active_cleaner/text_cleaner_spec.rb +56 -0
- data/spec/lib/active_cleaner_spec.rb +4 -0
- data/spec/spec_helper.rb +9 -0
- metadata +122 -0
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) Maxime Garcia
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
data/README.md
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
# ActiveCleaner
|
2
|
+
|
3
|
+
`ActiveCleaner` is a set of helpers that helps you in cleaning user-typed content in your ActiveModel depending models (ActiveRecord, Mongoid...)
|
4
|
+
|
5
|
+
Extra spaces mean extra storage. And it could ruin your indexes and your sortings.
|
6
|
+
|
7
|
+
Tired of doing everywhere:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
before_validation :clean_title
|
11
|
+
|
12
|
+
def clean_title
|
13
|
+
unless title.nil?
|
14
|
+
self.title = title.squish
|
15
|
+
end
|
16
|
+
self.title = nil if title.blank?
|
17
|
+
|
18
|
+
true
|
19
|
+
end
|
20
|
+
```
|
21
|
+
|
22
|
+
### Cleaners included
|
23
|
+
|
24
|
+
* `:string` (StringCleaner, the default one) : cleans all the space characters. It turns `" A \n \t title \t "` into `"A title"`.
|
25
|
+
* `:text` (TextCleaner) : like `:string`, but preserves new lines (with a max of 2 successive new lines). Usefull when the field is rendered with the `simple_format` Rails helper.
|
26
|
+
* `:markdown` (MarkdownCleaner) : like `:text`, but preserves spaces in the begining of lines (the indentation). Usefull for... markdown!
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
## Installation
|
31
|
+
|
32
|
+
Add the gem to your Gemfile:
|
33
|
+
|
34
|
+
gem 'activecleaner'
|
35
|
+
|
36
|
+
Or install with RubyGems:
|
37
|
+
|
38
|
+
$ gem install activecleaner
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
## Usage
|
43
|
+
|
44
|
+
### Basic usage
|
45
|
+
|
46
|
+
Add `include ActiveCleaner` in your model and also do:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
clean :field_1, :field_2 ... :field_n, options_1: :value, options_2: :value
|
50
|
+
```
|
51
|
+
|
52
|
+
### Options
|
53
|
+
|
54
|
+
* `:as` (default is `:string`) : the symbol name of the cleaner.
|
55
|
+
* `:nilify` (default is `false`) : set to `nil` when the field was or is cleaned to `""`.
|
56
|
+
|
57
|
+
### Example
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
class Post
|
61
|
+
include Mongoid::Document
|
62
|
+
include ActiveCleaner
|
63
|
+
|
64
|
+
field :title
|
65
|
+
field :subtitle
|
66
|
+
clean :title, :subtitle, nilify: true
|
67
|
+
|
68
|
+
field :body
|
69
|
+
clean :body, as: :text, nilify: true
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
## Contributing
|
74
|
+
|
75
|
+
Contributions and bug reports are welcome.
|
76
|
+
|
77
|
+
Clone the repository and run `bundle install` to setup the development environment.
|
78
|
+
|
79
|
+
Provide a case spec according to your changes/needs, taking example on existing ones (in `spec/cases`).
|
80
|
+
|
81
|
+
To run the specs:
|
82
|
+
|
83
|
+
bundle exec rspec
|
84
|
+
|
85
|
+
You can also use `guard` to run the specs during dev.
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
## Credits
|
90
|
+
|
91
|
+
* Maxime Garcia [emaxime.com](http://emaxime.com) [@maximegarcia](http://twitter.com/maximegarcia)
|
92
|
+
|
93
|
+
|
94
|
+
[License](https://github.com/maximeg/activecleaner/blob/master/LCENSE)
|
95
|
+
\- [Report a bug](https://github.com/maximeg/activecleaner/issues)
|
96
|
+
[](http://travis-ci.org/maximeg/activecleaner)
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module ActiveCleaner
|
4
|
+
class BaseCleaner
|
5
|
+
|
6
|
+
attr_reader :attr_name, :options
|
7
|
+
|
8
|
+
# Accepts options that will be made available through the +options+ reader.
|
9
|
+
def initialize(attr_name, options = {})
|
10
|
+
@attr_name = attr_name
|
11
|
+
@options = {
|
12
|
+
:nilify => false,
|
13
|
+
}.merge(options).freeze
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.kind
|
17
|
+
@kind ||= name.split('::').last.underscore.sub(/_cleaner$/, '').to_sym
|
18
|
+
end
|
19
|
+
|
20
|
+
def kind
|
21
|
+
self.class.kind
|
22
|
+
end
|
23
|
+
|
24
|
+
def clean(record)
|
25
|
+
value = record.read_attribute_for_cleaning(attr_name)
|
26
|
+
|
27
|
+
new_value = clean_value(value, record)
|
28
|
+
|
29
|
+
new_value = nil if @options[:nilify] && nilify_value?(new_value, record)
|
30
|
+
|
31
|
+
record.write_attribute_after_cleaning(attr_name, new_value) unless new_value == value
|
32
|
+
end
|
33
|
+
|
34
|
+
def clean_value(value, record=nil)
|
35
|
+
raise NotImplementedError, "Subclasses must implement a clean(value, record=nil) method."
|
36
|
+
end
|
37
|
+
|
38
|
+
# feel free to subclass for your custom cleaner
|
39
|
+
def nilify_value?(value, record=nil)
|
40
|
+
value == ""
|
41
|
+
end
|
42
|
+
|
43
|
+
def ==(other)
|
44
|
+
kind == other.kind && attr_name == other.attr_name && options == other.options
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module ActiveCleaner
|
4
|
+
module HelperMethods
|
5
|
+
|
6
|
+
def clean(*attr_names)
|
7
|
+
options = attr_names.extract_options!.symbolize_keys
|
8
|
+
attr_names.flatten!
|
9
|
+
|
10
|
+
options[:as] ||= :string
|
11
|
+
|
12
|
+
cleaner = "active_cleaner/#{options.delete(:as)}_cleaner".camelize.constantize
|
13
|
+
|
14
|
+
attr_names.each do |attr_name|
|
15
|
+
clean_with cleaner.new(attr_name, options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def clean_with(cleaner)
|
20
|
+
self._cleaners[cleaner.attr_name] << cleaner
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module ActiveCleaner
|
4
|
+
class MarkdownCleaner < BaseCleaner
|
5
|
+
|
6
|
+
def clean_value(old_value, record=nil)
|
7
|
+
unless old_value.nil?
|
8
|
+
value = old_value.dup
|
9
|
+
|
10
|
+
value.strip!
|
11
|
+
|
12
|
+
# clean the new lines mess among OS
|
13
|
+
value.gsub!(/\r\n|\r/, "\n")
|
14
|
+
|
15
|
+
# protect stuff to keep with a markup
|
16
|
+
value.gsub!(/\n/, "__NEW_LINE__")
|
17
|
+
value.gsub!(/(?<=__NEW_LINE__)\s+/) {|match| match.gsub(/\s/, "__SPACE__")}
|
18
|
+
|
19
|
+
value.gsub!(/\s+/, " ")
|
20
|
+
value.gsub!(/(__SPACE__|\s)*__NEW_LINE__\s*/, "__NEW_LINE__")
|
21
|
+
value.gsub!(/(__NEW_LINE__){3,}/, "__NEW_LINE____NEW_LINE__")
|
22
|
+
|
23
|
+
# reverse the safe markup
|
24
|
+
value.gsub!(/__NEW_LINE__/, "\n")
|
25
|
+
value.gsub!(/__SPACE__/, " ")
|
26
|
+
|
27
|
+
value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module ActiveCleaner
|
4
|
+
class StringCleaner < BaseCleaner
|
5
|
+
|
6
|
+
def clean_value(old_value, record=nil)
|
7
|
+
unless old_value.nil?
|
8
|
+
value = old_value.dup
|
9
|
+
|
10
|
+
value.strip!
|
11
|
+
value.gsub!(/\s+/, " ")
|
12
|
+
|
13
|
+
value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module ActiveCleaner
|
4
|
+
class TextCleaner < BaseCleaner
|
5
|
+
|
6
|
+
def clean_value(old_value, record=nil)
|
7
|
+
unless old_value.nil?
|
8
|
+
value = old_value.dup
|
9
|
+
|
10
|
+
value.strip!
|
11
|
+
|
12
|
+
# clean the new lines mess among OS
|
13
|
+
value.gsub!(/\r\n|\r/, "\n")
|
14
|
+
|
15
|
+
# protect stuff to keep with a markup
|
16
|
+
value.gsub!(/\n/, "__NEW_LINE__")
|
17
|
+
|
18
|
+
value.gsub!(/\s+/, " ")
|
19
|
+
value.gsub!(/ ?__NEW_LINE__ ?/, "__NEW_LINE__")
|
20
|
+
value.gsub!(/(__NEW_LINE__){3,}/, "__NEW_LINE____NEW_LINE__")
|
21
|
+
|
22
|
+
# reverse the safe markup
|
23
|
+
value.gsub!(/__NEW_LINE__/, "\n")
|
24
|
+
|
25
|
+
value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
#require 'active_support/rails'
|
5
|
+
require 'active_model'
|
6
|
+
|
7
|
+
require 'active_cleaner/helper_methods'
|
8
|
+
|
9
|
+
require 'active_cleaner/base_cleaner'
|
10
|
+
require 'active_cleaner/string_cleaner'
|
11
|
+
require 'active_cleaner/text_cleaner'
|
12
|
+
require 'active_cleaner/markdown_cleaner'
|
13
|
+
|
14
|
+
require 'active_cleaner/version'
|
15
|
+
|
16
|
+
module ActiveCleaner
|
17
|
+
extend ActiveSupport::Concern
|
18
|
+
|
19
|
+
included do
|
20
|
+
|
21
|
+
include ActiveModel::Validations
|
22
|
+
|
23
|
+
extend HelperMethods
|
24
|
+
include HelperMethods
|
25
|
+
|
26
|
+
define_callbacks :cleaning, :scope => :name
|
27
|
+
|
28
|
+
class_attribute :_cleaners
|
29
|
+
self._cleaners = Hash.new { |h,k| h[k] = [] }
|
30
|
+
|
31
|
+
set_callback :validate, :before, :run_cleaners!
|
32
|
+
|
33
|
+
end # included
|
34
|
+
|
35
|
+
|
36
|
+
module ClassMethods
|
37
|
+
|
38
|
+
def inherited(base) #:nodoc:
|
39
|
+
dup = _cleaners.dup
|
40
|
+
base._cleaners = dup.each { |k, v| dup[k] = v.dup }
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
end # ClassMethods
|
45
|
+
|
46
|
+
|
47
|
+
def run_cleaners!
|
48
|
+
self._cleaners.each do |attr_name, cleaners|
|
49
|
+
cleaners.each do |cleaner|
|
50
|
+
cleaner.clean(self)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
true
|
55
|
+
end
|
56
|
+
|
57
|
+
def read_attribute_for_cleaning(attr_name)
|
58
|
+
send(attr_name)
|
59
|
+
end
|
60
|
+
def write_attribute_after_cleaning(attr_name, value)
|
61
|
+
send(:"#{attr_name}=", value)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
#
|
5
|
+
# The case
|
6
|
+
#
|
7
|
+
# This is to demonstrate when we want to clean some simple fields
|
8
|
+
# in a common STI scenario.
|
9
|
+
#
|
10
|
+
class Ad
|
11
|
+
include ActiveCleaner
|
12
|
+
|
13
|
+
attr_accessor :title, :name
|
14
|
+
|
15
|
+
clean :title
|
16
|
+
clean :name, as: :string
|
17
|
+
end
|
18
|
+
|
19
|
+
class CarAd < Ad
|
20
|
+
attr_accessor :body
|
21
|
+
|
22
|
+
clean :body, as: :text
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# The specs
|
27
|
+
#
|
28
|
+
describe "Case: an ad and his inherited car ad" do
|
29
|
+
|
30
|
+
describe Ad, "._cleaners" do
|
31
|
+
|
32
|
+
subject { Ad._cleaners }
|
33
|
+
|
34
|
+
it { should have(2).fields_to_clean }
|
35
|
+
|
36
|
+
it "includes a StringCleaner for #title" do
|
37
|
+
subject[:title].first.should eq(ActiveCleaner::StringCleaner.new(:title))
|
38
|
+
end
|
39
|
+
|
40
|
+
it "includes a StringCleaner for #name" do
|
41
|
+
subject[:name].first.should eq(ActiveCleaner::StringCleaner.new(:name))
|
42
|
+
end
|
43
|
+
|
44
|
+
end # describe
|
45
|
+
|
46
|
+
describe CarAd, "._cleaners" do
|
47
|
+
|
48
|
+
subject { CarAd._cleaners }
|
49
|
+
|
50
|
+
it { should have(3).fields_to_clean }
|
51
|
+
|
52
|
+
it "includes a StringCleaner for #title" do
|
53
|
+
subject[:title].first.should eq(ActiveCleaner::StringCleaner.new(:title))
|
54
|
+
end
|
55
|
+
|
56
|
+
it "includes a StringCleaner for #name" do
|
57
|
+
subject[:name].first.should eq(ActiveCleaner::StringCleaner.new(:name))
|
58
|
+
end
|
59
|
+
|
60
|
+
it "includes a TextCleaner for #body" do
|
61
|
+
subject[:body].first.should eq(ActiveCleaner::TextCleaner.new(:body))
|
62
|
+
end
|
63
|
+
|
64
|
+
end # describe
|
65
|
+
|
66
|
+
context "considering a car ad" do
|
67
|
+
|
68
|
+
before do
|
69
|
+
@car_ad = CarAd.new
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#title, marked as to clean with no type" do
|
73
|
+
|
74
|
+
it "is untouched when legit" do
|
75
|
+
@car_ad.title = "A good title!"
|
76
|
+
@car_ad.valid?
|
77
|
+
@car_ad.title.should eq "A good title!"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "is cleaned as a string" do
|
81
|
+
@car_ad.title = " A \n good \t title! "
|
82
|
+
@car_ad.valid?
|
83
|
+
@car_ad.title.should eq "A good title!"
|
84
|
+
end
|
85
|
+
|
86
|
+
end # describe
|
87
|
+
|
88
|
+
describe "#name, marked as to clean as a string" do
|
89
|
+
|
90
|
+
it "is untouched when legit" do
|
91
|
+
@car_ad.name = "John Doe"
|
92
|
+
@car_ad.valid?
|
93
|
+
@car_ad.name.should eq "John Doe"
|
94
|
+
end
|
95
|
+
|
96
|
+
it "is cleaned as a string" do
|
97
|
+
@car_ad.name = " \t John \n Doe "
|
98
|
+
@car_ad.valid?
|
99
|
+
@car_ad.name.should eq "John Doe"
|
100
|
+
end
|
101
|
+
|
102
|
+
end # describe
|
103
|
+
|
104
|
+
describe "#body, marked as to clean as a text" do
|
105
|
+
|
106
|
+
it "is untouched when legit" do
|
107
|
+
@car_ad.body = "Lorem ipsum\ndolor sit amet.\n\nLorem."
|
108
|
+
@car_ad.valid?
|
109
|
+
@car_ad.body.should eq "Lorem ipsum\ndolor sit amet.\n\nLorem."
|
110
|
+
end
|
111
|
+
|
112
|
+
it "is cleaned as a text" do
|
113
|
+
@car_ad.body = "Lorem \t ipsum \t \n dolor \t sit \t amet.\n\n\nLorem."
|
114
|
+
@car_ad.valid?
|
115
|
+
@car_ad.body.should eq "Lorem ipsum\ndolor sit amet.\n\nLorem."
|
116
|
+
end
|
117
|
+
|
118
|
+
end # describe
|
119
|
+
|
120
|
+
end # context
|
121
|
+
|
122
|
+
end # describe
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
#
|
5
|
+
# The case
|
6
|
+
#
|
7
|
+
# This is to demonstrate when we want to clean some simple fields and nulify them
|
8
|
+
#
|
9
|
+
class OptimizedPost
|
10
|
+
include ActiveCleaner
|
11
|
+
|
12
|
+
attr_accessor :title, :name, :body
|
13
|
+
|
14
|
+
clean :title, nilify: true
|
15
|
+
clean :name, as: :string, nilify: true
|
16
|
+
clean :body, as: :text, nilify: true
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
#
|
21
|
+
# The specs
|
22
|
+
#
|
23
|
+
describe "Case: a simple post with nulify" do
|
24
|
+
|
25
|
+
describe OptimizedPost, "._cleaners" do
|
26
|
+
|
27
|
+
subject { OptimizedPost._cleaners }
|
28
|
+
|
29
|
+
it { should have(3).fields_to_clean }
|
30
|
+
|
31
|
+
it "includes a StringCleaner for #title" do
|
32
|
+
subject[:title].first.should eq(ActiveCleaner::StringCleaner.new(:title, nilify: true))
|
33
|
+
end
|
34
|
+
|
35
|
+
it "includes a StringCleaner for #name" do
|
36
|
+
subject[:name].first.should eq(ActiveCleaner::StringCleaner.new(:name, nilify: true))
|
37
|
+
end
|
38
|
+
|
39
|
+
it "includes a TextCleaner for #body" do
|
40
|
+
subject[:body].first.should eq(ActiveCleaner::TextCleaner.new(:body, nilify: true))
|
41
|
+
end
|
42
|
+
|
43
|
+
end # describe
|
44
|
+
|
45
|
+
context "considering a post" do
|
46
|
+
|
47
|
+
before do
|
48
|
+
@post = OptimizedPost.new
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#title, marked as to clean with no type" do
|
52
|
+
|
53
|
+
it "is untouched when legit" do
|
54
|
+
@post.title = "A good title!"
|
55
|
+
@post.valid?
|
56
|
+
@post.title.should eq "A good title!"
|
57
|
+
end
|
58
|
+
|
59
|
+
it "is nulified" do
|
60
|
+
@post.title = " \n \t "
|
61
|
+
@post.valid?
|
62
|
+
@post.title.should be_nil
|
63
|
+
end
|
64
|
+
|
65
|
+
end # describe
|
66
|
+
|
67
|
+
describe "#name, marked as to clean as a string" do
|
68
|
+
|
69
|
+
it "is untouched when legit" do
|
70
|
+
@post.name = "John Doe"
|
71
|
+
@post.valid?
|
72
|
+
@post.name.should eq "John Doe"
|
73
|
+
end
|
74
|
+
|
75
|
+
it "is nulified" do
|
76
|
+
@post.title = " \n \t "
|
77
|
+
@post.valid?
|
78
|
+
@post.title.should be_nil
|
79
|
+
end
|
80
|
+
|
81
|
+
end # describe
|
82
|
+
|
83
|
+
describe "#body, marked as to clean as a text" do
|
84
|
+
|
85
|
+
it "is untouched when legit" do
|
86
|
+
@post.body = "Lorem ipsum\ndolor sit amet.\n\nLorem."
|
87
|
+
@post.valid?
|
88
|
+
@post.body.should eq "Lorem ipsum\ndolor sit amet.\n\nLorem."
|
89
|
+
end
|
90
|
+
|
91
|
+
it "is nulified" do
|
92
|
+
@post.title = " \n \t "
|
93
|
+
@post.valid?
|
94
|
+
@post.title.should be_nil
|
95
|
+
end
|
96
|
+
|
97
|
+
end # describe
|
98
|
+
|
99
|
+
end # context
|
100
|
+
|
101
|
+
end # describe
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
#
|
5
|
+
# The case
|
6
|
+
#
|
7
|
+
# This is to demonstrate when we want to clean some simple fields
|
8
|
+
#
|
9
|
+
class Post
|
10
|
+
include ActiveCleaner
|
11
|
+
|
12
|
+
attr_accessor :title, :name, :body
|
13
|
+
|
14
|
+
clean :title
|
15
|
+
clean :name, as: :string
|
16
|
+
clean :body, as: :text
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
#
|
21
|
+
# The specs
|
22
|
+
#
|
23
|
+
describe "Case: a simple post" do
|
24
|
+
|
25
|
+
describe Post, "._cleaners" do
|
26
|
+
|
27
|
+
subject { Post._cleaners }
|
28
|
+
|
29
|
+
it { should have(3).fields_to_clean }
|
30
|
+
|
31
|
+
it "includes a StringCleaner for #title" do
|
32
|
+
subject[:title].first.should eq(ActiveCleaner::StringCleaner.new(:title))
|
33
|
+
end
|
34
|
+
|
35
|
+
it "includes a StringCleaner for #name" do
|
36
|
+
subject[:name].first.should eq(ActiveCleaner::StringCleaner.new(:name))
|
37
|
+
end
|
38
|
+
|
39
|
+
it "includes a TextCleaner for #body" do
|
40
|
+
subject[:body].first.should eq(ActiveCleaner::TextCleaner.new(:body))
|
41
|
+
end
|
42
|
+
|
43
|
+
end # describe
|
44
|
+
|
45
|
+
context "considering a post" do
|
46
|
+
|
47
|
+
before do
|
48
|
+
@post = Post.new
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#title, marked as to clean with no type" do
|
52
|
+
|
53
|
+
it "is untouched when legit" do
|
54
|
+
@post.title = "A good title!"
|
55
|
+
@post.valid?
|
56
|
+
@post.title.should eq "A good title!"
|
57
|
+
end
|
58
|
+
|
59
|
+
it "is cleaned as a string" do
|
60
|
+
@post.title = " A \n good \t title! "
|
61
|
+
@post.valid?
|
62
|
+
@post.title.should eq "A good title!"
|
63
|
+
end
|
64
|
+
|
65
|
+
end # describe
|
66
|
+
|
67
|
+
describe "#name, marked as to clean as a string" do
|
68
|
+
|
69
|
+
it "is untouched when legit" do
|
70
|
+
@post.name = "John Doe"
|
71
|
+
@post.valid?
|
72
|
+
@post.name.should eq "John Doe"
|
73
|
+
end
|
74
|
+
|
75
|
+
it "is cleaned as a string" do
|
76
|
+
@post.name = " \t John \n Doe "
|
77
|
+
@post.valid?
|
78
|
+
@post.name.should eq "John Doe"
|
79
|
+
end
|
80
|
+
|
81
|
+
end # describe
|
82
|
+
|
83
|
+
describe "#body, marked as to clean as a text" do
|
84
|
+
|
85
|
+
it "is untouched when legit" do
|
86
|
+
@post.body = "Lorem ipsum\ndolor sit amet.\n\nLorem."
|
87
|
+
@post.valid?
|
88
|
+
@post.body.should eq "Lorem ipsum\ndolor sit amet.\n\nLorem."
|
89
|
+
end
|
90
|
+
|
91
|
+
it "is cleaned as a text" do
|
92
|
+
@post.body = "Lorem \t ipsum \t \n dolor \t sit \t amet.\n\n\nLorem."
|
93
|
+
@post.valid?
|
94
|
+
@post.body.should eq "Lorem ipsum\ndolor sit amet.\n\nLorem."
|
95
|
+
end
|
96
|
+
|
97
|
+
end # describe
|
98
|
+
|
99
|
+
end # context
|
100
|
+
|
101
|
+
end # describe
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe ActiveCleaner::MarkdownCleaner do
|
5
|
+
|
6
|
+
before do
|
7
|
+
@cleaner = ActiveCleaner::MarkdownCleaner.new(:body)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#clean_value" do
|
11
|
+
|
12
|
+
it "doesn't touch legit value" do
|
13
|
+
body = ""
|
14
|
+
body << "= Title =\n"
|
15
|
+
body << "\n"
|
16
|
+
body << "A first paragraph.\n"
|
17
|
+
body << "\n"
|
18
|
+
body << "A **second** one, with a\n"
|
19
|
+
body << "line break.\n"
|
20
|
+
body << "\n"
|
21
|
+
body << " * first item\n"
|
22
|
+
body << " * second item\n"
|
23
|
+
body << "\n"
|
24
|
+
body << " <div id=\"test\">\n"
|
25
|
+
body << " <p>Text</p>\n"
|
26
|
+
body << " </div>\n"
|
27
|
+
body << "\n"
|
28
|
+
body << "A third paragraph."
|
29
|
+
|
30
|
+
@cleaner.clean_value(body).should eq body
|
31
|
+
end
|
32
|
+
|
33
|
+
it "empties string full of spaces" do
|
34
|
+
[
|
35
|
+
"",
|
36
|
+
" ",
|
37
|
+
"\t",
|
38
|
+
"\n",
|
39
|
+
" \t\n \t\n \t\n \t\n",
|
40
|
+
].each do |title|
|
41
|
+
@cleaner.clean_value(title).should eq ""
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it "cleans repeted spaces" do
|
46
|
+
@cleaner.clean_value("Lorem ipsum \ndolor sit amet.").should eq "Lorem ipsum\ndolor sit amet."
|
47
|
+
@cleaner.clean_value("Lorem \t ipsum \t \ndolor \t sit \t amet.").should eq "Lorem ipsum\ndolor sit amet."
|
48
|
+
end
|
49
|
+
|
50
|
+
context "considering the spaces in the beggining of lines" do
|
51
|
+
it "preserves them" do
|
52
|
+
@cleaner.clean_value("Lorem ipsum\n dolor sit amet.").should eq "Lorem ipsum\n dolor sit amet."
|
53
|
+
end
|
54
|
+
it "clears line full of spaces" do
|
55
|
+
@cleaner.clean_value("Lorem ipsum \n \n dolor sit amet.").should eq "Lorem ipsum\n\n dolor sit amet."
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it "keeps two max succeeding new line" do
|
60
|
+
@cleaner.clean_value("Lorem ipsum\n\n\ndolor sit amet.").should eq "Lorem ipsum\n\ndolor sit amet."
|
61
|
+
@cleaner.clean_value("Lorem ipsum\n\n\n\ndolor sit amet.").should eq "Lorem ipsum\n\ndolor sit amet."
|
62
|
+
@cleaner.clean_value("Lorem ipsum\n \n \n \ndolor sit amet.").should eq "Lorem ipsum\n\ndolor sit amet."
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe ActiveCleaner::StringCleaner do
|
5
|
+
|
6
|
+
before do
|
7
|
+
@cleaner = ActiveCleaner::StringCleaner.new(:title)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#clean_value" do
|
11
|
+
|
12
|
+
it "doesn't touch legit value" do
|
13
|
+
@cleaner.clean_value("A good title!").should eq "A good title!"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "empties string full of spaces" do
|
17
|
+
[
|
18
|
+
"",
|
19
|
+
" ",
|
20
|
+
"\t",
|
21
|
+
"\n",
|
22
|
+
" \t\n \t\n \t\n \t\n",
|
23
|
+
].each do |title|
|
24
|
+
@cleaner.clean_value(title).should eq ""
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it "cleans leading and trailing spaces" do
|
29
|
+
@cleaner.clean_value(" A good title! ").should eq "A good title!"
|
30
|
+
end
|
31
|
+
it "cleans leading and trailing tabs" do
|
32
|
+
@cleaner.clean_value("\tA good title!\t").should eq "A good title!"
|
33
|
+
end
|
34
|
+
it "cleans leading and trailing lines" do
|
35
|
+
@cleaner.clean_value("\nA good title!\n").should eq "A good title!"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "cleans repeted spaces" do
|
39
|
+
@cleaner.clean_value("A good title!").should eq "A good title!"
|
40
|
+
@cleaner.clean_value("A \n good \t title!").should eq "A good title!"
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe ActiveCleaner::TextCleaner do
|
5
|
+
|
6
|
+
before do
|
7
|
+
@cleaner = ActiveCleaner::TextCleaner.new(:text)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#clean_value" do
|
11
|
+
|
12
|
+
it "doesn't touch legit value" do
|
13
|
+
[
|
14
|
+
"Lorem ipsum dolor sit amet.",
|
15
|
+
"Lorem ipsum\ndolor sit amet.",
|
16
|
+
"Lorem ipsum\n\ndolor sit amet.",
|
17
|
+
].each do |text|
|
18
|
+
@cleaner.clean_value(text).should eq text
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "empties string full of spaces" do
|
23
|
+
[
|
24
|
+
"",
|
25
|
+
" ",
|
26
|
+
"\t",
|
27
|
+
"\n",
|
28
|
+
" \t\n \t\n \t\n \t\n",
|
29
|
+
].each do |title|
|
30
|
+
@cleaner.clean_value(title).should eq ""
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "cleans leading and trailing spaces" do
|
35
|
+
@cleaner.clean_value(" Lorem ipsum\ndolor sit amet. ").should eq "Lorem ipsum\ndolor sit amet."
|
36
|
+
end
|
37
|
+
it "cleans leading and trailing tabs" do
|
38
|
+
@cleaner.clean_value("\tLorem ipsum\ndolor sit amet.\t").should eq "Lorem ipsum\ndolor sit amet."
|
39
|
+
end
|
40
|
+
it "cleans leading and trailing lines" do
|
41
|
+
@cleaner.clean_value("\nLorem ipsum\ndolor sit amet.\n").should eq "Lorem ipsum\ndolor sit amet."
|
42
|
+
end
|
43
|
+
|
44
|
+
it "cleans repeted spaces" do
|
45
|
+
@cleaner.clean_value("Lorem ipsum \n dolor sit amet.").should eq "Lorem ipsum\ndolor sit amet."
|
46
|
+
@cleaner.clean_value("Lorem \t ipsum \t \n dolor \t sit \t amet.").should eq "Lorem ipsum\ndolor sit amet."
|
47
|
+
end
|
48
|
+
|
49
|
+
it "keeps two max succeeding new line" do
|
50
|
+
@cleaner.clean_value("Lorem ipsum\n\n\ndolor sit amet.").should eq "Lorem ipsum\n\ndolor sit amet."
|
51
|
+
@cleaner.clean_value("Lorem ipsum\n\n\n\ndolor sit amet.").should eq "Lorem ipsum\n\ndolor sit amet."
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: activecleaner
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Maxime Garcia
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-30 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
none: false
|
17
|
+
requirements:
|
18
|
+
- - ~>
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '3.1'
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
none: false
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.1'
|
27
|
+
prerelease: false
|
28
|
+
type: :runtime
|
29
|
+
name: activemodel
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
none: false
|
33
|
+
requirements:
|
34
|
+
- - ~>
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '3.1'
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ~>
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '3.1'
|
43
|
+
prerelease: false
|
44
|
+
type: :runtime
|
45
|
+
name: activesupport
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
requirement: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
prerelease: false
|
60
|
+
type: :development
|
61
|
+
name: rspec
|
62
|
+
description: ! ' ActiveCleaner is a set of helpers that helps you in cleaning user-typed
|
63
|
+
content in your ActiveModel depending models (ActiveRecord, Mongoid...)
|
64
|
+
|
65
|
+
'
|
66
|
+
email:
|
67
|
+
- maxime.garcia@free.fr
|
68
|
+
executables: []
|
69
|
+
extensions: []
|
70
|
+
extra_rdoc_files: []
|
71
|
+
files:
|
72
|
+
- README.md
|
73
|
+
- LICENSE
|
74
|
+
- lib/active_cleaner.rb
|
75
|
+
- lib/active_cleaner/markdown_cleaner.rb
|
76
|
+
- lib/active_cleaner/version.rb
|
77
|
+
- lib/active_cleaner/base_cleaner.rb
|
78
|
+
- lib/active_cleaner/helper_methods.rb
|
79
|
+
- lib/active_cleaner/string_cleaner.rb
|
80
|
+
- lib/active_cleaner/text_cleaner.rb
|
81
|
+
- lib/activecleaner.rb
|
82
|
+
- spec/lib/active_cleaner/string_cleaner_spec.rb
|
83
|
+
- spec/lib/active_cleaner/text_cleaner_spec.rb
|
84
|
+
- spec/lib/active_cleaner/markdown_cleaner_spec.rb
|
85
|
+
- spec/lib/active_cleaner_spec.rb
|
86
|
+
- spec/spec_helper.rb
|
87
|
+
- spec/cases/inherit_spec.rb
|
88
|
+
- spec/cases/simple_spec.rb
|
89
|
+
- spec/cases/nilify_spec.rb
|
90
|
+
homepage: http://github.com/maximeg/activecleaner
|
91
|
+
licenses: []
|
92
|
+
post_install_message:
|
93
|
+
rdoc_options: []
|
94
|
+
require_paths:
|
95
|
+
- lib
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
none: false
|
104
|
+
requirements:
|
105
|
+
- - ! '>='
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubyforge_project:
|
110
|
+
rubygems_version: 1.8.25
|
111
|
+
signing_key:
|
112
|
+
specification_version: 3
|
113
|
+
summary: Clean the fields in your models
|
114
|
+
test_files:
|
115
|
+
- spec/lib/active_cleaner/string_cleaner_spec.rb
|
116
|
+
- spec/lib/active_cleaner/text_cleaner_spec.rb
|
117
|
+
- spec/lib/active_cleaner/markdown_cleaner_spec.rb
|
118
|
+
- spec/lib/active_cleaner_spec.rb
|
119
|
+
- spec/spec_helper.rb
|
120
|
+
- spec/cases/inherit_spec.rb
|
121
|
+
- spec/cases/simple_spec.rb
|
122
|
+
- spec/cases/nilify_spec.rb
|