Module: Redis::Objects::ClassMethods

Defined in:
lib/redis/objects.rb

Overview

Class methods that appear in your class when you include Redis::Objects.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#redis_legacy_namingObject

Toggles whether to use the legacy redis key naming scheme, which causes naming conflicts in certain cases.



106
107
108
# File 'lib/redis/objects.rb', line 106

def redis_legacy_naming
  @redis_legacy_naming
end

#redis_objectsObject



100
101
102
# File 'lib/redis/objects.rb', line 100

def redis_objects
  @redis_objects ||= {}
end

#redis_silence_warningsObject

Returns the value of attribute redis_silence_warnings.



107
108
109
# File 'lib/redis/objects.rb', line 107

def redis_silence_warnings
  @redis_silence_warnings
end

Instance Method Details

#first_ancestor_with(name) ⇒ Object



226
227
228
229
230
231
232
# File 'lib/redis/objects.rb', line 226

def first_ancestor_with(name)
  if redis_objects && redis_objects.key?(name.to_sym)
    self
  elsif superclass && superclass.respond_to?(:redis_objects)
    superclass.first_ancestor_with(name)
  end
end

#migrate_redis_legacy_keysObject



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/redis/objects.rb', line 161

def migrate_redis_legacy_keys
  cursor = 0
  legacy = redis_legacy_prefix
  total_keys = 0
  if legacy == redis_prefix
    raise "Failed to migrate keys for #{self.name.to_s} as legacy and new redis_prefix are the same (#{redis_prefix})"
  end
  warn "[redis-objects] Migrating keys from #{legacy} prefix to #{redis_prefix}"

  loop do
    cursor, keys = redis.scan(cursor, :match => "#{legacy}:*")
    total_keys += keys.length
    keys.each do |key|
      # Split key name apart on ':'
      base_class, id, name = key.split(':')

      # Figure out the new name
      new_key = redis_field_key(name, id=id, context=self)

      # Rename the key
      warn "[redis-objects] Rename '#{key}', '#{new_key}'"
      ok = redis.rename(key, new_key)
      warn "[redis-objects] Warning: Rename '#{key}', '#{new_key}' failed: #{ok}" if ok != 'OK'
    end
    break if cursor == "0"
  end

  warn "[redis-objects] Migrated #{total_keys} total number of redis keys"
end

#redisObject



94
95
96
# File 'lib/redis/objects.rb', line 94

def redis
  @redis || Objects.redis
end

#redis=(conn) ⇒ Object

Enable per-class connections (eg, User and Post can use diff redis-server)



90
91
92
# File 'lib/redis/objects.rb', line 90

def redis=(conn)
  @redis = Objects::ConnectionPoolProxy.proxy_if_needed(conn)
end

#redis_field_key(name, id = nil, context = self) ⇒ Object

:nodoc:



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/redis/objects.rb', line 206

def redis_field_key(name, id=nil, context=self) #:nodoc:
  klass = first_ancestor_with(name)
  # READ THIS: This can never ever ever ever change or upgrades will corrupt all data
  # I don't think people were using Proc as keys before (that would create a weird key). Should be ok
  if key = klass.redis_objects[name.to_sym][:key]
    if key.respond_to?(:call)
      key = key.call context
    else
      context.instance_eval "%(#{key})"
    end
  else
    if id.nil? and !klass.redis_objects[name.to_sym][:global]
      raise NilObjectId,
        "[#{klass.redis_objects[name.to_sym]}] Attempt to address redis-object " +
        ":#{name} on class #{klass.name} with nil id (unsaved record?) [object_id=#{object_id}]"
    end
    "#{redis_prefix(klass)}:#{id}:#{name}"
  end
end

#redis_field_redis(name) ⇒ Object

:nodoc:



196
197
198
199
200
201
202
203
204
# File 'lib/redis/objects.rb', line 196

def redis_field_redis(name) #:nodoc:
  klass = first_ancestor_with(name)
  override_redis = klass.redis_objects[name.to_sym][:redis]
  if override_redis
    Objects::ConnectionPoolProxy.proxy_if_needed(override_redis)
  else
    self.redis
  end
end

#redis_id_field(id = nil) ⇒ Object



234
235
236
237
238
239
240
241
242
# File 'lib/redis/objects.rb', line 234

def redis_id_field(id=nil)
  @redis_id_field = id || @redis_id_field

  if superclass && superclass.respond_to?(:redis_id_field)
    @redis_id_field ||= superclass.redis_id_field
  end

  @redis_id_field ||= :id
end

#redis_legacy_naming_warning_message(klass) ⇒ Object

Temporary warning to help with migrating key names



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/redis/objects.rb', line 144

def redis_legacy_naming_warning_message(klass)
  # warn @silence_warnings_as_redis_prefix_was_set_manually.inspect
  unless redis_legacy_naming || redis_silence_warnings || @silence_warnings_as_redis_prefix_was_set_manually
    modern = redis_modern_prefix(klass)
    legacy = redis_legacy_prefix(klass)
    if modern != legacy
      warn <<EOW
[redis-objects] WARNING: In redis-objects 2.0.0, key naming will change to fix longstanding bugs.
[redis-objects] Your class #{klass.name.to_s} will be affected by this change!
[redis-objects] Current key prefix: #{legacy.inspect}
[redis-objects] Future  key prefix: #{modern.inspect}
[redis-objects] Read more at https://github.com/nateware/redis-objects/issues/231
EOW
    end
  end
end

#redis_legacy_prefix(klass = self) ⇒ Object

:nodoc:



135
136
137
138
139
140
141
# File 'lib/redis/objects.rb', line 135

def redis_legacy_prefix(klass = self) #:nodoc:
  klass.name.to_s.
    sub(%r{(.*::)}, '').                  # Nested::Class => Class (problematic)
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). # ClassName => Class_Name
    gsub(/([a-z\d])([A-Z])/,'\1_\2').     # className => class_Name
    downcase
end

#redis_modern_prefix(klass = self) ⇒ Object

:nodoc:



127
128
129
130
131
132
133
# File 'lib/redis/objects.rb', line 127

def redis_modern_prefix(klass = self) #:nodoc:
  klass.name.to_s.
    gsub(/::/, '__').                     # Nested::Class => Nested__Class
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). # ClassName => Class_Name
    gsub(/([a-z\d])([A-Z])/,'\1_\2').     # className => class_Name
    downcase
end

#redis_options(name) ⇒ Object



191
192
193
194
# File 'lib/redis/objects.rb', line 191

def redis_options(name)
  klass = first_ancestor_with(name)
  return klass.redis_objects[name.to_sym] || {}
end

#redis_prefix(klass = self) ⇒ Object

:nodoc:



115
116
117
118
119
120
121
122
123
124
125
# File 'lib/redis/objects.rb', line 115

def redis_prefix(klass = self) #:nodoc:
  @redis_prefix ||=
    if redis_legacy_naming
      redis_legacy_prefix(klass)
    else
      redis_legacy_naming_warning_message(klass)
      redis_modern_prefix(klass)
    end

  @redis_prefix
end

#redis_prefix=(redis_prefix) ⇒ Object

Set the Redis redis_prefix to use. Defaults to class_name.



110
111
112
113
# File 'lib/redis/objects.rb', line 110

def redis_prefix=(redis_prefix)
  @silence_warnings_as_redis_prefix_was_set_manually = true
  @redis_prefix = redis_prefix
end