fauna 0.2.6 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/fauna/set.rb ADDED
@@ -0,0 +1,184 @@
1
+ module Fauna
2
+ class Set
3
+
4
+ attr_reader :ref
5
+
6
+ def initialize(ref)
7
+ @ref = ref
8
+ end
9
+
10
+ def page(pagination = {})
11
+ SetPage.find(ref, {}, pagination)
12
+ end
13
+
14
+ def events(pagination = {})
15
+ EventsPage.find("#{ref}/events", {}, pagination)
16
+ end
17
+
18
+ # query DSL
19
+
20
+ def self.query(&block)
21
+ module_eval(&block)
22
+ end
23
+
24
+ def self.union(*args)
25
+ QuerySet.new('union', *args)
26
+ end
27
+
28
+ def self.intersection(*args)
29
+ QuerySet.new('intersection', *args)
30
+ end
31
+
32
+ def self.difference(*args)
33
+ QuerySet.new('difference', *args)
34
+ end
35
+
36
+ def self.merge(*args)
37
+ QuerySet.new('merge', *args)
38
+ end
39
+
40
+ def self.join(*args)
41
+ QuerySet.new('join', *args)
42
+ end
43
+
44
+ def self.match(*args)
45
+ QuerySet.new('match', *args)
46
+ end
47
+
48
+ # although each is handled via the query DSL, it might make more
49
+ # sense to add it as a modifier on Set instances, similar to events.
50
+
51
+ def self.each(*args)
52
+ EachSet.new(*args)
53
+ end
54
+ end
55
+
56
+ class QuerySet < Set
57
+ def initialize(function, *params)
58
+ @function = function
59
+ @params = params
60
+ end
61
+
62
+ def param_strings
63
+ @param_strings ||= @params.map do |p|
64
+ if p.respond_to? :expr
65
+ p.expr
66
+ elsif p.respond_to? :ref
67
+ p.ref
68
+ else
69
+ p
70
+ end
71
+ end
72
+ end
73
+
74
+ def expr
75
+ @expr ||= "#{@function}(#{param_strings.join ','})"
76
+ end
77
+
78
+ def ref
79
+ "query?q=#{expr}"
80
+ end
81
+
82
+ def page(pagination = {})
83
+ SetPage.find('query', { 'q' => expr }, pagination)
84
+ end
85
+
86
+ def events(pagination = {})
87
+ EventsPage.find("query", { 'q' => "events(#{expr})" }, pagination)
88
+ end
89
+ end
90
+
91
+ class EachSet < QuerySet
92
+ def initialize(*params)
93
+ super('each', *params)
94
+ end
95
+
96
+ def events(pagination = {})
97
+ query = param_strings.first
98
+ subqueries = param_strings.drop(1).join ','
99
+ EventsPage.find("query", { 'q' => "each(events(#{query}),#{subqueries})" }, pagination)
100
+ end
101
+ end
102
+
103
+ class CustomSet < Set
104
+ def add(resource)
105
+ self.class.add(self, resource)
106
+ end
107
+
108
+ def remove(resource)
109
+ self.class.remove(self, resource)
110
+ end
111
+
112
+ def self.add(set, resource)
113
+ set = set.ref if set.respond_to? :ref
114
+ resource = resource.ref if resource.respond_to? :ref
115
+ Fauna::Client.put("#{set}/#{resource}")
116
+ end
117
+
118
+ def self.remove(set, resource)
119
+ set = set.ref if set.respond_to? :ref
120
+ resource = resource.ref if resource.respond_to? :ref
121
+ Fauna::Client.delete("#{set}/#{resource}")
122
+ end
123
+ end
124
+
125
+ class SetPage < Fauna::Resource
126
+ include Enumerable
127
+
128
+ def refs
129
+ @refs ||= struct['resources']
130
+ end
131
+
132
+ def each(&block)
133
+ refs.each(&block)
134
+ end
135
+
136
+ def empty?
137
+ refs.empty?
138
+ end
139
+
140
+ def length; refs.length end
141
+ def size; refs.size end
142
+ end
143
+
144
+ class EventsPage < Fauna::Resource
145
+ include Enumerable
146
+
147
+ def events
148
+ @events ||= struct['events'].map { |e| Event.new(e) }
149
+ end
150
+
151
+ def each(&block)
152
+ events.each(&block)
153
+ end
154
+
155
+ def empty?
156
+ events.empty?
157
+ end
158
+
159
+ def length; events.length end
160
+ def size; events.size end
161
+ end
162
+
163
+ class Event
164
+ def initialize(attrs)
165
+ @attrs = attrs
166
+ end
167
+
168
+ def ts
169
+ Fauna.time_from_usecs(@attrs['ts'])
170
+ end
171
+
172
+ def resource
173
+ @attrs['resource']
174
+ end
175
+
176
+ def set
177
+ @attrs['set']
178
+ end
179
+
180
+ def action
181
+ @attrs['action']
182
+ end
183
+ end
184
+ end
data/lib/fauna/util.rb ADDED
@@ -0,0 +1,19 @@
1
+ module Fauna
2
+ def self.stringify_keys!(hash)
3
+ hash.keys.each do |k|
4
+ hash[k.to_s] = hash.delete k
5
+ end
6
+ end
7
+
8
+ def self.stringify_keys(hash)
9
+ stringify_keys!(hash.dup)
10
+ end
11
+
12
+ def self.time_from_usecs(microseconds)
13
+ Time.at(microseconds/1_000_000, microseconds % 1_000_000)
14
+ end
15
+
16
+ def self.usecs_from_time(time)
17
+ time.to_i * 1000000 + time.usec
18
+ end
19
+ end
data/lib/tasks/fauna.rake CHANGED
@@ -2,10 +2,70 @@
2
2
  task :environment
