chatbox 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e6ad08c199c036d9537849e7dee035ff14a1084e
4
- data.tar.gz: f0f6622961ca50cf53c19994a1e1cad8fbf25d09
3
+ metadata.gz: 5b66ba083f1d159cc4e17b4006dfc9890501b5a8
4
+ data.tar.gz: efdf4191ca17f8f92a5820efe735df7f39bbc888
5
5
  SHA512:
6
- metadata.gz: 7fe1ae1ce10604d614694ec7d2ad6d78b5ccdb002e4afc333e719f6b0d121a62b96325280746beb715735854450717a8d6542613bccff59ad1a5a8abf7790ff6
7
- data.tar.gz: 35caadb705b534d891aa817e97a9562f13cfb929bc0f12e897abf3e6d48df5cb6bd2dbb63354913080a8287f0450363919bf37da6e096e2cabcb682385bfe930
6
+ metadata.gz: 77bffe68cca61f58b1f0d177d3f5db898382c02030513a843f60f43cd5d3d8b854dca0d7140cfd34f13ed2f1ee7972f52f7e36af0c9b1aa1b1101f08a97e4997
7
+ data.tar.gz: 80f8b7d68f4c4bbcd38f29947440a805f59e46b68f2d47656e85f4a7b7b77d01d66f97fbee88e3cf27153d42fde073768b5e2f62654805aba1084f147f78a935
data/.rspec CHANGED
@@ -1,3 +1,2 @@
1
1
  --color
2
- --warnings
3
2
  --require spec_helper
data/.travis.yml CHANGED
@@ -5,3 +5,5 @@ rvm:
5
5
  script: bundle exec rspec
6
6
  before_install:
7
7
  - gem install bundler
