model_formatter 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ debug.log
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
data/CHANGELOG ADDED
@@ -0,0 +1,5 @@
1
+ *svn*
2
+ * added option to pass instance of a formatter
3
+ * added options to instantiation of the formatter
4
+ * added precision options to currency formatter, which now also stores currencies as an integer
5
+ * exposed formatters as class methods
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in model_formatter.gemspec
4
+ gemspec
5
+
6
+ gem 'rails'
7
+ gem 'rake', '0.8.7'
8
+ gem 'sqlite3'
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2005 Geoffrey Grosenbach
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.
data/README.md ADDED
@@ -0,0 +1,62 @@
1
+ ## Overview
2
+
3
+ The ModelFormatter module allows you to easily handle fields that need to be formatted or stripped
4
+ of formatting as they are set or retrieved from the database. You can designate one or more of your
5
+ columns as "formatted columns" like in this example:
6
+
7
+ class Widget < ActiveRecord::Base
8
+ # Set an integer field as a symbol
9
+ format_column :some_integer, :as => :integer
10
+
11
+ # Specify the type as a class
12
+ format_column :sales_tax, :as => Formatters::FormatCurrency
13
+ format_column :sales_tax, :as => Formatters::FormatCurrency.new(:precision => 4)
14
+
15
+ # Change the prefix of the generated methods and specify type as a symbol
16
+ format_column :sales_tax, :prefix => 'fmt_', :as => :currency, :options => {:precision => 4}
17
+
18
+ # Use specific procedures to convert the data +from+ and +to+ the target
19
+ format_column :area, :from => Proc.new {|value, options| number_with_delimiter sprintf('%2d', value)},
20
+ :to => Proc.new {|str, options| str.gsub(/,/, '')}
21
+
22
+ # Use a block to define the formatter methods
23
+ format_column :sales_tax do
24
+ def from(value, options = {})
25
+ number_to_currency value
26
+ end
27
+ def to(str, options = {})
28
+ str.gsub(/[\$,]/, '')
29
+ end
30
+ end
31
+
32
+ ...
33
+ end
34
+
35
+ The methods of this module are automatically included into `ActiveRecord::Base`
36
+ as class methods, so that you can use them in your models.
37
+
38
+
39
+ ## Documentation
40
+
41
+ For more detailed documentation, create the rdocs with the following command:
42
+
43
+ rake rdoc
44
+
45
+
46
+ ## Running Unit Tests
47
+
48
+ By default, the ModelFormatter plugin uses the mysql +test+ database, running on +localhost+. To run the tests, enter the following:
49
+
50
+ rake
51
+
52
+
53
+ ## Bugs & Feedback
54
+
55
+ Please file a bug report at http://github.com/bfolkens/model-formatter/issues
56
+
57
+ [![Build Status](https://secure.travis-ci.org/bfolkens/model-formatter.png)](http://travis-ci.org/bfolkens/model-formatter)
58
+
59
+ ## Credits
60
+
61
+ Sebastian Kanthak's file_column plugin - used for ideas and best practices.
62
+
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+
6
+ desc 'Default: run unit tests.'
7
+ task :default => :test
8
+
9
+ desc 'Test the model_formatter plugin.'
10
+ Rake::TestTask.new(:test) do |t|
11
+ t.libs << 'lib'
12
+ t.pattern = 'test/**/*_test.rb'
13
+ t.verbose = true
14
+ end
15
+
16
+ desc 'Generate documentation for the model_formatter plugin.'
17
+ Rake::RDocTask.new(:rdoc) do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = 'ModelFormatter'
20
+ rdoc.options << '--line-numbers' << '--inline-source'
21
+ rdoc.rdoc_files.include('README')
22
+ rdoc.rdoc_files.include('lib/**/*.rb')
23
+ end
data/lib/formatters.rb ADDED
@@ -0,0 +1,8 @@
1
+ module Formatters
2
+ FORMATTERS_BASE_PATH = File.join(File.dirname(__FILE__), 'formatters') unless defined? FORMATTERS_BASE_PATH
3
+
4
+ require File.join(FORMATTERS_BASE_PATH, 'format.rb')
5
+ Dir[File.join(FORMATTERS_BASE_PATH, 'format_*.rb')].each do |formatter|
6
+ require formatter
7
+ end
8
+ end
@@ -0,0 +1,23 @@
1
+ module Formatters
2
+ class Format
3
+ def initialize(options = {})
4
+ end
5
+
6
+ def from(value, options = {})
7
+ raise FormatNotDefinedException
8
+ end
9
+
10
+ def to(str, options = {})
11
+ raise FormatNotDefinedException
12
+ end
13
+ end
14
+
15
+ class FormattingException < Exception
16
+ end
17
+
18
+ class FormatNotDefinedException < Exception
19
+ end
20
+
21
+ class FormatNotFoundException < Exception
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ module Formatters
2
+ class FormatBoolean < Format
3
+ def initialize(options = {})
4
+ @on = 'yes'
5
+ @off = 'no'
6
+ end
7
+
8
+ def from(value, options = {})
9
+ value ? @on : @off
10
+ end
11
+
12
+ def to(str, options = {})
13
+ str == @on
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ require 'rubygems'
2
+ require 'action_view'
3
+
4
+ module Formatters
5
+ class FormatCurrency < Format
6
+ include ActionView::Helpers::NumberHelper
7
+
8
+ def initialize(options = {})
9
+ @precision = options[:precision] || 2
10
+ end
11
+
12
+ def from(value, options = {})
13
+ options = {:precision => @precision}.merge(options)
14
+ number_to_currency(value.to_f / (10 ** @precision), options)
15
+ end
16
+
17
+ def to(str, options = {})
18
+ return nil if str.nil? or str.empty?
19
+ val = str.gsub(/[^0-9.\-]/, '').to_f
20
+ (val * (10 ** @precision)) unless val.nil?
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+ require 'action_view'
3
+
4
+ module Formatters
5
+ class FormatDecimal < Format
6
+ include ActionView::Helpers::NumberHelper
7
+
8
+ def initialize(options = {})
9
+ end
10
+
11
+ def from(value, options = {})
12
+ options = {:precision => 3, :delimiter => ','}.merge(options)
13
+ number_with_precision value, options
14
+ end
15
+
16
+ def to(str, options = {})
17
+ return nil if str.nil? or str.empty?
18
+ str.gsub(/,/, '').to_f
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+ require 'action_view'
3
+
4
+ module Formatters
5
+ class FormatInteger < Format
6
+ include ActionView::Helpers::NumberHelper
7
+
8
+ def initialize(options = {})
9
+ end
10
+
11
+ def from(value, options = {})
12
+ options = {:delimiter => ','}.merge(options)
13
+ number_with_delimiter value, options
14
+ end
15
+
16
+ def to(str, options = {})
17
+ return nil if str.nil? or str.empty?
18
+ str.gsub(/,/, '').to_i
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ require 'action_view'
3
+
4
+ module Formatters
5
+ class FormatPercent < Format
6
+ include ActionView::Helpers::NumberHelper
7
+
8
+ def initialize(options = {})
9
+ end
10
+
11
+ def from(value, options = {})
12
+ number_to_percentage value, options
13
+ end
14
+
15
+ def to(str, options = {})
16
+ return nil if str.nil? or str.empty?
17
+ str.gsub(/[^0-9\.\-]/, '').to_f
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ require 'action_view'
3
+
4
+ module Formatters
5
+ class FormatPhone < Format
6
+ include ActionView::Helpers::NumberHelper
7
+
8
+ def initialize(options = {})
9
+ end
10
+
11
+ def from(value, options = {})
12
+ number_to_phone value, options
13
+ end
14
+
15
+ def to(str, options = {})
16
+ return nil if str.nil? or str.empty?
17
+ str.gsub(/[^0-9]/, '').to_i
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,222 @@
1
+ class Object
2
+ # The hidden singleton lurks behind everyone
3
+ def metaclass; class << self; self; end; end
4
+ def meta_eval &blk; metaclass.instance_eval &blk; end
5
+
6
+ # Adds methods to a metaclass
7
+ def meta_def name, &blk
8
+ meta_eval { define_method name, &blk }
9
+ end
10
+
11
+ # Defines an instance method within a class
12
+ def class_def name, &blk
13
+ class_eval { define_method name, &blk }
14
+ end
15
+ end
16
+
17
+ module ModelFormatter # :nodoc:
18
+ DEFAULT_FORMAT_PREFIX = 'formatted_'
19
+
20
+ def self.append_features(base) # :nodoc:
21
+ super
22
+ base.extend(ClassMethods)
23
+ end
24
+
25
+ def self.init_options(defaults, model, attr) # :nodoc:
26
+ options = defaults.dup
27
+ options[:attr] = attr
28
+ options[:prefix] ||= DEFAULT_FORMAT_PREFIX
29
+ options[:formatted_attr] ||= "#{options[:prefix]}#{attr}"
30
+
31
+ # If :as is set, then it must be either a formatter Class, formatter Object, Symbol, or String
32
+ options[:formatter] = formatter_for(options[:as], options[:options]) unless options[:as].nil?
33
+
34
+ # Define the formatter from a :block if :block is defined
35
+ options[:formatter] = define_formatter(attr, &options[:block]) unless options[:block].nil?
36
+
37
+ # Define :formatter from a block based on :from and :to if they're both set
38
+ if !options[:from].nil? and !options[:to].nil?
39
+ options[:formatter] = Module.new
40
+ options[:formatter].class.send :define_method, :from, options[:from]
41
+ options[:formatter].class.send :define_method, :to, options[:to]
42
+ end
43
+
44
+ # If :as is still not defined raise an error
45
+ raise 'No formatting options have been defined.' if options[:formatter].nil?
46
+
47
+ options
48
+ end
49
+
50
+ # Define a formatter like the actual physical classes
51
+ # this could easily be done with text and an eval...
52
+ # but this should be faster
53
+ def self.define_formatter(attr, &formatter) # :nodoc:
54
+ # The convention is to name these custom formatters
55
+ # differently than the other formatting classes
56
+ class_name = "CustomFormat#{attr.to_s.camelize}"
57
+
58
+ # Create a class in the same module as the others
59
+ clazz = Class.new(Formatters::Format)
60
+ silence_warnings do
61
+ Formatters.const_set class_name, clazz
62
+ end
63
+
64
+ # Define the class body
65
+ clazz.class_eval &formatter
66
+ return clazz.new
67
+ end
68
+
69
+ # Return the formatter for a class, formatter object, symbol, or
70
+ # string defining the name of a formatter class. If it's a symbol, check
71
+ # the Formatters module for the class that matches the camelized name
72
+ # of the symbol with 'Format' prepended. Options hash is passed to the
73
+ # instantiation of the formatter object.
74
+ def self.formatter_for(type_name, options = {}) # :nodoc:
75
+ # If the type_name is an instance of a formatter, just return with it
76
+ return type_name if type_name.is_a? Formatters::Format
77
+
78
+ # If the type_name is a class just assign it to the formatter_class for instantiation later
79
+ formatter_class = type_name if type_name.is_a? Class
80
+
81
+ # Format a symbol or string into a formatter_class
82
+ if type_name.is_a? Symbol or type_name.is_a? String
83
+ type_name = type_name.to_s.camelize
84
+
85
+ # Construct the class name from the type_name
86
+ formatter_name = "Format#{type_name}"
87
+ formatter_class = nil
88
+ begin
89
+ formatter_class = Formatters.const_get(formatter_name)
90
+ rescue NameError => ne
91
+ # Ignore this, caught below
92
+ end
93
+ end
94
+
95
+ # Make sure the name of this is found in the Formatters module and that
96
+ # it's the correct superclass
97
+ return formatter_class.new(options) unless formatter_class.nil? or
98
+ formatter_class.superclass != Formatters::Format
99
+
100
+ raise Formatters::FormatNotFoundException.new("Cannot find formatter 'Formatters::#{formatter_name}'")
101
+ end
102
+
103
+ require File.dirname(__FILE__) + '/formatters.rb'
104
+
105
+ # == Usage
106
+ # class Widget < ActiveRecord::Base
107
+ # # Set an integer field as a symbol
108
+ # format_column :some_integer, :as => :integer
109
+ #
110
+ # # Specify the type as a class
111
+ # format_column :sales_tax, :as => Formatters::FormatCurrency
112
+ # format_column :sales_tax, :as => Formatters::FormatCurrency.new(:precision => 4)
113
+ #
114
+ # # Change the prefix of the generated methods and specify type as a symbol
115
+ # format_column :sales_tax, :prefix => 'fmt_', :as => :currency, :options => {:precision => 4}
116
+ #
117
+ # # Use specific procedures to convert the data +from+ and +to+ the target
118
+ # format_column :area, :from => Proc.new {|value, options| number_with_delimiter sprintf('%2d', value)},
119
+ # :to => Proc.new {|str, options| str.gsub(/,/, '')}
120
+ #
121
+ # # Use a block to define the formatter methods
122
+ # format_column :sales_tax do
123
+ # def from(value, options = {})
124
+ # number_to_currency value
125
+ # end
126
+ # def to(str, options = {})
127
+ # str.gsub(/[\$,]/, '')
128
+ # end
129
+ # end
130
+ #
131
+ # ...
132
+ # end
133
+ module ClassMethods
134
+
135
+ # You can override the default options with +model_formatter+'s +options+ parameter
136
+ DEFAULT_OPTIONS = {
137
+ :prefix => nil,
138
+ :formatted_attr => nil,
139
+ :as => nil,
140
+ :from => nil,
141
+ :to => nil,
142
+ :options => {}
143
+ }.freeze
144
+
145
+ # After calling "<tt>format_column :sales_tax</tt>" as in the example above, a number of instance methods
146
+ # will automatically be generated, all prefixed by "formatted_" unless :prefix or :formatter_attr
147
+ # have been set:
148
+ #
149
+ # * <tt>Widget.sales_tax_formatter(value)</tt>: Format the sales tax and return the formatted version
150
+ # * <tt>Widget.sales_tax_unformatter(str)</tt>: "Un"format sales tax and return the unformatted version
151
+ # * <tt>Widget#formatted_sales_tax=(value)</tt>: This will set the <tt>sales_tax</tt> of the widget using the value stripped of its formatting.
152
+ # * <tt>Widget#formatted_sales_tax</tt>: This will return the <tt>sales_tax</tt> of the widget using the formatter specified in the options to +format+.
153
+ # * <tt>Widget#sales_tax_formatting_options</tt>: Access the options this formatter was created with. Useful for declaring field length and later referencing it in display helpers.
154
+ #
155
+ # === Options:
156
+ # * <tt>:formatted_attr</tt> - The actual name used for the formatted attribute. By default, the formatted attribute
157
+ # name is composed of the <tt>:prefix</tt>, followed by the name of the attribute.
158
+ # * <tt>:prefix</tt> - Change the prefix prepended to the formatted columns. By default, formatted columns
159
+ # are prepended with "formatted_".
160
+ # * <tt>:as</tt> - Format the column as the specified format. This can be provided in either a String,
161
+ # a Symbol, or as a Class reference to the formatter. The class should subclass Formatters::Format and define <tt>from(value, options = {})</tt> and <tt>to(str, options = {})</tt>.
162
+ # * <tt>:from</tt> - Data coming from the attribute retriever method is sent to this +Proc+, then returned as a
163
+ # manipulated attribute.
164
+ # * <tt>:to</tt> - Data being sent to the attribute setter method is sent to this +Proc+ first to be manipulated,
165
+ # and the returned attribute is then sent to the attribute setter.
166
+ # * <tt>:options</tt> - Passed to the formatter blocks, instantiating formatter classes and/or methods as additional formatting options.
167
+ def format_column(attr, options={}, &fmt_block)
168
+ options[:block] = fmt_block if block_given?
169
+ options = DEFAULT_OPTIONS.merge(options) if options
170
+
171
+ # Create the actual options
172
+ my_options = ModelFormatter::init_options(options,
173
+ ActiveSupport::Inflector.underscore(self.name).to_s,
174
+ attr.to_s)
175
+
176
+
177
+ # Create the class methods
178
+ attr_fmt_options_accessor = "#{my_options[:formatted_attr]}_formatting_options".to_sym
179
+ attr_formatter_method = "#{my_options[:formatted_attr]}_formatter".to_sym
180
+ attr_unformatter_method = "#{my_options[:formatted_attr]}_unformatter".to_sym
181
+
182
+ metaclass.class_eval do
183
+ # Create an options accessor
184
+ define_method attr_fmt_options_accessor do
185
+ my_options
186
+ end
187
+
188
+ # Define a formatter accessor
189
+ define_method attr_formatter_method do |value|
190
+ return value if value.nil?
191
+
192
+ from_method = my_options[:formatter].method(:from)
193
+ from_method.call(value, my_options[:options])
194
+ end
195
+
196
+ # Define an unformatter accessor
197
+ define_method attr_unformatter_method do |str|
198
+ to_method = my_options[:formatter].method(:to)
199
+ to_method.call(str, my_options[:options])
200
+ end
201
+ end
202
+
203
+ # Define the instance method formatter for attr
204
+ define_method my_options[:formatted_attr] do |*params|
205
+ value = self.send(attr, *params)
206
+ self.class.send attr_formatter_method, value
207
+ end
208
+
209
+ # Define the instance method unformatter for attr
210
+ define_method my_options[:formatted_attr] + '=' do |str|
211
+ value = self.class.send(attr_unformatter_method, str)
212
+ self.send(attr.to_s + '=', value)
213
+ end
214
+ end
215
+
216
+ def is_formatted?(attr)
217
+ !public_methods.reject {|method| method !~ /#{attr.to_s}_formatting_options$/}.empty?
218
+ end
219
+ end
220
+ end
221
+
222
+ ActiveRecord::Base.send(:include, ModelFormatter)
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "model_formatter"
6
+ s.version = '0.0.3'
7
+ s.authors = ["Brad Folkens", "Tyler Rick"]
8
+ s.email = ["bfolkens@gmail.com", "tyler@tylerrick.com"]
9
+ s.homepage = "https://github.com/bfolkens/model-formatter"
10
+ s.summary = %q{Allows you to easily handle fields in Rails / ActiveRecord that need to be formatted or stripped of formatting as they are set or retrieved from the database.}
11
+ s.description = s.summary
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ s.require_paths = ["lib"]
17
+ end
@@ -0,0 +1,11 @@
1
+ require 'logger'
2
+
3
+ ActiveRecord::Base.logger = Logger.new("debug.log")
4
+ ActiveRecord::Base.establish_connection(
5
+ :adapter => "sqlite3",
6
+ :database => ":memory:",
7
+ :timeout => 500
8
+ )
9
+
10
+ load File.dirname(__FILE__) + "/fixtures/schema.rb"
11
+
@@ -0,0 +1,2 @@
1
+ class Entry < ActiveRecord::Base
2
+ end
@@ -0,0 +1,11 @@
1
+ ActiveRecord::Schema.define do
2
+ create_table :entries, :force => true do |t|
3
+ t.column :some_integer, :integer
4
+ t.column :some_boolean, :boolean
5
+ t.column :sales_tax, :integer
6
+ t.column :super_precise_tax, :integer
7
+ t.column :area, :float
8
+ t.column :complex_field, :string
9
+ t.column :phone, :integer
10
+ end
11
+ end
@@ -0,0 +1,136 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'active_support'
4
+ require 'active_record'
5
+ require 'action_view'
6
+
7
+ $:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
8
+ $:.unshift File.expand_path(File.dirname(__FILE__))
9
+
10
+ require 'connection'
11
+ require 'model_formatter'
12
+ require 'fixtures/entry'
13
+
14
+
15
+ class ModelFormatterTest < Test::Unit::TestCase
16
+ def setup
17
+ Entry.format_column :some_integer, :as => :integer
18
+ Entry.format_column :some_boolean, :prefix => 'fmt_', :as => :boolean
19
+
20
+ Entry.format_column :sales_tax, :as => :currency, :options => {:precision => 3}
21
+ Entry.format_column :super_precise_tax, :as => Formatters::FormatCurrency.new(:precision => 6)
22
+
23
+ Entry.format_column :area, :from => Proc.new {|value, options| sprintf('%2d', value) + options[:sample_format]},
24
+ :to => Proc.new {|str, options| str.gsub(/[^0-9]/, '').to_i},
25
+ :options => {:sample_format => ' sq. ft.'}
26
+
27
+ Entry.format_column :complex_field do
28
+ def from(value, options = {})
29
+ 'bouya ' + value
30
+ end
31
+
32
+ def to(str, options = {})
33
+ str.gsub(/^bouya /, '')
34
+ end
35
+ end
36
+
37
+ Entry.format_column :phone, :as => :phone
38
+ end
39
+
40
+ def test_should_define_format_accessors
41
+ assert Entry.respond_to?('formatted_some_integer_formatter')
42
+ assert Entry.respond_to?('formatted_some_integer_unformatter')
43
+ end
44
+
45
+ def test_should_define_getters
46
+ assert Entry.new.respond_to?('formatted_some_integer')
47
+ assert Entry.new.respond_to?('fmt_some_boolean')
48
+ assert Entry.new.respond_to?('formatted_sales_tax')
49
+ assert Entry.new.respond_to?('formatted_super_precise_tax')
50
+ assert Entry.new.respond_to?('formatted_area')
51
+ assert Entry.new.respond_to?('formatted_complex_field')
52
+ assert Entry.new.respond_to?('formatted_phone')
53
+ end
54
+
55
+ def test_should_define_setters
56
+ assert Entry.new.respond_to?('formatted_some_integer=')
57
+ assert Entry.new.respond_to?('fmt_some_boolean=')
58
+ assert Entry.new.respond_to?('formatted_sales_tax=')
59
+ assert Entry.new.respond_to?('formatted_super_precise_tax=')
60
+ assert Entry.new.respond_to?('formatted_area=')
61
+ assert Entry.new.respond_to?('formatted_complex_field=')
62
+ assert Entry.new.respond_to?('formatted_phone=')
63
+ end
64
+
65
+ def test_should_know_formatters
66
+ assert !Entry.is_formatted?(:id)
67
+
68
+ assert Entry.is_formatted?(:some_integer)
69
+ assert Entry.is_formatted?(:some_boolean)
70
+ assert Entry.is_formatted?(:sales_tax)
71
+
72
+ assert Entry.is_formatted?('super_precise_tax')
73
+ assert Entry.is_formatted?('area')
74
+ assert Entry.is_formatted?('complex_field')
75
+ assert Entry.is_formatted?('phone')
76
+ end
77
+
78
+ def test_should_respond_to_basic_definition
79
+ e = Entry.new
80
+
81
+ assert_equal '3,123', Entry.formatted_some_integer_formatter(3123)
82
+ e.some_integer = 3123
83
+ assert_equal '3,123', e.formatted_some_integer
84
+
85
+ assert_equal 3123, Entry.formatted_some_integer_unformatter('3,123')
86
+ e.formatted_some_integer = '3,123'
87
+ assert_equal 3123, e.some_integer
88
+ end
89
+
90
+ def test_should_respond_to_proc_definition
91
+ e = Entry.new
92
+
93
+ assert_equal '3123 sq. ft.', Entry.formatted_area_formatter(3123)
94
+ e.area = 3123
95
+ assert_equal '3123 sq. ft.', e.formatted_area
96
+
97
+ assert_equal 3123, Entry.formatted_area_unformatter('3123 sq. ft.')
98
+ e.formatted_area = '3123 sq. ft.'
99
+ assert_equal 3123, e.area
100
+ end
101
+
102
+ def test_should_respond_to_block_definition
103
+ e = Entry.new
104
+
105
+ assert_equal 'bouya test me', Entry.formatted_complex_field_formatter('test me')
106
+ e.complex_field = 'test me'
107
+ assert_equal 'bouya test me', e.formatted_complex_field
108
+
109
+ assert_equal 'here and bouya there', Entry.formatted_complex_field_unformatter('bouya here and bouya there')
110
+ e.formatted_complex_field = 'bouya here and bouya there'
111
+ assert_equal 'here and bouya there', e.complex_field
112
+ end
113
+
114
+ def test_should_pass_options_upon_instantiation
115
+ e = Entry.new
116
+
117
+ # Check format accessors
118
+ assert_equal '$12,412.292', Entry.formatted_sales_tax_formatter(12412292)
119
+ assert_equal 12412292, Entry.formatted_sales_tax_unformatter('$12,412.292')
120
+
121
+ # Check symbol use
122
+ e.sales_tax = 12412292
123
+ assert_equal '$12,412.292', e.formatted_sales_tax
124
+
125
+ e.formatted_sales_tax = '$12,412.292'
126
+ assert_equal 12412292, e.sales_tax
127
+
128
+ # Check instance use
129
+ e.super_precise_tax = 12412292888
130
+ assert_equal '$12,412.292888', e.formatted_super_precise_tax
131
+
132
+ e.formatted_super_precise_tax = '$12,412.292888'
133
+ assert_equal 12412292888, e.super_precise_tax
134
+ end
135
+ end
136
+
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: model_formatter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Brad Folkens
9
+ - Tyler Rick
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2014-10-10 00:00:00.000000000 Z
14
+ dependencies: []
15
+ description: Allows you to easily handle fields in Rails / ActiveRecord that need
16
+ to be formatted or stripped of formatting as they are set or retrieved from the
17
+ database.
18
+ email:
19
+ - bfolkens@gmail.com
20
+ - tyler@tylerrick.com
21
+ executables: []
22
+ extensions: []
23
+ extra_rdoc_files: []
24
+ files:
25
+ - .gitignore
26
+ - .travis.yml
27
+ - CHANGELOG
28
+ - Gemfile
29
+ - MIT-LICENSE
30
+ - README.md
31
+ - Rakefile
32
+ - lib/formatters.rb
33
+ - lib/formatters/format.rb
34
+ - lib/formatters/format_boolean.rb
35
+ - lib/formatters/format_currency.rb
36
+ - lib/formatters/format_decimal.rb
37
+ - lib/formatters/format_integer.rb
38
+ - lib/formatters/format_percent.rb
39
+ - lib/formatters/format_phone.rb
40
+ - lib/model_formatter.rb
41
+ - model_formatter.gemspec
42
+ - test/connection.rb
43
+ - test/fixtures/entry.rb
44
+ - test/fixtures/schema.rb
45
+ - test/model_formatter_test.rb
46
+ homepage: https://github.com/bfolkens/model-formatter
47
+ licenses: []
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ segments:
59
+ - 0
60
+ hash: 126899651837855101
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ segments:
68
+ - 0
69
+ hash: 126899651837855101
70
+ requirements: []
71
+ rubyforge_project:
72
+ rubygems_version: 1.8.23.2
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: Allows you to easily handle fields in Rails / ActiveRecord that need to be
76
+ formatted or stripped of formatting as they are set or retrieved from the database.
77
+ test_files: []