Class: Ably::Models::Message

Inherits:
Object
  • Object
show all
Includes:
Ably::Modules::Conversions, Ably::Modules::Encodeable, Ably::Modules::ModelCommon, Ably::Modules::SafeDeferrable
Defined in:
lib/submodules/ably-ruby/lib/ably/models/message.rb,
lib/ably-rest/modules/eventmachine_deferrable.rb

Overview

A class representing an individual message to be sent or received via the Ably Realtime service.

Defined Under Namespace

Modules: EventMachine

Instance Attribute Summary collapse

Attributes included from Ably::Modules::ModelCommon

#hash

Instance Method Summary collapse

Methods included from Ably::Modules::SafeDeferrable

#callback, #errback, #fail, #succeed

Methods included from Ably::Modules::ModelCommon

#==, #[], #as_json, included, #to_s

Methods included from Ably::Modules::MessagePack

#to_msgpack

Methods included from Ably::Modules::Encodeable

#decode, #encode, included, #original_encoding

Constructor Details

#initialize(attributes, options = {}) ⇒ Message

Ably::Models::Message initializer

Parameters:

  • attributes (Hash)

    object with the underlying message detail key value attributes

  • options (Hash) (defaults to: {})

    an options Hash for this initializer

Options Hash (options):



58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/submodules/ably-ruby/lib/ably/models/message.rb', line 58

def initialize(attributes, options = {})
  @logger           = options[:logger] # Logger expected for SafeDeferrable
  @protocol_message = options[:protocol_message]
  @raw_hash_object  = attributes

  set_attributes_object attributes

  self.attributes[:name] = ensure_utf_8(:name, name, allow_nil: true) if name
  self.attributes[:client_id] = ensure_utf_8(:client_id, client_id, allow_nil: true) if client_id
  self.attributes[:encoding] = ensure_utf_8(:encoding,  encoding,  allow_nil: true) if encoding

  self.attributes.freeze
end

Instance Attribute Details

#attributesHash (readonly)

Returns Access the protocol message Hash object ruby'fied to use symbolized keys.

Returns:

  • (Hash)

    Access the protocol message Hash object ruby'fied to use symbolized keys



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/submodules/ably-ruby/lib/ably/models/message.rb', line 42

class Message
  include Ably::Modules::Conversions
  include Ably::Modules::Encodeable
  include Ably::Modules::ModelCommon
  include Ably::Modules::SafeDeferrable if defined?(Ably::Realtime)

  # Statically register a default set of encoders for this class
  Ably::Models::MessageEncoders.register_default_encoders self

  # {Message} initializer
  #
  # @param  attributes [Hash]             object with the underlying message detail key value attributes
  # @param  [Hash]      options           an options Hash for this initializer
  # @option options     [ProtocolMessage] :protocol_message  An optional protocol message to assocate the presence message with
  # @option options     [Logger]          :logger            An optional Logger to be used by {Ably::Modules::SafeDeferrable} if an exception is caught in a callback
  #
  def initialize(attributes, options = {})
    @logger           = options[:logger] # Logger expected for SafeDeferrable
    @protocol_message = options[:protocol_message]
    @raw_hash_object  = attributes

    set_attributes_object attributes

    self.attributes[:name] = ensure_utf_8(:name, name, allow_nil: true) if name
    self.attributes[:client_id] = ensure_utf_8(:client_id, client_id, allow_nil: true) if client_id
    self.attributes[:encoding] = ensure_utf_8(:encoding,  encoding,  allow_nil: true) if encoding

    self.attributes.freeze
  end

  %w( name client_id encoding ).each do |attribute|
    define_method attribute do
      attributes[attribute.to_sym]
    end
  end

  def data
    @data ||= attributes[:data].freeze
  end

  def id
    attributes.fetch(:id) { "#{protocol_message.id!}:#{protocol_message_index}" }
  end

  def connection_id
    attributes.fetch(:connection_id) { protocol_message.connection_id if assigned_to_protocol_message? }
  end

  def timestamp
    if attributes[:timestamp]
      as_time_from_epoch(attributes[:timestamp])
    else
      protocol_message.timestamp
    end
  end

  def attributes
    @attributes
  end

  def to_json(*args)
    as_json(*args).tap do |message|
      decode_binary_data_before_to_json message
    end.to_json
  end

  # The size is the sum over name, data, clientId, and extras in bytes (TO3l8a)
  #
  def size
    %w(name data client_id extras).map do |attr|
      if (value = attributes[attr.to_sym]).is_a?(String)
        value.bytesize
      elsif value.nil?
        0
      else
        value.to_json.bytesize
      end
    end.sum
  end

  # Assign this message to a ProtocolMessage before delivery to the Ably system
  # @api private
  def assign_to_protocol_message(protocol_message)
    @protocol_message = protocol_message
  end

  # True if this message is assigned to a ProtocolMessage for delivery to Ably, or received from Ably
  # @return [Boolean]
  # @api private
  def assigned_to_protocol_message?
    !!@protocol_message
  end

  # The optional ProtocolMessage this message is assigned to.  If ProtocolMessage is nil, an error will be raised.
  # @return [Ably::Models::ProtocolMessage]
  # @api private
  def protocol_message
    raise RuntimeError, 'Message is not yet published with a ProtocolMessage. ProtocolMessage is nil' if @protocol_message.nil?
    @protocol_message
  end

  # Contains any arbitrary key value pairs which may also contain other primitive JSON types, JSON-encodable objects or JSON-encodable arrays.
  # The extras field is provided to contain message metadata and/or ancillary payloads in support of specific functionality, e.g. push
  # 1.2 adds the delta extension which is of type DeltaExtras, and the headers extension, which contains arbitrary string->string key-value pairs,
  # settable at publish time. Unless otherwise specified, the client library should not attempt to do any filtering or validation of the extras
  # field itself, but should treat it opaquely, encoding it and passing it to realtime unaltered.
  # @api private
  def extras
    attributes[:extras].tap do |val|
      unless val.kind_of?(IdiomaticRubyWrapper) || val.kind_of?(Array) || val.kind_of?(Hash) || val.nil?
        raise ArgumentError, "extras contains an unsupported type #{val.class}"
      end
    end
  end

  # Delta extras extension (TM2i)
  # @return [DeltaExtras, nil]
  # @api private
  def delta_extras
    return nil if attributes[:extras][:delta].nil?
    @delta_extras ||= DeltaExtras.new(attributes[:extras][:delta]).freeze
  end

  private
  def raw_hash_object
    @raw_hash_object
  end

  def protocol_message_index
    protocol_message.messages.map(&:object_id).index(self.object_id)
  end

  def set_attributes_object(new_attributes)
    @attributes = IdiomaticRubyWrapper(new_attributes.clone, stop_at: [:data, :extras])
  end

  def logger
    return @logger if @logger
    protocol_message.logger if protocol_message
  end
