simple_model 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,26 +4,13 @@ module SimpleModel
4
4
  require 'date'
5
5
  require 'bigdecimal'
6
6
  require 'bigdecimal/util'
7
-
8
- Object.class_eval do
9
-
10
- # Expects an array of symboles representing methods for casting the object
11
- # EX: "1".cast_to(:float) # => 1.0
12
- def cast_to(methods=[])
13
- val = self
14
- methods.each do |method|
15
- val = val.send(method)
16
- end
17
- val
18
- end
19
- end
20
7
 
21
- Float.class_eval do
22
-
23
- # any value greater than 0.0 is true
8
+ Float.class_eval do
9
+ # that does not equal 0.0 is true
24
10
  def to_b
25
- self > 0.0
11
+ self != 0.0
26
12
  end
13
+
27
14
  # Rounds float to the precision specified
28
15
  # 100.5235.round_to #=> 101.0
29
16
  # 100.5235.round_to(1) #=> 101.5
@@ -40,8 +27,7 @@ module SimpleModel
40
27
  end
41
28
 
42
29
  # Returns a string with representation of currency, rounded to nearest hundredth
43
- def to_currency_s(symbol="$")
44
-
30
+ def to_currency_s(symbol="$")
45
31
  num = self.round_to(2).to_s
46
32
  neg = num.include?("-")
47
33
  while num.index('.') != (num.length-3)
@@ -59,9 +45,16 @@ module SimpleModel
59
45
  end
60
46
  num
61
47
  end
48
+
49
+ def to_time
50
+ Time.at(self)
51
+ end
52
+
53
+ def to_date
54
+ Time.at(self).to_date
55
+ end
62
56
  end
63
57
 
64
-
65
58
  #Extend Ruby String.rb
66
59
  String.class_eval do
67
60
 
@@ -70,21 +63,22 @@ module SimpleModel
70
63
  ['1',"true", "t"].include?(self)
71
64
  end
72
65
 
73
-
74
66
  # Takes known US formatted date/time strings (MM/DD/YYYY TIME) and converts
75
- # them to international format (YYYY/MM/DD TIME)
67
+ # them to international format (YYYY/MM/DD TIME). Also cleans up C# JSON
68
+ # Date (really a time integer) value.
76
69
  #
77
- # * safe_date_string("12/31/2010") # => '2010-12-31'
78
- # * safe_date_string("12/31/2010T23:30:25") # => '2010-12-31T23:30:25'
79
- # * safe_date_string("12/31/2010 23:30:25") # => '2010-12-31 23:30:25'
70
+ # * safe_date_string("12/31/2010") # => '2010-12-31'
71
+ # * safe_date_string("12/31/2010T23:30:25") # => '2010-12-31T23:30:25'
72
+ # * safe_date_string("12/31/2010 23:30:25") # => '2010-12-31 23:30:25'
73
+ # * safe_date_string("\/Date(1310669017000)\/") # =>
80
74
  def safe_datetime_string
81
- date = self
82
- date_string = ""
83
- if date[0..9].match(/^(0[1-9]|[1-9]|1[012])[- \/.]([1-9]|0[1-9]|[12][0-9]|3[01])[- \/.][0-9][0-9][0-9][0-9]/)
84
- if date.include?("/")
85
- split = date.split("/")
75
+ safe_date = nil
76
+ if self[0..9].match(/^(0[1-9]|[1-9]|1[012])[- \/.]([1-9]|0[1-9]|[12][0-9]|3[01])[- \/.][0-9][0-9][0-9][0-9]/)
77
+ safe_date = ""
78
+ if self.include?("/")
79
+ split = self.split("/")
86
80
  else
87
- split = date.split("-")
81
+ split = self.split("-")
88
82
  end
89
83
  time = ""
90
84
  if split[2].length > 4
@@ -92,108 +86,111 @@ module SimpleModel
92
86
  split[2] = split[2][0..3]
93
87
  end
94
88
  if split.length == 3 && split[2].length == 4
