curly_mustache 0.1.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.
@@ -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