end

#client_idString (readonly)

Returns The id of the publisher of this message.

Returns:

  • (String)

    The id of the publisher of this message



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/submodules/ably-ruby/lib/ably/models/message.rb', line 42

class Message
  include Ably::Modules::Conversions
  include Ably::Modules::Encodeable
  include Ably::Modules::ModelCommon
  include Ably::Modules::SafeDeferrable if defined?(Ably::Realtime)

  # Statically register a default set of encoders for this class
  Ably::Models::MessageEncoders.register_default_encoders self

  # {Message} initializer
  #
  # @param  attributes [Hash]             object with the underlying message detail key value attributes
  # @param  [Hash]      options           an options Hash for this initializer
  # @option options     [ProtocolMessage] :protocol_message  An optional protocol message to assocate the presence message with
  # @option options     [Logger]          :logger            An optional Logger to be used by {Ably::Modules::SafeDeferrable} if an exception is caught in a callback
  #
  def initialize(attributes, options = {})
    @logger           = options[:logger] # Logger expected for SafeDeferrable
    @protocol_message = options[:protocol_message]
    @raw_hash_object  = attributes

    set_attributes_object attributes

    self.attributes[:name] = ensure_utf_8(:name, name, allow_nil: true) if name
    self.attributes[:client_id] = ensure_utf_8(:client_id, client_id, allow_nil: true) if client_id
    self.attributes[:encoding] = ensure_utf_8(:encoding,  encoding,  allow_nil: true) if encoding

    self.attributes.freeze
  end

  %w( name client_id encoding ).each do |attribute|
    define_method attribute do
      attributes[attribute.to_sym]
    end
  end

  def data
    @data ||= attributes[:data].freeze
  end

  def id
    attributes.fetch(:id) { "#{protocol_message.id!}:#{protocol_message_index}" }
  end

  def connection_id
    attributes.fetch(:connection_id) { protocol_message.connection_id if assigned_to_protocol_message? }
  end

  def timestamp
    if attributes[:timestamp]
      as_time_from_epoch(attributes[:timestamp])
    else
      protocol_message.timestamp
    end
  end

  def attributes
    @attributes
  end

  def to_json(*args)
    as_json(*args).tap do |message|
      decode_binary_data_before_to_json message
    end.to_json
  end

  # The size is the sum over name, data, clientId, and extras in bytes (TO3l8a)
  #
  def size
    %w(name data client_id extras).map do |attr|
      if (value = attributes[attr.to_sym]).is_a?(String)
        value.bytesize
      elsif value.nil?
        0
      else
        value.to_json.bytesize
      end
    end.sum
  end

  # Assign this message to a ProtocolMessage before delivery to the Ably system
  # @api private
  def assign_to_protocol_message(protocol_message)
    @protocol_message = protocol_message
  end

  # True if this message is assigned to a ProtocolMessage for delivery to Ably, or received from Ably
  # @return [Boolean]
  # @api private
  def assigned_to_protocol_message?
    !!@protocol_message
  end

  # The optional ProtocolMessage this message is assigned to.  If ProtocolMessage is nil, an error will be raised.
  # @return [Ably::Models::ProtocolMessage]
  # @api private
  def protocol_message
    raise RuntimeError, 'Message is not yet published with a ProtocolMessage. ProtocolMessage is nil' if @protocol_message.nil?
    @protocol_message
  end

  # Contains any arbitrary key value pairs which may also contain other primitive JSON types, JSON-encodable objects or JSON-encodable arrays.
  # The extras field is provided to contain message metadata and/or ancillary payloads in support of specific functionality, e.g. push
  # 1.2 adds the delta extension which is of type DeltaExtras, and the headers extension, which contains arbitrary string->string key-value pairs,
  # settable at publish time. Unless otherwise specified, the client library should not attempt to do any filtering or validation of the extras
  # field itself, but should treat it opaquely, encoding it and passing it to realtime unaltered.
  # @api private
  def extras
    attributes[:extras].tap do |val|
      unless val.kind_of?(IdiomaticRubyWrapper) || val.kind_of?(Array) || val.kind_of?(Hash) || val.nil?
        raise ArgumentError, "extras contains an unsupported type #{val.class}"
      end
    end
  end

  # Delta extras extension (TM2i)
  # @return [DeltaExtras, nil]
  # @api private
  def delta_extras
    return nil if attributes[:extras][:delta].nil?
    @delta_extras ||= DeltaExtras.new(attributes[:extras][:delta]).freeze
  end

  private
  def raw_hash_object
    @raw_hash_object
  end

  def protocol_message_index
    protocol_message.messages.map(&:object_id).index(self.object_id)
  end

  def set_attributes_object(new_attributes)
    @attributes = IdiomaticRubyWrapper(new_attributes.clone, stop_at: [:data, :extras])
  end

  def logger
    return @logger if @logger
    protocol_message.logger if protocol_message
  end