3
3
 
4
4
  namespace :fauna do
5
- desc "Migrate your fauna database to the latest version"
5
+ desc "Migrate your Fauna database to the latest version of your schema"
6
6
  task :migrate => :environment do
7
+ puts "Migrating #{Rails.env} Fauna database schema"
7
8
  Fauna::Client.context(Fauna.connection) do
8
9
  Fauna.migrate_schema!
9
10
  end
10
11
  end
12
+
13
+ desc "Completely reset your Fauna database"
14
+ task :reset => :environment do
15
+ if Rails.env.production?
16
+ puts "Won't reset #{Rails.env} Fauna database"
17
+ else
18
+ Fauna::Client.context(Fauna.root_connection) do
19
+ puts "Resetting #{Rails.env} Fauna database"
20
+ Fauna::Client.delete("everything")
21
+ end
22
+ Fauna.auth!
23
+ end
24
+ end
25
+
26
+ desc "Dump the contents of your Fauna database to 'test/fixtures/fauna'"
27
+ task :dump => :environment do
28
+ puts "Dumping #{Rails.env} Fauna database contents to #{Fauna::FIXTURES_DIR}"
29
+ Fauna::Client.context(Fauna.connection) do
30
+ FileUtils.mkdir_p(Fauna::FIXTURES_DIR)
31
+
32
+ class_configs = Fauna.connection.get("/classes")["references"] || {}
33
+ class_configs["users"] = nil
34
+
35
+ Dir.chdir(Fauna::FIXTURES_DIR) do
36
+ class_configs.each do |ref, value|
37
+ class_name = ref[0..-8]
38
+ FileUtils.mkdir_p(class_name)
39
+
40
+ Dir.chdir(class_name) do
41
+ # FIXME shouldn't round trip JSON
42
+ File.open("config.json", "w") { |f| f.write(value.to_json)} if value
43
+ (Fauna.connection.get(class_name)["references"] || {}).each do |ref, value|
44
+ File.open("#{ref.split("/").last}.json", "w") { |f| f.write(value.to_json) }
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ desc "Load the contents of your Fauna database"
53
+ task :load => :environment do
54
+ puts "Loading #{Rails.env} Fauna database contents from #{Fauna::FIXTURES_DIR}"
55
+ Fauna::Client.context(Fauna.connection) do
56
+ Dir.chdir(Fauna::FIXTURES_DIR) do
57
+ Dir["**/*.json"].map do |filename|
58
+ value = JSON.parse(File.open(filename) { |f| f.read })
59
+ begin
60
+ Fauna.connection.put(value["ref"], value)
61
+ rescue Fauna::Connection::NotFound
62
+ Fauna.connection.post(value["ref"].split("/")[0..-2].join("/"), value)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+
11
69
  end
70
+
71
+ task :test => ["fauna:reset", "fauna:migrate", "fauna:load"]
data/test/class_test.rb CHANGED
@@ -1,111 +1,82 @@
1
1
  require File.expand_path('../test_helper', __FILE__)
