Class: Ohm::Set

Inherits:
Object
  • Object
show all
Includes:
Collection
Defined in:
lib/ohm.rb

Direct Known Subclasses

MutableSet

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Collection

#each, #empty?, #fetch, #to_a, #to_json

Constructor Details

#initialize(model, namespace, key) ⇒ Set


331
332
333
334
335
# File 'lib/ohm.rb', line 331

def initialize(model, namespace, key)
  @model = model
  @namespace = namespace
  @key = key
end

Instance Attribute Details

#keyObject (readonly)

Returns the value of attribute key


327
328
329
# File 'lib/ohm.rb', line 327

def key
  @key
end

#modelObject (readonly)

Returns the value of attribute model


328
329
330
# File 'lib/ohm.rb', line 328

def model
  @model
end

#namespaceObject (readonly)

Returns the value of attribute namespace


329
330
331
# File 'lib/ohm.rb', line 329

def namespace
  @namespace
end

Instance Method Details

#[](id) ⇒ Object

Retrieve a specific element using an ID from this set.

Example:

# Let's say we got the ID 1 from a request parameter.
id = 1

# Retrieve the post if it's included in the user's posts.
post = user.posts[id]

347
348
349
# File 'lib/ohm.rb', line 347

def [](id)
  model[id] if exists?(id)
end

#combine(dict) ⇒ Object

Perform an intersection between the existent set and the new set created by the union of the passed filters.

Example:

set = User.find(:status => "active")
set.combine(:name => ["John", "Jane"])

# The result will include all users with active status
# and with names "John" or "Jane".

536
537
538
539
540
# File 'lib/ohm.rb', line 536

def combine(dict)
  Ohm::Set.new(
    model, namespace, [:SINTER, key, [:SUNION, *model.filters(dict)]]
  )
end

#except(dict) ⇒ Object

Reduce the set using any number of filters.

Example:

set = User.find(:name => "John")
set.except(:country => "US")

# You can also do it in one line.
User.find(:name => "John").except(:country => "US")

520
521
522
523
524
# File 'lib/ohm.rb', line 520

def except(dict)
  Ohm::Set.new(
    model, namespace, [:SDIFF, key, [:SUNION, *model.filters(dict)]]
  )
end

#exists?(id) ⇒ Boolean

Returns true if id is included in the set. Otherwise, returns false.

Example:

class Post < Ohm::Model
end

class User < Ohm::Model
  set :posts, :Post
end

user = User.create
post = Post.create
user.posts.add(post)

user.posts.exists?('nonexistent') # => false
user.posts.exists?(post.id)       # => true

403
404
405
# File 'lib/ohm.rb', line 403

def exists?(id)
  Stal.solve(redis, ["SISMEMBER", key, id]) == 1
end

#find(dict) ⇒ Object

Chain new fiters on an existing set.

Example:

set = User.find(:name => "John")
set.find(:age => 30)

504
505
506
507
508
# File 'lib/ohm.rb', line 504

def find(dict)
  Ohm::Set.new(
    model, namespace, [:SINTER, key, *model.filters(dict)]
  )
end

#first(options = {}) ⇒ Object

Syntactic sugar for `sort_by` or `sort` when you only need the first element.

Example:

User.all.first ==
  User.all.sort(:limit => [0, 1]).first

User.all.first(:by => :name, "ALPHA") ==
  User.all.sort_by(:name, :order => "ALPHA", :limit => [0, 1]).first

486
487
488
489
490
491
492
493
494
495
# File 'lib/ohm.rb', line 486

def first(options = {})
  opts = options.dup
  opts.merge!(:limit => [0, 1])

  if opts[:by]
    sort_by(opts.delete(:by), opts).first
  else
    sort(opts).first
  end
end

#idsObject

Returns an array with all the ID's of the set.

class Post < Ohm::Model
end

class User < Ohm::Model
  attribute :name
  index :name

  set :posts, :Post
end

User.create(name: "John")
User.create(name: "Jane")

User.all.ids
# => ["1", "2"]

User.find(name: "John").union(name: "Jane").ids
# => ["1", "2"]

372
373
374
375
376
377
378
# File 'lib/ohm.rb', line 372

def ids
  if Array === key
    Stal.solve(redis, key)
  else
    redis.call("SMEMBERS", key)
  end
end

#include?(model) ⇒ Boolean

Check if a model is included in this set.

Example:

u = User.create

User.all.include?(u)
# => true

Note: Ohm simply checks that the model's ID is included in the set. It doesn't do any form of type checking.


419
420
421
# File 'lib/ohm.rb', line 419

def include?(model)
  exists?(model.id)
end

#sizeObject

Returns the total size of the set using SCARD.


381
382
383
# File 'lib/ohm.rb', line 381

def size
  Stal.solve(redis, ["SCARD", key])
end

#sort(options = {}) ⇒ Object

Allows you to sort your models using their IDs. This is much faster than `sort_by`. If you simply want to get records in ascending or descending order, then this is the best method to do that.

Example:

class User < Ohm::Model
  attribute :name
end

User.create(:name => "John")
User.create(:name => "Jane")

User.all.sort.map(&:id) == ["1", "2"]
# => true

User.all.sort(:order => "ASC").map(&:id) == ["1", "2"]
# => true

User.all.sort(:order => "DESC").map(&:id) == ["2", "1"]
# => true

446
447
448
449
450
451
452
453
454
# File 'lib/ohm.rb', line 446

def sort(options = {})
  if options.has_key?(:get)
    options[:get] = to_key(options[:get])

    Stal.solve(redis, ["SORT", key, *Utils.sort_options(options)])
  else
    fetch(Stal.solve(redis, ["SORT", key, *Utils.sort_options(options)]))
  end
end

#sort_by(att, options = {}) ⇒ Object

Allows you to sort by any attribute in the hash, this doesn't include the id. If you want to sort by ID, use #sort.

class User < Ohm::Model
  attribute :name
end

User.all.sort_by(:name, :order => "ALPHA")
User.all.sort_by(:name, :order => "ALPHA DESC")
User.all.sort_by(:name, :order => "ALPHA DESC", :limit => [0, 10])

Note: This is slower compared to just doing `sort`, specifically because Redis has to read each individual hash in order to sort them.


471
472
473
# File 'lib/ohm.rb', line 471

def sort_by(att, options = {})
  sort(options.merge(:by => to_key(att)))
end

#union(dict) ⇒ Object

Do a union to the existing set using any number of filters.

Example:

set = User.find(:name => "John")
set.union(:name => "Jane")

# You can also do it in one line.
User.find(:name => "John").union(:name => "Jane")

552
553
554
555
556
# File 'lib/ohm.rb', line 552

def union(dict)
  Ohm::Set.new(
    model, namespace, [:SUNION, key, [:SINTER, *model.filters(dict)]]
  )
end