end

#connection_idString (readonly)

Returns The connection_id of the publisher of the message.

Returns:

  • (String)

    The connection_id of the publisher of the message



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/submodules/ably-ruby/lib/ably/models/message.rb', line 42

class Message
  include Ably::Modules::Conversions
  include Ably::Modules::Encodeable
  include Ably::Modules::ModelCommon
  include Ably::Modules::SafeDeferrable if defined?(Ably::Realtime)

  # Statically register a default set of encoders for this class
  Ably::Models::MessageEncoders.register_default_encoders self

  # {Message} initializer
  #
  # @param  attributes [Hash]             object with the underlying message detail key value attributes
  # @param  [Hash]      options           an options Hash for this initializer
  # @option options     [ProtocolMessage] :protocol_message  An optional protocol message to assocate the presence message with
  # @option options     [Logger]          :logger            An optional Logger to be used by {Ably::Modules::SafeDeferrable} if an exception is caught in a callback
  #
  def initialize(attributes, options = {})
    @logger           = options[:logger] # Logger expected for SafeDeferrable
    @protocol_message = options[:protocol_message]
    @raw_hash_object  = attributes

    set_attributes_object attributes

    self.attributes[:name] = ensure_utf_8(:name, name, allow_nil: true) if name
    self.attributes[:client_id] = ensure_utf_8(:client_id, client_id, allow_nil: true) if client_id
    self.attributes[:encoding] = ensure_utf_8(:encoding,  encoding,  allow_nil: true) if encoding

    self.attributes.freeze
  end

  %w( name client_id encoding ).each do |attribute|
    define_method attribute do
      attributes[attribute.to_sym]
    end
  end

  def data
    @data ||= attributes[:data].freeze
  end

  def id
    attributes.fetch(:id) { "#{protocol_message.id!}:#{protocol_message_index}" }
  end

  def connection_id
    attributes.fetch(:connection_id) { protocol_message.connection_id if assigned_to_protocol_message? }
  end

  def timestamp
    if attributes[:timestamp]
      as_time_from_epoch(attributes[:timestamp])
    else
      protocol_message.timestamp
    end
  end

  def attributes
    @attributes
  end

  def to_json(*args)
    as_json(*args).tap do |message|
      decode_binary_data_before_to_json message
    end.to_json
  end

  # The size is the sum over name, data, clientId, and extras in bytes (TO3l8a)
  #
  def size
    %w(name data client_id extras).map do |attr|
      if (value = attributes[attr.to_sym]).is_a?(String)
        value.bytesize
      elsif value.nil?
        0
      else
        value.to_json.bytesize
      end
    end.sum
  end

  # Assign this message to a ProtocolMessage before delivery to the Ably system
  # @api private
  def assign_to_protocol_message(protocol_message)
    @protocol_message = protocol_message
  end

  # True if this message is assigned to a ProtocolMessage for delivery to Ably, or received from Ably
  # @return [Boolean]
  # @api private
  def assigned_to_protocol_message?
    !!@protocol_message
  end

  # The optional ProtocolMessage this message is assigned to.  If ProtocolMessage is nil, an error will be raised.
  # @return [Ably::Models::ProtocolMessage]
  # @api private
  def protocol_message
    raise RuntimeError, 'Message is not yet published with a ProtocolMessage. ProtocolMessage is nil' if @protocol_message.nil?
    @protocol_message
  end

  # Contains any arbitrary key value pairs which may also contain other primitive JSON types, JSON-encodable objects or JSON-encodable arrays.
  # The extras field is provided to contain message metadata and/or ancillary payloads in support of specific functionality, e.g. push
  # 1.2 adds the delta extension which is of type DeltaExtras, and the headers extension, which contains arbitrary string->string key-value pairs,
  # settable at publish time. Unless otherwise specified, the client library should not attempt to do any filtering or validation of the extras
  # field itself, but should treat it opaquely, encoding it and passing it to realtime unaltered.
  # @api private
  def extras
    attributes[:extras].tap do |val|
      unless val.kind_of?(IdiomaticRubyWrapper) || val.kind_of?(Array) || val.kind_of?(Hash) || val.nil?
        raise ArgumentError, "extras contains an unsupported type #{val.class}"
      end
    end
  end

  # Delta extras extension (TM2i)
  # @return [DeltaExtras, nil]
  # @api private
  def delta_extras
    return nil if attributes[:extras][:delta].nil?
    @delta_extras ||= DeltaExtras.new(attributes[:extras][:delta]).freeze
  end

  private
  def raw_hash_object
    @raw_hash_object
  end

  def protocol_message_index
    protocol_message.messages.map(&:object_id).index(self.object_id)
  end

  def set_attributes_object(new_attributes)
    @attributes = IdiomaticRubyWrapper(new_attributes.clone, stop_at: [:data, :extras])
  end

  def logger
    return @logger if @logger
    protocol_message.logger if protocol_message
  end
end

#dataObject (readonly)