2
2
 
3
- class ClassTest < ActiveModel::TestCase
4
- include ActiveModel::Lint::Tests
3
+ class InstanceTest < MiniTest::Unit::TestCase
5
4
 
6
5
  def setup
7
6
  super
8
- @model = Pig.new
9
- end
10
-
11
- def test_class_name
12
- assert_equal 'classes/pigs', Pig.fauna_class
13
- assert_equal 'classes/pigs/config', Pig.config_ref
14
- end
15
-
16
- def test_class_save
17
- Pig.update_data! do |data|
18
- data["class_visited"] = true
19
- end
20
- assert Pig.data["class_visited"]
7
+ @model = Fauna::Resource.new('classes/pigs')
21
8
  end
22
9
 
23
10
  def test_create
24
- pig = Pig.create(:visited => false)
25
- assert_equal false, pig.visited
11
+ pig = Fauna::Resource.create 'classes/pigs', :data => { :visited => true }
12
+ assert_equal true, pig.data['visited']
26
13
  assert pig.persisted?
27
14
  assert pig.ref
28
15
  end
29
16
 
30
17
  def test_all
31
- pig = Pig.create
32
- assert Pig.all.resources.include?(pig)
18
+ pig = Fauna::Resource.create 'classes/pigs'
19
+ assert Fauna::Set.new('classes/pigs/instances').page.include?(pig.ref)
33
20
  end
34
21
 
35
22
  def test_save
36
- pig = Pig.new
23
+ pig = Fauna::Resource.new 'classes/pigs'
37
24
  pig.save
38
25
  assert pig.persisted?
39
26
  end
40
27
 
41
28
  def test_update
42
- pig = Pig.new(:visited => false)
29
+ pig = Fauna::Resource.new 'classes/pigs', :data => { :visited => false }
43
30
  pig.save
44
- pig.update(:visited => true)
45
- assert pig.visited
46
- end
47
-
48
- def test_changes
49
- pig = Pig.new(:visited => true)
31
+ pig.data['visited'] = true
50
32
  pig.save
51
- pig.update(:visited => false)
52
- assert_equal pig.changes.page.events.length, 2
53
- end
54
33
 
55
- def test_find_by_ref
56
- pig = Pig.create
57
- pig1 = Pig.find_by_ref(pig.ref)
58
- assert_equal pig.ref, pig1.ref
59
- assert pig1.persisted?
34
+ assert pig.data['visited']
35
+ assert_equal pig.events.length, 2
60
36
  end
61
37
 
62
- def test_find_by_unique_id
63
- pig = Pig.create(:unique_id => "the pig")
64
- pig1 = Pig.find_by_unique_id("the pig")
38
+ def test_find
39
+ pig = Fauna::Resource.create 'classes/pigs'
40
+ pig1 = Fauna::Resource.find(pig.ref)
65
41
  assert_equal pig.ref, pig1.ref
66
42
  assert pig1.persisted?
67
43
  end
68
44
 
69
- def test_find
70
- pig = Pig.create
71
-
72
- pig1 = Pig.find(pig.id)
45
+ def test_find_by_constraint
46
+ pig = Fauna::Resource.create 'classes/pigs', :constraints => { :name => "the pig" }
47
+ pig1 = Fauna::Resource.find('classes/pigs/constraints/name/the%20pig')
73
48
  assert_equal pig.ref, pig1.ref
74
49
  assert pig1.persisted?
75
-
76
- pig2 = Pig.find_by_id(pig.id)
77
- assert_equal pig.ref, pig2.ref
78
- assert pig2.persisted?
79
50
  end
80
51
 
81
- def test_destroy
82
- pig = Pig.create
83
- pig.destroy
84
- assert pig.destroyed?
52
+ def test_delete
53
+ pig = Fauna::Resource.create 'classes/pigs'
54
+ pig.delete
55
+ assert pig.deleted?
85
56
  end
86
57
 
87
58
  def test_ts
88
- pig = Pig.create
59
+ pig = Fauna::Resource.create 'classes/pigs'
89
60
  assert_instance_of(Time, pig.ts)
90
61
 
91
- pig = Pig.new
62
+ pig = Fauna::Resource.new 'classes/pigs'
92
63
  assert_nil pig.ts
93
64
  end
94
65
 
95
66
  def test_ts_assignment