95
- date_string << "#{split[2]}-#{split[0]}-#{split[1]}"
96
- date_string << "#{time}" unless time.nil? || time.to_s.length == 0
89
+ safe_date << "#{split[2]}-#{split[0]}-#{split[1]}"
90
+ safe_date << "#{time}" unless time.nil? || time.to_s.length == 0
97
91
  end
92
+ elsif self.match(/^\/Date\(/)
93
+ safe_date = Time.at(((self.gsub(/(\/Date\()/,"")).gsub(/\)\/$/,"").to_f) / 1000).to_s
94
+ else
95
+ safe_date = self
98
96
  end
99
- date_string = date if date_string.length == 0
100
- date_string
97
+ safe_date
101
98
  end
102
99
 
103
100
  # Use safe_datetime_string help with those pesky US date formats in Ruby 1.9
101
+ # or to change an integer string to date
104
102
  def to_date
103
+ return safe_datetime_string.to_i.to_date if self.match(/^+d$/)
105
104
  Date.parse(safe_datetime_string)
106
105
  end
107
106
 
108
107
  # Use safe_datetime_string help with those pesky US date formats in Ruby 1.9
108
+ # or to change an integer string to date
109
109
  def to_time
110
+ return safe_datetime_string.to_i.to_time if self.match(/^+d$/)
110
111
  Time.parse(safe_datetime_string)
111
112
  end
112
113
 
113
-
114
- alias :old_to_f :to_f
114
+ alias :core_to_f :to_f
115
115
 
116
116
  # Remove none numeric characters then run default ruby float cast
117
117
  def to_f
118
- gsub(/[^0-9\.\+\-]/, '').old_to_f
118
+ gsub(/[^0-9\.\+\-]/, '').core_to_f
119
119
  end
120
-
121
- # Cleans all none pertinent characters and returns a BigDecimal rounded to nearest hundredth
122
- # Why decimal?..because precision matters when dealing with money ;)
123
- def to_currency
124
- gsub(/[^0-9\.\+\-]/, '').to_d.round(2)
120
+
121
+ alias :core_to_d :to_d
122
+
123
+ def to_d
124
+ gsub(/[^0-9\.\+\-]/, '').core_to_d
125
125
  end
126
-
126
+ alias :to_currency :to_d
127
+
128
+ end
127
129
 
128
- # Parse a full name into it's parts. http://pastie.org/867415
129
- # Based on :http://artofmission.com/articles/2009/5/31/parse-full-names-with-ruby
130
- #
131
- # Options:
132
- # +name+
133
- # +seperate_middle_name+ defaults to true. if false, will combine middle name into last name.
134
-
135
- def parse_name(seperate_middle_name=true)
136
- str = self
137
- if str.include?(',') # Rearrange names formatted as Doe, John C. to John C. Doe
138
- temp = str.split(',')
139
- temp << temp[0]
140
- temp.delete_at(0)
141
- str = temp.join(" ")
142
-
143
- end
144
- parts = str.split # First, split the name into an array
145
-
146
- parts.each_with_index do |part, i|
147
- # If any part is "and", then put together the two parts around it
148
- # For example, "Mr. and Mrs." or "Mickey and Minnie"
149
- if part=~/^(and|&)$/i && i > 0
150
- parts[i-1] = [parts.delete_at(i+1), parts.at(i).downcase, parts.delete_at(i-1)].reverse * " "
151
- end
152
- end if self=~/\s(and|&)\s/i # optimize
153
-
154
- { :prefix => (parts.shift if parts[0]=~/^\w+\./),
155
- :first_name => parts.shift || "", # if name is "", then atleast first_name should be ""
156
- :suffix => (parts.pop if parts[-1]=~/(\w+\.|[IVXLM]+|[A-Z]+\.|(?i)jr|(?i)sr )$/),
157
- :last_name => (seperate_middle_name ? parts.pop : parts.slice!(0..-1) * " "),
158
- :middle_name => (parts * " " unless parts.empty?) }
130
+ BigDecimal.class_eval do
131
+ def to_currency_s(symbol="$")
132
+ self.to_f.to_currency_s(symbol)
133
+ end
134
+
135
+ def to_b
136
+ self != 0.0
159
137
  end
160
138
  end
161
139
 
162
- BigDecimal.class_eval do
163
- def to_currency_s(symbol="$")
164
- self.to_f.to_currency_s(symbol)
165
- end
166
- end
167
-
168
140
  Fixnum.class_eval do
169
- #Any value greater than 0 is true
170
- def to_b
171
- self > 0
141
+ def to_currency_s(symbol="$")
142
+ self.to_f.to_currency_s(symbol)
172
143
  end
173
144
 
174
- def to_d
175
- BigDecimal.new("#{self}.0")
145
+ unless Fixnum.instance_methods.include?(:to_b)
146
+ #Any value greater than 0 is true
147
+ def to_b
148
+ self > 0
149
+ end
150
+ end
151
+
152
+ unless Fixnum.instance_methods.include?(:to_d)
153
+ def to_d
154
+ BigDecimal.new("#{self}.0")
155
+ end
156
+ end
157
+
158
+ unless Fixnum.instance_methods.include?(:to_date)
159
+ def to_date
160
+ Time.at(self).to_date
161
+ end
162
+ end
163
+ unless Fixnum.instance_methods.include?(:to_time)
164
+ def to_time
165
+ Time.at(self)
166
+ end
176
167
  end
177
168
  end
178
169
 
179
170
  NilClass.class_eval do
180
- def to_b
181
- false
171
+ unless NilClass.instance_methods.include?(:to_b)
172
+ def to_b
173
+ false
174
+ end
182
175
  end
183
-
184
- def to_d
185
- BigDecimal.new("0.0")
176
+ unless NilClass.instance_methods.include?(:to_d)
177
+ def to_d
178
+ BigDecimal.new("0.0")
179
+ end
186
180
  end
187
181
  end
188
182
  TrueClass.class_eval do
189
-
190
- def to_b
191
- self
183
+ unless TrueClass.instance_methods.include?(:to_b)
184
+ def to_b
185
+ self
186
+ end
192
187
  end
193
188
  end
194
189
  FalseClass.class_eval do
195
- def to_b
196
- self
190
+ unless FalseClass.instance_methods.include?(:to_b)
191
+ def to_b
192
+ self
193
+ end
197
194
  end
198
195
  end
199
196
  end
@@ -1,3 +1,3 @@
1
1
  module SimpleModel
2
- VERSION = "1.1.1"
2
+ VERSION = "1.2.0"
3
3
  end
data/lib/simple_model.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2010-2011 Joshua Thomas Mckinney
2
+ # Copyright (c) 2010-2012 Joshua Thomas Mckinney
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -21,20 +21,30 @@
21
21
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  #++
23
23
  module SimpleModel
24
-
25
- #Get those rails goodies
26
24
  require 'active_support'
27
25
  require 'active_support/i18n'
26
+ require 'active_support/time'
27
+ require 'active_support/core_ext/class/attribute'
28
+ require 'active_support/core_ext/class/attribute_accessors'
29
+ require 'active_support/core_ext/class/delegating_attributes'
30
+ require 'active_support/core_ext/class/attribute'
31
+ require 'active_support/core_ext/array/extract_options'
32
+ require 'active_support/core_ext/hash/deep_merge'
33
+ require 'active_support/core_ext/hash/indifferent_access'
34
+ require 'active_support/core_ext/hash/slice'
35
+ require 'active_support/core_ext/string/behavior'
36
+ require 'active_support/core_ext/kernel/singleton_class'
37
+ require 'active_support/core_ext/module/delegation'
38
+ require 'active_support/core_ext/module/introspection'
39
+ require 'active_support/core_ext/object/duplicable'
40
+ require 'active_support/core_ext/object/blank'
28
41
  require 'active_model'
29
-
30
- # Load as necessary
31
- autoload :ExtendCore, "simple_model/extend_core"
32
- autoload :Attributes, "simple_model/attributes"
33
- autoload :ErrorHelpers, "simple_model/error_helpers"
34
- autoload :Validation, "simple_model/validation"
35
- autoload :Base, "simple_model/base"
36
-
37
- #Railtie
42
+ require "simple_model/extend_core"
43
+ require 'simple_model/exceptions'
44
+ require "simple_model/attributes"
45
+ require "simple_model/error_helpers"
46
+ require "simple_model/validation"
47
+ require "simple_model/base"
38
48
  require 'simple_model/simple_model_railtie.rb' if defined?(Rails)
39
-
49
+
40
50
  end
data/simple_model.gemspec CHANGED
@@ -17,6 +17,7 @@ Gem::Specification.new do |s|
17
17
 
18
18
  s.add_development_dependency 'rspec'
19
19
  s.add_development_dependency 'autotest'
20
+ s.add_development_dependency 'debugger'
20
21
 
21
22
  s.rubyforge_project = "simple_model"
22
23
 
@@ -9,84 +9,159 @@ describe SimpleModel::Attributes do
9
9
  @init = TestInit.new(:test1 => "1", :test2 => '2')
10
10
  end
11
11
 
12
-
13
12
  it "should set provided attributes on initialize" do
14
-
15
13
  @init.test1.should eql("1")
16
14
  @init.test2.should eql("2")
17
15
  end
18
16
 
19
17
  it "should include set attributes in attributes hash" do
20
- @init.attributes.class.should eql(Hash)
18
+ @init.attributes.should be_kind_of(ActiveSupport::HashWithIndifferentAccess)
21
19
  @init.attributes[:test1].should eql("1")
22
20
  @init.attributes[:test2].should eql("2")
23
21
  end
24
-
25
- end
26
- describe SimpleModel::Attributes, 'define_reader_with_options' do
27
- before(:each) do
28
- class TestDefault
29
- include SimpleModel::Attributes
30
- attr_accessor :test
31
- define_reader_with_options :test, :default => "test"
22
+
23
+ context '#new_with_store'do
24
+ it "should use the provided object as the attribute store" do
25
+ my_store = {:test1 => 1,:test2 => 2}
26
+ new = TestInit.new_with_store(my_store)
27
+ new.test1 = 3
28
+ new.test1.should eql(3)
29
+ my_store[:test1].should eql(new.test1)
32
30
  end
33
31
  end
34
-
35
- it "should define setter method with default value" do
36
- default = TestDefault.new
37
- default.test.should eql("test")
38
- end
39
- it "should not intefer with setting" do
40
- default = TestDefault.new
41
- default.test = "New"
42
- default.test.should eql("New")
43
- end
44
32
 
45
- context 'default value is a symbol' do
46
- it "should call the method it describes" do
33
+ context "AVAILABLE_ATTRIBUTE_METHODS" do
34
+ SimpleModel::Attributes::ClassMethods::AVAILABLE_ATTRIBUTE_METHODS.each do |m,options|
35
+ it "should respond to #{m}" do
36
+ TestInit.respond_to?(m).should be_true
37
+ end
38
+ it "should respond to alias #{options[:alias]}" do
39
+ TestInit.respond_to?(options[:alias]).should be_true
40
+ end
41
+ end
42
+ end
43
+
44
+ context '#has_attribute' do
45
+ before(:all) do
47
46
  class TestDefault
48
47
  include SimpleModel::Attributes
49
- attr_accessor :test
50
- define_reader_with_options :test, :default => :default_value
48
+ has_attribute :foo, :default => "foo", :allow_blank => false
49
+ has_attribute :bar, :default => :default_value
50
+ has_attribute :fab, :default => :some_symbol
51
+ has_attribute :hop, :default => :default_hop, :allow_blank => false
52
+ has_attribute :tip, :default => "2", :initialize => false, :allow_blank => false
53
+ has_attribute :nap
54
+ has_attribute :my_array, :default => []
51
55
  def default_value
52
- "test"
56
+ "bar"
57
+ end
58
+
59
+ def default_hop
60
+ "hop" if nap
53
61
  end
54
62
  end
55
-
56
- default = TestDefault.new
57
- default.test.should eql("test")
58
63
  end
59
- end
60
-
64
+
65
+ before(:each) do
66
+ @default = TestDefault.new
67
+ end
61
68
 
62
- end
63
- describe SimpleModel::Attributes, 'has_booleans' do
64
- before(:all) do
65
- class TestBoolean
66
- include SimpleModel::Attributes
67
- has_booleans :test
69
+ it "should define setter method" do
70
+ @default.respond_to?(:foo=).should be_true
71
+ end
72
+
73
+ it "should define reader/getter method" do
74
+ @default.respond_to?(:foo).should be_true
75
+ end
76
+
77
+ context ':initialize => false' do
78
+ it "should not initialize with the default value" do
79
+ @default.attributes[:tip].should be_nil
80
+ @default.tip.should eql("2")
81
+ end
82
+ context "allow_blank => false"do
83
+ it "should not initialize, but should set the value on get" do
84
+ @default.attributes[:tip].should be_nil
85
+ @default.tip.should eql("2")
86
+ end
87
+ end
68
88
  end
89
+
90
+ it "should call the method it describe by the default value if it exists" do
91
+ @default.attributes[:bar].should eql("bar")
92
+ end
93
+
94
+ it "should set the defaul to the supplied symbol, if the method does not exist" do
95
+ @default.attributes[:fab].should eql(:some_symbol)
96
+ end
97
+
98
+ it "should allow default value to be an empty array" do
99
+ @default.my_array.should eql([])
100
+ end
101
+
102
+ it "should create a boolean? method for each attribute" do
103
+ @default.respond_to?(:foo?).should be_true
104
+ end
105
+
106
+ it "should return !blank?" do
107
+ @default.my_array.should eql([]) # blank array
108
+ @default.my_array?.should be_false
109
+ @default.my_array << 1
110
+ @default.my_array?.should be_true
111
+ end
112
+
113
+ it "should not allow blank if set" do
114
+ @default.foo.should eql("foo")
115
+ @default.foo = ""
116
+ @default.foo.should eql("foo")
117
+ @default.foo = "not blank"
118
+ @default.foo.should eql("not blank")
119
+ end
120
+
121
+ it "should try for the default if its blank on get" do
122
+ @default.hop.blank?.should be_true
123
+ @default.nap = "yep"
124
+ @default.hop.should eql("hop")
125
+ end
126
+
127
+
69
128
  end
70
-
71
- it "should add setter=, getter and getter? methods" do
72
- methods = TestBoolean.new.methods
73
- union = methods | [:test, :test=, :test?]
74
- union.should eql(methods)
129
+
130
+ context "on get" do
131
+ it "should perform on_get when set" do
132
+ class OnGet
133
+ include SimpleModel::Attributes
134
+ has_attribute :foo, :on_get => lambda{|obj,attr| (attr.blank? ? obj.send(:foo_default) : attr)}
135
+
136
+ def foo_default
137
+ "test"
138
+ end
139
+ end
140
+
141
+ new = OnGet.new
142
+ new.foo.should eql("test")
143
+ new.foo = "foo"
144
+ new.foo.should eql("foo")
145
+ end
75
146
  end
76
-
77
- end
78
- describe SimpleModel::Attributes, 'has_attributes' do
79
- before(:all) do
80
- class TestBoolean
81
- include SimpleModel::Attributes
82
- has_attributes :my_array, :default => []
147
+
148
+ context 'if supplied value can be cast' do
149
+ it "should throw an exception" do
150
+ class TestThrow
151
+ include SimpleModel::Attributes
152
+ has_booleans :boo
153
+ end
154
+
155
+ lambda{TestThrow.new(:boo => [])}.should raise_error(SimpleModel::ArgumentError)
83
156
  end
157
+
84
158
  end
85
-
86
- it "should allow default value to be an empty array" do
87
- test = TestBoolean.new
88
- test.my_array.should eql([])
159
+
160
+
161
+ after(:all) do
162
+ Object.send(:remove_const,:TestThrow)
163
+ Object.send(:remove_const,:OnGet)
164
+ Object.send(:remove_const,:TestDefault)
165
+ Object.send(:remove_const,:TestInit)
89
166
  end
90
-
91
- end
92
-
167
+ end