Returns The message payload. See the documentation for supported datatypes.

Returns:

  • (Object)

    The message payload. See the documentation for supported datatypes.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/submodules/ably-ruby/lib/ably/models/message.rb', line 42

class Message
  include Ably::Modules::Conversions
  include Ably::Modules::Encodeable
  include Ably::Modules::ModelCommon
  include Ably::Modules::SafeDeferrable if defined?(Ably::Realtime)

  # Statically register a default set of encoders for this class
  Ably::Models::MessageEncoders.register_default_encoders self

  # {Message} initializer
  #
  # @param  attributes [Hash]             object with the underlying message detail key value attributes
  # @param  [Hash]      options           an options Hash for this initializer
  # @option options     [ProtocolMessage] :protocol_message  An optional protocol message to assocate the presence message with
  # @option options     [Logger]          :logger            An optional Logger to be used by {Ably::Modules::SafeDeferrable} if an exception is caught in a callback
  #
  def initialize(attributes, options = {})
    @logger           = options[:logger] # Logger expected for SafeDeferrable
    @protocol_message = options[:protocol_message]
    @raw_hash_object  = attributes

    set_attributes_object attributes

    self.attributes[:name] = ensure_utf_8(:name, name, allow_nil: true) if name
    self.attributes[:client_id] = ensure_utf_8(:client_id, client_id, allow_nil: true) if client_id
    self.attributes[:encoding] = ensure_utf_8(:encoding,  encoding,  allow_nil: true) if encoding

    self.attributes.freeze
  end

  %w( name client_id encoding ).each do |attribute|
    define_method attribute do
      attributes[attribute.to_sym]
    end
  end

  def data
    @data ||= attributes[:data].freeze
  end

  def id
    attributes.fetch(:id) { "#{protocol_message.id!}:#{protocol_message_index}" }
  end

  def connection_id
    attributes.fetch(:connection_id) { protocol_message.connection_id if assigned_to_protocol_message? }
  end

  def timestamp
    if attributes[:timestamp]
      as_time_from_epoch(attributes[:timestamp])
    else
      protocol_message.timestamp
    end
  end

  def attributes
    @attributes
  end

  def to_json(*args)
    as_json(*args).tap do |message|
      decode_binary_data_before_to_json message
    end.to_json
  end

  # The size is the sum over name, data, clientId, and extras in bytes (TO3l8a)
  #
  def size
    %w(name data client_id extras).map do |attr|
      if (value = attributes[attr.to_sym]).is_a?(String)
        value.bytesize
      elsif value.nil?
        0
      else
        value.to_json.bytesize
      end
    end.sum
  end

  # Assign this message to a ProtocolMessage before delivery to the Ably system
  # @api private
  def assign_to_protocol_message(protocol_message)
    @protocol_message = protocol_message
  end

  # True if this message is assigned to a ProtocolMessage for delivery to Ably, or received from Ably
  # @return [Boolean]
  # @api private
  def assigned_to_protocol_message?
    !!@protocol_message
  end

  # The optional ProtocolMessage this message is assigned to.  If ProtocolMessage is nil, an error will be raised.
  # @return [Ably::Models::ProtocolMessage]
  # @api private
  def protocol_message
    raise RuntimeError, 'Message is not yet published with a ProtocolMessage. ProtocolMessage is nil' if @protocol_message.nil?
    @protocol_message
  end

  # Contains any arbitrary key value pairs which may also contain other primitive JSON types, JSON-encodable objects or JSON-encodable arrays.
  # The extras field is provided to contain message metadata and/or ancillary payloads in support of specific functionality, e.g. push
  # 1.2 adds the delta extension which is of type DeltaExtras, and the headers extension, which contains arbitrary string->string key-value pairs,
  # settable at publish time. Unless otherwise specified, the client library should not attempt to do any filtering or validation of the extras
  # field itself, but should treat it opaquely, encoding it and passing it to realtime unaltered.
  # @api private
  def extras
    attributes[:extras].tap do |val|
      unless val.kind_of?(IdiomaticRubyWrapper) || val.kind_of?(Array) || val.kind_of?(Hash) || val.nil?
        raise ArgumentError, "extras contains an unsupported type #{val.class}"
      end
    end
  end

  # Delta extras extension (TM2i)
  # @return [DeltaExtras, nil]
  # @api private
  def delta_extras
    return nil if attributes[:extras][:delta].nil?
    @delta_extras ||= DeltaExtras.new(attributes[:extras][:delta]).freeze
  end

  private
  def raw_hash_object
    @raw_hash_object
  end

  def protocol_message_index
    protocol_message.messages.map(&:object_id).index(self.object_id)
  end

  def set_attributes_object(new_attributes)
    @attributes = IdiomaticRubyWrapper(new_attributes.clone, stop_at: [:data, :extras])
  end

  def logger
    return @logger if @logger
    protocol_message.logger if protocol_message
  end
end

#encodingObject (readonly)

Returns The encoding for the message data. Encoding and decoding of messages is handled automatically by the client library. Therefore, the `encoding` attribute should always be nil unless an Ably library decoding error has occurred.

Returns:

  • (Object)

    The encoding for the message data. Encoding and decoding of messages is handled automatically by the client library. Therefore, the `encoding` attribute should always be nil unless an Ably library decoding error has occurred.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/submodules/ably-ruby/lib/ably/models/message.rb', line 42

