chatbox 0.1.1 → 0.2.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.
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