normatron 0.3.0 → 0.3.1
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/README.md +345 -0
- data/lib/generators/normatron/install_generator.rb +11 -5
- data/lib/generators/normatron/templates/normatron.rb +18 -1
- data/lib/normatron/configuration.rb +1 -0
- data/lib/normatron/extensions/active_record.rb +15 -11
- data/lib/normatron/filters.rb +27 -21
- data/lib/normatron/filters/ascii_filter.rb +26 -0
- data/lib/normatron/filters/helpers.rb +0 -10
- data/lib/normatron/filters/strip_filter.rb +15 -3
- data/lib/normatron/filters/upcase_filter.rb +3 -3
- data/lib/normatron/version.rb +1 -1
- data/spec/normatron/configuration_spec.rb +29 -20
- data/spec/normatron/extensions/active_record_spec.rb +22 -7
- data/spec/normatron/filters/ascii_filter_spec.rb +14 -0
- metadata +22 -3
- data/README.textile +0 -200
data/README.md
ADDED
@@ -0,0 +1,345 @@
|
|
1
|
+
# Normatron
|
2
|
+
|
3
|
+
Normatron is a Ruby On Rails plugin that perform attribute normalizations for ActiveRecord objects.<br />
|
4
|
+
With it you can normalize attributes to the desired format before saving them in the database.<br />
|
5
|
+
This gem inhibits the work of having to override attributes or create a specific method to perform most of the normalizations.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Let the bundler install the gem by adding the following into your application gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'normatron'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then bundle it up:
|
16
|
+
|
17
|
+
```bash
|
18
|
+
$ bundle install
|
19
|
+
```
|
20
|
+
|
21
|
+
Or install it by yourself:
|
22
|
+
|
23
|
+
```bash
|
24
|
+
$ gem install normatron
|
25
|
+
```
|
26
|
+
|
27
|
+
Then run the generator:
|
28
|
+
|
29
|
+
```bash
|
30
|
+
$ rails generator normatron:install
|
31
|
+
```
|
32
|
+
|
33
|
+
## The problem
|
34
|
+
|
35
|
+
Suppose you have a product model as the following:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
# ./db/migrate/20120101010000_create_products.rb
|
39
|
+
class CreateProducts < ActiveRecord::Migration
|
40
|
+
def change
|
41
|
+
create_table :products do |t|
|
42
|
+
t.string :name
|
43
|
+
t.decimal :price, :precision => 10, :scale => 2
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
```
|
48
|
+
```ruby
|
49
|
+
# ./app/models/products.rb
|
50
|
+
class Product < ActiveRecord::Base
|
51
|
+
attr_accessible :name, :price
|
52
|
+
end
|
53
|
+
```
|
54
|
+
|
55
|
+
If you want the *name* attribute be uppercased before saving it into the database, the most usual approaches includes:
|
56
|
+
|
57
|
+
* Override the *name* setter and convert the value to an uppercased string.
|
58
|
+
* Write a method or block and bind it to an [ActiveRecord callback](http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html) (like *before_validation* or *before_save*).
|
59
|
+
|
60
|
+
Both ways are ilenegant, boring to implement, error prone and very expensive.<br />
|
61
|
+
What led me to make this gem and offer a third way to handle this.
|
62
|
+
|
63
|
+
## Usage
|
64
|
+
|
65
|
+
Call the [normalize](http://www.rubydoc.info/github/fernandors87/normatron/Normatron/Extensions/ActiveRecord/ClassMethods:normalize) class method inside your model to set the normalization rules:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
# ./app/models/products.rb
|
69
|
+
class Product < ActiveRecord::Base
|
70
|
+
attr_accessible :name, :price
|
71
|
+
normalize :name
|
72
|
+
end
|
73
|
+
```
|
74
|
+
|
75
|
+
And it will behave like this:
|
76
|
+
|
77
|
+
```bash
|
78
|
+
$ rails console
|
79
|
+
> memory = Product.create name: " memory card "
|
80
|
+
=> #<Product id: nil, name: "memory card", price: nil>
|
81
|
+
> unknown = Product.create name: " "
|
82
|
+
=> #<Product id: nil, name: nil, price: nil>
|
83
|
+
```
|
84
|
+
|
85
|
+
In this case the `:with` option was ommited, then the [:blank](http://rubydoc.info/gems/normatron/Normatron/Filters/BlankFilter) and [:squish](http://rubydoc.info/gems/normatron/Normatron/Filters/SquishFilter) filters was called to the *name* attribute.<br />
|
86
|
+
These are the default filters and can be easily changed in the initializer file.
|
87
|
+
|
88
|
+
To specify which kind of filters will be binded to each attribute, pass the filter name to the `:with` option:
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
class MyModel < ActiveRecord::Base
|
92
|
+
# Single filter to a single attribute
|
93
|
+
normalize :attr_a, :with => :upcase
|
94
|
+
|
95
|
+
# Multiple filters to multiple attributes
|
96
|
+
normalize :attr_b, :attr_c, :attr_d, :with => [:upcase, :squish]
|
97
|
+
|
98
|
+
# The :keep filter is an example of filter that uses arguments.
|
99
|
+
# In this case, the filter is passed as a Hash, where the key is the filter name,
|
100
|
+
# and the value is an Array of arguments.
|
101
|
+
normalize :attr_e, :with => {:keep => [:Latin, :Z]}
|
102
|
+
|
103
|
+
# The same as above can be obtained using an Array instead of a Hash.
|
104
|
+
# But when filter uses arguments, set him inside another Array is mandatory.
|
105
|
+
normalize :attr_f, :with => [[:keep, :Latin, :Z]]
|
106
|
+
|
107
|
+
# Mix simple filters with filters carrying arguments this way:
|
108
|
+
normalize :attr_g, :with => [:blank, {:keep => [:Latin, :Z]}, :squish]
|
109
|
+
|
110
|
+
# Or this way:
|
111
|
+
normalize :attr_h, :with => [:blank, [:keep, :Latin, :Z], :squish]
|
112
|
+
end
|
113
|
+
```
|
114
|
+
|
115
|
+
### Filter Stackings
|
116
|
+
|
117
|
+
The normalize method stack the filters when called multiple times to the same attribute.
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
# 1st Way: Without stacking filters
|
121
|
+
class MyModel < ActiveRecord::Base
|
122
|
+
normalize :attr_a, :with => :blank
|
123
|
+
normalize :attr_b, :with => [:blank, :squish]
|
124
|
+
normalize :attr_c, :with => [:blank, :squish, :upcase]
|
125
|
+
end
|
126
|
+
|
127
|
+
# 2nd Way: Stacking filters
|
128
|
+
# This piece of code produces the exactly the same results as 1st way.
|
129
|
+
class MyModel < ActiveRecord::Base
|
130
|
+
normalize :attr_a, :attr_b, :attr_c, :with => :blank
|
131
|
+
normalize :attr_b, :attr_c, :with => :squish
|
132
|
+
normalize :attr_c, :with => :upcase
|
133
|
+
end
|
134
|
+
```
|
135
|
+
|
136
|
+
### Typing Less
|
137
|
+
|
138
|
+
In some cases is possible to write much less by passing multiple attributes to normalize method:
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
# 1st Way: Setting rules to single attributes
|
142
|
+
class MyModel < ActiveRecord::Base
|
143
|
+
normalize :attr_a, :with => :blank
|
144
|
+
normalize :attr_b, :with => :squish
|
145
|
+
normalize :attr_c, :with => :upcase
|
146
|
+
normalize :attr_d, :with => [:blank, :squish]
|
147
|
+
normalize :attr_e, :with => [:blank, :upcase]
|
148
|
+
normalize :attr_f, :with => [:squish, :upcase]
|
149
|
+
normalize :attr_g, :with => [:blank, :squish, :upcase]
|
150
|
+
end
|
151
|
+
|
152
|
+
# 2nd Way: Setting rules to multiple attributes
|
153
|
+
class MyModel < ActiveRecord::Base
|
154
|
+
normalize :attr_a, :attr_d, :attr_e, :attr_g, :with => :blank
|
155
|
+
normalize :attr_b, :attr_d, :attr_f, :attr_g, :with => :squish
|
156
|
+
normalize :attr_c, :attr_e, :attr_f, :attr_g, :with => :upcase
|
157
|
+
end
|
158
|
+
```
|
159
|
+
|
160
|
+
### Filters
|
161
|
+
|
162
|
+
Normatron have a bunch of built-in filters.<br />
|
163
|
+
The list of all filters and instructions of how to use them can be found in the [Normatron::Filters](http://rubydoc.info/gems/normatron/Normatron/Filters) documentation.
|
164
|
+
|
165
|
+
### Getting Normalization Rules
|
166
|
+
|
167
|
+
You can know what kind of rules was set to a model as following:
|
168
|
+
|
169
|
+
```
|
170
|
+
$ rails console
|
171
|
+
> User.normalize_rules
|
172
|
+
=> {:login => {:blank => nil, :remove => [:Zs]},
|
173
|
+
:email => {:blank => nil, :squish => nil, :downcase => nil},
|
174
|
+
:name => {:blank => nil, :squish => nil, :upcase => nil}}
|
175
|
+
```
|
176
|
+
|
177
|
+
### Applying Normalizations
|
178
|
+
|
179
|
+
All attributes are automatically normalized by [before_validation](http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html) callback, what means any method that evoke the *before_validation* callback will perform the normalizations.<br />
|
180
|
+
Some of these methods includes:
|
181
|
+
|
182
|
+
* [ActiveRecord::Validations#valid?](http://api.rubyonrails.org/classes/ActiveRecord/Validations.html#method-i-valid-3F)
|
183
|
+
* [ActiveRecord::Persistence#save](http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-save)
|
184
|
+
* [ActiveRecord::Persistence::ClassMethods#create](http://api.rubyonrails.org/classes/ActiveRecord/Persistence/ClassMethods.html#method-i-create)
|
185
|
+
|
186
|
+
To apply the normalizations without doing validations or persistence, just call the [apply_normalizations](http://rubydoc.info/gems/normatron/Normatron/Extensions/ActiveRecord/InstanceMethods#apply_normalizations-instance_method) method as following:
|
187
|
+
|
188
|
+
```
|
189
|
+
$ rails console
|
190
|
+
> user = User.new
|
191
|
+
> user.name = " anon "
|
192
|
+
> user.email = "ANON@GMAIL.COM"
|
193
|
+
> user.login = "my name \n is anon"
|
194
|
+
> user.attributes
|
195
|
+
=> {:id => nil,
|
196
|
+
:name => " anon ",
|
197
|
+
:email => "ANON@GMAIL.COM",
|
198
|
+
:login => "my name \n is anon"}
|
199
|
+
> user.apply_normalizations
|
200
|
+
> user.attributes
|
201
|
+
=> {:id => nil,
|
202
|
+
:name => "ANON",
|
203
|
+
:email => "anon@gmail.com",
|
204
|
+
:login => "mynameisanon"}
|
205
|
+
```
|
206
|
+
|
207
|
+
### Building Your Own Filters
|
208
|
+
|
209
|
+
#### 1st way: Defining a filter as a module
|
210
|
+
|
211
|
+
Create a new module with the following characteristics:
|
212
|
+
|
213
|
+
* Having a module method called evaluate
|
214
|
+
* The evaluate method must receive at least one argument
|
215
|
+
* The first argument must be the value to be filtered
|
216
|
+
|
217
|
+
Here is an example:
|
218
|
+
|
219
|
+
```ruby
|
220
|
+
# ./lib/my_filters/emoticon_filter.rb
|
221
|
+
module MyFilters
|
222
|
+
module EmoticonFilter
|
223
|
+
def self.evaluate(value, type)
|
224
|
+
emot = (type == :sad) ? ":(" : ":D"
|
225
|
+
value + emot
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
```
|
230
|
+
|
231
|
+
Then add him to your Normatron initializer file:
|
232
|
+
|
233
|
+
```ruby
|
234
|
+
require 'lib/my_filters/emoticon_filter'
|
235
|
+
Normatron.setup do |config|
|
236
|
+
#...
|
237
|
+
config.filters[:emoticon] = MyFilter::EmoticonFilter
|
238
|
+
#...
|
239
|
+
end
|
240
|
+
```
|
241
|
+
|
242
|
+
Usage:
|
243
|
+
|
244
|
+
```ruby
|
245
|
+
class Message < ActiveRecord::Base
|
246
|
+
belongs_to :person
|
247
|
+
normalize :content, :with => {:emoticon => :happy} # Always happy
|
248
|
+
end
|
249
|
+
```
|
250
|
+
|
251
|
+
1. Pros
|
252
|
+
* Allow create specific documentation for your filter
|
253
|
+
* More easy to make them portable for multiple applications and purposes
|
254
|
+
2. Cons
|
255
|
+
* Verbose
|
256
|
+
|
257
|
+
#### 2nd way: Defining a filter as a lambda
|
258
|
+
|
259
|
+
Create a new lambda object with the following characteristics:
|
260
|
+
|
261
|
+
* Must receive at least one argument
|
262
|
+
* The first argument must be the value to be filtered
|
263
|
+
|
264
|
+
The lambda will be defined inside Normatron initializer:
|
265
|
+
|
266
|
+
```ruby
|
267
|
+
Normatron.setup do |config|
|
268
|
+
#...
|
269
|
+
|
270
|
+
config.filters[:emoticon] = lambda do |value, type|
|
271
|
+
emot = (type == :sad) ? ":(" : ":D"
|
272
|
+
value + emot
|
273
|
+
end
|
274
|
+
|
275
|
+
#...
|
276
|
+
end
|
277
|
+
```
|
278
|
+
|
279
|
+
Usage:
|
280
|
+
|
281
|
+
```ruby
|
282
|
+
class Message < ActiveRecord::Base
|
283
|
+
belongs_to :person
|
284
|
+
normalize :content, :with => {:emoticon => :sad} # Always sad
|
285
|
+
end
|
286
|
+
```
|
287
|
+
|
288
|
+
1. Pros
|
289
|
+
* Less verbose than 1st method
|
290
|
+
2. Cons
|
291
|
+
* Hard to share filter functionalities between other applications
|
292
|
+
* Hard to use filter functionalities for other purposes
|
293
|
+
|
294
|
+
#### 3th way: Defining a filter as model instance method
|
295
|
+
|
296
|
+
Create a new instance method within your model with the following characteristics:
|
297
|
+
|
298
|
+
* Must receive at least one argument
|
299
|
+
* The first argument must be the value to be filtered
|
300
|
+
|
301
|
+
The method will be defined inside your model class:
|
302
|
+
|
303
|
+
```ruby
|
304
|
+
class Message < ActiveRecord::Base
|
305
|
+
belongs_to :person
|
306
|
+
normalize :content, :with => :emoticon # Happy or sad according person's mood
|
307
|
+
|
308
|
+
def emoticon(value)
|
309
|
+
emot = (person.mood == :happy) ? ":D" : ":("
|
310
|
+
value + emot
|
311
|
+
end
|
312
|
+
end
|
313
|
+
```
|
314
|
+
|
315
|
+
1. Pros
|
316
|
+
* Can use instance variables
|
317
|
+
2. Cons
|
318
|
+
* Cannot be shared between objects
|
319
|
+
|
320
|
+
# Contributing
|
321
|
+
|
322
|
+
There are several ways to make this gem even better:
|
323
|
+
|
324
|
+
* Forking this project
|
325
|
+
* Adding new features or bug fixes
|
326
|
+
* Making tests
|
327
|
+
* Commiting your changes
|
328
|
+
* Reporting any bug or unexpected behavior
|
329
|
+
* Suggesting any improvement
|
330
|
+
* Sharing with your friends, forums, communities, job, etc...
|
331
|
+
* Helping users with difficulty using this gem
|
332
|
+
* Paying me a beer =]
|
333
|
+
|
334
|
+
# Credits
|
335
|
+
|
336
|
+
This gem was initially inspired on:
|
337
|
+
|
338
|
+
* [normalize_attributes](https://github.com/fnando/normalize_attributes) - I liked the cleaner code and simplicity of this gem.
|
339
|
+
* [attribute_normalizer](https://github.com/mdeering/attribute_normalizer) - Very powerful.
|
340
|
+
|
341
|
+
The idea is to mix the good things of both gems, adding some features and changing something to fit my taste.
|
342
|
+
|
343
|
+
# License
|
344
|
+
|
345
|
+
See file attached to source code or [click here](https://github.com/fernandors87/normatron/blob/master/MIT-LICENSE).
|
@@ -2,19 +2,25 @@ module Normatron
|
|
2
2
|
##
|
3
3
|
# Creates all necessary files to run Normatron in your Ruby On Rails project.
|
4
4
|
#
|
5
|
-
#
|
5
|
+
# Even when required, Normatron doesn't include his functionalities into your ORM automatically.
|
6
|
+
# It behaves this way to avoid some potential issues.
|
7
|
+
#
|
8
|
+
# Using this generator, you can get fully control of Normatron behavior through initialization file.
|
9
|
+
#
|
10
|
+
# These files includes:
|
6
11
|
# * config/initializers/normatron.rb
|
7
12
|
#
|
8
|
-
#
|
9
|
-
#
|
13
|
+
# h2. Usage
|
14
|
+
#
|
15
|
+
# pre. $ rails generator normatron:install
|
10
16
|
class InstallGenerator < Rails::Generators::Base
|
11
17
|
source_root File.expand_path('../templates', __FILE__)
|
12
18
|
desc "Create all necessary files to run Normatron in your Ruby On Rails project."
|
13
19
|
|
14
20
|
##
|
15
|
-
# Copy files from templates to their respective destination
|
21
|
+
# Copy files from templates to their respective destination.
|
16
22
|
#
|
17
|
-
# These files
|
23
|
+
# These files includes:
|
18
24
|
# * config/initializers/normatron.rb
|
19
25
|
def copy_files
|
20
26
|
copy_file "normatron.rb", "config/initializers/normatron.rb"
|
@@ -1,4 +1,21 @@
|
|
1
1
|
Normatron.setup do |config|
|
2
|
-
|
2
|
+
# Comment the line below to disable Normatron
|
3
3
|
config.add_orm Normatron::Extensions::ActiveRecord
|
4
|
+
|
5
|
+
# Create your own filters using a Proc/lambda as following:
|
6
|
+
#
|
7
|
+
# config.filters[:smile] = lambda do |value|
|
8
|
+
# value.kind_of?(String) : value + " =]" : value
|
9
|
+
# end
|
10
|
+
|
11
|
+
# Include your own filter module as following:
|
12
|
+
#
|
13
|
+
# config.filters[:laugh] = YourNamespace::YourFilterSet::YourFilter
|
14
|
+
|
15
|
+
# Set the default filters.
|
16
|
+
#
|
17
|
+
# Examples:
|
18
|
+
# config.default_filters = :upcase, {:keep => [:L, :N]}
|
19
|
+
# config.default_filters = :ascii, [:keep, :L, :N]
|
20
|
+
config.default_filters = :blank, :squish
|
4
21
|
end
|
@@ -9,6 +9,7 @@ module Normatron
|
|
9
9
|
@default_filters = { blank: nil, squish: nil }
|
10
10
|
|
11
11
|
@filters = {}
|
12
|
+
@filters[:ascii] = Normatron::Filters::AsciiFilter
|
12
13
|
@filters[:blank] = Normatron::Filters::BlankFilter
|
13
14
|
@filters[:camelize] = Normatron::Filters::CamelizeFilter
|
14
15
|
@filters[:capitalize] = Normatron::Filters::CapitalizeFilter
|
@@ -13,30 +13,32 @@ module Normatron
|
|
13
13
|
before_validation :apply_normalizations
|
14
14
|
|
15
15
|
class << self
|
16
|
-
attr_accessor :
|
16
|
+
attr_accessor :normalize_rules
|
17
|
+
alias :normalize_filters :normalize_rules
|
18
|
+
alias :normalize_filters= :normalize_rules=
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
21
23
|
module ClassMethods
|
22
24
|
def normalize(*args)
|
23
|
-
# Check existence of all attributes
|
25
|
+
# Check the existence of all attributes
|
24
26
|
options = args.extract_options!
|
25
27
|
filters, columns = args.map(&:to_s), column_names
|
26
28
|
raise UnknownAttributeError if (columns & filters).size != filters.size
|
27
29
|
|
28
|
-
#
|
30
|
+
# Need to use default filters?
|
29
31
|
if options[:with].nil? || options[:with].blank?
|
30
32
|
new_filters = Normatron.config.default_filters
|
31
33
|
else
|
32
34
|
new_filters = Normatron.build_hash(options[:with])
|
33
35
|
end
|
34
36
|
|
35
|
-
# Append
|
36
|
-
@
|
37
|
-
@
|
38
|
-
args.reduce(@
|
39
|
-
filters = (@
|
37
|
+
# Append new filters to rules
|
38
|
+
@normalize_rules ||= {}
|
39
|
+
@normalize_rules =
|
40
|
+
args.reduce(@normalize_rules) do |hash, att|
|
41
|
+
filters = (@normalize_rules[att] || {}).merge(new_filters)
|
40
42
|
hash.merge({att => filters})
|
41
43
|
end
|
42
44
|
end
|
@@ -44,7 +46,7 @@ module Normatron
|
|
44
46
|
|
45
47
|
module InstanceMethods
|
46
48
|
def apply_normalizations
|
47
|
-
|
49
|
+
listed_filters = Normatron.configuration.filters
|
48
50
|
|
49
51
|
self.class.normalize_filters.each do |attribute, filters|
|
50
52
|
value = send("#{attribute}_before_type_cast") || send(attribute)
|
@@ -52,8 +54,10 @@ module Normatron
|
|
52
54
|
filters.each do |filter, args|
|
53
55
|
if self.respond_to? filter
|
54
56
|
value = send(filter, value, *args)
|
55
|
-
elsif
|
56
|
-
value =
|
57
|
+
elsif listed_filters[filter].kind_of? Module
|
58
|
+
value = listed_filters[filter].evaluate(value, *args)
|
59
|
+
elsif listed_filters[filter].kind_of? Proc
|
60
|
+
value = listed_filters[filter].call(value, *args)
|
57
61
|
else
|
58
62
|
raise UnknownFilterError
|
59
63
|
end
|
data/lib/normatron/filters.rb
CHANGED
@@ -1,31 +1,37 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
|
4
|
-
require 'normatron/filters/chomp_filter'
|
5
|
-
require 'normatron/filters/dasherize_filter'
|
6
|
-
require 'normatron/filters/downcase_filter'
|
7
|
-
require 'normatron/filters/dump_filter'
|
8
|
-
require 'normatron/filters/keep_filter'
|
9
|
-
require 'normatron/filters/remove_filter'
|
10
|
-
require 'normatron/filters/squeeze_filter'
|
11
|
-
require 'normatron/filters/squish_filter'
|
12
|
-
require 'normatron/filters/strip_filter'
|
13
|
-
require 'normatron/filters/swapcase_filter'
|
14
|
-
require 'normatron/filters/titleize_filter'
|
15
|
-
require 'normatron/filters/underscore_filter'
|
16
|
-
require 'normatron/filters/upcase_filter'
|
1
|
+
Dir[File.dirname(__FILE__) + "/filters/*_filter.rb"].each do |file|
|
2
|
+
require file
|
3
|
+
end
|
17
4
|
|
18
5
|
module Normatron
|
19
|
-
|
20
|
-
#
|
6
|
+
|
7
|
+
# Top-Level namespace of all built-in Normatron filters.
|
8
|
+
#
|
21
9
|
# All filters share some characteristics:
|
22
10
|
# * They have the <code>Filter</code> suffix in the name.
|
23
11
|
# * Has a class method called <code>evaluate</code>, which runs what the filter claims to do.
|
24
12
|
# * The first argument of the method <code>evaluate</code> always will be the variable to be filtered.
|
25
|
-
# * They returns a different object from the input variable,
|
26
|
-
# * They treat
|
13
|
+
# * They returns a different object from the input variable, i.e., even if object value remains unchanged, the <code>object_id</code> will be different.
|
14
|
+
# * They treat unicode characters(<code>/\p{Ll}\p{Lu}/u</code>) instead of only ASCII characters(<code>/[a-zA-Z]/</code>).
|
15
|
+
#
|
16
|
+
# table{font-family: monospace; font-size: 90%}.
|
17
|
+
# |_. CLASS |_. SYMBOL |_. SHORT DESCRIPTION |
|
18
|
+
# |"AsciiFilter":./Filters/AsciiFilter |:ascii |Converts Unicode(and accented ASCII) characters to their plain-text ASCII equivalents.|
|
19
|
+
# |"BlankFilter":./Filters/BlankFilter |:blank |Returns nil for a blank string or the string itself otherwise. |
|
20
|
+
# |"CamelizeFilter":./Filters/CamelizeFilter |:camelize |Convert string to UpperCamelCase or lowerCamelCase. |
|
21
|
+
# |"CapitalizeFilter":./Filters/CapitalizeFilter|:capitalize|Makes only the first character as capital letter. |
|
22
|
+
# |"ChompFilter":./Filters/ChompFilter |:chomp |Remove the given record separator from the end of the string. |
|
23
|
+
# |"DasherizeFilter":./Filters/DasherizeFilter |:dasherize |Replaces all underscores with dashes. |
|
24
|
+
# |"DowncaseFilter":./Filters/DowncaseFilter |:downcase |Lowercase all characters. |
|
25
|
+
# |"DumpFilter":./Filters/DumpFilter |:dump |Creates a literal string representation. |
|
26
|
+
# |"KeepFilter":./Filters/KeepFilter |:keep |Remove the characters that doesn't match the given properties. |
|
27
|
+
# |"RemoveFilter":./Filters/RemoveFilter |:remove |Remove the characters that match the given properties. |
|
28
|
+
# |"SqueezeFilter":./Filters/SqueezeFilter |:squeeze |Remove multiple occurences of the same character. |
|
29
|
+
# |"SquishFilter":./Filters/SquishFilter |:squish |Strips the input, remove line-breaks and multiple spaces. |
|
30
|
+
# |"SwapcaseFilter":./Filters/SwapcaseFilter |:swapcase |Replaces uppercased characters by lowercased and vice versa. |
|
31
|
+
# |"TitleizeFilter":./Filters/TitleizeFilter |:titleize |Capitalizes the first character of each word. |
|
32
|
+
# |"UnderscoreFilter":./Filters/UnderscoreFilter|:underscore|Makes an underscored lowercase form from the expression in the string. |
|
33
|
+
# |"UpcaseFilter":./Filters/UpcaseFilter |:upcase |Uppercase all characters. |
|
27
34
|
module Filters
|
28
35
|
end
|
29
36
|
end
|
30
37
|
|
31
|
-
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'stringex/unidecoder'
|
2
|
+
|
3
|
+
module Normatron
|
4
|
+
module Filters
|
5
|
+
module AsciiFilter
|
6
|
+
|
7
|
+
##
|
8
|
+
# Converts Unicode(and accented ASCII) characters to their plain-text ASCII equivalents.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# AsciiFilter.evaluate("EVOLUÇÃO") #=> "EVOLUCAO"
|
12
|
+
# AsciiFilter.evaluate("⠋⠗⠁⠝⠉⠑") #=> "france"
|
13
|
+
#
|
14
|
+
# @example Using as ActiveRecord::Base normalizer
|
15
|
+
# normalize :attribute_a, :with => :ascii
|
16
|
+
# normalize :attribute_b, :with => [:custom_filter, :ascii]
|
17
|
+
#
|
18
|
+
# @param [String] input A character sequence
|
19
|
+
# @return [String] The transliterated character sequence or the object itself
|
20
|
+
# @see http://rubydoc.info/gems/stringex/Stringex/Unidecoder Stringex::Unidecoder
|
21
|
+
def self.evaluate(input, *args)
|
22
|
+
input.kind_of?(String) ? Stringex::Unidecoder.decode(input) : input
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -14,16 +14,6 @@ module Normatron
|
|
14
14
|
value.gsub(regex, "")
|
15
15
|
end
|
16
16
|
|
17
|
-
def evaluate_strip(value, edges)
|
18
|
-
constructs = []
|
19
|
-
constructs << '\A\s*' if edges == :L || edges == :LR
|
20
|
-
constructs << '\s*\z' if edges == :R || edges == :LR
|
21
|
-
regex_string = constructs.join '|'
|
22
|
-
regex = Regexp.new(/#{regex_string}/)
|
23
|
-
|
24
|
-
value.gsub(regex, '')
|
25
|
-
end
|
26
|
-
|
27
17
|
def acronyms
|
28
18
|
inflections.acronyms
|
29
19
|
end
|
@@ -22,11 +22,23 @@ module Normatron
|
|
22
22
|
# normalize :attribute_e, :with => [:custom_filter, {:strip => :R}]
|
23
23
|
#
|
24
24
|
# @param [String] input A character sequence
|
25
|
-
# @param [Symbol]
|
25
|
+
# @param [Symbol] edges :L to strip trailing spaces, :R for leading spaces and :LR for both
|
26
26
|
# @return [String] The character sequence without trailing and leading spaces or the object itself
|
27
27
|
# @see http://www.ruby-doc.org/core-1.9.3/String.html#method-i-strip String#strip
|
28
|
-
def self.evaluate(input,
|
29
|
-
input.kind_of?(String)
|
28
|
+
def self.evaluate(input, edges=:LR)
|
29
|
+
return input unless input.kind_of?(String)
|
30
|
+
|
31
|
+
regex_string =
|
32
|
+
case edges
|
33
|
+
when :L
|
34
|
+
'\A\s*'
|
35
|
+
when :R
|
36
|
+
'\s*\z'
|
37
|
+
when :LR
|
38
|
+
'\A\s*|\s*\z'
|
39
|
+
end
|
40
|
+
regex = Regexp.new(/#{regex_string}/)
|
41
|
+
input.gsub(regex, '')
|
30
42
|
end
|
31
43
|
end
|
32
44
|
end
|
@@ -9,14 +9,14 @@ module Normatron
|
|
9
9
|
# Uppercase all characters.
|
10
10
|
#
|
11
11
|
# @example
|
12
|
-
#
|
12
|
+
# UpcaseFilter.evaluate("borderlands") #=> "BORDERLANDS"
|
13
13
|
#
|
14
14
|
# @example Using as ActiveRecord::Base normalizer
|
15
15
|
# normalize :attribute_a, :with => :upcase
|
16
16
|
# normalize :attribute_b, :with => [:custom_filter, :upcase]
|
17
17
|
#
|
18
|
-
# @
|
19
|
-
# @
|
18
|
+
# @param [String] input A character sequence
|
19
|
+
# @return [String] The uppercased character sequence or the object itself
|
20
20
|
# @see http://api.rubyonrails.org/classes/ActiveSupport/Multibyte/Chars.html#method-i-upcase ActiveSupport::Multibyte::Chars#upcase
|
21
21
|
# @see DownFilter Normatron::Filters::DownFilter
|
22
22
|
# @see TitleizeFilter Normatron::Filters::TitleizeFilter
|
data/lib/normatron/version.rb
CHANGED
@@ -21,28 +21,37 @@ describe Normatron::Configuration do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
describe :filters do
|
24
|
-
|
25
|
-
subject.filters[:
|
26
|
-
subject.filters[:
|
27
|
-
subject.filters[:
|
28
|
-
subject.filters[:
|
29
|
-
subject.filters[:
|
30
|
-
subject.filters[:
|
31
|
-
subject.filters[:
|
32
|
-
subject.filters[:
|
33
|
-
subject.filters[:
|
34
|
-
subject.filters[:
|
35
|
-
subject.filters[:
|
36
|
-
subject.filters[:
|
37
|
-
subject.filters[:
|
38
|
-
subject.filters[:
|
39
|
-
subject.filters[:
|
40
|
-
subject.filters[:
|
24
|
+
context "when initialized" do
|
25
|
+
it { subject.filters[:ascii] .should eq Normatron::Filters::AsciiFilter }
|
26
|
+
it { subject.filters[:blank] .should eq Normatron::Filters::BlankFilter }
|
27
|
+
it { subject.filters[:camelize] .should eq Normatron::Filters::CamelizeFilter }
|
28
|
+
it { subject.filters[:capitalize].should eq Normatron::Filters::CapitalizeFilter }
|
29
|
+
it { subject.filters[:chomp] .should eq Normatron::Filters::ChompFilter }
|
30
|
+
it { subject.filters[:dasherize] .should eq Normatron::Filters::DasherizeFilter }
|
31
|
+
it { subject.filters[:downcase] .should eq Normatron::Filters::DowncaseFilter }
|
32
|
+
it { subject.filters[:dump] .should eq Normatron::Filters::DumpFilter }
|
33
|
+
it { subject.filters[:keep] .should eq Normatron::Filters::KeepFilter }
|
34
|
+
it { subject.filters[:remove] .should eq Normatron::Filters::RemoveFilter }
|
35
|
+
it { subject.filters[:squeeze] .should eq Normatron::Filters::SqueezeFilter }
|
36
|
+
it { subject.filters[:squish] .should eq Normatron::Filters::SquishFilter }
|
37
|
+
it { subject.filters[:strip] .should eq Normatron::Filters::StripFilter }
|
38
|
+
it { subject.filters[:swapcase] .should eq Normatron::Filters::SwapcaseFilter }
|
39
|
+
it { subject.filters[:titleize] .should eq Normatron::Filters::TitleizeFilter }
|
40
|
+
it { subject.filters[:underscore].should eq Normatron::Filters::UnderscoreFilter }
|
41
|
+
it { subject.filters[:upcase] .should eq Normatron::Filters::UpcaseFilter }
|
41
42
|
end
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
44
|
+
context "when new filter is added" do
|
45
|
+
it "module filter should be set" do
|
46
|
+
subject.filters[:smile] = MyFilters::SmileFilter
|
47
|
+
subject.filters[:smile].should eq MyFilters::SmileFilter
|
48
|
+
end
|
49
|
+
|
50
|
+
it "lambda filter should be set" do
|
51
|
+
lambda_filter = lambda { |input, value| input << value }
|
52
|
+
subject.filters[:append] = lambda_filter
|
53
|
+
subject.filters[:append].should eq lambda_filter
|
54
|
+
end
|
46
55
|
end
|
47
56
|
|
48
57
|
it "should allow remove filters" do
|
@@ -10,13 +10,12 @@ describe Normatron::Extensions::ActiveRecord do
|
|
10
10
|
let(:model) { User }
|
11
11
|
|
12
12
|
before(:all) { ActiveRecord::Base.send(:include, Normatron::Extensions::ActiveRecord) }
|
13
|
-
before(:each) { model.
|
13
|
+
before(:each) { model.normalize_rules = nil }
|
14
14
|
after(:all) do
|
15
15
|
ActiveRecord.send(:remove_const, :Base)
|
16
16
|
load 'active_record/base.rb'
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
19
|
describe :normalize do
|
21
20
|
subject { model }
|
22
21
|
|
@@ -28,31 +27,31 @@ describe Normatron::Extensions::ActiveRecord do
|
|
28
27
|
|
29
28
|
it "should append default filters" do
|
30
29
|
subject.normalize :login, :email
|
31
|
-
subject.
|
30
|
+
subject.normalize_rules.should == { :login => configuration.default_filters,
|
32
31
|
:email => configuration.default_filters }
|
33
32
|
end
|
34
33
|
|
35
34
|
it "should stack filters for multiple calls" do
|
36
35
|
subject.normalize :login
|
37
36
|
subject.normalize :login, :with => :upcase
|
38
|
-
subject.
|
37
|
+
subject.normalize_rules.should == { :login => configuration.default_filters.merge({ :upcase => nil }) }
|
39
38
|
end
|
40
39
|
|
41
40
|
it "should append multiple attributes" do
|
42
41
|
subject.normalize :login, :email, :phone
|
43
|
-
subject.
|
42
|
+
subject.normalize_rules.should == { login: { squish: nil, blank: nil },
|
44
43
|
email: { squish: nil, blank: nil },
|
45
44
|
phone: { squish: nil, blank: nil } }
|
46
45
|
end
|
47
46
|
|
48
47
|
it "should allow multiple filters" do
|
49
48
|
subject.normalize :login, :with => [:upcase, :blank]
|
50
|
-
subject.
|
49
|
+
subject.normalize_rules.should == { login: { upcase: nil, blank: nil } }
|
51
50
|
end
|
52
51
|
|
53
52
|
it "should allow multiple filters" do
|
54
53
|
subject.normalize :login, :with => [[:keep, :L], { :remove => [:N] }]
|
55
|
-
subject.
|
54
|
+
subject.normalize_rules.should == { login: { keep: [:L], remove: [:N] } }
|
56
55
|
end
|
57
56
|
end
|
58
57
|
|
@@ -73,6 +72,22 @@ describe Normatron::Extensions::ActiveRecord do
|
|
73
72
|
subject.login.should eq "... =("
|
74
73
|
end
|
75
74
|
|
75
|
+
it "should run module filter" do
|
76
|
+
Normatron.configuration.filters[:smile] = MyFilters::SmileFilter
|
77
|
+
model.normalize :login, :with => :smile
|
78
|
+
subject.login = "hello!"
|
79
|
+
subject.apply_normalizations
|
80
|
+
subject.login.should eq "hello! =]"
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should run lambda filter" do
|
84
|
+
Normatron.configuration.filters[:dots] = lambda { |value| value + "..."}
|
85
|
+
model.normalize :login, :with => :dots
|
86
|
+
subject.login = "word"
|
87
|
+
subject.apply_normalizations
|
88
|
+
subject.login.should eq "word..."
|
89
|
+
end
|
90
|
+
|
76
91
|
it "should run native filter" do
|
77
92
|
model.normalize :login, :with => :squish
|
78
93
|
subject.login = " word "
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'normatron/filters/ascii_filter'
|
5
|
+
|
6
|
+
describe Normatron::Filters::AsciiFilter do
|
7
|
+
it_should_behave_like "string processor"
|
8
|
+
it_should_behave_like "evaluable filter", ["ÉBRIO" ], "EBRIO"
|
9
|
+
it_should_behave_like "evaluable filter", ["até" ], "ate"
|
10
|
+
it_should_behave_like "evaluable filter", ["cirurgião" ], "cirurgiao"
|
11
|
+
it_should_behave_like "evaluable filter", ["email@domain.com" ], "email@domain.com"
|
12
|
+
it_should_behave_like "evaluable filter", ["éçü&! *¬¬" ], "ecu&! *!!"
|
13
|
+
it_should_behave_like "evaluable filter", ["⠋⠗⠁⠝⠉⠑" ], "france"
|
14
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: normatron
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-10-
|
12
|
+
date: 2012-10-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -43,6 +43,22 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: 3.2.0
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: stringex
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.4.0
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.4.0
|
46
62
|
- !ruby/object:Gem::Dependency
|
47
63
|
name: sqlite3
|
48
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -106,13 +122,14 @@ files:
|
|
106
122
|
- lib/normatron/filters/helpers.rb
|
107
123
|
- lib/normatron/filters/downcase_filter.rb
|
108
124
|
- lib/normatron/filters/chomp_filter.rb
|
125
|
+
- lib/normatron/filters/ascii_filter.rb
|
109
126
|
- lib/normatron/extensions.rb
|
110
127
|
- lib/normatron/version.rb
|
111
128
|
- lib/normatron/extensions/active_record.rb
|
112
129
|
- lib/normatron.rb
|
113
130
|
- MIT-LICENSE
|
114
131
|
- Rakefile
|
115
|
-
- README.
|
132
|
+
- README.md
|
116
133
|
- spec/spec_helper.rb
|
117
134
|
- spec/support/user_model.rb
|
118
135
|
- spec/support/my_filters.rb
|
@@ -123,6 +140,7 @@ files:
|
|
123
140
|
- spec/normatron/filters/chomp_filter_spec.rb
|
124
141
|
- spec/normatron/filters/capitalize_filter_spec.rb
|
125
142
|
- spec/normatron/filters/upcase_filter_spec.rb
|
143
|
+
- spec/normatron/filters/ascii_filter_spec.rb
|
126
144
|
- spec/normatron/filters/strip_filter_spec.rb
|
127
145
|
- spec/normatron/filters/underscore_filter_spec.rb
|
128
146
|
- spec/normatron/filters/keep_filter_spec.rb
|
@@ -170,6 +188,7 @@ test_files:
|
|
170
188
|
- spec/normatron/filters/chomp_filter_spec.rb
|
171
189
|
- spec/normatron/filters/capitalize_filter_spec.rb
|
172
190
|
- spec/normatron/filters/upcase_filter_spec.rb
|
191
|
+
- spec/normatron/filters/ascii_filter_spec.rb
|
173
192
|
- spec/normatron/filters/strip_filter_spec.rb
|
174
193
|
- spec/normatron/filters/underscore_filter_spec.rb
|
175
194
|
- spec/normatron/filters/keep_filter_spec.rb
|
data/README.textile
DELETED
@@ -1,200 +0,0 @@
|
|
1
|
-
h1. Normatron
|
2
|
-
|
3
|
-
Normatron is a Ruby On Rails plugin that perform attribute normalizations for ActiveRecord objects.
|
4
|
-
With it you can normalize attributes to the desired format before saving them in the database.
|
5
|
-
This gem inhibits the work of having to override attributes or create a specific method to perform most of the normalizations.
|
6
|
-
|
7
|
-
h2. Installation
|
8
|
-
|
9
|
-
Let the bundler install the gem by adding the following into your application gemfile:
|
10
|
-
|
11
|
-
pre. gem 'normatron'
|
12
|
-
|
13
|
-
And then bundle it up:
|
14
|
-
|
15
|
-
pre. $ bundle install
|
16
|
-
|
17
|
-
Or install it by yourself:
|
18
|
-
|
19
|
-
pre. $ gem install normatron
|
20
|
-
|
21
|
-
Then run the generator:
|
22
|
-
|
23
|
-
pre. $ rails generator normatron:install
|
24
|
-
|
25
|
-
h2. The problem
|
26
|
-
|
27
|
-
Suppose you have a product model as the following:
|
28
|
-
|
29
|
-
pre. # ./db/migrate/20120101010000_create_products.rb
|
30
|
-
class CreateProducts < ActiveRecord::Migration
|
31
|
-
def change
|
32
|
-
create_table :products do |t|
|
33
|
-
t.string :name
|
34
|
-
t.decimal :price, :precision => 10, :scale => 2
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
pre. # ./app/models/products.rb
|
40
|
-
class Product < ActiveRecord::Base
|
41
|
-
attr_accessible :name, :price
|
42
|
-
end
|
43
|
-
|
44
|
-
And we want the _name_ attribute be uppercased before saving it into the database.
|
45
|
-
The most usual approach to do this includes:
|
46
|
-
|
47
|
-
* Override the _name_ setter and convert the value to an uppercased string.
|
48
|
-
* Write a method or block and bind it to the "before_validation":http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html callback.
|
49
|
-
|
50
|
-
Both ways are ilenegant, boring, error prone and very expensive.
|
51
|
-
What led me to make this gem and offer a third way to solve this issue:
|
52
|
-
|
53
|
-
h2. Usage
|
54
|
-
|
55
|
-
Normatron uses ":squish":http://rubydoc.info/gems/normatron/Normatron/Filters/SquishFilter and ":blank":http://rubydoc.info/gems/normatron/Normatron/Filters/BlankFilter as default filters.
|
56
|
-
These filters are applied to all attributes through "normalize":http://rubydoc.info/gems/normatron/Normatron/Extensions/ActiveRecord/ClassMethods#normalize-instance_method function, since no options is given.
|
57
|
-
|
58
|
-
pre. # ./app/models/products.rb
|
59
|
-
class Product < ActiveRecord::Base
|
60
|
-
attr_accessible :name, :price
|
61
|
-
normalize :name
|
62
|
-
end
|
63
|
-
|
64
|
-
pre. $ rails console
|
65
|
-
> memory = Product.create name: " memory card "
|
66
|
-
=> #<Product id: nil, name: "memory card", price: nil>
|
67
|
-
> null = Product.create name: " "
|
68
|
-
=> #<Product id: nil, name: nil, price: nil>
|
69
|
-
|
70
|
-
h3. Configurations
|
71
|
-
|
72
|
-
"normatron:install":http://rubydoc.info/gems/normatron/Normatron/InstallGenerator generator creates a configuration file located at @./config/initializers/normatron.rb@.
|
73
|
-
|
74
|
-
For now, you can set the default normalization filters or disable normatron by commenting the @add_orm@ line.
|
75
|
-
|
76
|
-
h3. Applying normalizations
|
77
|
-
|
78
|
-
Methods like "create":http://api.rubyonrails.org/classes/ActiveRecord/Persistence/ClassMethods.html#method-i-create, "valid?":http://api.rubyonrails.org/classes/ActiveRecord/Validations.html#method-i-valid-3F or "save":http://api.rubyonrails.org/classes/ActiveRecord/Validations.html#method-i-valid-3F always call the "apply_normalizations":http://rubydoc.info/gems/normatron/Normatron/Extensions/ActiveRecord/InstanceMethods#apply_normalizations-instance_method method, thought "before_validation":http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html callback.
|
79
|
-
This is the method that invokes all filters to their attributes. So you can perform the normalizations without necessarily having to perform the model validations.
|
80
|
-
|
81
|
-
pre. $ rails console
|
82
|
-
> product = Product.new name: " hard drive"
|
83
|
-
=> #<Product id: nil, name: " hard drive", price: nil>
|
84
|
-
> product.apply_normalizations
|
85
|
-
> product
|
86
|
-
=> #<Product id: nil, name: "hard drive", price: nil>
|
87
|
-
|
88
|
-
h3. Setting normalization rules
|
89
|
-
|
90
|
-
The @:with@ option allows to bind filters to one or more attribute.
|
91
|
-
|
92
|
-
pre. class Product < ActiveRecord::Base
|
93
|
-
normalize :name, :with => :upcase
|
94
|
-
end
|
95
|
-
|
96
|
-
pre. $ rails console
|
97
|
-
> Product.normalize_filters
|
98
|
-
=> { :name => { :upcase => [] } }
|
99
|
-
|
100
|
-
The filters passed throught @:with@ option will not stack with default filters.
|
101
|
-
When "normalize":http://rubydoc.info/gems/normatron/Normatron/Extensions/ActiveRecord/ClassMethods#normalize-instance_method method is used multiple times for the same attribute, it will stack the filter bindings.
|
102
|
-
|
103
|
-
pre. class Product < ActiveRecord::Base
|
104
|
-
normalize :name
|
105
|
-
normalize :name, :with => :upcase
|
106
|
-
end
|
107
|
-
|
108
|
-
pre. $ rails console
|
109
|
-
> Product.normalize_filters
|
110
|
-
=> { :name => { :squish => [],
|
111
|
-
:blank => [],
|
112
|
-
:upcase => [] } }
|
113
|
-
|
114
|
-
The same result can be obtained using:
|
115
|
-
|
116
|
-
pre. normalize :name, :with => [:squish, :blank, :upcase]
|
117
|
-
|
118
|
-
Some filters may use arguments to perferm normalizations.
|
119
|
-
There are two approaches to deal with filter arguments in Normatron:
|
120
|
-
|
121
|
-
a) Using a Hash where the key is the filter name and the value is an arguments Array.
|
122
|
-
|
123
|
-
pre. class Product < ActiveRecord::Base
|
124
|
-
normalize :name, :with => [ { :keep => [:Latin], :remove => [:Nd, :Zs] } ]
|
125
|
-
normalize :description, :with => :squeeze
|
126
|
-
normalize :brand, :with => { :squeeze => ["a-z"] }
|
127
|
-
end
|
128
|
-
|
129
|
-
b) Using an Array where the first element if the attribute name and rest is the filter arguments.
|
130
|
-
|
131
|
-
pre. class Product < ActiveRecord::Base
|
132
|
-
normalize :name, :with => [ [:keep, :Latin], [:remove, :Nd, :Zs] ]
|
133
|
-
normalize :description, :with => :squeeze
|
134
|
-
normalize :brand, :with => [ [:squeeze, "a-z"] ]
|
135
|
-
end
|
136
|
-
|
137
|
-
Both ways will produce the same result:
|
138
|
-
|
139
|
-
pre. $ rails console
|
140
|
-
> Product.normalize_filters
|
141
|
-
=> { :name => { :keep => [:Latin],
|
142
|
-
:remove => [:Nd, :Zs] },
|
143
|
-
:description => { :squeeze => [] },
|
144
|
-
:brand => { :squeeze => ["a-z"] } }
|
145
|
-
|
146
|
-
h3. Using instance method as filter
|
147
|
-
|
148
|
-
Create an instance method returning the value as you want.
|
149
|
-
The first argument is mandatory, and will receive the original value of the attribute.
|
150
|
-
If you need to use aditional arguments or varargs, just add them after the first argument.
|
151
|
-
|
152
|
-
<pre>
|
153
|
-
# ./app/models/client.rb
|
154
|
-
class Client < ActiveRecord::Base
|
155
|
-
normalize :phone, :with => [:custom_a, [:custom_b, :a, :b], {:custom_c => [:a, :b, :c]}]
|
156
|
-
normalize :mobile, :with => [:custom_a, {:custom_b => [:a, :b]}, [:custom_c, :a, :b, :c]]
|
157
|
-
|
158
|
-
def custom_a(value)
|
159
|
-
# ...
|
160
|
-
end
|
161
|
-
|
162
|
-
def custom_b(value, *args)
|
163
|
-
# ...
|
164
|
-
end
|
165
|
-
|
166
|
-
def custom_c(value, arg_a, arg_b, arg_c)
|
167
|
-
# ...
|
168
|
-
end
|
169
|
-
end
|
170
|
-
</pre>
|
171
|
-
|
172
|
-
h2. Filters
|
173
|
-
|
174
|
-
Information about native filters and how to use them can be found in "Normatron::Filters(Normatron::Filters Rubydoc)":http://rubydoc.info/gems/normatron/Normatron/Filters.
|
175
|
-
|
176
|
-
h1. Contributing
|
177
|
-
|
178
|
-
There are several ways to make this gem even better:
|
179
|
-
|
180
|
-
* Forking this project
|
181
|
-
* Adding new features or bug fixes
|
182
|
-
* Making tests
|
183
|
-
* Commiting your changes
|
184
|
-
* Reporting any bug or unexpected behavior
|
185
|
-
* Suggesting any improvement
|
186
|
-
* Sharing with your friends, forums, communities, job, etc...
|
187
|
-
* Helping users with difficulty using this gem
|
188
|
-
* Paying me a beer =]
|
189
|
-
|
190
|
-
h1. Credits
|
191
|
-
|
192
|
-
This gem was initially inspired on:
|
193
|
-
* "normalize_attributes (normalize_attributes Gem)":https://github.com/fnando/normalize_attributes - I liked the cleaner code and simplicity of this gem.
|
194
|
-
* "attribute_normalizer (attribute_normalizer Gem)":https://github.com/mdeering/attribute_normalizer - Very powerful.
|
195
|
-
|
196
|
-
The idea is to mix the good things of both gems, adding some features and changing something to fit my taste.
|
197
|
-
|
198
|
-
h1. License
|
199
|
-
|
200
|
-
See file attached to source code or click "here":https://github.com/fernandors87/normatron/blob/master/MIT-LICENSE.
|