Skip to content

Commit

Permalink
WIP #54: add local store.
Browse files Browse the repository at this point in the history
  • Loading branch information
dblock committed Jan 30, 2016
1 parent a303f3d commit 9a4e166
Show file tree
Hide file tree
Showing 17 changed files with 160 additions and 11 deletions.
10 changes: 5 additions & 5 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2016-01-24 16:12:44 -0500 using RuboCop version 0.35.0.
# on 2016-01-30 17:48:20 -0500 using RuboCop version 0.35.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
Expand Down Expand Up @@ -28,19 +28,19 @@ Metrics/AbcSize:
# Offense count: 1
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 112
Max: 123

# Offense count: 457
# Offense count: 497
# Configuration parameters: AllowURI, URISchemes.
Metrics/LineLength:
Max: 288

# Offense count: 5
# Offense count: 6
# Configuration parameters: CountComments.
Metrics/MethodLength:
Max: 27

# Offense count: 48
# Offense count: 51
# Configuration parameters: Exclude.
Style/Documentation:
Enabled: false
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
### 0.6.0 (TBD)

* [#54](https://github.com/dblock/slack-ruby-client/issues/54): RealTime client maintains a local store of team data - [@dblock](https://github.com/dblock).

### 0.5.5 (Next)

* [#52](https://github.com/dblock/slack-ruby-client/issues/52): Added `users_search` - [@dblock](https://github.com/dblock).
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,19 +200,21 @@ You can send a ping with `ping`.
client.ping
```

The client exposes the properties of [rtm.start](https://api.slack.com/methods/rtm.start) upon a successful connection.
The client exposes and maintains a local store with the properties of [rtm.start](https://api.slack.com/methods/rtm.start) upon a successful connection.

property | description
---------|-------------------------------------------------------------------------------------------------
url | A WebSocket Message Server URL.
self | Details on the authenticated user.
team | Details on the authenticated user's team.
users | A list of user objects, one for every member of the team.
users | A hash of user objects by user ID.
channels | A list of channel objects, one for every channel visible to the authenticated user.
groups | A list of group objects, one for every group the authenticated user is in.
ims | A list of IM objects, one for every direct message channel visible to the authenticated user.
bots | Details of the integrations set up on this team.

The RealTime client tracks changes, such as users being renamed, added or deleted, therefore `client.users` is always up-to-date.

You can configure the RealTime client either globally or via the initializer.

```ruby
Expand Down
10 changes: 10 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
Upgrading Slack-Ruby-Client
===========================

### Upgrading to >= 0.6.0

#### Changes to RealTime Local Store

Upon a successful `rtm.start` the RealTime client keeps a local cache of objects, including `self` or `users`. It will now also track changes to these objects. The following changes have been made to the data structures.

##### client.users

The `client.users` collection has been changed from `Array` to `Hash`, with user ID as key. Replace any code iterating over the array with `client.users.values.each` or `client.users.each_pair`.

### Upgrading to >= 0.5.0

#### Changes to Real Time Concurrency
Expand Down
2 changes: 2 additions & 0 deletions lib/slack-ruby-client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,7 @@
require 'slack/real_time/api/ping'
require 'slack/real_time/api/message'
require 'slack/real_time/api/typing'
require 'slack/real_time/models'
require 'slack/real_time/config'
require 'slack/real_time/client'
require 'slack/real_time/store'
22 changes: 19 additions & 3 deletions lib/slack/real_time/client.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module Slack
module RealTime
class Client
extend Forwardable

class ClientNotStartedError < StandardError; end
class ClientAlreadyStartedError < StandardError; end

Expand All @@ -9,7 +11,14 @@ class ClientAlreadyStartedError < StandardError; end
include Api::Message
include Api::Typing

@events = {}

class << self
attr_accessor :events
end

attr_accessor :web_client
attr_accessor :store
attr_accessor(*Config::ATTRIBUTES)

def initialize(options = {})
Expand All @@ -21,7 +30,9 @@ def initialize(options = {})
@web_client = Slack::Web::Client.new(token: token)
end

[:url, :team, :self, :users, :channels, :groups, :ims, :bots].each do |attr|
def_delegators :@store, :users

[:url, :team, :self, :channels, :groups, :ims, :bots].each do |attr|
define_method attr do
@options[attr.to_s] if @options
end
Expand Down Expand Up @@ -72,7 +83,7 @@ def config
def build_socket
fail ClientAlreadyStartedError if started?
@options = web_client.rtm_start

@store = Slack::RealTime::Store::Memory.new(@options)
socket_class.new(@options.fetch('url'), socket_options)
end

Expand Down Expand Up @@ -140,7 +151,12 @@ def dispatch(event)
data = JSON.parse(event.data)
type = data['type']
return false unless type
callbacks = self.callbacks[type.to_s]
type = type.to_s
# event handlers
handler = Slack::RealTime::Client.events[type]
handler.call(self, data) if handler
# callbacks
callbacks = self.callbacks[type]
return false unless callbacks
callbacks.each do |c|
c.call(data)
Expand Down
2 changes: 2 additions & 0 deletions lib/slack/real_time/models.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require 'slack/real_time/models/base'
require 'slack/real_time/models/user'
13 changes: 13 additions & 0 deletions lib/slack/real_time/models/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module Slack
module RealTime
module Models
class Base < Hash
def initialize(attrs = {})
attrs.each do |k, v|
self[k] = v
end
end
end
end
end
end
8 changes: 8 additions & 0 deletions lib/slack/real_time/models/user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module Slack
module RealTime
module Models
class User < Base
end
end
end
end
2 changes: 2 additions & 0 deletions lib/slack/real_time/store.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require 'slack/real_time/store/memory'
require 'slack/real_time/store/handlers'
2 changes: 2 additions & 0 deletions lib/slack/real_time/store/handlers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require 'slack/real_time/store/handlers/user_change'
require 'slack/real_time/store/handlers/team_join'
15 changes: 15 additions & 0 deletions lib/slack/real_time/store/handlers/team_join.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module Slack
module RealTime
module Store
module Handlers
module TeamJoin
def self.call(client, data)
client.users[data['user']['id']] = Models::User.new(data['user'])
end
end
end
end
end
end

Slack::RealTime::Client.events['team_join'] = Slack::RealTime::Store::Handlers::TeamJoin
15 changes: 15 additions & 0 deletions lib/slack/real_time/store/handlers/user_change.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module Slack
module RealTime
module Store
module Handlers
module UserChange
def self.call(client, data)
client.users[data['user']['id']] = Models::User.new(data['user'])
end
end
end
end
end
end

Slack::RealTime::Client.events['user_change'] = Slack::RealTime::Store::Handlers::UserChange
16 changes: 16 additions & 0 deletions lib/slack/real_time/store/memory.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module Slack
module RealTime
module Store
class Memory
attr_accessor :users

def initialize(attrs = {})
@users = {}
attrs['users'].each do |data|
@users[data['id']] = Models::User.new(data)
end
end
end
end
end
end
31 changes: 31 additions & 0 deletions spec/slack/real_time/api/store_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require 'spec_helper'

RSpec.describe Slack::RealTime::Client, vcr: { cassette_name: 'web/rtm_start' } do
include_context 'connected client'

describe '#user_change' do
it 'updates user in store' do
expect(client.users['U07KECJ77']['name']).to eq 'aws'
event = Slack::RealTime::Event.new(
'type' => 'user_change',
'user' => {
'id' => 'U07KECJ77', 'name' => 'renamed'
})
client.send(:dispatch, event)
expect(client.users['U07KECJ77']['name']).to eq 'renamed'
end
end
describe '#team_join' do
it 'creates a user in store' do
expect do
event = Slack::RealTime::Event.new(
'type' => 'team_join',
'user' => {
'id' => 'DEADBEEF', 'name' => 'added'
})
client.send(:dispatch, event)
end.to change(client.users, :count).by(1)
expect(client.users['DEADBEEF']['name']).to eq 'added'
end
end
end
2 changes: 1 addition & 1 deletion spec/slack/real_time/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
end
it 'sets users' do
expect(client.users.count).to eq 7
expect(client.users.first['id']).to eq 'U07KECJ77'
expect(client.users.values.first['id']).to eq 'U07KECJ77'
end
it 'sets channels' do
expect(client.channels.count).to eq 8
Expand Down
11 changes: 11 additions & 0 deletions spec/support/real_time/event.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Slack
module RealTime
class Event
attr_accessor :data

def initialize(data)
@data = data.to_json
end
end
end
end

0 comments on commit 9a4e166

Please sign in to comment.