communicator 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +4 -0
- data/README.rdoc +5 -0
- data/Rakefile +4 -1
- data/VERSION +1 -1
- data/communicator.gemspec +7 -1
- data/lib/communicator/active_record_integration.rb +15 -3
- data/lib/communicator/server.rb +20 -2
- data/lib/communicator.rb +14 -1
- data/test/config.ru +1 -0
- data/test/helper.rb +4 -0
- data/test/lib/comment.rb +7 -0
- data/test/lib/test_server_database/comment.rb +4 -0
- data/test/migrate/20101103120519_create_comments.rb +13 -0
- data/test/test_client.rb +16 -0
- metadata +9 -3
data/Gemfile.lock
CHANGED
@@ -6,6 +6,7 @@ PATH
|
|
6
6
|
httparty (>= 0.6.1)
|
7
7
|
json (>= 1.4.0)
|
8
8
|
sinatra (~> 1.1.0)
|
9
|
+
sinatra-basic-auth
|
9
10
|
|
10
11
|
GEM
|
11
12
|
remote: http://rubygems.org/
|
@@ -25,6 +26,8 @@ GEM
|
|
25
26
|
sinatra (1.1.0)
|
26
27
|
rack (~> 1.1)
|
27
28
|
tilt (~> 1.1)
|
29
|
+
sinatra-basic-auth (0.1.0)
|
30
|
+
sinatra
|
28
31
|
sqlite3-ruby (1.3.2)
|
29
32
|
tilt (1.1)
|
30
33
|
|
@@ -41,4 +44,5 @@ DEPENDENCIES
|
|
41
44
|
rack-test (>= 0.5.6)
|
42
45
|
shoulda (= 2.10.3)
|
43
46
|
sinatra (~> 1.1.0)
|
47
|
+
sinatra-basic-auth
|
44
48
|
sqlite3-ruby (>= 1.3.0)
|
data/README.rdoc
CHANGED
@@ -59,6 +59,11 @@ class receives updates from like this:
|
|
59
59
|
class Post < ActiveRecord::Base
|
60
60
|
receives_from :post
|
61
61
|
end
|
62
|
+
|
63
|
+
If you want to skip some remote attributes and not let them progapate into local instances,
|
64
|
+
use `receives_from :post, :except => [:user_id]`.
|
65
|
+
|
66
|
+
Attributes that are not physically present in the local database will be skipped automatically.
|
62
67
|
|
63
68
|
Use the automatically added `publish` instance method on your models to push changes
|
64
69
|
to the other side. They will be enqueued in the local `outbound_messages` table and
|
data/Rakefile
CHANGED
@@ -54,7 +54,10 @@ namespace :test_server do
|
|
54
54
|
Thread.new do
|
55
55
|
# Capture sinatra output (to hide it away...)
|
56
56
|
require "open3"
|
57
|
-
|
57
|
+
rackup = "bundle exec rackup test/config.ru -p 20359 --pid=#{File.join(File.dirname(__FILE__), 'test', 'rack.pid')}"
|
58
|
+
Open3.popen3(rackup)
|
59
|
+
#`#{rackup}` # Uncomment to see actual server output
|
60
|
+
|
58
61
|
end
|
59
62
|
sleep 2.0
|
60
63
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.1
|
data/communicator.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{communicator}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Christoph Olszowka"]
|
@@ -39,11 +39,14 @@ Gem::Specification.new do |s|
|
|
39
39
|
"test/config.ru",
|
40
40
|
"test/factories.rb",
|
41
41
|
"test/helper.rb",
|
42
|
+
"test/lib/comment.rb",
|
42
43
|
"test/lib/post.rb",
|
44
|
+
"test/lib/test_server_database/comment.rb",
|
43
45
|
"test/lib/test_server_database/inbound_message.rb",
|
44
46
|
"test/lib/test_server_database/outbound_message.rb",
|
45
47
|
"test/lib/test_server_database/post.rb",
|
46
48
|
"test/migrate/20101101093519_create_posts.rb",
|
49
|
+
"test/migrate/20101103120519_create_comments.rb",
|
47
50
|
"test/test_client.rb",
|
48
51
|
"test/test_message_models.rb",
|
49
52
|
"test/test_server.rb"
|
@@ -56,11 +59,14 @@ Gem::Specification.new do |s|
|
|
56
59
|
s.test_files = [
|
57
60
|
"test/factories.rb",
|
58
61
|
"test/helper.rb",
|
62
|
+
"test/lib/comment.rb",
|
59
63
|
"test/lib/post.rb",
|
64
|
+
"test/lib/test_server_database/comment.rb",
|
60
65
|
"test/lib/test_server_database/inbound_message.rb",
|
61
66
|
"test/lib/test_server_database/outbound_message.rb",
|
62
67
|
"test/lib/test_server_database/post.rb",
|
63
68
|
"test/migrate/20101101093519_create_posts.rb",
|
69
|
+
"test/migrate/20101103120519_create_comments.rb",
|
64
70
|
"test/test_client.rb",
|
65
71
|
"test/test_message_models.rb",
|
66
72
|
"test/test_server.rb"
|
@@ -8,8 +8,18 @@ module Communicator::ActiveRecordIntegration
|
|
8
8
|
# receives_from :post
|
9
9
|
# end
|
10
10
|
#
|
11
|
-
def receives_from(source)
|
12
|
-
Communicator.register_receiver(self, source)
|
11
|
+
def receives_from(source, options={})
|
12
|
+
Communicator.register_receiver(self, source, options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def skipped_remote_attributes
|
16
|
+
@skipped_remote_attributes ||= []
|
17
|
+
end
|
18
|
+
|
19
|
+
def skip_remote_attributes(*attr_names)
|
20
|
+
attr_names.each do |attr_name|
|
21
|
+
skipped_remote_attributes << attr_name.to_sym
|
22
|
+
end
|
13
23
|
end
|
14
24
|
end
|
15
25
|
|
@@ -24,11 +34,13 @@ module Communicator::ActiveRecordIntegration
|
|
24
34
|
end
|
25
35
|
|
26
36
|
# Processes the given message body by applying all contained attributes and their values
|
27
|
-
# and saving
|
37
|
+
# and saving. When the setter instance method is missing on the local record, skip that attribute.
|
28
38
|
def process_message(input)
|
29
39
|
# When the input is still json, parse it. Otherwise we're assuming it's already a demarshalled hash
|
30
40
|
input = JSON.parse(input) if input.kind_of?(String)
|
31
41
|
input.each do |attr_name, value|
|
42
|
+
# Exclude skipped attributes
|
43
|
+
next if self.class.skipped_remote_attributes.include?(attr_name.to_sym) or !attributes.has_key?(attr_name)
|
32
44
|
self.send("#{attr_name}=", value)
|
33
45
|
end
|
34
46
|
self.updated_from_message = true
|
data/lib/communicator/server.rb
CHANGED
@@ -16,12 +16,28 @@ class Communicator::Server < Sinatra::Base
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
use Rack::Auth::Basic do |username, password|
|
20
|
-
|
19
|
+
# use Rack::Auth::Basic do |username, password|
|
20
|
+
# [username, password] == [Communicator::Server.username, Communicator::Server.password]
|
21
|
+
# end
|
22
|
+
|
23
|
+
helpers do
|
24
|
+
def protected!
|
25
|
+
unless authorized?
|
26
|
+
response['WWW-Authenticate'] = %(Basic realm="Testing HTTP Auth")
|
27
|
+
throw(:halt, [401, "Not authorized\n"])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def authorized?
|
32
|
+
@auth ||= Rack::Auth::Basic::Request.new(request.env)
|
33
|
+
@auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == [Communicator::Server.username, Communicator::Server.password]
|
34
|
+
end
|
21
35
|
end
|
36
|
+
|
22
37
|
|
23
38
|
# PULL
|
24
39
|
get '/messages.json' do
|
40
|
+
protected!
|
25
41
|
# Require from_id attribute
|
26
42
|
return [409, "Specify from_id!"] unless params[:from_id]
|
27
43
|
|
@@ -39,6 +55,8 @@ class Communicator::Server < Sinatra::Base
|
|
39
55
|
|
40
56
|
# PUSH
|
41
57
|
post '/messages.json' do
|
58
|
+
protected!
|
59
|
+
|
42
60
|
body = request.body.read.strip
|
43
61
|
# Make sure a message body is given!
|
44
62
|
return [409, "No data given"] if body.length < 2
|
data/lib/communicator.rb
CHANGED
@@ -20,15 +20,28 @@ module Communicator
|
|
20
20
|
# Register a given class as a receiver from source (underscored name). Will then
|
21
21
|
# mix in the instance methods from Communicator::ActiveRecord::InstanceMethods so
|
22
22
|
# message processing and publishing functionality is included
|
23
|
-
def register_receiver(target, source)
|
23
|
+
def register_receiver(target, source, options={})
|
24
24
|
receivers[source] = target
|
25
25
|
target.send(:include, Communicator::ActiveRecordIntegration::InstanceMethods)
|
26
|
+
|
27
|
+
target.skip_remote_attributes(*options[:except]) if options[:except]
|
28
|
+
|
29
|
+
target
|
26
30
|
end
|
27
31
|
|
28
32
|
# Tries to find the receiver for given source, raising Communicator::ReceiverUnknown
|
29
33
|
# on failure
|
30
34
|
def receiver_for(source)
|
31
35
|
return receivers[source] if receivers[source]
|
36
|
+
|
37
|
+
# If not found in the first place, maybe the class just isn't loaded yet and
|
38
|
+
# thus hasn't registered - let's require all models and try again
|
39
|
+
if defined?(Rails)
|
40
|
+
Dir[File.join(Rails.root, 'app/models/**/*.rb')].each {|model| require model}
|
41
|
+
return receivers[source] if receivers[source]
|
42
|
+
end
|
43
|
+
|
44
|
+
# When everything else fails, just throw an exception...
|
32
45
|
raise Communicator::ReceiverUnknown.new("No receiver registered for '#{source}'")
|
33
46
|
end
|
34
47
|
end
|
data/test/config.ru
CHANGED
@@ -9,6 +9,7 @@ require 'communicator'
|
|
9
9
|
|
10
10
|
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => "db/test_server.sqlite3")
|
11
11
|
require 'lib/post'
|
12
|
+
require 'lib/comment'
|
12
13
|
|
13
14
|
Communicator::Server.username = 'testuser'
|
14
15
|
Communicator::Server.password = 'pwd'
|
data/test/helper.rb
CHANGED
@@ -16,12 +16,14 @@ require 'factories'
|
|
16
16
|
# Connect to client test database
|
17
17
|
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => "db/test_client.sqlite3")
|
18
18
|
require 'lib/post'
|
19
|
+
require 'lib/comment'
|
19
20
|
|
20
21
|
# Connect to server database too so we can peek into what's happening over there
|
21
22
|
class TestServerDatabase < ActiveRecord::Base
|
22
23
|
establish_connection(:adapter => 'sqlite3', :database => "db/test_server.sqlite3")
|
23
24
|
end
|
24
25
|
require 'lib/test_server_database/post'
|
26
|
+
require 'lib/test_server_database/comment'
|
25
27
|
require 'lib/test_server_database/inbound_message'
|
26
28
|
require 'lib/test_server_database/outbound_message'
|
27
29
|
|
@@ -39,9 +41,11 @@ class Test::Unit::TestCase
|
|
39
41
|
Communicator::InboundMessage.delete_all
|
40
42
|
Communicator::OutboundMessage.delete_all
|
41
43
|
Post.delete_all
|
44
|
+
Comment.delete_all
|
42
45
|
|
43
46
|
TestServerDatabase::InboundMessage.delete_all
|
44
47
|
TestServerDatabase::OutboundMessage.delete_all
|
45
48
|
TestServerDatabase::Post.delete_all
|
49
|
+
TestServerDatabase::Comment.delete_all
|
46
50
|
end
|
47
51
|
end
|
data/test/lib/comment.rb
ADDED
data/test/test_client.rb
CHANGED
@@ -121,6 +121,22 @@ class TestClient < Test::Unit::TestCase
|
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
124
|
+
# Make sure attributes skipped with :except are not saved at remote
|
125
|
+
context "PUSHing a new comment" do
|
126
|
+
setup do
|
127
|
+
assert @comment = Comment.create(:title => 'my comment', :body => 'some comment')
|
128
|
+
Communicator::Client.push
|
129
|
+
end
|
130
|
+
|
131
|
+
should "have created the comment at remote" do
|
132
|
+
assert_equal 'some comment', TestServerDatabase::Comment.first.body
|
133
|
+
end
|
134
|
+
|
135
|
+
should "have skipped permissions attribute when processing at remote" do
|
136
|
+
assert_nil TestServerDatabase::Comment.first.title
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
124
140
|
context "when an update message is created at remote" do
|
125
141
|
setup do
|
126
142
|
@remote_msg = TestServerDatabase::OutboundMessage.create!(:body => {:post => {:id => 25, :title => 'new title', :body => 'remote body'}}.to_json)
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: communicator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Christoph Olszowka
|
@@ -194,11 +194,14 @@ files:
|
|
194
194
|
- test/config.ru
|
195
195
|
- test/factories.rb
|
196
196
|
- test/helper.rb
|
197
|
+
- test/lib/comment.rb
|
197
198
|
- test/lib/post.rb
|
199
|
+
- test/lib/test_server_database/comment.rb
|
198
200
|
- test/lib/test_server_database/inbound_message.rb
|
199
201
|
- test/lib/test_server_database/outbound_message.rb
|
200
202
|
- test/lib/test_server_database/post.rb
|
201
203
|
- test/migrate/20101101093519_create_posts.rb
|
204
|
+
- test/migrate/20101103120519_create_comments.rb
|
202
205
|
- test/test_client.rb
|
203
206
|
- test/test_message_models.rb
|
204
207
|
- test/test_server.rb
|
@@ -239,11 +242,14 @@ summary: Data push/pull between apps with local inbound/outbound queue and easy
|
|
239
242
|
test_files:
|
240
243
|
- test/factories.rb
|
241
244
|
- test/helper.rb
|
245
|
+
- test/lib/comment.rb
|
242
246
|
- test/lib/post.rb
|
247
|
+
- test/lib/test_server_database/comment.rb
|
243
248
|
- test/lib/test_server_database/inbound_message.rb
|
244
249
|
- test/lib/test_server_database/outbound_message.rb
|
245
250
|
- test/lib/test_server_database/post.rb
|
246
251
|
- test/migrate/20101101093519_create_posts.rb
|
252
|
+
- test/migrate/20101103120519_create_comments.rb
|
247
253
|
- test/test_client.rb
|
248
254
|
- test/test_message_models.rb
|
249
255
|
- test/test_server.rb
|