curly_mustache 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ require "curly_mustache/attributes/types"
2
+
3
+ types = CurlyMustache::Attributes::Types
4
+ types.define(:integer){ |value| Integer(value) rescue 0 }
5
+ types.define(:string){ |value| String(value) rescue "" }
6
+ types.define(:float){ |value| Float(value) rescue 0.0 }
7
+ types.define(:boolean){ |value| !!value }
8
+ types.define(:time) do |value|
9
+ if value.kind_of?(Time)
10
+ value
11
+ elsif value.kind_of?(String)
12
+ Time.parse(value)
13
+ elsif value.kind_of?(Integer) or value.kind_of?(Float)
14
+ Time.at(value)
15
+ else
16
+ nil
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ module CurlyMustache
2
+ class NoKeyError < RuntimeError; end
3
+ class AttributeNotDefinedError < RuntimeError; end
4
+ class IdNotSettableError < RuntimeError; end
5
+ class InvaildAttributeType < ArgumentError; end
6
+ class InvalidAssociation < RuntimeError; end
7
+ class NotImplementedError < RuntimeError
8
+ def initialize
9
+ super("Not implemented!")
10
+ end
11
+ end
12
+ class RecordNotFound < RuntimeError; end
13
+ class RecordInvalid < RuntimeError; end
14
+ end
@@ -0,0 +1,83 @@
1
+ require "timeout"
2
+
3
+ module CurlyMustache
4
+ module Locking
5
+
6
+ def self.included(mod)
7
+ mod.send(:extend, ClassMethods)
8
+ mod.send(:include, InstanceMethods)
9
+ end
10
+
11
+ module ClassMethods
12
+
13
+ def lock(id, timeout = nil)
14
+ if timeout.nil?
15
+ connection.lock(lock_key(id))
16
+ else
17
+ lock_with_timeout(id, timeout)
18
+ end
19
+ end
20
+
21
+ def lock_with_timeout(id, timeout)
22
+ start_time = Time.now
23
+ while (Time.now.to_f - start_time.to_f) < timeout
24
+ connection.lock(lock_key(id)) and return true
25
+ sleep(0.1)
26
+ end
27
+ raise Timeout::Error, "aquiring lock for #{id_to_key(id)}"
28
+ end
29
+
30
+ def unlock(id)
31
+ connection.unlock(lock_key(id))
32
+ end
33
+
34
+ def lock_and_find(id, timeout = nil, &block)
35
+ lock(id, timeout) or return false
36
+ unlock(id) and return if (record = find(id)).blank?
37
+ if block_given?
38
+ do_locked_block(id, record, &block)
39
+ else
40
+ record
41
+ end
42
+ end
43
+
44
+ def do_locked_block(id, record, &block)
45
+ yield(record)
46
+ rescue Exception
47
+ raise
48
+ ensure
49
+ unlock(id)
50
+ end
51
+
52
+ def lock_key(id)
53
+ "#{lock_prefix}:#{id_to_key(id)}"
54
+ end
55
+
56
+ def lock_prefix
57
+ "lock"
58
+ end
59
+
60
+ end
61
+
62
+ module InstanceMethods
63
+
64
+ def lock(timeout = nil, &block)
65
+ self.class.lock(self.id, timeout) or return false
66
+ if block_given?
67
+ self.class.do_locked_block(self.id, self.reload, &block)
68
+ else
69
+ true
70
+ end
71
+ end
72
+
73
+ def unlock
74
+ self.class.unlock(self.id)
75
+ end
76
+
77
+ def locked?
78
+ connection.locked?(self.class.lock_key(id))
79
+ end
80
+
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,22 @@
1
+ require "test_helper"
2
+
3
+ class BadAdapter < CurlyMustache::Adapters::Abstract; end
4
+
5
+ class AbstractAdapterTest < ActiveSupport::TestCase
6
+
7
+ def test_not_implemented
8
+ assert_raise(CurlyMustache::NotImplementedError){ BadAdapter.new(nil) }
9
+ BadAdapter.class_eval do
10
+ def initialize(config); nil; end
11
+ end
12
+ adapter = BadAdapter.new(nil)
13
+ assert_raise(CurlyMustache::NotImplementedError){ adapter.get(1) }
14
+ assert_raise(CurlyMustache::NotImplementedError){ adapter.mget([1, 2]) }
15
+ assert_raise(CurlyMustache::NotImplementedError){ adapter.put(1, "one") }
16
+ assert_raise(CurlyMustache::NotImplementedError){ adapter.delete(1) }
17
+ assert_raise(CurlyMustache::NotImplementedError){ adapter.flush_db }
18
+ assert_raise(CurlyMustache::NotImplementedError){ adapter.lock(1) }
19
+ assert_raise(CurlyMustache::NotImplementedError){ adapter.unlock(1) }
20
+ end
21
+
22
+ end
@@ -0,0 +1,6 @@
1
+ memcached:
2
+ servers: localhost:11211
3
+
4
+ cassandra:
5
+ servers: 127.0.0.1:9160
6
+ keyspace: CurlyMustache
@@ -0,0 +1,96 @@
1
+ require "test_helper"
2
+
3
+ class AttributesTest < ActiveSupport::TestCase
4
+
5
+ def teardown
6
+ Account.allow_settable_id!(false) # Leave pristine.
7
+ end
8
+
9
+ def test_attribute_type
10
+ assert_equal :string, Account.attribute_type(:name)
11
+ end
12
+
13
+ def test_allow_settable_id
14
+ assert_equal false, Account.allow_settable_id
15
+ assert_raise(CurlyMustache::IdNotSettableError){ Account.create(:id => "123abc") }
16
+ Account.allow_settable_id!
17
+ assert_equal "123abc", Account.create(:id => "123abc").id
18
+ end
19
+
20
+ def test_attributes
21
+ time = Time.now
22
+ attributes = { :name => "test", :created_at => time, :updated_at => time }.stringify_keys
23
+ account = Account.new
24
+ account.attributes = attributes
25
+ assert_equal attributes, account.attributes
26
+ end
27
+
28
+ def test_class_attributes
29
+ assert_equal %w[id name phone_number balance is_admin created_at updated_at].sort, User.attributes.keys.sort
30
+ assert_equal %w[id name created_at updated_at].sort, Account.attributes.keys.sort
31
+ assert_equal :integer, User.attribute_type(:id)
32
+ assert_equal :string, Account.attribute_type(:id)
33
+ end
34
+
35
+ def test_set_attributes
36
+ assert_equal false, Account.allow_settable_id
37
+ account = Account.new
38
+ account.send(:set_attributes, :id => "123abc")
39
+ assert_equal "123abc", account.id
40
+ end
41
+
42
+ def test_time_type
43
+ time = Time.now
44
+ account = Account.new
45
+
46
+ account.created_at = time.to_s(:number)
47
+ assert_equal Time.parse(time.to_s(:number)), account.created_at
48
+
49
+ account.created_at = time.to_i
50
+ assert_equal Time.at(time.to_i), account.created_at
51
+
52
+ account.created_at = Object.new
53
+ assert_equal nil, account.created_at
54
+ end
55
+
56
+ def test_set_to_nil
57
+ user = User.new(:phone_number => 5123334444)
58
+ assert_equal 5123334444, user.phone_number
59
+ user.phone_number = nil
60
+ assert_nil user.phone_number
61
+
62
+ account = Account.new(:name => "blah")
63
+ assert_equal "blah", account.name
64
+ account.name = nil
65
+ assert_equal "", account.name
66
+ end
67
+
68
+ def test_dirty
69
+ user = User.create(:name => "chris")
70
+ assert_equal false, user.changed?
71
+ assert_equal false, user.name_changed?
72
+
73
+ user.name = "callie"
74
+ assert_equal true, user.changed?
75
+ assert_equal true, user.name_changed?
76
+ assert_equal({ "name" => ["chris", "callie"] }, user.changes)
77
+
78
+ user.reset_name!
79
+ assert_equal false, user.changed?
80
+ assert_equal false, user.name_changed?
81
+ assert_equal({}, user.changes)
82
+
83
+ user.name = "callie"
84
+ user.phone_number = 5123334444
85
+ assert_equal true, user.changed?
86
+ assert_equal true, user.name_changed?
87
+ assert_equal true, user.phone_number_changed?
88
+ assert_equal({ "name" => ["chris", "callie"], "phone_number" => [nil, 5123334444] }, user.changes)
89
+ user.reset_phone_number!
90
+ assert_equal true, user.changed?
91
+ assert_equal true, user.name_changed?
92
+ assert_equal false, user.phone_number_changed?
93
+ assert_equal({ "name" => ["chris", "callie"] }, user.changes)
94
+ end
95
+
96
+ end
@@ -0,0 +1,22 @@
1
+ require "test_helper"
2
+
3
+ class CallbacksTest < ActiveSupport::TestCase
4
+
5
+ def test_callbacks
6
+ account = Account.create(:name => "blah")
7
+ assert_equal [:before_validation_on_create, :before_validation, :after_validation, :after_validation_on_create, :before_create, :before_save, :after_save, :after_create], account.callbacks_made
8
+
9
+ account.callbacks_made = []
10
+ account.save
11
+ assert_equal [:before_validation_on_update, :before_validation, :after_validation, :after_validation_on_update, :before_update, :before_save, :after_save, :after_update], account.callbacks_made
12
+
13
+ account.callbacks_made = []
14
+ account = Account.find(account.id)
15
+ assert_equal [:after_find], account.callbacks_made
16
+
17
+ account.callbacks_made = []
18
+ account.destroy
19
+ assert_equal [:before_destroy, :after_destroy], account.callbacks_made
20
+ end
21
+
22
+ end
@@ -0,0 +1,169 @@
1
+ require "test_helper"
2
+
3
+ class CrudTest < ActiveSupport::TestCase
4
+
5
+ def setup
6
+ CurlyMustache::Base.connection.flush_db
7
+ end
8
+
9
+ def attributes_hash
10
+ { :id => 123,
11
+ :name => "chris",
12
+ :phone_number => 5128258325,
13
+ :balance => 1.01,
14
+ :is_admin => true,
15
+ :created_at => Time.parse("2009-04-23 22:09:50 -05:00"),
16
+ :updated_at => Time.parse("2009-04-23 22:09:50 -05:00") }.dup
17
+ end
18
+
19
+ def assert_attributes(record, attributes = nil)
20
+ (attributes or attributes_hash).each do |k, v|
21
+ assert_equal v, record.send(k), "for attribute '#{k}'"
22
+ end
23
+ end
24
+
25
+ def test_create
26
+ user = User.create(attributes_hash)
27
+ assert(user)
28
+ assert(!user.new_record?)
29
+ user = User.find(user.id)
30
+ assert_attributes(user)
31
+ end
32
+
33
+ def test_create_with_autogenerated_id
34
+ user = User.create(attributes_hash.reject{ |k, v| k == :id })
35
+ assert user.id != attributes_hash[:id]
36
+ assert_attributes(user, attributes_hash.merge(:id => user.id))
37
+ end
38
+
39
+ def test_create_autogenerated_id_by_expectation
40
+ id = "1341adb122d8190872c2928dbcc08b9d"
41
+ User.any_instance.expects(:generate_id).returns(id)
42
+ user = User.create :name => "christopher"
43
+ assert_equal id, user.id
44
+ end
45
+
46
+ def test_find
47
+ attributes1 = attributes_hash
48
+ attributes1[:id] = 1
49
+ User.create(attributes1)
50
+
51
+ attributes2 = attributes_hash
52
+ attributes2[:id] = 2
53
+ User.create(attributes2)
54
+
55
+ assert_equal User.find(1), User.find(1)
56
+
57
+ user1 = User.find(1)
58
+ assert_attributes(user1, attributes1)
59
+
60
+ user2 = User.find(2)
61
+ assert_attributes(user2, attributes2)
62
+
63
+ assert_equal [user1, user2], User.find(1, 2)
64
+ assert_raise(CurlyMustache::RecordNotFound){ User.find(3) }
65
+ assert_raise(CurlyMustache::RecordNotFound){ User.find(1, 2, 3) }
66
+ end
67
+
68
+ def test_find_by_id
69
+ assert_nil User.find_by_id(attributes_hash[:id])
70
+ User.create(attributes_hash)
71
+ assert_attributes(User.find_by_id(attributes_hash[:id]))
72
+ end
73
+
74
+ def test_find_all_by_id
75
+ 1.upto(3) do |i|
76
+ attributes = attributes_hash
77
+ attributes[:id] = i
78
+ User.create(attributes)
79
+ end
80
+ user1, user2, user3 = User.find_all_by_id(1, 2, 3)
81
+ assert_attributes(user1, attributes_hash.merge(:id => 1))
82
+ assert_attributes(user2, attributes_hash.merge(:id => 2))
83
+ assert_attributes(user3, attributes_hash.merge(:id => 3))
84
+ end
85
+
86
+ def test_delete_all
87
+ 1.upto(3) do |i|
88
+ attributes = attributes_hash
89
+ attributes[:id] = i
90
+ User.create(attributes)
91
+ end
92
+
93
+ User.delete_all(1, 2)
94
+ assert_raise(CurlyMustache::RecordNotFound){ User.find(1) }
95
+ assert_raise(CurlyMustache::RecordNotFound){ User.find(2) }
96
+ assert(User.find(3))
97
+ end
98
+
99
+ def test_destroy_all
100
+ 1.upto(3) do |i|
101
+ attributes = attributes_hash
102
+ attributes[:id] = i
103
+ User.create(attributes)
104
+ end
105
+
106
+ User.destroy_all(1, 2)
107
+ assert_raise(CurlyMustache::RecordNotFound){ User.find(1) }
108
+ assert_raise(CurlyMustache::RecordNotFound){ User.find(2) }
109
+ assert(User.find(3))
110
+ end
111
+
112
+ def test_new
113
+ user = User.new(attributes_hash)
114
+ assert_attributes(user)
115
+ assert(user.new_record?)
116
+ end
117
+
118
+ def test_reload
119
+ user = User.new(attributes_hash)
120
+ assert_raise(CurlyMustache::RecordNotFound){ user.reload }
121
+
122
+ assert(user = User.create(attributes_hash))
123
+ User.delete_all(user.id)
124
+ assert_raise(CurlyMustache::RecordNotFound){ user.reload }
125
+
126
+ assert(user = User.create(attributes_hash))
127
+ user.name = "callie"
128
+ assert_equal(user.read_attribute(:name), "callie")
129
+ user.reload
130
+ assert_equal(user.read_attribute(:name), attributes_hash[:name])
131
+
132
+ # Strange reload bug where it sets the id to 0.
133
+ # Ahh, this was happening because attributes_manager wasn't inheriting properly.
134
+ account = Account.create(:name => "blah")
135
+ assert_equal 32, (account_id = account.id).length
136
+ account.reload
137
+ assert_equal account_id, account.id
138
+ end
139
+
140
+ def test_save_by_expectations
141
+ user = User.new(attributes_hash)
142
+ user.expects(:create).once
143
+ user.save
144
+
145
+ user = User.create(attributes_hash)
146
+ user.expects(:update).once
147
+ user.save
148
+ end
149
+
150
+ def test_save
151
+ user = User.new(attributes_hash)
152
+ user.save
153
+ assert_attributes(user.reload)
154
+
155
+ user = User.create(attributes_hash)
156
+ user.name = "callie"
157
+ user.save
158
+ user.reload
159
+ assert_equal("callie", user.name)
160
+ end
161
+
162
+ def test_destroy
163
+ user = User.create(attributes_hash)
164
+ user.destroy
165
+ assert(user.frozen?)
166
+ assert_raise(CurlyMustache::RecordNotFound){ user.reload }
167
+ end
168
+
169
+ end
@@ -0,0 +1,57 @@
1
+ require "test_helper"
2
+
3
+ unless [:cassandra].include?(CurlyMustache::Base.connection.adapter_name)
4
+ require "curly_mustache/locking"
5
+ CurlyMustache::Base.send(:include, CurlyMustache::Locking)
6
+ end
7
+
8
+ class LockingTest < ActiveSupport::TestCase
9
+
10
+ def setup
11
+ if CurlyMustache::Base.method_defined?(:lock)
12
+ CurlyMustache::Base.connection.flush_db
13
+ @account = Account.create :name => "chris"
14
+ else
15
+ disable_tests
16
+ end
17
+ end
18
+
19
+ def test_lock_unlock
20
+ assert !@account.unlock
21
+ assert @account.lock
22
+ assert !@account.lock
23
+ assert @account.unlock
24
+ end
25
+
26
+ def test_lock_with_block
27
+ assert_equal "chris", @account.lock{ |user| user.name }
28
+ assert_equal false, @account.locked?
29
+ assert_equal true, @account.lock
30
+ assert_equal false, @account.lock{ |user| user.name }
31
+ assert_equal true, @account.locked?
32
+ assert_equal true, @account.unlock
33
+ assert_equal false, @account.locked?
34
+ @account.lock{ raise "blah" } rescue nil
35
+ assert_equal false, @account.locked?
36
+ end
37
+
38
+ def test_lock_with_timeout
39
+ assert_equal true, @account.lock
40
+ assert_raise(Timeout::Error){ @account.lock(0.1) }
41
+ assert_equal true, @account.unlock
42
+ assert_equal "chris", @account.lock(0.1){ |user| user.name }
43
+ assert_equal false, @account.unlock
44
+ end
45
+
46
+ def test_lock_and_find
47
+ assert_equal true, @account.lock
48
+ assert_equal false, Account.lock_and_find(@account.id)
49
+ assert_raise(Timeout::Error){ Account.lock_and_find(@account.id, 0.1) }
50
+ assert_equal true, @account.unlock
51
+ assert_equal "chris", Account.lock_and_find(@account.id).name
52
+ assert_equal true, @account.unlock
53
+ assert_equal "chris", Account.lock_and_find(@account.id){ |user| user.name }
54
+ assert_equal false, @account.unlock
55
+ end
56
+
57
+ end