96
67
  time = Time.at(0)
97
- pig = Pig.create
68
+ pig = Fauna::Resource.create 'classes/pigs'
98
69
  pig.ts = time
99
70
 
100
- Fauna::Client.context(@publisher_connection) do
101
- pig2 = Pig.find(pig.id)
102
- assert_not_equal time, pig2.ts
71
+ Fauna::Client.context(@server_connection) do
72
+ pig2 = Fauna::Resource.find(pig.ref)
73
+ assert(time != pig2.ts)
103
74
  end
104
75
 
105
76
  pig.save
106
77
 
107
- Fauna::Client.context(@publisher_connection) do
108
- pig3 = Pig.find(pig.id)
78
+ Fauna::Client.context(@server_connection) do
79
+ pig3 = Fauna::Resource.find(pig.ref)
109
80
  # Waiting on server support for timestamp overrides
110
81
  # assert_equal time, pig3.ts
111
82
  end
data/test/client_test.rb CHANGED
@@ -6,17 +6,17 @@ class ClientTest < MiniTest::Unit::TestCase
6
6
  @attributes = { "name" => "Princess Eilonwy", "email" => email, "password" => password }
7
7
  end
8
8
 
9
- def test_publisher_context
10
- Fauna::Client.context(@publisher_connection) do
9
+ def test_database_context
10
+ Fauna::Client.context(@server_connection) do
11
11
  user = Fauna::Client.post("users", @attributes)
12
- user = Fauna::Client.get(user.ref)
13
- Fauna::Client.delete(user.ref)
12
+ user = Fauna::Client.get(user['ref'])
13
+ Fauna::Client.delete(user['ref'])
14
14
  end
15
15
  end
16
16
 
17
17
  def test_client_context
18
18
  Fauna::Client.context(@client_connection) do
19
- user = Fauna::Client.post("users", @attributes)
19
+ user = Fauna::Resource.create("users", @attributes)
20
20
  Fauna::Client.context(@client_connection) do
21
21
  assert_raises(Fauna::Connection::Unauthorized) do
22
22
  Fauna::Client.get(user.ref)
@@ -26,7 +26,7 @@ class ClientTest < MiniTest::Unit::TestCase
26
26
  end
27
27
 
28
28
  def test_token_context
29
- Fauna::Client.context(@publisher_connection) do
29
+ Fauna::Client.context(@server_connection) do
30
30
  Fauna::Client.post("users", @attributes)
31
31
  end
32
32
 
@@ -34,28 +34,28 @@ class ClientTest < MiniTest::Unit::TestCase
34
34
  @token = Fauna::Client.post("tokens", @attributes)
35
35
  end
36
36
 
37
- Fauna::Client.context(Fauna::Connection.new(:token => @token.token)) do
38
- user = Fauna::Client.get(@token.user)
39
- Fauna::Client.delete(user.ref)
37
+ Fauna::Client.context(Fauna::Connection.new(:secret => @token['secret'], :domain => @server_connection.domain, :scheme => @server_connection.scheme)) do
38
+ user = Fauna::Client.get(@token['user'])
39
+ Fauna::Client.delete(user['ref'])
40
40
  end
41
41
  end
42
42
 
43
43
  def test_caching_1
44
- Fauna::Client.context(@publisher_connection) do
45
- @user = Fauna::Client.post("users", @attributes)
46
- @publisher_connection.expects(:get).never
47
- Fauna::Client.get(@user.ref)
44
+ Fauna::Client.context(@server_connection) do
45
+ user = Fauna::Client.post("users", @attributes)
46
+ @server_connection.expects(:get).never
47
+ Fauna::Client.get(user['ref'])
48
48
  end
49
49
  end
50
50
 
51
51
  def test_caching_2
52
52
  Fauna::Client.context(@client_connection) do
53
- @user = Fauna::Client.post("users", @attributes)
53
+ user = Fauna::Client.post("users", @attributes)
54
54
 
55
- Fauna::Client.context(@publisher_connection) do
56
- Fauna::Client.get(@user.ref)
57
- @publisher_connection.expects(:get).never
58
- Fauna::Client.get(@user.ref)
55
+ Fauna::Client.context(@server_connection) do
56
+ Fauna::Client.get(user['ref'])
57
+ @server_connection.expects(:get).never
58
+ Fauna::Client.get(user['ref'])
59
59
  end
60
60
  end
61
61
  end