attr_default 0.5.2 → 0.5.3
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/attr_default.gemspec +4 -3
- data/lib/attr_default/version.rb +1 -1
- data/lib/attr_default.rb +65 -42
- data/test/test_attr_default.rb +43 -16
- metadata +41 -20
data/attr_default.gemspec
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
require File.expand_path('../lib/attr_default/version', __FILE__)
|
2
2
|
|
3
3
|
Gem::Specification.new do |gem|
|
4
|
-
gem.
|
5
|
-
gem.
|
4
|
+
gem.add_development_dependency 'rack', '~> 1.1.0'
|
5
|
+
gem.add_development_dependency 'rake', '~>0.9'
|
6
|
+
gem.add_development_dependency 'rails', '2.3.14'
|
6
7
|
gem.add_development_dependency 'sqlite3'
|
7
|
-
gem.add_development_dependency 'hobofields'
|
8
|
+
gem.add_development_dependency 'hobofields', '0.9.103'
|
8
9
|
gem.authors = ["Colin Kelley", "Nick Burwell"]
|
9
10
|
gem.email = ["colindkelley@gmail.com"]
|
10
11
|
gem.description = %q{Dynamic Ruby defaults for ActiveRecord attributes}
|
data/lib/attr_default/version.rb
CHANGED
data/lib/attr_default.rb
CHANGED
@@ -2,21 +2,22 @@ module AttrDefault
|
|
2
2
|
module ClassMethods
|
3
3
|
def attr_default attr_name, default
|
4
4
|
if !method_defined?(:_attr_default_set)
|
5
|
-
include AttrDefault
|
5
|
+
include AttrDefault::InstanceMethods
|
6
6
|
end
|
7
7
|
|
8
8
|
attr_name = attr_name.to_s
|
9
|
-
|
9
|
+
_attr_defaults[attr_name] = default
|
10
|
+
|
11
|
+
define_method(attr_name) do
|
10
12
|
if new_record? && !@_attr_defaults_set_from_clone && !_attr_default_set[attr_name]
|
11
|
-
|
12
|
-
send "#{attr_name}=", default_value
|
13
|
+
reset_to_default_value(attr_name)
|
13
14
|
end
|
14
|
-
read_attribute_with_fixups(
|
15
|
+
read_attribute_with_fixups(attr_name)
|
15
16
|
end
|
16
17
|
|
17
|
-
define_method
|
18
|
+
define_method("#{attr_name}=") do |*args|
|
18
19
|
_attr_default_set[attr_name] = true
|
19
|
-
write_attribute_with_fixups(
|
20
|
+
write_attribute_with_fixups(attr_name, args)
|
20
21
|
end
|
21
22
|
|
22
23
|
touch_proc = lambda { |obj| obj.send(attr_name); true }
|
@@ -26,57 +27,79 @@ module AttrDefault
|
|
26
27
|
|
27
28
|
# Hobo Fields field declaration
|
28
29
|
def field_added(name, type, args, options)
|
29
|
-
if (default = options[:ruby_default])
|
30
|
+
if (default = options[:ruby_default])
|
30
31
|
attr_default name, default
|
31
|
-
elsif (default = options[:default]) && Proc
|
32
|
+
elsif (default = options[:default]) && default.is_a?(Proc)
|
33
|
+
ActiveSupport::Deprecation.warn(':default => Proc has been deprecated. Use :ruby_default.', caller)
|
32
34
|
attr_default name, default
|
33
35
|
options.delete(:default)
|
34
36
|
options[:ruby_default] = default
|
35
37
|
end
|
36
38
|
end
|
37
|
-
end
|
38
39
|
|
39
|
-
|
40
|
-
|
40
|
+
def _attr_defaults
|
41
|
+
@_attr_defaults ||= {}
|
42
|
+
end
|
41
43
|
end
|
42
44
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
45
|
+
module InstanceMethods
|
46
|
+
def default_value_for(attr_name)
|
47
|
+
attr_name = attr_name.to_s
|
48
|
+
if self.class._attr_defaults.has_key?(attr_name)
|
49
|
+
attr_default = self.class._attr_defaults[attr_name]
|
50
|
+
attr_default.is_a?(Proc) ? instance_eval(&attr_default) : (attr_default.dup rescue attr_default)
|
51
|
+
else
|
52
|
+
column_data = self.class.columns_hash[attr_name] or raise ArgumentError, "#{self.class.name}##{attr_name} not found"
|
53
|
+
column_data.default
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def reset_to_default_value(attr_name)
|
58
|
+
send("#{attr_name}=", default_value_for(attr_name))
|
59
|
+
end
|
60
|
+
|
61
|
+
def _attr_default_set
|
62
|
+
@_attr_default_set ||= {}
|
50
63
|
end
|
51
|
-
end
|
52
64
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
65
|
+
def read_attribute_with_fixups(attr_name)
|
66
|
+
if needs_time_zone_fixup?(attr_name)
|
67
|
+
cached = @attributes_cache[attr_name] and return cached
|
68
|
+
time = read_attribute(attr_name)
|
69
|
+
@attributes_cache[attr_name] = time.acts_like?(:time) ? time.in_time_zone : time
|
70
|
+
else
|
71
|
+
read_attribute(attr_name)
|
58
72
|
end
|
59
|
-
time = time.in_time_zone rescue nil if time
|
60
|
-
write_attribute(attr_name, time)
|
61
|
-
else
|
62
|
-
write_attribute(attr_name, *args)
|
63
73
|
end
|
64
|
-
end
|
65
74
|
|
66
|
-
|
67
|
-
|
68
|
-
|
75
|
+
def write_attribute_with_fixups(attr_name, args)
|
76
|
+
if needs_time_zone_fixup?(attr_name)
|
77
|
+
time = args.first
|
78
|
+
unless time.acts_like?(:time)
|
79
|
+
time = time.is_a?(String) ? Time.zone.parse(time) : time.to_time rescue time
|
80
|
+
end
|
81
|
+
time = time.in_time_zone rescue nil if time
|
82
|
+
write_attribute(attr_name, time)
|
83
|
+
else
|
84
|
+
write_attribute(attr_name, *args)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def needs_time_zone_fixup?(attr_name)
|
89
|
+
self.class.send(:create_time_zone_conversion_attribute?, attr_name, self.class.columns_hash[attr_name])
|
90
|
+
end
|
69
91
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
92
|
+
def clone
|
93
|
+
result = super
|
94
|
+
result.created_at = nil unless !result.class.columns_hash.has_key?('created_at')
|
95
|
+
result.updated_at = nil unless !result.class.columns_hash.has_key?('updated_at')
|
96
|
+
if self.new_record?
|
97
|
+
result.instance_variable_set(:@_attr_default_set, self._attr_default_set.dup)
|
98
|
+
else
|
99
|
+
result.instance_variable_set(:@_attr_defaults_set_from_clone, true)
|
100
|
+
end
|
101
|
+
result
|
78
102
|
end
|
79
|
-
result
|
80
103
|
end
|
81
104
|
end
|
82
105
|
|
data/test/test_attr_default.rb
CHANGED
@@ -1,16 +1,9 @@
|
|
1
|
-
WANT_RAILS_VERSION = "~> #{ENV.fetch('WANT_RAILS_VERSION', '3.0.15')}"
|
2
|
-
|
3
1
|
require 'rubygems'
|
4
|
-
|
5
|
-
|
6
|
-
begin
|
7
|
-
require 'rails/railtie'
|
8
|
-
rescue LoadError
|
9
|
-
end
|
2
|
+
require 'active_support'
|
3
|
+
require 'active_support/dependencies'
|
10
4
|
require 'active_record'
|
11
5
|
ActiveRecord::ActiveRecordError # work-around from https://rails.lighthouseapp.com/projects/8994/tickets/2577-when-using-activerecordassociations-outside-of-rails-a-nameerror-is-thrown
|
12
6
|
require 'test/unit'
|
13
|
-
require 'active_support/dependencies'
|
14
7
|
require 'active_support/core_ext/logger'
|
15
8
|
require 'hobofields' if ENV['INCLUDE_HOBO']
|
16
9
|
|
@@ -33,9 +26,9 @@ ActiveRecord::Base.establish_connection(
|
|
33
26
|
)
|
34
27
|
|
35
28
|
ActiveRecord::Base.connection.create_table(:test_users, :force => true) do |t|
|
36
|
-
t.string :first_name
|
29
|
+
t.string :first_name, :default => ''
|
37
30
|
t.string :last_name
|
38
|
-
t.boolean :managed
|
31
|
+
t.boolean :managed, :default => false
|
39
32
|
t.timestamp :timestamp
|
40
33
|
end
|
41
34
|
|
@@ -58,8 +51,8 @@ class TestUser < ActiveRecord::Base
|
|
58
51
|
|
59
52
|
if ENV['INCLUDE_HOBO']
|
60
53
|
fields do
|
61
|
-
first_name :string, :default => '', :ruby_default => 'John'
|
62
|
-
last_name :string, :
|
54
|
+
first_name :string, :default => '', :ruby_default => lambda { 'John' }
|
55
|
+
last_name :string, :ruby_default => 'Doe'
|
63
56
|
timestamp :timestamp, :default => lambda { (Time.zone || ActiveSupport::TimeZone['Pacific Time (US & Canada)']).now }
|
64
57
|
end
|
65
58
|
else
|
@@ -112,7 +105,7 @@ class AttrDefaultTest < Test::Unit::TestCase
|
|
112
105
|
|
113
106
|
def test_use_default_if_not_set
|
114
107
|
u = TestUser.new
|
115
|
-
assert_equal
|
108
|
+
assert_equal '', u.read_attribute(:first_name)
|
116
109
|
assert_equal "Doe", u.last_name
|
117
110
|
end
|
118
111
|
|
@@ -130,15 +123,45 @@ class AttrDefaultTest < Test::Unit::TestCase
|
|
130
123
|
end
|
131
124
|
|
132
125
|
def test_allow_an_override_to_be_specified
|
133
|
-
u = TestUser.new(
|
126
|
+
u = TestUser.new(:last_name => "override")
|
134
127
|
assert_equal "override", u.read_attribute(:last_name)
|
135
128
|
assert_equal "override", u.last_name
|
136
129
|
end
|
137
130
|
|
131
|
+
def test_proc_default_value_for_string_and_symbol
|
132
|
+
u = TestUser.new(:first_name => "override")
|
133
|
+
u.save!
|
134
|
+
assert_equal "override", u.first_name
|
135
|
+
assert_equal "John", u.default_value_for("first_name")
|
136
|
+
assert_equal "John", u.default_value_for(:first_name)
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_nonproc_default_value_for_string_and_symbol
|
140
|
+
u = TestUser.new(:managed => true)
|
141
|
+
u.save!
|
142
|
+
assert_equal true, u.managed
|
143
|
+
assert_equal false, u.default_value_for("managed")
|
144
|
+
assert_equal false, u.default_value_for(:managed)
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_reset_to_default_value_string
|
148
|
+
u = TestUser.create!(:last_name => "override")
|
149
|
+
assert_equal "override", u.last_name
|
150
|
+
u.reset_to_default_value("last_name")
|
151
|
+
assert_equal "Doe", u.last_name
|
152
|
+
end
|
153
|
+
|
154
|
+
def test_reset_to_default_value_symbol
|
155
|
+
u = TestUser.create!(:last_name => "override")
|
156
|
+
assert_equal "override", u.last_name
|
157
|
+
u.reset_to_default_value(:last_name)
|
158
|
+
assert_equal "Doe", u.last_name
|
159
|
+
end
|
160
|
+
|
138
161
|
if ENV['INCLUDE_HOBO']
|
139
162
|
def test_hobo_allow_default_and_ruby_default
|
140
163
|
u = TestUser.new
|
141
|
-
assert_equal
|
164
|
+
assert_equal "", u.read_attribute(:first_name)
|
142
165
|
assert_equal "", TestUser.field_specs['first_name'].options[:default]
|
143
166
|
assert_equal "John", TestUser.field_specs['first_name'].options[:ruby_default].call
|
144
167
|
assert_equal "John", u.first_name
|
@@ -149,11 +172,15 @@ class AttrDefaultTest < Test::Unit::TestCase
|
|
149
172
|
u = TestUser.new
|
150
173
|
u2 = TestUser.new
|
151
174
|
|
175
|
+
assert_equal "John", u2.first_name
|
152
176
|
assert_equal "Doe", u2.last_name
|
177
|
+
u.first_name.upcase!
|
153
178
|
u.last_name.upcase!
|
179
|
+
assert_equal "John", u2.first_name # should not be JOHN
|
154
180
|
assert_equal "Doe", u2.last_name # should not be DOE
|
155
181
|
|
156
182
|
u3 = TestUser.new
|
183
|
+
assert_equal "John", u2.first_name
|
157
184
|
assert_equal "Doe", u3.last_name
|
158
185
|
end
|
159
186
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attr_default
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 13
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 5
|
9
|
-
-
|
10
|
-
version: 0.5.
|
9
|
+
- 3
|
10
|
+
version: 0.5.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Colin Kelley
|
@@ -16,49 +16,54 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date:
|
19
|
+
date: 2013-01-06 00:00:00 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
requirement: &id001 !ruby/object:Gem::Requirement
|
23
23
|
none: false
|
24
24
|
requirements:
|
25
|
-
- -
|
25
|
+
- - ~>
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
hash:
|
27
|
+
hash: 19
|
28
28
|
segments:
|
29
|
+
- 1
|
30
|
+
- 1
|
29
31
|
- 0
|
30
|
-
version:
|
32
|
+
version: 1.1.0
|
31
33
|
prerelease: false
|
32
|
-
type: :
|
33
|
-
name:
|
34
|
+
type: :development
|
35
|
+
name: rack
|
34
36
|
version_requirements: *id001
|
35
37
|
- !ruby/object:Gem::Dependency
|
36
38
|
requirement: &id002 !ruby/object:Gem::Requirement
|
37
39
|
none: false
|
38
40
|
requirements:
|
39
|
-
- -
|
41
|
+
- - ~>
|
40
42
|
- !ruby/object:Gem::Version
|
41
|
-
hash:
|
43
|
+
hash: 25
|
42
44
|
segments:
|
43
45
|
- 0
|
44
|
-
|
46
|
+
- 9
|
47
|
+
version: "0.9"
|
45
48
|
prerelease: false
|
46
|
-
type: :
|
47
|
-
name:
|
49
|
+
type: :development
|
50
|
+
name: rake
|
48
51
|
version_requirements: *id002
|
49
52
|
- !ruby/object:Gem::Dependency
|
50
53
|
requirement: &id003 !ruby/object:Gem::Requirement
|
51
54
|
none: false
|
52
55
|
requirements:
|
53
|
-
- - "
|
56
|
+
- - "="
|
54
57
|
- !ruby/object:Gem::Version
|
55
|
-
hash:
|
58
|
+
hash: 31
|
56
59
|
segments:
|
57
|
-
-
|
58
|
-
|
60
|
+
- 2
|
61
|
+
- 3
|
62
|
+
- 14
|
63
|
+
version: 2.3.14
|
59
64
|
prerelease: false
|
60
65
|
type: :development
|
61
|
-
name:
|
66
|
+
name: rails
|
62
67
|
version_requirements: *id003
|
63
68
|
- !ruby/object:Gem::Dependency
|
64
69
|
requirement: &id004 !ruby/object:Gem::Requirement
|
@@ -72,8 +77,24 @@ dependencies:
|
|
72
77
|
version: "0"
|
73
78
|
prerelease: false
|
74
79
|
type: :development
|
75
|
-
name:
|
80
|
+
name: sqlite3
|
76
81
|
version_requirements: *id004
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - "="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
hash: 245
|
89
|
+
segments:
|
90
|
+
- 0
|
91
|
+
- 9
|
92
|
+
- 103
|
93
|
+
version: 0.9.103
|
94
|
+
prerelease: false
|
95
|
+
type: :development
|
96
|
+
name: hobofields
|
97
|
+
version_requirements: *id005
|
77
98
|
description: Dynamic Ruby defaults for ActiveRecord attributes
|
78
99
|
email:
|
79
100
|
- colindkelley@gmail.com
|