class Message
  include Ably::Modules::Conversions
  include Ably::Modules::Encodeable
  include Ably::Modules::ModelCommon
  include Ably::Modules::SafeDeferrable if defined?(Ably::Realtime)

  # Statically register a default set of encoders for this class
  Ably::Models::MessageEncoders.register_default_encoders self

  # {Message} initializer
  #
  # @param  attributes [Hash]             object with the underlying message detail key value attributes
  # @param  [Hash]      options           an options Hash for this initializer
  # @option options     [ProtocolMessage] :protocol_message  An optional protocol message to assocate the presence message with
  # @option options     [Logger]          :logger            An optional Logger to be used by {Ably::Modules::SafeDeferrable} if an exception is caught in a callback
  #
  def initialize(attributes, options = {})
    @logger           = options[:logger] # Logger expected for SafeDeferrable
    @protocol_message = options[:protocol_message]
    @raw_hash_object  = attributes

    set_attributes_object attributes

    self.attributes[:name] = ensure_utf_8(:name, name, allow_nil: true) if name
    self.attributes[:client_id] = ensure_utf_8(:client_id, client_id, allow_nil: true) if client_id
    self.attributes[:encoding] = ensure_utf_8(:encoding,  encoding,  allow_nil: true) if encoding

    self.attributes.freeze
  end

  %w( name client_id encoding ).each do |attribute|
    define_method attribute do
      attributes[attribute.to_sym]
    end
  end

  def data
    @data ||= attributes[:data].freeze
  end

  def id
    attributes.fetch(:id) { "#{protocol_message.id!}:#{protocol_message_index}" }
  end

  def connection_id
    attributes.fetch(:connection_id) { protocol_message.connection_id if assigned_to_protocol_message? }
  end

  def timestamp
    if attributes[:timestamp]
      as_time_from_epoch(attributes[:timestamp])
    else
      protocol_message.timestamp
    end
  end

  def attributes
    @attributes
  end

  def to_json(*args)
    as_json(*args).tap do |message|
      decode_binary_data_before_to_json message
    end.to_json
  end

  # The size is the sum over name, data, clientId, and extras in bytes (TO3l8a)
  #
  def size
    %w(name data client_id extras).map do |attr|
      if (value = attributes[attr.to_sym]).is_a?(String)
        value.bytesize
      elsif value.nil?
        0
      else
        value.to_json.bytesize
      end
    end.sum
  end

  # Assign this message to a ProtocolMessage before delivery to the Ably system
  # @api private
  def assign_to_protocol_message(protocol_message)
    @protocol_message = protocol_message
  end

  # True if this message is assigned to a ProtocolMessage for delivery to Ably, or received from Ably
  # @return [Boolean]
  # @api private
  def assigned_to_protocol_message?
    !!@protocol_message
  end

  # The optional ProtocolMessage this message is assigned to.  If ProtocolMessage is nil, an error will be raised.
  # @return [Ably::Models::ProtocolMessage]
  # @api private
  def protocol_message
    raise RuntimeError, 'Message is not yet published with a ProtocolMessage. ProtocolMessage is nil' if @protocol_message.nil?
    @protocol_message
  end

  # Contains any arbitrary key value pairs which may also contain other primitive JSON types, JSON-encodable objects or JSON-encodable arrays.
  # The extras field is provided to contain message metadata and/or ancillary payloads in support of specific functionality, e.g. push
  # 1.2 adds the delta extension which is of type DeltaExtras, and the headers extension, which contains arbitrary string->string key-value pairs,
  # settable at publish time. Unless otherwise specified, the client library should not attempt to do any filtering or validation of the extras
  # field itself, but should treat it opaquely, encoding it and passing it to realtime unaltered.
  # @api private
  def extras
    attributes[:extras].tap do |val|
      unless val.kind_of?(IdiomaticRubyWrapper) || val.kind_of?(Array) || val.kind_of?(Hash) || val.nil?
        raise ArgumentError, "extras contains an unsupported type #{val.class}"
      end
    end
  end

  # Delta extras extension (TM2i)
  # @return [DeltaExtras, nil]
  # @api private
  def delta_extras
    return nil if attributes[:extras][:delta].nil?
    @delta_extras ||= DeltaExtras.new(attributes[:extras][:delta]).freeze
  end

  private
  def raw_hash_object
    @raw_hash_object
  end

  def protocol_message_index
    protocol_message.messages.map(&:object_id).index(self.object_id)
  end

  def set_attributes_object(new_attributes)
    @attributes = IdiomaticRubyWrapper(new_attributes.clone, stop_at: [:data, :extras])
  end

  def logger
    return @logger if @logger
    protocol_message.logger if protocol_message
  end
end

#idString (readonly)

Returns A globally unique message ID.

Returns:

  • (String)

    A globally unique message ID



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/submodules/ably-ruby/lib/ably/models/message.rb', line 42

