Module: LiveResource::Attributes

Included in:
Resource
Defined in:
lib/live_resource/attributes.rb

Instance Method Summary collapse

Instance Method Details

#redisObject



3
4
5
# File 'lib/live_resource/attributes.rb', line 3

def redis
  @_redis ||= RedisClient.new(resource_class, resource_name)
end

#remote_attribute_modify(*attributes, &block) ⇒ Object

Modify an attribute or set of attributes based on the current value(s). Uses the optimistic locking mechanism provided by Redis WATCH/MULTI/EXEC transactions.

The user passes in the a block which will be used to update the attribute(s). Since the block may need to be replayed, the user should not update any external state that relies on the block executing only once.



39
40
41
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
# File 'lib/live_resource/attributes.rb', line 39

def remote_attribute_modify(*attributes, &block)
  invalid_attrs = attributes - redis.registered_attributes
  unless invalid_attrs.empty?
    raise ArgumentError.new("remote_modify: no such attribute(s) '#{invalid_attrs}'")
  end

  unless block
    raise ArgumentError.new("remote_modify requires a block")
  end

  # Optimistic locking implemented along the lines of:
  #   http://redis.io/topics/transactions
  loop do
    # Gather up the attributes and their new values
    mods = attributes.map do |a|
      # Watch/get the value
      redis.attribute_watch(a)
      v = redis.attribute_read(a)

      # Block modifies the value
      v = block.call(a, v)
      [a, v]
    end

    # Start the transaction
    redis.multi

    mods.each do |mod|
      # Set to new value; if ok, we're done.
      redis.attribute_write(mod[0], mod[1])
    end

    # Attempt to execute the transaction. Otherwise we'll loop and
    # try again with the new value.
    break if redis.exec
  end
end

#remote_attribute_read(key, options = {}) ⇒ Object



15
16
17
# File 'lib/live_resource/attributes.rb', line 15

def remote_attribute_read(key, options = {})
  redis.attribute_read(key, options)
end

#remote_attribute_write(key, value, options = {}) ⇒ Object



19
20
21
22
23
24
25
# File 'lib/live_resource/attributes.rb', line 19

def remote_attribute_write(key, value, options = {})
  if (key.to_sym == self.class.resource_name_attr) and !self.is_a?(Class)
    @_redis = RedisClient.new(resource_class, value)
  end

  redis.attribute_write(key, value, options)
end

#remote_attribute_writenx(key, value) ⇒ Object

Write a new value to an attribute if it doesn’t exist yet.



28
29
30
# File 'lib/live_resource/attributes.rb', line 28

def remote_attribute_writenx(key, value)
  remote_attribute_write(key, value, no_overwrite: true)
end

#remote_attributesObject



7
8
9
10
11
12
13
# File 'lib/live_resource/attributes.rb', line 7

def remote_attributes
  if self.is_a? Class
    []
  else
    self.class.remote_instance_attributes
  end
end