turntabler 0.0.1 → 0.1.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.
- data/CHANGELOG.md +15 -0
- data/README.md +118 -76
- data/examples/Gemfile.lock +1 -1
- data/examples/autobop.rb +4 -4
- data/examples/autofan.rb +4 -4
- data/examples/blacklist.rb +4 -4
- data/examples/bop.rb +4 -4
- data/examples/bopcount.rb +4 -4
- data/examples/chat_bot.rb +4 -4
- data/examples/modlist.rb +4 -4
- data/examples/switch.rb +4 -4
- data/examples/time_afk_list.rb +4 -4
- data/lib/turntabler/authorized_user.rb +47 -11
- data/lib/turntabler/boot.rb +1 -1
- data/lib/turntabler/client.rb +64 -20
- data/lib/turntabler/connection.rb +4 -4
- data/lib/turntabler/digest_helpers.rb +3 -1
- data/lib/turntabler/event.rb +25 -15
- data/lib/turntabler/handler.rb +16 -9
- data/lib/turntabler/loggable.rb +2 -0
- data/lib/turntabler/playlist.rb +1 -1
- data/lib/turntabler/preferences.rb +12 -11
- data/lib/turntabler/resource.rb +15 -13
- data/lib/turntabler/room.rb +19 -13
- data/lib/turntabler/room_directory.rb +6 -6
- data/lib/turntabler/song.rb +1 -1
- data/lib/turntabler/sticker.rb +2 -2
- data/lib/turntabler/sticker_placement.rb +1 -1
- data/lib/turntabler/user.rb +10 -11
- data/lib/turntabler/version.rb +2 -2
- data/lib/turntabler.rb +8 -4
- metadata +2 -2
data/lib/turntabler/boot.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'turntabler/resource'
|
2
2
|
|
3
3
|
module Turntabler
|
4
|
-
# Represents an
|
4
|
+
# Represents an event where a user has been booted from a room
|
5
5
|
class Boot < Resource
|
6
6
|
# The user that was booted from the room
|
7
7
|
# @return [Turntabler::User]
|
data/lib/turntabler/client.rb
CHANGED
@@ -24,8 +24,8 @@ module Turntabler
|
|
24
24
|
attr_reader :id
|
25
25
|
|
26
26
|
# Sets the current room the user is in
|
27
|
-
# @param [Turntabler::Room] value The new room
|
28
27
|
# @api private
|
28
|
+
# @param [Turntabler::Room] value The new room
|
29
29
|
attr_writer :room
|
30
30
|
|
31
31
|
# The directory for looking up / creating rooms
|
@@ -37,29 +37,31 @@ module Turntabler
|
|
37
37
|
attr_reader :timeout
|
38
38
|
|
39
39
|
# Creates a new client for communicating with Turntable.fm with the given
|
40
|
-
#
|
40
|
+
# email / password.
|
41
41
|
#
|
42
|
-
# @param [String]
|
43
|
-
# @param [String]
|
42
|
+
# @param [String] email The e-mail address of the user to authenticate with
|
43
|
+
# @param [String] password The Turntable password associated with the email address
|
44
44
|
# @param [Hash] options The configuration options for the client
|
45
45
|
# @option options [String] :id The unique identifier representing this client
|
46
46
|
# @option options [String] :room The id of the room to initially enter
|
47
|
+
# @option options [String] :user_id The Turntable id for the authenticating user (required if the user does not have an associated password)
|
48
|
+
# @option options [String] :auth The authentication token for the user (required if the user does not have an associated password)
|
47
49
|
# @option options [Fixnum] :timeout (10) The amount of seconds to allow to elapse for requests before timing out
|
48
50
|
# @option options [Boolean] :reconnect (false) Whether to allow the client to automatically reconnect when disconnected either by Turntable or by the network
|
49
51
|
# @option options [Fixnum] :reconnect_wait (5) The amount of seconds to wait before reconnecting
|
50
52
|
# @raise [Turntabler::Error] if an invalid option is specified
|
51
53
|
# @yield Runs the given block within the context if the client (for DSL-type usage)
|
52
|
-
def initialize(
|
54
|
+
def initialize(email, password, options = {}, &block)
|
53
55
|
options = {
|
54
56
|
:id => "#{Time.now.to_i}-#{rand}",
|
55
57
|
:timeout => 10,
|
56
58
|
:reconnect => false,
|
57
59
|
:reconnect_wait => 5
|
58
60
|
}.merge(options)
|
59
|
-
assert_valid_keys(options, :id, :room, :url, :timeout, :reconnect, :reconnect_wait)
|
61
|
+
assert_valid_keys(options, :id, :room, :url, :user_id, :auth, :timeout, :reconnect, :reconnect_wait)
|
60
62
|
|
61
63
|
@id = options[:id]
|
62
|
-
@user = AuthorizedUser.new(self, :_id => user_id, :
|
64
|
+
@user = AuthorizedUser.new(self, :email => email, :password => password, :_id => options[:user_id], :userauth => options[:auth])
|
63
65
|
@rooms = RoomDirectory.new(self)
|
64
66
|
@event_handlers = {}
|
65
67
|
@timeout = options[:timeout]
|
@@ -101,8 +103,8 @@ module Turntabler
|
|
101
103
|
@connection.start
|
102
104
|
|
103
105
|
# Wait until the connection is authenticated
|
104
|
-
wait do |
|
105
|
-
on(:session_missing, :once => true) {
|
106
|
+
wait do |&resume|
|
107
|
+
on(:session_missing, :once => true) { resume.call }
|
106
108
|
end
|
107
109
|
end
|
108
110
|
|
@@ -118,8 +120,8 @@ module Turntabler
|
|
118
120
|
@update_timer = nil
|
119
121
|
@connection.close
|
120
122
|
|
121
|
-
wait do |
|
122
|
-
on(:session_ended, :once => true) {
|
123
|
+
wait do |&resume|
|
124
|
+
on(:session_ended, :once => true) { resume.call }
|
123
125
|
end
|
124
126
|
|
125
127
|
on_session_ended(allow_reconnect)
|
@@ -149,8 +151,8 @@ module Turntabler
|
|
149
151
|
message_id = @connection.publish(params.merge(:api => command))
|
150
152
|
|
151
153
|
# Wait until we get a response for the given message
|
152
|
-
data = wait do |
|
153
|
-
on(:response_received, :once => true, :if => {'msgid' => message_id}) {|data|
|
154
|
+
data = wait do |&resume|
|
155
|
+
on(:response_received, :once => true, :if => {'msgid' => message_id}) {|data| resume.call(data)}
|
154
156
|
end
|
155
157
|
|
156
158
|
if data['success']
|
@@ -169,6 +171,16 @@ module Turntabler
|
|
169
171
|
# @option options [Boolean] :once (false) Whether to only run the handler once
|
170
172
|
# @return [true]
|
171
173
|
#
|
174
|
+
# == Client Events
|
175
|
+
#
|
176
|
+
# * +:reconnected+ - The client reconnected (and re-entered any room that the user was previously in)
|
177
|
+
#
|
178
|
+
# @example
|
179
|
+
# client.on :reconnected do
|
180
|
+
# client.room.dj
|
181
|
+
# # ...
|
182
|
+
# end
|
183
|
+
#
|
172
184
|
# == Room Events
|
173
185
|
#
|
174
186
|
# * +:room_updated+ - Information about the room was updated
|
@@ -334,6 +346,21 @@ module Turntabler
|
|
334
346
|
user_id ? User.new(self, :_id => user_id) : @user
|
335
347
|
end
|
336
348
|
|
349
|
+
# Gets the user with the given DJ name. This should only be used if the id
|
350
|
+
# of the user is unknown.
|
351
|
+
#
|
352
|
+
# @param [String] name The user's DJ name
|
353
|
+
# @return [Turntabler::User]
|
354
|
+
# @raise [Turntabler::Error] if the command fails
|
355
|
+
# @example
|
356
|
+
# client.user_by_name('DJSpinster') # => #<Turntabler::User id="a34bd..." ...>
|
357
|
+
def user_by_name(name)
|
358
|
+
data = api('user.get_id', :name => name)
|
359
|
+
user = self.user(data['userid'])
|
360
|
+
user.attributes = {'name' => name}
|
361
|
+
user
|
362
|
+
end
|
363
|
+
|
337
364
|
# Get all avatars availble on Turntable.
|
338
365
|
#
|
339
366
|
# @return [Array<Turntabler::Avatar>]
|
@@ -389,17 +416,20 @@ module Turntabler
|
|
389
416
|
api('file.search', :query => query, :page => options[:page])
|
390
417
|
|
391
418
|
# Wait for the async callback
|
392
|
-
songs = wait do |
|
393
|
-
on(:search_completed, :once => true, :if => {'query' => query}) {|songs|
|
394
|
-
on(:search_failed, :once => true, :if => {'query' => query}) {
|
419
|
+
songs = wait do |&resume|
|
420
|
+
on(:search_completed, :once => true, :if => {'query' => query}) {|songs| resume.call(songs)}
|
421
|
+
on(:search_failed, :once => true, :if => {'query' => query}) { resume.call }
|
395
422
|
end
|
396
423
|
|
397
424
|
songs || raise(Error, 'Search failed to complete')
|
398
425
|
end
|
399
426
|
|
400
|
-
private
|
401
427
|
# Callback when a message has been received from Turntable. This will run
|
402
428
|
# any handlers registered for the event associated with the message.
|
429
|
+
#
|
430
|
+
# @api private
|
431
|
+
# @param [Hash<String, Object>] data The message data received
|
432
|
+
# @return nil
|
403
433
|
def on_message(data)
|
404
434
|
if Event.command?(data['command'])
|
405
435
|
event = Event.new(self, data)
|
@@ -411,6 +441,7 @@ module Turntabler
|
|
411
441
|
end
|
412
442
|
end
|
413
443
|
|
444
|
+
private
|
414
445
|
# Callback when a heartbeat message has been received from Turntable determining
|
415
446
|
# whether this client is still alive.
|
416
447
|
def on_heartbeat
|
@@ -442,16 +473,29 @@ module Turntabler
|
|
442
473
|
if @reconnect && allow_reconnect
|
443
474
|
EM::Synchrony.add_timer(@reconnect_wait) do
|
444
475
|
room ? room.enter : connect(url)
|
476
|
+
on_message('command' => 'reconnected')
|
445
477
|
end
|
446
478
|
end
|
447
479
|
end
|
448
480
|
|
449
481
|
# Pauses the current fiber until it is resumed with response data. This
|
450
482
|
# can only get resumed explicitly by the provided block.
|
451
|
-
def wait
|
483
|
+
def wait(&block)
|
452
484
|
fiber = Fiber.current
|
453
|
-
|
454
|
-
|
485
|
+
|
486
|
+
# Resume the fiber when a response is received
|
487
|
+
allow_resume = true
|
488
|
+
block.call do |*args|
|
489
|
+
fiber.resume(*args) if allow_resume
|
490
|
+
end
|
491
|
+
|
492
|
+
# Attempt to pause the fiber until a response is received
|
493
|
+
begin
|
494
|
+
Fiber.yield
|
495
|
+
rescue FiberError => ex
|
496
|
+
allow_resume = false
|
497
|
+
raise Error, 'Turntabler APIs cannot be called from root fiber; use Turntabler.run { ... } instead'
|
498
|
+
end
|
455
499
|
end
|
456
500
|
end
|
457
501
|
end
|
@@ -78,7 +78,7 @@ module Turntabler
|
|
78
78
|
def publish(params)
|
79
79
|
params[:msgid] = message_id = next_message_id
|
80
80
|
params = @default_params.merge(params)
|
81
|
-
|
81
|
+
|
82
82
|
logger.debug "Message sent: #{params.inspect}"
|
83
83
|
|
84
84
|
if HTTP_APIS.include?(params[:api])
|
@@ -86,7 +86,7 @@ module Turntabler
|
|
86
86
|
else
|
87
87
|
publish_to_socket(params)
|
88
88
|
end
|
89
|
-
|
89
|
+
|
90
90
|
# Add timeout handler
|
91
91
|
EventMachine.add_timer(@timeout) do
|
92
92
|
dispatch('msgid' => message_id, 'command' => 'response_received', 'error' => 'timed out')
|
@@ -102,7 +102,7 @@ module Turntabler
|
|
102
102
|
data = "~m~#{message.length}~m~#{message}"
|
103
103
|
@socket.send(data)
|
104
104
|
end
|
105
|
-
|
105
|
+
|
106
106
|
# Publishes the given params to the HTTP API
|
107
107
|
def publish_to_http(params)
|
108
108
|
api = params.delete(:api)
|
@@ -124,7 +124,7 @@ module Turntabler
|
|
124
124
|
event = Faye::WebSocket::API::Event.new('message', :data => "~m~#{Time.now.to_i}~m~#{JSON.generate(message)}")
|
125
125
|
on_message(event)
|
126
126
|
end
|
127
|
-
|
127
|
+
|
128
128
|
# Runs the configured handler with the given message
|
129
129
|
def dispatch(message)
|
130
130
|
Turntabler.run { @handler.call(message) } if @handler
|
@@ -1,8 +1,10 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
|
1
3
|
module Turntabler
|
2
4
|
# Provides a set of helper functions for dealing with message digests
|
3
5
|
# @api private
|
4
6
|
module DigestHelpers
|
5
|
-
# Generates a SHA1 hash from the given data
|
7
|
+
# Generates a SHA1 hash from the given data.
|
6
8
|
#
|
7
9
|
# @param [String] data The data to create a hash from
|
8
10
|
# @return [String]
|
data/lib/turntabler/event.rb
CHANGED
@@ -29,8 +29,8 @@ module Turntabler
|
|
29
29
|
define_method("typecast_#{command}_event", &block)
|
30
30
|
protected :"typecast_#{command}_event"
|
31
31
|
end
|
32
|
-
|
33
|
-
# Determines whether the given command is handled
|
32
|
+
|
33
|
+
# Determines whether the given command is handled.
|
34
34
|
#
|
35
35
|
# @param [String] command The command to check for the existence of
|
36
36
|
# @return [Boolean] +true+ if the command exists, otherwise +false+
|
@@ -56,6 +56,9 @@ module Turntabler
|
|
56
56
|
# The client's connection has closed
|
57
57
|
handle :session_ended
|
58
58
|
|
59
|
+
# The client re-connected after previously being disconnected
|
60
|
+
handle :reconnected
|
61
|
+
|
59
62
|
# A heartbeat was received from Turntable to ensure the client's connection
|
60
63
|
# is still valid
|
61
64
|
handle :heartbeat
|
@@ -119,7 +122,6 @@ module Turntabler
|
|
119
122
|
new_djs = []
|
120
123
|
data['user'].each_with_index do |attrs, index|
|
121
124
|
new_djs << user = room.build_user(attrs.merge('placements' => data['placements'][index]))
|
122
|
-
room.listeners << user
|
123
125
|
room.djs << user
|
124
126
|
end
|
125
127
|
new_djs
|
@@ -129,7 +131,6 @@ module Turntabler
|
|
129
131
|
handle :dj_removed, :rem_dj do
|
130
132
|
data['user'].map do |attrs|
|
131
133
|
user = room.build_user(attrs)
|
132
|
-
room.listeners << user
|
133
134
|
room.djs.delete(user)
|
134
135
|
user
|
135
136
|
end
|
@@ -138,7 +139,6 @@ module Turntabler
|
|
138
139
|
# A new moderator was added to the room
|
139
140
|
handle :moderator_added, :new_moderator do
|
140
141
|
user = room.build_user(data)
|
141
|
-
room.listeners << user
|
142
142
|
room.moderators << user
|
143
143
|
user
|
144
144
|
end
|
@@ -152,26 +152,34 @@ module Turntabler
|
|
152
152
|
|
153
153
|
# There are no more songs to play in the room
|
154
154
|
handle :song_unavailable, :nosong do
|
155
|
+
client.on_message('command' => 'song_ended') if room.current_song
|
155
156
|
room.attributes = data['room'].merge('current_song' => nil)
|
156
157
|
nil
|
157
158
|
end
|
158
159
|
|
159
160
|
# A new song has started playing
|
160
161
|
handle :song_started, :newsong do
|
162
|
+
client.on_message('command' => 'song_ended') if room.current_song
|
161
163
|
room.attributes = data['room']
|
162
164
|
room.current_song
|
163
165
|
end
|
164
166
|
|
165
167
|
# The current song has ended
|
166
|
-
handle :song_ended
|
167
|
-
room.attributes = data['room']
|
168
|
+
handle :song_ended do
|
168
169
|
room.current_song
|
169
170
|
end
|
170
171
|
|
171
172
|
# A vote was cast for the song
|
172
173
|
handle :song_voted, :update_votes do
|
174
|
+
song = room.current_song
|
175
|
+
initial_up_votes_count = song.up_votes_count
|
173
176
|
room.attributes = data['room']
|
174
|
-
|
177
|
+
|
178
|
+
# Update DJ point count
|
179
|
+
dj = room.current_dj
|
180
|
+
dj.attributes = {'points' => dj.points + song.up_votes_count - initial_up_votes_count}
|
181
|
+
|
182
|
+
song
|
175
183
|
end
|
176
184
|
|
177
185
|
# A user in the room has queued the current song onto their playlist
|
@@ -181,11 +189,13 @@ module Turntabler
|
|
181
189
|
|
182
190
|
# A song was skipped due to a copyright claim
|
183
191
|
handle :song_blocked do
|
192
|
+
client.on_message('command' => 'song_ended') if room.current_song
|
184
193
|
Song.new(client, data)
|
185
194
|
end
|
186
195
|
|
187
196
|
# A song was skipped due to a limit on # of plays per hour
|
188
197
|
handle :song_limited, :dmca_error do
|
198
|
+
client.on_message('command' => 'song_ended') if room.current_song
|
189
199
|
Song.new(client, data)
|
190
200
|
end
|
191
201
|
|
@@ -201,19 +211,19 @@ module Turntabler
|
|
201
211
|
|
202
212
|
# A song search failed to complete
|
203
213
|
handle :search_failed
|
204
|
-
|
214
|
+
|
205
215
|
# The name of the event that was triggered
|
206
216
|
# @return [String]
|
207
217
|
attr_reader :name
|
208
|
-
|
218
|
+
|
209
219
|
# The raw hash of data parsed from the event
|
210
|
-
# @return [Hash]
|
220
|
+
# @return [Hash<String, Object>]
|
211
221
|
attr_reader :data
|
212
|
-
|
222
|
+
|
213
223
|
# The typecasted results parsed from the data
|
214
224
|
# @return [Array]
|
215
225
|
attr_reader :results
|
216
|
-
|
226
|
+
|
217
227
|
# Creates a new event triggered with the given data
|
218
228
|
#
|
219
229
|
# @param [Turntabler::Client] client The client that this event is bound to
|
@@ -226,11 +236,11 @@ module Turntabler
|
|
226
236
|
@results = __send__("typecast_#{command}_event")
|
227
237
|
@results = [@results] unless @results.is_a?(Array)
|
228
238
|
end
|
229
|
-
|
239
|
+
|
230
240
|
private
|
231
241
|
# The client that all APIs filter through
|
232
242
|
attr_reader :client
|
233
|
-
|
243
|
+
|
234
244
|
# Gets the current room the user is in
|
235
245
|
def room
|
236
246
|
client.room
|
data/lib/turntabler/handler.rb
CHANGED
@@ -1,23 +1,26 @@
|
|
1
|
+
require 'turntabler/assertions'
|
1
2
|
require 'turntabler/event'
|
3
|
+
require 'turntabler/loggable'
|
2
4
|
|
3
5
|
module Turntabler
|
4
6
|
# Represents a callback that's been bound to a particular event
|
5
7
|
# @api private
|
6
8
|
class Handler
|
7
9
|
include Assertions
|
10
|
+
include Loggable
|
8
11
|
|
9
12
|
# The event this handler is bound to
|
10
13
|
# @return [String]
|
11
14
|
attr_reader :event
|
12
|
-
|
15
|
+
|
13
16
|
# Whether to only call the handler once and then never again
|
14
17
|
# @return [Boolean] +true+ if only called once, otherwise +false+
|
15
18
|
attr_reader :once
|
16
|
-
|
19
|
+
|
17
20
|
# The data that must be matched in order for the handler to run
|
18
21
|
# @return [Hash<String, Object>]
|
19
22
|
attr_reader :conditions
|
20
|
-
|
23
|
+
|
21
24
|
# Builds a new handler bound to the given event.
|
22
25
|
#
|
23
26
|
# @param [String] event The name of the event to bind to
|
@@ -35,18 +38,22 @@ module Turntabler
|
|
35
38
|
@conditions = options[:if]
|
36
39
|
@block = block
|
37
40
|
end
|
38
|
-
|
39
|
-
# Runs this handler
|
41
|
+
|
42
|
+
# Runs this handler for each result from the given event.
|
40
43
|
#
|
41
|
-
# @param [
|
42
|
-
# @return [Boolean] +true+ if conditions were
|
44
|
+
# @param [Turntabler::Event] event The event being triggered
|
45
|
+
# @return [Boolean] +true+ if conditions were matched to run the handler, otherwise +false+
|
43
46
|
def run(event)
|
44
47
|
if conditions_match?(event.data)
|
45
48
|
# Run the block for each individual result
|
46
49
|
event.results.each do |result|
|
47
|
-
|
50
|
+
begin
|
51
|
+
@block.call(*[result].compact)
|
52
|
+
rescue StandardError => ex
|
53
|
+
logger.error(([ex.message] + ex.backtrace) * "\n")
|
54
|
+
end
|
48
55
|
end
|
49
|
-
|
56
|
+
|
50
57
|
true
|
51
58
|
else
|
52
59
|
false
|
data/lib/turntabler/loggable.rb
CHANGED
data/lib/turntabler/playlist.rb
CHANGED
@@ -6,47 +6,48 @@ module Turntabler
|
|
6
6
|
# Send e-mails if a fan starts DJing
|
7
7
|
# @return [Boolean]
|
8
8
|
attribute :notify_dj
|
9
|
-
|
9
|
+
|
10
10
|
# Send e-mails when someone becomes a fan
|
11
11
|
# @return [Boolean]
|
12
12
|
attribute :notify_fan
|
13
|
-
|
13
|
+
|
14
14
|
# Sends infrequent e-mails about news
|
15
15
|
# @return [Boolean]
|
16
16
|
attribute :notify_news
|
17
|
-
|
17
|
+
|
18
18
|
# Sends e-mails at random times with a different subsection of the digits of pi
|
19
19
|
# @return [Boolean]
|
20
20
|
attribute :notify_random
|
21
|
-
|
22
|
-
# Publishes to facebook songs
|
21
|
+
|
22
|
+
# Publishes to facebook songs voted up in public rooms
|
23
23
|
# @return [Boolean]
|
24
24
|
attribute :facebook_awesome
|
25
|
-
|
25
|
+
|
26
26
|
# Publishes to facebook when a public room is joined
|
27
27
|
# @return [Boolean]
|
28
28
|
attribute :facebook_join
|
29
|
-
|
29
|
+
|
30
30
|
# Publishes to facebook when DJing in a public room
|
31
31
|
# @return [Boolean]
|
32
32
|
attribute :facebook_dj
|
33
|
-
|
33
|
+
|
34
34
|
# Loads the user's current Turntable preferences.
|
35
35
|
#
|
36
36
|
# @return [true]
|
37
37
|
# @raise [Turntabler::Error] if the command fails
|
38
38
|
# @example
|
39
|
-
# preferences.load
|
39
|
+
# preferences.load # => true
|
40
|
+
# preferences.notify_dj # => false
|
40
41
|
def load
|
41
42
|
data = api('user.get_prefs')
|
42
|
-
self.attributes = data['result'].inject({}) do |result, (preference, value,
|
43
|
+
self.attributes = data['result'].inject({}) do |result, (preference, value, *)|
|
43
44
|
result[preference] = value
|
44
45
|
result
|
45
46
|
end
|
46
47
|
super
|
47
48
|
end
|
48
49
|
|
49
|
-
# Updates the preferences.
|
50
|
+
# Updates the user's preferences.
|
50
51
|
#
|
51
52
|
# @param [Hash] attributes The attributes to update
|
52
53
|
# @option attributes [Boolean] :notify_dj
|
data/lib/turntabler/resource.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'pp'
|
2
|
-
require 'digest/sha1'
|
3
2
|
require 'turntabler/assertions'
|
4
3
|
require 'turntabler/digest_helpers'
|
5
4
|
|
@@ -14,18 +13,18 @@ module Turntabler
|
|
14
13
|
|
15
14
|
class << self
|
16
15
|
include Assertions
|
17
|
-
|
16
|
+
|
18
17
|
# Defines a new Turntable attribute on this class. By default, the name
|
19
18
|
# of the attribute is assumed to be the same name that Turntable specifies
|
20
19
|
# in its API. If the names are different, this can be overridden on a
|
21
20
|
# per-attribute basis.
|
22
21
|
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
22
|
+
# @api private
|
23
|
+
# @param [String] name The public name for the attribute
|
24
|
+
# @param [Hash] options The configuration options
|
25
|
+
# @option options [Boolean] :load (true) Whether the resource should be loaded remotely from Turntable in order to access the attribute
|
26
|
+
# @raise [ArgumentError] if an invalid option is specified
|
27
|
+
# @example
|
29
28
|
# # Define a "name" attribute that maps to a Turntable "name" attribute
|
30
29
|
# attribute :name
|
31
30
|
#
|
@@ -51,7 +50,6 @@ module Turntabler
|
|
51
50
|
# # when accessed
|
52
51
|
# attribute :friends, :load => false
|
53
52
|
#
|
54
|
-
# @api private
|
55
53
|
# @!macro [attach] attribute
|
56
54
|
# @!attribute [r] $1
|
57
55
|
def attribute(name, *turntable_names, &block)
|
@@ -64,12 +62,12 @@ module Turntabler
|
|
64
62
|
load if instance_variable_get("@#{name}").nil? && !loaded? && options[:load]
|
65
63
|
instance_variable_get("@#{name}")
|
66
64
|
end
|
67
|
-
|
65
|
+
|
68
66
|
# Query
|
69
67
|
define_method("#{name}?") do
|
70
68
|
!!__send__(name)
|
71
69
|
end
|
72
|
-
|
70
|
+
|
73
71
|
# Typecasting
|
74
72
|
block ||= lambda {|value| value}
|
75
73
|
define_method("typecast_#{name}", &block)
|
@@ -123,6 +121,7 @@ module Turntabler
|
|
123
121
|
# "metadata" properties as additional attributes.
|
124
122
|
#
|
125
123
|
# @api private
|
124
|
+
# @param [Hash] attributes The updated attributes for the resource
|
126
125
|
def attributes=(attributes)
|
127
126
|
if attributes
|
128
127
|
attributes.each do |attribute, value|
|
@@ -135,19 +134,21 @@ module Turntabler
|
|
135
134
|
end
|
136
135
|
end
|
137
136
|
end
|
138
|
-
|
137
|
+
|
139
138
|
# Forces this object to use PP's implementation of inspection.
|
140
139
|
#
|
141
140
|
# @api private
|
141
|
+
# @return [String]
|
142
142
|
def pretty_print(q)
|
143
143
|
q.pp_object(self)
|
144
144
|
end
|
145
145
|
alias inspect pretty_print_inspect
|
146
146
|
|
147
147
|
# Defines the instance variables that should be printed when inspecting this
|
148
|
-
# object. This ignores the
|
148
|
+
# object. This ignores the +@client+ and +@loaded+ variables.
|
149
149
|
#
|
150
150
|
# @api private
|
151
|
+
# @return [Array<Symbol>]
|
151
152
|
def pretty_print_instance_variables
|
152
153
|
(instance_variables - [:'@client', :'@loaded']).sort
|
153
154
|
end
|
@@ -155,6 +156,7 @@ module Turntabler
|
|
155
156
|
# Determines whether this resource is equal to another based on their
|
156
157
|
# unique identifiers.
|
157
158
|
#
|
159
|
+
# @param [Object] other The object this resource is being compared against
|
158
160
|
# @return [Boolean] +true+ if the resource ids are equal, otherwise +false+
|
159
161
|
def ==(other)
|
160
162
|
if other && other.respond_to?(:id) && other.id
|