class Message
  include Ably::Modules::Conversions
  include Ably::Modules::Encodeable
  include Ably::Modules::ModelCommon
  include Ably::Modules::SafeDeferrable if defined?(Ably::Realtime)

  # Statically register a default set of encoders for this class
  Ably::Models::MessageEncoders.register_default_encoders self

  # {Message} initializer
  #
  # @param  attributes [Hash]             object with the underlying message detail key value attributes
  # @param  [Hash]      options           an options Hash for this initializer
  # @option options     [ProtocolMessage] :protocol_message  An optional protocol message to assocate the presence message with
  # @option options     [Logger]          :logger            An optional Logger to be used by {Ably::Modules::SafeDeferrable} if an exception is caught in a callback
  #
  def initialize(attributes, options = {})
    @logger           = options[:logger] # Logger expected for SafeDeferrable
    @protocol_message = options[:protocol_message]
    @raw_hash_object  = attributes

    set_attributes_object attributes

    self.attributes[:name] = ensure_utf_8(:name, name, allow_nil: true) if name
    self.attributes[:client_id] = ensure_utf_8(:client_id, client_id, allow_nil: true) if client_id
    self.attributes[:encoding] = ensure_utf_8(:encoding,  encoding,  allow_nil: true) if encoding

    self.attributes.freeze
  end

  %w( name client_id encoding ).each do |attribute|
    define_method attribute do
      attributes[attribute.to_sym]
    end
  end

  def data
    @data ||= attributes[:data].freeze
  end

  def id
    attributes.fetch(:id) { "#{protocol_message.id!}:#{protocol_message_index}" }
  end

  def connection_id
    attributes.fetch(:connection_id) { protocol_message.connection_id if assigned_to_protocol_message? }
  end

  def timestamp
    if attributes[:timestamp]
      as_time_from_epoch(attributes[:timestamp])
    else
      protocol_message.timestamp
    end
  end

  def attributes
    @attributes
  end

  def to_json(*args)
    as_json(*args).tap do |message|
      decode_binary_data_before_to_json message
    end.to_json
  end

  # The size is the sum over name, data, clientId, and extras in bytes (TO3l8a)
  #
  def size
    %w(name data client_id extras).map do |attr|
      if (value = attributes[attr.to_sym]).is_a?(String)
        value.bytesize
      elsif value.nil?
        0
      else
        value.to_json.bytesize
      end
    end.sum
  end

  # Assign this message to a ProtocolMessage before delivery to the Ably system
  # @api private
  def assign_to_protocol_message(protocol_message)
    @protocol_message = protocol_message
  end

  # True if this message is assigned to a ProtocolMessage for delivery to Ably, or received from Ably
  # @return [Boolean]
  # @api private
  def assigned_to_protocol_message?
    !!@protocol_message
  end

  # The optional ProtocolMessage this message is assigned to.  If ProtocolMessage is nil, an error will be raised.
  # @return [Ably::Models::ProtocolMessage]
  # @api private
  def protocol_message
    raise RuntimeError, 'Message is not yet published with a ProtocolMessage. ProtocolMessage is nil' if @protocol_message.nil?
    @protocol_message
  end

  # Contains any arbitrary key value pairs which may also contain other primitive JSON types, JSON-encodable objects or JSON-encodable arrays.
  # The extras field is provided to contain message metadata and/or ancillary payloads in support of specific functionality, e.g. push
  # 1.2 adds the delta extension which is of type DeltaExtras, and the headers extension, which contains arbitrary string->string key-value pairs,
  # settable at publish time. Unless otherwise specified, the client library should not attempt to do any filtering or validation of the extras
  # field itself, but should treat it opaquely, encoding it and passing it to realtime unaltered.
  # @api private
  def extras
    attributes[:extras].tap do |val|
      unless val.kind_of?(IdiomaticRubyWrapper) || val.kind_of?(Array) || val.kind_of?(Hash) || val.nil?
        raise ArgumentError, "extras contains an unsupported type #{val.class}"
      end
    end
  end

  # Delta extras extension (TM2i)
  # @return [DeltaExtras, nil]
  # @api private
  def delta_extras
    return nil if attributes[:extras][:delta].nil?
    @delta_extras ||= DeltaExtras.new(attributes[:extras][:delta]).freeze
  end

  private
  def raw_hash_object
    @raw_hash_object
  end

  def protocol_message_index
    protocol_message.messages.map(&:object_id).index(self.object_id)
  end

  def set_attributes_object(new_attributes)
    @attributes = IdiomaticRubyWrapper(new_attributes.clone, stop_at: [:data, :extras])
  end

  def logger
    return @logger if @logger
    protocol_message.logger if protocol_message
  end
end

#nameString (readonly)

Returns The event name, if available.

Returns:

  • (String)

    The event name, if available



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/submodules/ably-ruby/lib/ably/models/message.rb', line 42