8
+ notifications:
9
+ email: false
data/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ [![Gem Version](https://badge.fury.io/rb/chatbox.svg)](http://badge.fury.io/rb/chatbox)
2
+ [![Build Status](https://travis-ci.org/austinthecoder/chatbox.svg?branch=master)](https://travis-ci.org/austinthecoder/chatbox)
3
+ [![Code Climate](https://codeclimate.com/github/austinthecoder/chatbox/badges/gpa.svg)](https://codeclimate.com/github/austinthecoder/chatbox)
4
+
1
5
  # Chatbox
2
6
 
3
7
  Simple messaging system.
data/chatbox.gemspec CHANGED
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency 'bundler', '~> 1.7'
22
22
  spec.add_development_dependency 'rake', '~> 10.0'
23
23
  spec.add_development_dependency 'rspec', '~> 3.0'
24
+ spec.add_development_dependency 'dalli', '~> 2.7'
24
25
 
25
26
  spec.add_dependency 'activesupport', '>= 3'
26
27
  end
data/lib/chatbox/draft.rb CHANGED
@@ -1,24 +1,29 @@
1
+ require 'securerandom'
1
2
  require 'chatbox/fake_missing_keywords'
2
3
 
3
4
  module Chatbox
4
5
  class Draft
5
6
  include FakeMissingKeywords
6
7
 
7
- def initialize(from: req(:from), to: req(:to), body: req(:body), store: req(:store))
8
- @from_id = from.chatbox_id
9
- @to_id = to.chatbox_id
8
+ def initialize(from: req(:from), to: req(:to), body: req(:body), store: req(:store), id_generator: -> { SecureRandom.uuid })
9
+ @from = from
10
+ @to = to
10
11
  @body = body
11
12
  @store = store
13
+ @id_generator = id_generator
12
14
  end
13
15
 
14
- attr_reader :to_id, :from_id, :body
15
-
16
16
  def deliver!
17
- store.add_message self
17
+ store.add_message(
18
+ 'id' => id_generator.(),
19
+ 'from_id' => from.chatbox_id,
20
+ 'to_id' => to.chatbox_id,
21
+ 'body' => body,
22
+ )
18
23
  end
19
24
 
20
25
  private
21
26
 
22
- attr_reader :store
27
+ attr_reader :from, :to, :body, :store, :id_generator
23
28
  end
24
29
  end
data/lib/chatbox/inbox.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'chatbox/fake_missing_keywords'
2
+ require 'chatbox/message'
2
3
 
3
4
  module Chatbox
4
5
  class Inbox
@@ -28,7 +29,10 @@ module Chatbox
28
29
  private
29
30
 
30
31
  def messages
31
- @messages ||= store.find_all_messages_by_to_id id
32
+ @messages ||= begin
33
+ records = store.find_all_messages_by_to_id id
34
+ records.map { |record| Message.new record: record, store: store }
35
+ end
32
36
  end
33
37
  end
34
38
  end
@@ -0,0 +1,93 @@
1
+ require 'dalli'
2
+ require 'json'
3
+
4
+ module Chatbox
5
+ class MemcachedStore
6
+ def initialize(namespace: nil)
7
+ @dalli = Dalli::Client.new nil, namespace: namespace
8
+ end
9
+
10
+ delegate :flush, to: :dalli
11
+
12
+ def add_message(attrs)
13
+ @dalli.set "messages/#{attrs['id']}", JSON.generate(
14
+ 'from_id' => attrs['from_id'],
15
+ 'to_id' => attrs['to_id'],
16
+ 'body' => attrs['body'],
17
+ )
18
+
19
+ from_list = JSON.parse(@dalli.get("from/#{attrs['from_id']}") || '[]')
20
+ from_list << {'from_id' => attrs['from_id'], 'message_id' => attrs['id']}
21
+ @dalli.set "from/#{attrs['from_id']}", JSON.generate(from_list)
22
+
23
+ to_list = JSON.parse(@dalli.get("to/#{attrs['to_id']}") || '[]')
24
+ to_list << {'to_id' => attrs['to_id'], 'message_id' => attrs['id']}
25
+ @dalli.set "to/#{attrs['to_id']}", JSON.generate(to_list)
26
+ end
27
+
28
+ ##########
29
+
30
+ def mark_message_read!(id)
31
+ attrs = JSON.parse @dalli.get("messages/#{id}")
32
+ attrs['read'] = true
33
+ @dalli.set "messages/#{id}", JSON.generate(attrs)
34
+ end
35
+
36
+ def mark_message_unread!(id)
37
+ attrs = JSON.parse @dalli.get("messages/#{id}")
38
+ attrs['read'] = false
39
+ @dalli.set "messages/#{id}", JSON.generate(attrs)
40
+ end
41
+
42
+ ##########
43
+
44
+ def find_message(id)
45
+ if json = @dalli.get("messages/#{id}")
46
+ Record.new id, JSON.parse(json)
47
+ end
48
+ end
49
+
50
+ def find_all_messages_by_to_id(id)
51
+ if json = @dalli.get("to/#{id}")
52
+ JSON.parse(json).map do |attrs|
53
+ find_message attrs['message_id']
54
+ end
55
+ else
56
+ []
57
+ end
58
+ end
59
+
60
+ def find_all_messages_by_from_id(id)
61
+ if json = @dalli.get("from/#{id}")
62
+ JSON.parse(json).map do |attrs|
63
+ find_message attrs['message_id']
64
+ end
65
+ else
66
+ []
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ attr_reader :dalli
73
+
74
+ class Record
75
+ def initialize(id, attrs)
76
+ @id = id
77
+ @attrs = attrs
78
+ end
79
+
80
+ attr_reader :id
81
+
82
+ %w[from_id to_id body read].each do |name|
83
+ define_method name do
84
+ attrs[name]
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ attr_reader :attrs
91
+ end
92
+ end
93
+ end
@@ -1,21 +1,53 @@
1
1
  module Chatbox
2
2
  class MemoryStore
3
- def add_message(message)
4
- messages << message
3
+ def add_message(attrs)
4
+ attrs_list << attrs
5
5
  end
6
6
 
7
- def find_all_messages_by_to_id(to_id)
8
- messages.select { |message| message.to_id == to_id }
7
+ def mark_message_read!(id)
8
+ attrs_list.detect { |attrs| attrs['id'] == id }.merge! 'read' => true
9
9
  end
10
10
 
11
- def find_all_messages_by_from_id(from_id)
12
- messages.select { |message| message.from_id == from_id }
11
+ def mark_message_unread!(id)
12
+ attrs_list.detect { |attrs| attrs['id'] == id }.merge! 'read' => false
13
+ end
14
+
15
+ ##########
16
+
17
+ def find_message(id)
18
+ if attrs = attrs_list.detect { |attrs| attrs['id'] == id }
19
+ Record.new attrs
20
+ end
21
+ end
22
+
23
+ def find_all_messages_by_to_id(id)
24
+ attrs_list.select { |attrs| attrs['to_id'] == id }.map { |attrs| Record.new attrs }
25
+ end
26
+
27
+ def find_all_messages_by_from_id(id)
28
+ attrs_list.select { |attrs| attrs['from_id'] == id }.map { |attrs| Record.new attrs }
13
29
  end
14
30
 
15
31
  private
16
32
 
17
- def messages
18
- @messages ||= []
33
+ def attrs_list
34
+ @attrs_list ||= []
35
+ end
36
+
37
+ class Record
38
+ def initialize(attrs)
39
+ @attrs = attrs
40
+ end
41
+
42
+ %w[id from_id to_id body read].each do |name|
43
+ define_method name do
44
+ attrs[name]
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ attr_reader :attrs
19
51
  end
20
52
  end
21
53
  end
@@ -0,0 +1,36 @@
1
+ require 'chatbox/fake_missing_keywords'
2
+
3
+ module Chatbox
4
+ class Message
5
+ include FakeMissingKeywords
6
+
7
+ def initialize(record: req(:record), store: req(:store))
8
+ @record = record
9
+ @store = store
10
+ end
11
+
12
+ delegate :id, :from_id, :to_id, :body, to: :record
13
+
14
+ def read?
15
+ record.read
16
+ end
17
+
18
+ def mark_as_read!
19
+ store.mark_message_read! id
20
+ @record = store.find_message id
21
+ end
22
+
23
+ def mark_as_unread!
24
+ store.mark_message_unread! id
25
+ @record = store.find_message id
26
+ end
27
+
28
+ def ==(other)
29
+ other.is_a?(self.class) && record == other.record && store == other.store
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :record, :store
35
+ end
36
+ end
@@ -1,10 +1,11 @@
1
1
  require 'chatbox/fake_missing_keywords'
2
+ require 'chatbox/message'
2
3
 
3
4
  module Chatbox
4
5
  class Outbox
5
6
  include FakeMissingKeywords
6
7
 
7
- def initialize(entity: req(:entity), store: req(:store))
8
+ def initialize(entity: req(:entity), store: req(:store))
8
9
  @id = entity.chatbox_id
9
10
  @store = store
10
11
  end
@@ -28,7 +29,10 @@ module Chatbox
28
29
  private
29
30
 
30
31
  def messages
31
- @messages ||= store.find_all_messages_by_from_id id
32
+ @messages ||= begin
33
+ records = store.find_all_messages_by_from_id(id)
34
+ records.map { |record| Message.new record: record, store: store }
35
+ end
32
36
  end
33
37
  end
34
38
  end
@@ -1,3 +1,3 @@
1
1
  module Chatbox
2
- VERSION = '0.1.1'
2
+ VERSION = '0.2.0'
3
3
  end
data/spec/chatbox_spec.rb CHANGED
@@ -1,32 +1,8 @@
1
- require 'chatbox'
2
-
3
1
  describe Chatbox do
4
- before { Chatbox.reset_config! }
5
-
6
- context 'integration' do
7
- it 'sending and receiving a message' do
8
- austin = double 'entity', chatbox_id: 1
9
- rachel = double 'entity', chatbox_id: 2
10
-
11
- Chatbox.deliver_message! from: austin, to: rachel, body: 'Hello! How are you?'
12
-
13
- rachels_inbox = Chatbox.fetch_inbox_for rachel
14
- expect(rachels_inbox.size).to eq 1
15
- message = rachels_inbox[0]
16
- expect(message.from_id).to eq 1
17
- expect(message.body).to eq 'Hello! How are you?'
18
-
19
- austins_outbox = Chatbox.fetch_outbox_for austin
20
- expect(austins_outbox.size).to eq 1
21
- expect(message.to_id).to eq 2
22
- expect(message.body).to eq 'Hello! How are you?'
23
- end
24
- end
25
-
26
2
  describe '.deliver_message!' do
27
3
  before do
28
- @from = double 'entity'
29
- @to = double 'entity'
4
+ @from = double 'entity', chatbox_id: 1
5
+ @to = double 'entity', chatbox_id: 2
30
6
  @draft = double 'draft', deliver!: nil
31
7
  allow(Chatbox::Draft).to receive(:new).and_return @draft
32
8
  end
@@ -0,0 +1,73 @@
1
+ require 'chatbox/memcached_store'
2
+
3
+ describe 'chatbox' do
4
+ before do
5
+ @austin = double 'entity', chatbox_id: 1
6
+ @rachel = double 'entity', chatbox_id: 2
7
+ end
8
+
9
+ [:memcached, :memory].each do |store_type|
10
+ context "using #{store_type} store" do
11
+ before do
12
+ if store_type == :memcached
13
+ memcached_store = Chatbox::MemcachedStore.new namespace: 'chatbox-text'
14
+ memcached_store.flush
15
+ Chatbox.configure { |config| config.store = memcached_store }
16
+ end
17
+ end
18
+
19
+ it 'sending a message' do
20
+ Chatbox.deliver_message! from: @austin, to: @rachel, body: 'Hello! How are you?'
21
+
22
+ austins_outbox = Chatbox.fetch_outbox_for @austin
23
+ expect(austins_outbox.size).to eq 1
24
+
25
+ message = austins_outbox[0]
26
+ expect(message.to_id).to eq 2
27
+ expect(message.body).to eq 'Hello! How are you?'
28
+ end
29
+
30
+ it 'receiving a message' do
31
+ Chatbox.deliver_message! from: @austin, to: @rachel, body: 'Hello! How are you?'
32
+
33
+ rachels_inbox = Chatbox.fetch_inbox_for @rachel
34
+ expect(rachels_inbox.size).to eq 1
35
+
36
+ message = rachels_inbox[0]
37
+ expect(message.from_id).to eq 1
38
+ expect(message.body).to eq 'Hello! How are you?'
39
+ end
40
+
41
+ it 'marking messages as read' do
42
+ Chatbox.deliver_message! from: @austin, to: @rachel, body: 'Hello! How are you?'
43
+
44
+ rachels_inbox = Chatbox.fetch_inbox_for @rachel
45
+
46
+ message = rachels_inbox[0]
47
+ expect(message).to_not be_read
48
+
49
+ message.mark_as_read!
50
+ expect(message).to be_read
51
+
52
+ expect(Chatbox.fetch_inbox_for(@rachel)[0]).to be_read
53
+ end
54
+
55
+ it 'marking messages as unread' do
56
+ Chatbox.deliver_message! from: @austin, to: @rachel, body: 'Hello! How are you?'
57
+
58
+ rachels_inbox = Chatbox.fetch_inbox_for @rachel
59
+
60
+ message = rachels_inbox[0]
61
+ expect(message).to_not be_read
62
+
63
+ message.mark_as_read!
64
+ message.mark_as_unread!
65
+
66
+ message = rachels_inbox[0]
67
+ expect(message).to_not be_read
68
+
69
+ expect(Chatbox.fetch_inbox_for(@rachel)[0]).to_not be_read
70
+ end
71
+ end
72
+ end
73
+ end
@@ -9,8 +9,15 @@ describe Chatbox::Draft do
9
9
  to: double('entity', chatbox_id: 2),
10
10
  body: 'Hi',
11
11
  store: store,
12
+ id_generator: -> { 'b00c7e15-668b-44b8-9336-e87e7b7d892e' },
13
+ )
14
+
15
+ expect(store).to receive(:add_message).with(
16
+ 'id' => 'b00c7e15-668b-44b8-9336-e87e7b7d892e',
17
+ 'from_id' => 1,
18
+ 'to_id' => 2,
19
+ 'body' => 'Hi',
12
20
  )
13
- expect(store).to receive(:add_message).with draft
14
21
  draft.deliver!
15
22
  end
16
23
  end
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,10 @@
1
+ require 'chatbox'
2
+
1
3
  RSpec.configure do |config|
4
+ config.before do
5
+ Chatbox.reset_config!
6
+ end
7
+
2
8
  # More verbose output when running an individual spec file.
3
9
  if config.files_to_run.one?
4
10
  # Use the documentation formatter for detailed output,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chatbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Austin Schneider
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-22 00:00:00.000000000 Z
11
+ date: 2014-08-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: dalli
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.7'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.7'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: activesupport
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -86,10 +100,13 @@ files:
86
100
  - lib/chatbox/draft.rb
87
101
  - lib/chatbox/fake_missing_keywords.rb
88
102
  - lib/chatbox/inbox.rb
103
+ - lib/chatbox/memcached_store.rb
89
104
  - lib/chatbox/memory_store.rb
105
+ - lib/chatbox/message.rb
90
106
  - lib/chatbox/outbox.rb
91
107
  - lib/chatbox/version.rb
92
108
  - spec/chatbox_spec.rb
109
+ - spec/integration_spec.rb
93
110
  - spec/lib/draft_spec.rb
94
111
  - spec/spec_helper.rb
95
112
  homepage: ''
@@ -118,5 +135,6 @@ specification_version: 4
118
135
  summary: Simple messaging system.
119
136
  test_files:
120
137
  - spec/chatbox_spec.rb
138
+ - spec/integration_spec.rb
121
139
  - spec/lib/draft_spec.rb
122
140
  - spec/spec_helper.rb