has_easy 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +16 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +100 -0
- data/MIT-LICENSE +20 -0
- data/README +306 -0
- data/README.rdoc +306 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/lib/generators/has_easy_migration/USAGE +0 -0
- data/lib/generators/has_easy_migration/has_easy_migration_generator.rb +19 -0
- data/lib/generators/has_easy_migration/templates/has_easy_migration.rb +16 -0
- data/lib/has_easy/association_extension.rb +53 -0
- data/lib/has_easy/configurator.rb +87 -0
- data/lib/has_easy/definition.rb +56 -0
- data/lib/has_easy/errors.rb +4 -0
- data/lib/has_easy/helpers.rb +11 -0
- data/lib/has_easy.rb +133 -0
- data/lib/has_easy_thing.rb +49 -0
- data/lib/tasks/has_easy_tasks.rake +4 -0
- data/test/test_has_easy.rb +337 -0
- metadata +167 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
module Izzle
|
2
|
+
module HasEasy
|
3
|
+
class Configurator
|
4
|
+
|
5
|
+
attr_accessor :definitions, :aliases
|
6
|
+
|
7
|
+
def initialize(klass, name, options)
|
8
|
+
@klass = klass
|
9
|
+
@name = name
|
10
|
+
@definitions = {}
|
11
|
+
|
12
|
+
@aliases = []
|
13
|
+
if options.has_key?(:aliases)
|
14
|
+
@aliases = options[:aliases]
|
15
|
+
elsif options.has_key?(:alias)
|
16
|
+
@aliases = [options[:alias]]
|
17
|
+
end
|
18
|
+
@aliases = @aliases.collect{ |a| a.to_s }
|
19
|
+
end
|
20
|
+
|
21
|
+
def define(name, options = {})
|
22
|
+
name = Helpers.normalize(name)
|
23
|
+
raise ArgumentError, "class #{@klass} has_easy('#{@name}') already defines '#{name}'" if @definitions.has_key?(name)
|
24
|
+
@definitions[name] = Definition.new(name, options)
|
25
|
+
end
|
26
|
+
|
27
|
+
def do_metaprogramming_magic_aka_define_methods
|
28
|
+
|
29
|
+
easy_accessors, object_accessors = [], []
|
30
|
+
@definitions.values.each do |definition|
|
31
|
+
|
32
|
+
easy_accessors << <<-end_eval
|
33
|
+
def #{@name}_#{definition.name}=(value)
|
34
|
+
set_has_easy_thing('#{@name}', '#{definition.name}', value, true)
|
35
|
+
end
|
36
|
+
def #{@name}_#{definition.name}
|
37
|
+
get_has_easy_thing('#{@name}', '#{definition.name}', true)
|
38
|
+
end
|
39
|
+
def #{@name}_#{definition.name}?
|
40
|
+
!!get_has_easy_thing('#{@name}', '#{definition.name}', true)
|
41
|
+
end
|
42
|
+
end_eval
|
43
|
+
|
44
|
+
object_accessors << <<-end_eval
|
45
|
+
def #{definition.name}=(value)
|
46
|
+
proxy_association.owner.set_has_easy_thing('#{@name}', '#{definition.name}', value)
|
47
|
+
end
|
48
|
+
def #{definition.name}
|
49
|
+
proxy_association.owner.get_has_easy_thing('#{@name}', '#{definition.name}')
|
50
|
+
end
|
51
|
+
def #{definition.name}?
|
52
|
+
!!proxy_association.owner.get_has_easy_thing('#{@name}', '#{definition.name}')
|
53
|
+
end
|
54
|
+
end_eval
|
55
|
+
end
|
56
|
+
|
57
|
+
method_aliases = @aliases.inject([]) do |memo, alias_name|
|
58
|
+
memo << "alias_method :#{alias_name}, :#{@name}"
|
59
|
+
@definitions.values.each do |definition|
|
60
|
+
memo << "alias_method :#{alias_name}_#{definition.name}=, :#{@name}_#{definition.name}="
|
61
|
+
memo << "alias_method :#{alias_name}_#{definition.name}, :#{@name}_#{definition.name}"
|
62
|
+
memo << "alias_method :#{alias_name}_#{definition.name}?, :#{@name}_#{definition.name}?"
|
63
|
+
end
|
64
|
+
memo
|
65
|
+
end
|
66
|
+
|
67
|
+
@klass.class_eval <<-end_eval
|
68
|
+
# first define the has many relationship
|
69
|
+
has_many :#{@name}, :class_name => 'HasEasyThing',
|
70
|
+
:as => :model,
|
71
|
+
:extend => AssocationExtension,
|
72
|
+
:dependent => :destroy do
|
73
|
+
#{object_accessors.join("\n")}
|
74
|
+
end
|
75
|
+
|
76
|
+
# now define the easy accessors
|
77
|
+
#{easy_accessors.join("\n")}
|
78
|
+
|
79
|
+
# define the aliases
|
80
|
+
#{method_aliases.join("\n")}
|
81
|
+
end_eval
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Izzle
|
2
|
+
module HasEasy
|
3
|
+
class Definition
|
4
|
+
|
5
|
+
attr_accessor :name
|
6
|
+
attr_accessor :has_type_check, :type_check
|
7
|
+
attr_accessor :has_validate, :validate
|
8
|
+
attr_accessor :has_default, :default
|
9
|
+
attr_accessor :has_default_through, :default_through
|
10
|
+
attr_accessor :has_default_dynamic, :default_dynamic
|
11
|
+
attr_accessor :has_preprocess, :preprocess
|
12
|
+
attr_accessor :has_postprocess, :postprocess
|
13
|
+
|
14
|
+
def initialize(name, options = {})
|
15
|
+
@name = name
|
16
|
+
|
17
|
+
if options.has_key?(:type_check)
|
18
|
+
@has_type_check = true
|
19
|
+
@type_check = options[:type_check].instance_of?(Array) ? options[:type_check] : [options[:type_check]]
|
20
|
+
end
|
21
|
+
|
22
|
+
if options.has_key?(:validate)
|
23
|
+
@has_validate = true
|
24
|
+
@validate = options[:validate]
|
25
|
+
end
|
26
|
+
|
27
|
+
if options.has_key?(:default)
|
28
|
+
@has_default = true
|
29
|
+
@default = options[:default]
|
30
|
+
end
|
31
|
+
|
32
|
+
if options.has_key?(:default_through)
|
33
|
+
@has_default_through = true
|
34
|
+
@default_through = options[:default_through]
|
35
|
+
end
|
36
|
+
|
37
|
+
if options.has_key?(:default_dynamic)
|
38
|
+
@has_default_dynamic = true
|
39
|
+
@default_dynamic = options[:default_dynamic]
|
40
|
+
end
|
41
|
+
|
42
|
+
if options.has_key?(:preprocess)
|
43
|
+
@has_preprocess = true
|
44
|
+
@preprocess = options[:preprocess]
|
45
|
+
end
|
46
|
+
|
47
|
+
if options.has_key?(:postprocess)
|
48
|
+
@has_postprocess = true
|
49
|
+
@postprocess = options[:postprocess]
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/has_easy.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'has_easy/association_extension'
|
2
|
+
require 'has_easy/configurator'
|
3
|
+
require 'has_easy/definition'
|
4
|
+
require 'has_easy/errors'
|
5
|
+
require 'has_easy/helpers'
|
6
|
+
require 'has_easy_thing'
|
7
|
+
|
8
|
+
module Izzle
|
9
|
+
|
10
|
+
module HasEasy
|
11
|
+
|
12
|
+
def self.included(klass)
|
13
|
+
klass.extend ClassMethods
|
14
|
+
klass.send(:include, InstanceMethods)
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
|
19
|
+
def has_easy(context = nil, options = {})
|
20
|
+
context = Helpers.normalize(context)
|
21
|
+
|
22
|
+
# initialize the class instance var to hold our configuration info
|
23
|
+
class << self
|
24
|
+
attr_accessor :has_easy_configurators unless method_defined?(:has_easy_configurators)
|
25
|
+
end
|
26
|
+
self.has_easy_configurators = {} if self.has_easy_configurators.nil?
|
27
|
+
|
28
|
+
# don't let the user redefine a context
|
29
|
+
raise ArgumentError, "class #{self} already has_easy('#{context}')" if self.has_easy_configurators.has_key?(context)
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
configurator = Configurator.new(self, context, options)
|
34
|
+
yield configurator
|
35
|
+
configurator.do_metaprogramming_magic_aka_define_methods
|
36
|
+
has_easy_configurators[context] = configurator
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
module InstanceMethods
|
42
|
+
|
43
|
+
def set_has_easy_thing(context, name, value, do_preprocess = false)
|
44
|
+
context = Helpers.normalize(context)
|
45
|
+
name = Helpers.normalize(name)
|
46
|
+
|
47
|
+
# TODO dry this shit out, it's a copy/paste job with get_has_easy_thing
|
48
|
+
|
49
|
+
# check to make sure the context exists
|
50
|
+
raise ArgumentError, "has_easy('#{context}') is not defined for class #{self.class}" \
|
51
|
+
unless self.class.has_easy_configurators.has_key?(context)
|
52
|
+
configurator = self.class.has_easy_configurators[context]
|
53
|
+
|
54
|
+
# check to make sure the name of the thing exists
|
55
|
+
raise ArgumentError, "'#{name}' not defined for has_easy('#{context}') for class #{self.class}" \
|
56
|
+
unless configurator.definitions.has_key?(name)
|
57
|
+
definition = configurator.definitions[name]
|
58
|
+
|
59
|
+
# do preprocess here, type_check and validate can be done as AR validation in HasEasyThing
|
60
|
+
value = definition.preprocess.call(value) if do_preprocess and definition.has_preprocess
|
61
|
+
|
62
|
+
# invoke the assocation
|
63
|
+
things = send(context)
|
64
|
+
|
65
|
+
# if thing already exists, update it, otherwise add a new one
|
66
|
+
thing = things.detect{ |thing| thing.name == name }
|
67
|
+
if thing.blank?
|
68
|
+
thing = HasEasyThing.new :context => context,
|
69
|
+
:name => name,
|
70
|
+
:value => value
|
71
|
+
thing.model = self
|
72
|
+
#thing.set_model_target(self) # for the bug regarding thing's validation trying to invoke the 'model' assocation when self is a new record
|
73
|
+
send("#{context}").send("<<", thing)
|
74
|
+
else
|
75
|
+
thing.value = value
|
76
|
+
end
|
77
|
+
|
78
|
+
thing.value
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_has_easy_thing(context, name, do_postprocess = false)
|
83
|
+
context = Helpers.normalize(context)
|
84
|
+
name = Helpers.normalize(name)
|
85
|
+
|
86
|
+
# check to make sure the context exists
|
87
|
+
raise ArgumentError, "has_easy('#{context}') is not defined for class #{self.class}" \
|
88
|
+
unless self.class.has_easy_configurators.has_key?(context)
|
89
|
+
configurator = self.class.has_easy_configurators[context]
|
90
|
+
|
91
|
+
# check to make sure the name of the thing exists
|
92
|
+
raise ArgumentError, "'#{name}' not defined for has_easy('#{context}') for class #{self.class}" \
|
93
|
+
unless configurator.definitions.has_key?(name)
|
94
|
+
definition = configurator.definitions[name]
|
95
|
+
|
96
|
+
# invoke the association
|
97
|
+
things = send(context)
|
98
|
+
|
99
|
+
# try to find what they are looking for
|
100
|
+
thing = things.detect{ |thing| thing.name == name }
|
101
|
+
|
102
|
+
# if the thing isn't found, try to fallback on a default
|
103
|
+
if thing.blank?
|
104
|
+
# TODO break all these nested if statements out into helper methods, i like prettier code
|
105
|
+
# TODO raise an exception if we don't respond to default_through or the resulting object doesn't respond to the context
|
106
|
+
if definition.has_default_through and respond_to?(definition.default_through) and (through = send(definition.default_through)).blank? == false
|
107
|
+
value = through.send(context)[name]
|
108
|
+
elsif definition.has_default_dynamic
|
109
|
+
if definition.default_dynamic.instance_of?(Proc)
|
110
|
+
value = definition.default_dynamic.call(self)
|
111
|
+
else
|
112
|
+
# TODO raise an exception if we don't respond to default_dynamic
|
113
|
+
value = send(definition.default_dynamic)
|
114
|
+
end
|
115
|
+
elsif definition.has_default
|
116
|
+
value = Marshal::load(Marshal.dump(definition.default)) # BUGFIX deep cloning default values
|
117
|
+
else
|
118
|
+
value = nil
|
119
|
+
end
|
120
|
+
else
|
121
|
+
value = thing.value
|
122
|
+
end
|
123
|
+
|
124
|
+
value = definition.postprocess.call(value) if do_postprocess and definition.has_postprocess
|
125
|
+
value
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
ActiveRecord::Base.send(:include, Izzle::HasEasy)
|
@@ -0,0 +1,49 @@
|
|
1
|
+
class HasEasyThing < ActiveRecord::Base
|
2
|
+
belongs_to :model, :polymorphic => true
|
3
|
+
attr_accessor :model_cache, :definition, :value_cache
|
4
|
+
before_validation :get_definition
|
5
|
+
validate :validate_type_check, :validate_validate
|
6
|
+
|
7
|
+
def get_definition
|
8
|
+
self.model_cache = model if model_cache.blank?
|
9
|
+
self.definition = model_cache.class.has_easy_configurators[self.context].definitions[self.name] if self.definition.blank?
|
10
|
+
end
|
11
|
+
|
12
|
+
def validate_type_check
|
13
|
+
return unless definition.has_type_check
|
14
|
+
self.errors.add(:value, "has_easy type check failed for '#{self.name}'") unless definition.type_check.include?(value.class)
|
15
|
+
end
|
16
|
+
|
17
|
+
def validate_validate
|
18
|
+
return unless definition.has_validate
|
19
|
+
success = true
|
20
|
+
|
21
|
+
if definition.validate.instance_of?(Array) and definition.validate.include?(value) == false
|
22
|
+
success = false
|
23
|
+
elsif definition.validate.instance_of?(Symbol)
|
24
|
+
success = model_cache.send(definition.validate, value)
|
25
|
+
elsif definition.validate.instance_of?(Proc)
|
26
|
+
begin
|
27
|
+
success = definition.validate.call(value)
|
28
|
+
rescue HasEasy::ValidationError
|
29
|
+
success = false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
if success == false
|
34
|
+
self.errors[:base] << "has_easy validation failed for '#{self.name}'"
|
35
|
+
elsif success.instance_of?(Array)
|
36
|
+
success.each{ |message| self.errors[:base] << message }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def value=(v)
|
41
|
+
method_missing(:value=, v.to_yaml)
|
42
|
+
self.value_cache = v
|
43
|
+
end
|
44
|
+
|
45
|
+
def value
|
46
|
+
self.value_cache ||= YAML.load(method_missing(:value))
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,337 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'active_record'
|
5
|
+
|
6
|
+
$:.unshift File.dirname(__FILE__) + '/../lib'
|
7
|
+
require File.dirname(__FILE__) + '/../init'
|
8
|
+
|
9
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
10
|
+
|
11
|
+
# AR keeps printing annoying schema statements
|
12
|
+
$stdout = StringIO.new
|
13
|
+
|
14
|
+
def setup_db
|
15
|
+
ActiveRecord::Base.logger
|
16
|
+
ActiveRecord::Schema.define(:version => 1) do
|
17
|
+
create_table :has_easy_user_tests, :force => true do |t|
|
18
|
+
t.integer :client_id
|
19
|
+
end
|
20
|
+
create_table :has_easy_client_tests, :force => true do
|
21
|
+
end
|
22
|
+
create_table :has_easy_things do |t|
|
23
|
+
t.string :model_type, :null => false
|
24
|
+
t.integer :model_id, :null => false
|
25
|
+
t.string :context
|
26
|
+
t.string :name, :null => false
|
27
|
+
t.string :value
|
28
|
+
t.timestamps
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def teardown_db
|
34
|
+
ActiveRecord::Base.connection.tables.each do |table|
|
35
|
+
ActiveRecord::Base.connection.drop_table(table)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class HasEasyClientTest < ActiveRecord::Base
|
40
|
+
has_many :users, :class_name => 'HasEasyUserTest', :foreign_key => 'client_id'
|
41
|
+
has_easy :flags do |f|
|
42
|
+
f.define :default_through_test_1, :default => 'client default'
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def self.default_array
|
47
|
+
[1,2,3]
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
class HasEasyUserTest < ActiveRecord::Base
|
53
|
+
belongs_to :client, :class_name => 'HasEasyClientTest', :foreign_key => 'client_id'
|
54
|
+
cattr_accessor :count1, :count2
|
55
|
+
@@count1, @@count2 = 0, 0
|
56
|
+
has_easy :preferences, :alias => :prefs do |p|
|
57
|
+
p.define :color
|
58
|
+
p.define :theme, :type_check => String
|
59
|
+
p.define :validate_test_1, :validate => [true, 'true', 1, 't']
|
60
|
+
p.define :validate_test_2, :validate => Proc.new { |value|
|
61
|
+
[true, 'true', 1, 't'].include?(value)
|
62
|
+
}
|
63
|
+
p.define :validate_test_3, :validate => Proc.new { |value|
|
64
|
+
raise HasEasy::ValidationError unless [true, 'true', 1, 't'].include?(value)
|
65
|
+
}
|
66
|
+
p.define :validate_test_4, :validate => :validate_test_4
|
67
|
+
p.define :preprocess_test_1, :preprocess => Proc.new { |value| [true, 'true', 1, 't'].include?(value) ? true : false }
|
68
|
+
p.define :postprocess_test_1, :postprocess => Proc.new { |value| [true, 'true', 1, 't'].include?(value) ? true : false }
|
69
|
+
p.define :form_usage_test, :default => false,
|
70
|
+
:type_check => [TrueClass, FalseClass],
|
71
|
+
:preprocess => Proc.new{ |value| value == 'true' },
|
72
|
+
:postprocess => Proc.new{ |value| value ? 'true' : 'false' }
|
73
|
+
end
|
74
|
+
|
75
|
+
has_easy :flags do |f|
|
76
|
+
f.define :admin
|
77
|
+
f.define :default_test_1, :default => 'funky town'
|
78
|
+
f.define :default_through_test_1, :default => 'user default', :default_through => :client
|
79
|
+
f.define :default_dynamic_test_1, :default_dynamic => :default_dynamic_test_1
|
80
|
+
f.define :default_dynamic_test_2, :default_dynamic => Proc.new{ |user| user.class.count2 += 1 }
|
81
|
+
f.define :default_reference, :default => HasEasyClientTest.default_array # demonstrates a bug found by swaltered
|
82
|
+
end
|
83
|
+
|
84
|
+
def validate_test_4(value)
|
85
|
+
["1one", "2two"]
|
86
|
+
end
|
87
|
+
|
88
|
+
def default_dynamic_test_1
|
89
|
+
self.class.count1 += 1
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class HasEasyTest < Test::Unit::TestCase
|
94
|
+
|
95
|
+
def setup
|
96
|
+
setup_db
|
97
|
+
HasEasyThing.delete_all
|
98
|
+
@client = HasEasyClientTest.create
|
99
|
+
@user = @client.users.create!
|
100
|
+
end
|
101
|
+
|
102
|
+
def teardown
|
103
|
+
teardown_db
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_setter_getter
|
107
|
+
@user.set_has_easy_thing(:preferences, :color, 'red')
|
108
|
+
assert_equal 'red', @user.get_has_easy_thing(:preferences, :color)
|
109
|
+
assert_equal 1, HasEasyThing.count(:conditions => { :model_type => @user.class.name, :model_id => @user.id })
|
110
|
+
|
111
|
+
@user.set_has_easy_thing(:flags, :admin, true)
|
112
|
+
assert_equal true, @user.get_has_easy_thing(:flags, :admin)
|
113
|
+
assert_equal 2, HasEasyThing.count(:conditions => { :model_type => @user.class.name, :model_id => @user.id })
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_array_access
|
117
|
+
@user.preferences[:color] = 'red'
|
118
|
+
assert_equal 'red', @user.preferences[:color]
|
119
|
+
assert_equal 1, HasEasyThing.count(:conditions => { :model_type => @user.class.name, :model_id => @user.id })
|
120
|
+
|
121
|
+
@user.flags[:admin] = true
|
122
|
+
assert_equal true, @user.flags[:admin]
|
123
|
+
assert_equal 2, HasEasyThing.count(:conditions => { :model_type => @user.class.name, :model_id => @user.id })
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_object_access
|
127
|
+
@user.preferences.color = 'red'
|
128
|
+
assert_equal 'red', @user.preferences.color
|
129
|
+
assert_equal 1, HasEasyThing.count(:conditions => { :model_type => @user.class.name, :model_id => @user.id })
|
130
|
+
|
131
|
+
@user.flags.admin = true
|
132
|
+
assert_equal true, @user.flags.admin
|
133
|
+
assert_equal 2, HasEasyThing.count(:conditions => { :model_type => @user.class.name, :model_id => @user.id })
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_easy_access
|
137
|
+
@user.preferences_color = 'red'
|
138
|
+
assert_equal 'red', @user.preferences_color
|
139
|
+
assert_equal true, @user.preferences_color?
|
140
|
+
assert_equal 1, HasEasyThing.count(:conditions => { :model_type => @user.class.name, :model_id => @user.id })
|
141
|
+
|
142
|
+
@user.flags_admin = true
|
143
|
+
assert_equal true, @user.flags_admin
|
144
|
+
assert_equal true, @user.flags_admin?
|
145
|
+
assert_equal 2, HasEasyThing.count(:conditions => { :model_type => @user.class.name, :model_id => @user.id })
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_overwrite
|
149
|
+
@user.preferences[:color] = 'red'
|
150
|
+
assert_equal 'red', @user.preferences[:color]
|
151
|
+
assert_equal 1, HasEasyThing.count(:conditions => { :model_type => @user.class.name, :model_id => @user.id })
|
152
|
+
|
153
|
+
@user.preferences[:color] = 'blue'
|
154
|
+
assert_equal 'blue', @user.preferences[:color]
|
155
|
+
assert_equal 1, HasEasyThing.count(:conditions => { :model_type => @user.class.name, :model_id => @user.id })
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_alias
|
159
|
+
@user.preferences.theme = "savage thunder"
|
160
|
+
assert_equal @user.preferences[:theme], @user.prefs[:theme]
|
161
|
+
assert_equal @user.preferences.theme, @user.prefs.theme
|
162
|
+
assert_equal @user.preferences_theme, @user.prefs_theme
|
163
|
+
assert_equal @user.preferences_theme?, @user.prefs_theme?
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_type_check
|
167
|
+
@user.preferences.theme = "savage thunder"
|
168
|
+
assert @user.preferences.save
|
169
|
+
|
170
|
+
@user.preferences.theme = 1
|
171
|
+
assert_raise(ActiveRecord::RecordInvalid){ @user.preferences.save! }
|
172
|
+
|
173
|
+
assert !@user.preferences.save
|
174
|
+
assert !@user.errors.empty?
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_validate_1
|
178
|
+
@user.preferences.validate_test_1 = 1
|
179
|
+
assert @user.preferences.save
|
180
|
+
@user.preferences.validate_test_1 = true
|
181
|
+
assert @user.preferences.save
|
182
|
+
@user.preferences.validate_test_1 = 'true'
|
183
|
+
assert @user.preferences.save
|
184
|
+
|
185
|
+
@user.preferences.validate_test_1 = false
|
186
|
+
assert_raise(ActiveRecord::RecordInvalid){ @user.preferences.save! }
|
187
|
+
assert !@user.preferences.save
|
188
|
+
assert !@user.errors.empty?
|
189
|
+
end
|
190
|
+
|
191
|
+
def test_validate_2
|
192
|
+
@user.preferences.validate_test_2 = 1
|
193
|
+
assert @user.preferences.save
|
194
|
+
@user.preferences.validate_test_2 = true
|
195
|
+
assert @user.preferences.save
|
196
|
+
@user.preferences.validate_test_2 = 'true'
|
197
|
+
assert @user.preferences.save
|
198
|
+
|
199
|
+
@user.preferences.validate_test_2 = false
|
200
|
+
assert_raise(ActiveRecord::RecordInvalid){ @user.preferences.save! }
|
201
|
+
assert !@user.preferences.save
|
202
|
+
assert !@user.errors.empty?
|
203
|
+
end
|
204
|
+
|
205
|
+
def test_validate_3
|
206
|
+
@user.preferences.validate_test_3 = 1
|
207
|
+
assert @user.preferences.save
|
208
|
+
@user.preferences.validate_test_3 = true
|
209
|
+
assert @user.preferences.save
|
210
|
+
@user.preferences.validate_test_3 = 'true'
|
211
|
+
assert @user.preferences.save
|
212
|
+
|
213
|
+
@user.preferences.validate_test_3 = false
|
214
|
+
assert_raise(ActiveRecord::RecordInvalid){ @user.preferences.save! }
|
215
|
+
assert !@user.preferences.save
|
216
|
+
assert !@user.errors.empty?
|
217
|
+
end
|
218
|
+
|
219
|
+
def test_validate_4
|
220
|
+
@user.preferences.validate_test_4 = "blah"
|
221
|
+
assert_raise(ActiveRecord::RecordInvalid){ @user.preferences.save! }
|
222
|
+
assert !@user.preferences.save
|
223
|
+
assert 2, @user.errors.get(:preferences).length
|
224
|
+
assert '1one', @user.errors.get(:preferences)[0]
|
225
|
+
assert '2two', @user.errors.get(:preferences)[1]
|
226
|
+
|
227
|
+
# nasty bug when the parent is a new record
|
228
|
+
user = @user.class.new :preferences_validate_test_4 => "blah"
|
229
|
+
assert !user.save
|
230
|
+
assert 2, @user.errors.get(:preferences).length
|
231
|
+
assert '1one', @user.errors.get(:preferences)[0]
|
232
|
+
assert '2two', @user.errors.get(:preferences)[1]
|
233
|
+
end
|
234
|
+
|
235
|
+
def test_validate_4_has_easy_errors_added_to_base
|
236
|
+
@user.preferences.validate_test_4 = "blah"
|
237
|
+
@user.preferences.save
|
238
|
+
@preference = @user.preferences.detect { |pref| !pref.errors.empty? }
|
239
|
+
assert_equal ['1one','2two'], @preference.errors.full_messages
|
240
|
+
end
|
241
|
+
|
242
|
+
def test_preprocess_1
|
243
|
+
@user.preferences.preprocess_test_1 = "blah"
|
244
|
+
assert_equal "blah", @user.preferences.preprocess_test_1
|
245
|
+
assert_equal "blah", @user.preferences_preprocess_test_1
|
246
|
+
@user.preferences_preprocess_test_1 = "blah"
|
247
|
+
assert_equal false, @user.preferences.preprocess_test_1
|
248
|
+
assert_equal false, @user.preferences_preprocess_test_1
|
249
|
+
|
250
|
+
@user.preferences.preprocess_test_1 = "true"
|
251
|
+
assert_equal "true", @user.preferences.preprocess_test_1
|
252
|
+
assert_equal "true", @user.preferences_preprocess_test_1
|
253
|
+
@user.preferences_preprocess_test_1 = "true"
|
254
|
+
assert_equal true, @user.preferences.preprocess_test_1
|
255
|
+
assert_equal true, @user.preferences_preprocess_test_1
|
256
|
+
end
|
257
|
+
|
258
|
+
def test_postprocess_1
|
259
|
+
@user.preferences.postprocess_test_1 = "blah"
|
260
|
+
assert_equal "blah", @user.preferences.postprocess_test_1
|
261
|
+
assert_equal false, @user.preferences_postprocess_test_1
|
262
|
+
|
263
|
+
@user.preferences.postprocess_test_1 = "true"
|
264
|
+
assert_equal "true", @user.preferences.postprocess_test_1
|
265
|
+
assert_equal true, @user.preferences_postprocess_test_1
|
266
|
+
end
|
267
|
+
|
268
|
+
def test_default_1
|
269
|
+
assert_equal 'funky town', HasEasyUserTest.new.flags.default_test_1
|
270
|
+
assert_equal 'funky town', @user.flags.default_test_1
|
271
|
+
@user.flags.default_test_1 = "stupid town"
|
272
|
+
assert_equal "stupid town", @user.flags.default_test_1
|
273
|
+
@user.flags.save
|
274
|
+
@user = HasEasyUserTest.find(@user.id)
|
275
|
+
assert_equal "stupid town", @user.flags.default_test_1
|
276
|
+
end
|
277
|
+
|
278
|
+
def test_default_though_1
|
279
|
+
client = HasEasyClientTest.create
|
280
|
+
user = client.users.create
|
281
|
+
assert_equal 'client default', user.flags.default_through_test_1
|
282
|
+
|
283
|
+
client.flags.default_through_test_1 = 'not client default'
|
284
|
+
client.flags.save
|
285
|
+
user.client(true)
|
286
|
+
assert_equal 'not client default', user.flags.default_through_test_1
|
287
|
+
|
288
|
+
user.flags.default_through_test_1 = 'not user default'
|
289
|
+
assert_equal 'not user default', user.flags.default_through_test_1
|
290
|
+
|
291
|
+
assert_equal 'user default', HasEasyUserTest.new.flags.default_through_test_1
|
292
|
+
end
|
293
|
+
|
294
|
+
def test_default_dynamic_1
|
295
|
+
assert_equal 1, @user.flags.default_dynamic_test_1
|
296
|
+
assert_equal 2, @user.flags.default_dynamic_test_1
|
297
|
+
end
|
298
|
+
|
299
|
+
def test_default_dynamic_2
|
300
|
+
assert_equal 1, @user.flags.default_dynamic_test_2
|
301
|
+
assert_equal 2, @user.flags.default_dynamic_test_2
|
302
|
+
end
|
303
|
+
|
304
|
+
# This is from a bug that swalterd found that has to do with how has_easy assigns default values.
|
305
|
+
# Each thing shares the same default value, so changing it for one will change it for everyone.
|
306
|
+
# The fix is to clone (if possible) the default value when a new HasEasyThing is created.
|
307
|
+
def test_default_reference
|
308
|
+
v = @user.flags.default_reference[0]
|
309
|
+
@user.flags.default_reference[0] = rand(10) + 10
|
310
|
+
new_user = HasEasyUserTest.new
|
311
|
+
assert_equal v, new_user.flags_default_reference[0]
|
312
|
+
end
|
313
|
+
|
314
|
+
def test_form_usage
|
315
|
+
assert_equal false, @user.prefs.form_usage_test
|
316
|
+
assert_equal 'false', @user.prefs_form_usage_test
|
317
|
+
|
318
|
+
params = { :person => {:prefs_form_usage_test => 'true'} }
|
319
|
+
assert @user.update_attributes(params[:person])
|
320
|
+
assert_equal true, @user.prefs.form_usage_test
|
321
|
+
assert_equal 'true', @user.prefs_form_usage_test
|
322
|
+
@user.preferences.save!
|
323
|
+
@user = @user.class.find(@user.id)
|
324
|
+
assert_equal true, @user.prefs.form_usage_test
|
325
|
+
assert_equal 'true', @user.prefs_form_usage_test
|
326
|
+
|
327
|
+
params = { :person => {:prefs_form_usage_test => 'false'} }
|
328
|
+
assert @user.update_attributes(params[:person])
|
329
|
+
assert_equal false, @user.prefs.form_usage_test
|
330
|
+
assert_equal 'false', @user.prefs_form_usage_test
|
331
|
+
@user.preferences.save!
|
332
|
+
@user = @user.class.find(@user.id)
|
333
|
+
assert_equal false, @user.prefs.form_usage_test
|
334
|
+
assert_equal 'false', @user.prefs_form_usage_test
|
335
|
+
end
|
336
|
+
|
337
|
+
end
|