class Message
  include Ably::Modules::Conversions
  include Ably::Modules::Encodeable
  include Ably::Modules::ModelCommon
  include Ably::Modules::SafeDeferrable if defined?(Ably::Realtime)

  # Statically register a default set of encoders for this class
  Ably::Models::MessageEncoders.register_default_encoders self

  # {Message} initializer
  #
  # @param  attributes [Hash]             object with the underlying message detail key value attributes
  # @param  [Hash]      options           an options Hash for this initializer
  # @option options     [ProtocolMessage] :protocol_message  An optional protocol message to assocate the presence message with
  # @option options     [Logger]          :logger            An optional Logger to be used by {Ably::Modules::SafeDeferrable} if an exception is caught in a callback
  #
  def initialize(attributes, options = {})
    @logger           = options[:logger] # Logger expected for SafeDeferrable
    @protocol_message = options[:protocol_message]
    @raw_hash_object  = attributes

    set_attributes_object attributes

    self.attributes[:name] = ensure_utf_8(:name, name, allow_nil: true) if name
    self.attributes[:client_id] = ensure_utf_8(:client_id, client_id, allow_nil: true) if client_id
    self.attributes[:encoding] = ensure_utf_8(:encoding,  encoding,  allow_nil: true) if encoding

    self.attributes.freeze
  end

  %w( name client_id encoding ).each do |attribute|
    define_method attribute do
      attributes[attribute.to_sym]
    end
  end

  def data
    @data ||= attributes[:data].freeze
  end

  def id
    attributes.fetch(:id) { "#{protocol_message.id!}:#{protocol_message_index}" }
  end

  def connection_id
    attributes.fetch(:connection_id) { protocol_message.connection_id if assigned_to_protocol_message? }
  end

  def timestamp
    if attributes[:timestamp]
      as_time_from_epoch(attributes[:timestamp])
    else
      protocol_message.timestamp
    end
  end

  def attributes
    @attributes
  end

  def to_json(*args)
    as_json(*args).tap do |message|
      decode_binary_data_before_to_json message
    end.to_json
  end

  # The size is the sum over name, data, clientId, and extras in bytes (TO3l8a)
  #
  def size
    %w(name data client_id extras).map do |attr|
      if (value = attributes[attr.to_sym]).is_a?(String)
        value.bytesize
      elsif value.nil?
        0
      else
        value.to_json.bytesize
      end
    end.sum
  end

  # Assign this message to a ProtocolMessage before delivery to the Ably system
  # @api private
  def assign_to_protocol_message(protocol_message)
    @protocol_message = protocol_message
  end

  # True if this message is assigned to a ProtocolMessage for delivery to Ably, or received from Ably
  # @return [Boolean]
  # @api private
  def assigned_to_protocol_message?
    !!@protocol_message
  end

  # The optional ProtocolMessage this message is assigned to.  If ProtocolMessage is nil, an error will be raised.
  # @return [Ably::Models::ProtocolMessage]
  # @api private
  def protocol_message
    raise RuntimeError, 'Message is not yet published with a ProtocolMessage. ProtocolMessage is nil' if @protocol_message.nil?
    @protocol_message
  end

  # Contains any arbitrary key value pairs which may also contain other primitive JSON types, JSON-encodable objects or JSON-encodable arrays.
  # The extras field is provided to contain message metadata and/or ancillary payloads in support of specific functionality, e.g. push
  # 1.2 adds the delta extension which is of type DeltaExtras, and the headers extension, which contains arbitrary string->string key-value pairs,
  # settable at publish time. Unless otherwise specified, the client library should not attempt to do any filtering or validation of the extras
  # field itself, but should treat it opaquely, encoding it and passing it to realtime unaltered.
  # @api private
  def extras
    attributes[:extras].tap do |val|
      unless val.kind_of?(IdiomaticRubyWrapper) || val.kind_of?(Array) || val.kind_of?(Hash) || val.nil?
        raise ArgumentError, "extras contains an unsupported type #{val.class}"
      end
    end
  end

  # Delta extras extension (TM2i)
  # @return [DeltaExtras, nil]
  # @api private
  def delta_extras
    return nil if attributes[:extras][:delta].nil?
    @delta_extras ||= DeltaExtras.new(attributes[:extras][:delta]).freeze
  end

  private
  def raw_hash_object
    @raw_hash_object
  end

  def protocol_message_index
    protocol_message.messages.map(&:object_id).index(self.object_id)
  end

  def set_attributes_object(new_attributes)
    @attributes = IdiomaticRubyWrapper(new_attributes.clone, stop_at: [:data, :extras])
  end

  def logger
    return @logger if @logger
    protocol_message.logger if protocol_message
  end
end

#timestampTime (readonly)

Returns Timestamp when the message was received by the Ably the realtime service.

Returns:

  • (Time)

    Timestamp when the message was received by the Ably the realtime service



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/submodules/ably-ruby/lib/ably/models/message.rb', line 42

class Message
  include Ably::Modules::Conversions
  include Ably::Modules::Encodeable
  include Ably::Modules::ModelCommon
  include Ably::Modules::SafeDeferrable if defined?(Ably::Realtime)

  # Statically register a default set of encoders for this class
  Ably::Models::MessageEncoders.register_default_encoders self

  # {Message} initializer
  #
  # @param  attributes [Hash]             object with the underlying message detail key value attributes
  # @param  [Hash]      options           an options Hash for this initializer
  # @option options     [ProtocolMessage] :protocol_message  An optional protocol message to assocate the presence message with
  # @option options     [Logger]          :logger            An optional Logger to be used by {Ably::Modules::SafeDeferrable} if an exception is caught in a callback
  #
  def initialize(attributes, options = {})
    @logger           = options[:logger] # Logger expected for SafeDeferrable
    @protocol_message = options[:protocol_message]
    @raw_hash_object  = attributes

    set_attributes_object attributes

    self.attributes[:name] = ensure_utf_8(:name, name, allow_nil: true) if name
    self.attributes[:client_id] = ensure_utf_8(:client_id, client_id, allow_nil: true) if client_id
    self.attributes[:encoding] = ensure_utf_8(:encoding,  encoding,  allow_nil: true) if encoding

    self.attributes.freeze
  end

  %w( name client_id encoding ).each do |attribute|
    define_method attribute do
      attributes[attribute.to_sym]
    end
  end

  def data
    @data ||= attributes[:data].freeze
  end

  def id
    attributes.fetch(:id) { "#{protocol_message.id!}:#{protocol_message_index}" }
  end

  def connection_id
    attributes.fetch(:connection_id) { protocol_message.connection_id if assigned_to_protocol_message? }
  end

  def timestamp
    if attributes[:timestamp]
      as_time_from_epoch(attributes[:timestamp])
    else
      protocol_message.timestamp
    end
  end

  def attributes
    @attributes
  end

  def to_json(*args)
    as_json(*args).tap do |message|
      decode_binary_data_before_to_json message
    end.to_json
  end

  # The size is the sum over name, data, clientId, and extras in bytes (TO3l8a)
  #
  def size
    %w(name data client_id extras).map do |attr|
      if (value = attributes[attr.to_sym]).is_a?(String)
        value.bytesize
      elsif value.nil?
        0
      else
        value.to_json.bytesize
      end
    end.sum
  end

  # Assign this message to a ProtocolMessage before delivery to the Ably system
  # @api private
  def assign_to_protocol_message(protocol_message)
    @protocol_message = protocol_message
  end

  # True if this message is assigned to a ProtocolMessage for delivery to Ably, or received from Ably
  # @return [Boolean]
  # @api private
  def assigned_to_protocol_message?
    !!@protocol_message
  end

  # The optional ProtocolMessage this message is assigned to.  If ProtocolMessage is nil, an error will be raised.
  # @return [Ably::Models::ProtocolMessage]
  # @api private
  def protocol_message
    raise RuntimeError, 'Message is not yet published with a ProtocolMessage. ProtocolMessage is nil' if @protocol_message.nil?
    @protocol_message
  end

  # Contains any arbitrary key value pairs which may also contain other primitive JSON types, JSON-encodable objects or JSON-encodable arrays.
  # The extras field is provided to contain message metadata and/or ancillary payloads in support of specific functionality, e.g. push
  # 1.2 adds the delta extension which is of type DeltaExtras, and the headers extension, which contains arbitrary string->string key-value pairs,
  # settable at publish time. Unless otherwise specified, the client library should not attempt to do any filtering or validation of the extras
  # field itself, but should treat it opaquely, encoding it and passing it to realtime unaltered.
  # @api private
  def extras
    attributes[:extras].tap do |val|
      unless val.kind_of?(IdiomaticRubyWrapper) || val.kind_of?(Array) || val.kind_of?(Hash) || val.nil?
        raise ArgumentError, "extras contains an unsupported type #{val.class}"
      end
    end
  end

  # Delta extras extension (TM2i)
  # @return [DeltaExtras, nil]
  # @api private
  def delta_extras
    return nil if attributes[:extras][:delta].nil?
    @delta_extras ||= DeltaExtras.new(attributes[:extras][:delta]).freeze
  end

  private
  def raw_hash_object
    @raw_hash_object
  end

  def protocol_message_index
    protocol_message.messages.map(&:object_id).index(self.object_id)
  end

  def set_attributes_object(new_attributes)
    @attributes = IdiomaticRubyWrapper(new_attributes.clone, stop_at: [:data, :extras])
  end

  def logger
    return @logger if @logger
    protocol_message.logger if protocol_message
  end
end

Instance Method Details

#assign_to_protocol_message(protocol_message) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Assign this message to a ProtocolMessage before delivery to the Ably system



124
125
126
# File 'lib/submodules/ably-ruby/lib/ably/models/message.rb', line 124

def assign_to_protocol_message(protocol_message)
  @protocol_message = protocol_message
end

#assigned_to_protocol_message?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

True if this message is assigned to a ProtocolMessage for delivery to Ably, or received from Ably

Returns:

  • (Boolean)


131
132
133
# File 'lib/submodules/ably-ruby/lib/ably/models/message.rb', line 131

def assigned_to_protocol_message?
  !!@protocol_message
end

#delta_extrasDeltaExtras?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Delta extras extension (TM2i)

Returns:



160
161
162
163
# File 'lib/submodules/ably-ruby/lib/ably/models/message.rb', line 160

def delta_extras
  return nil if attributes[:extras][:delta].nil?
  @delta_extras ||= DeltaExtras.new(attributes[:extras][:delta]).freeze
end

#extrasObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Contains any arbitrary key value pairs which may also contain other primitive JSON types, JSON-encodable objects or JSON-encodable arrays. The extras field is provided to contain message metadata and/or ancillary payloads in support of specific functionality, e.g. push 1.2 adds the delta extension which is of type DeltaExtras, and the headers extension, which contains arbitrary string->string key-value pairs, settable at publish time. Unless otherwise specified, the client library should not attempt to do any filtering or validation of the extras field itself, but should treat it opaquely, encoding it and passing it to realtime unaltered.



149
150
151
152
153
154
155
# File 'lib/submodules/ably-ruby/lib/ably/models/message.rb', line 149

def extras
  attributes[:extras].tap do |val|
    unless val.kind_of?(IdiomaticRubyWrapper) || val.kind_of?(Array) || val.kind_of?(Hash) || val.nil?
      raise ArgumentError, "extras contains an unsupported type #{val.class}"
    end
  end
end

#protocol_messageAbly::Models::ProtocolMessage

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The optional ProtocolMessage this message is assigned to. If ProtocolMessage is nil, an error will be raised.

Returns:

Raises:

  • (RuntimeError)


138
139
140
141
# File 'lib/submodules/ably-ruby/lib/ably/models/message.rb', line 138

def protocol_message
  raise RuntimeError, 'Message is not yet published with a ProtocolMessage. ProtocolMessage is nil' if @protocol_message.nil?
  @protocol_message
end

#sizeObject

The size is the sum over name, data, clientId, and extras in bytes (TO3l8a)



110
111
112
113
114
115
116
117
118
119
120
# File 'lib/submodules/ably-ruby/lib/ably/models/message.rb', line 110

def size
  %w(name data client_id extras).map do |attr|
    if (value = attributes[attr.to_sym]).is_a?(String)
      value.bytesize
    elsif value.nil?
      0
    else
      value.to_json.bytesize
    end
  end.sum
end

#to_json(*args) ⇒ Object



102
103
104
105
106
# File 'lib/submodules/ably-ruby/lib/ably/models/message.rb', line 102

def to_json(*args)
  as_json(*args).tap do |message|
    decode_binary_data_before_to_json message
  end.to_json
end