Class: Canery::Backend

Inherits:
Object
  • Object
show all
Defined in:
lib/canery/backend.rb

Constant Summary collapse

TABLE_PREFIX =
"canery_"

Instance Method Summary collapse

Constructor Details

#initialize(connection_uri) ⇒ Backend

Returns a new instance of Backend.

Raises:

  • (ArgumentError)


12
13
14
15
16
# File 'lib/canery/backend.rb', line 12

def initialize(connection_uri)
  raise ArgumentError, "connection_uri must be a String or nil" unless NilClass === connection_uri || String === connection_uri
  @connection = connection_uri.nil? ? Sequel.sqlite : Sequel.connect(connection_uri)
  @namespace_cache = {}
end

Instance Method Details

#clear(name) ⇒ Object



88
89
90
# File 'lib/canery/backend.rb', line 88

def clear(name)
  namespace(name).delete && "OK"
end

#create_namespace(name) ⇒ Object

Basic namespace methods #



21
22
23
24
25
26
# File 'lib/canery/backend.rb', line 21

def create_namespace(name)
  connection.create_table basic_tub_name(name) do
    String :key, :primary_key => true
    String :value, :text => true
  end
end

#delete(name, key) ⇒ Object



84
85
86
# File 'lib/canery/backend.rb', line 84

def delete(name, key)
  namespace(name).where(:key => build_key(key)).limit(1).delete && "OK"
end

#delete_namespace(name) ⇒ Object



28
29
30
31
# File 'lib/canery/backend.rb', line 28

def delete_namespace(name)
  @namespace_cache.delete(basic_tub_name(name)) if @namespace_cache[basic_tub_name(name)]
  connection.drop_table?(basic_tub_name(name)) && "OK"
end

#get(name, key) ⇒ Object

Methods for get, set, etc. #



49
50
51
52
# File 'lib/canery/backend.rb', line 49

def get(name, key)
  data = namespace(name).first(:key => build_key(key))
  data.nil? ? nil : load(data[:value])
end

#has_key?(name, key) ⇒ Boolean

Returns:

  • (Boolean)


96
97
98
# File 'lib/canery/backend.rb', line 96

def has_key?(name, key)
  !!get(name, key)
end

#keys(name) ⇒ Object



100
101
102
# File 'lib/canery/backend.rb', line 100

def keys(name)
  namespace(name).map{ |dataset| dataset[:key] }
end

#length(name) ⇒ Object



129
130
131
# File 'lib/canery/backend.rb', line 129

def length(name)
  namespace(name).count
end

#mget(name, keys) ⇒ Object

Raises:

  • (ArgumentError)


54
55
56
57
58
59
60
# File 'lib/canery/backend.rb', line 54

def mget(name, keys)
  raise ArgumentError, "keys argument must be an Array of keys" unless Array === keys
  keys.map!{ |key| build_key(key) }

  # Sort data in the order they appear in the 'keys' Array
  namespace(name).where(:key => keys).sort_by { |element| keys.index(element[:key]) }.map {|dataset| load(dataset[:value]) }
end

#mset(name, data) ⇒ Object

Raises:

  • (ArgumentError)


72
73
74
75
76
77
78
79
80
81
82
# File 'lib/canery/backend.rb', line 72

def mset(name, data)
  raise ArgumentError, "data must be a Hash with keys and values" unless Hash === data
  begin
    namespace(name).multi_insert(data.map{ |key, value| {:key => build_key(key), :value => dump(value)} }) && "OK"
  rescue
    # Fallback to the slower update method
    data.each do |key, value|
      update(name, key, value)
    end && "OK"
  end
end

#namespace(name) ⇒ Object



33
34
35
# File 'lib/canery/backend.rb', line 33

def namespace(name)
  @namespace_cache[basic_tub_name(name)] ||= connection.dataset.select(:key, :value).from(basic_tub_name(name))
end

#namespace?(name) ⇒ Boolean

Returns:

  • (Boolean)


41
42
43
# File 'lib/canery/backend.rb', line 41

def namespace?(name)
  connection.table_exists?(basic_tub_name(name))
end

#namespacesObject



37
38
39
# File 'lib/canery/backend.rb', line 37

def namespaces
  connection.tables.select{ |name| name =~ /^#{TABLE_PREFIX}/ }.map{ |tub_name| tub_name.to_s[TABLE_PREFIX.length..-1] }
end

#rename(name, old_key, new_key) ⇒ Object



125
126
127
# File 'lib/canery/backend.rb', line 125

def rename(name, old_key, new_key)
  namespace(name).where(:key => build_key(old_key)).limit(1).update(:key => build_key(new_key)) && "OK"
end

#set(name, key, value) ⇒ Object



62
63
64
65
66
67
68
69
70
# File 'lib/canery/backend.rb', line 62

def set(name, key, value)
  begin
    namespace(name).insert(:key => build_key(key), :value => dump(value)) && build_key(key)
  rescue Sequel::DatabaseError # raised if the key already exists, than update
    update(name, key, value)
  rescue
    "ERROR"
  end
end

#sort(name, order, limit) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/canery/backend.rb', line 108

def sort(name, order, limit)
  data = case order.downcase
    when :asc, 'asc'
      namespace(name).order(Sequel.asc(:key))
    when :desc, 'desc'
      namespace(name).order(Sequel.desc(:key))
    else
      namespace(name).order(Sequel.asc(:key))
  end
  
  unless limit.nil?
    raise ArgumentError, "limit must be a positive Integer" unless Integer === limit
    data = data.limit(limit)
  end
  data.map{ |dataset| dataset[:key] }
end

#update(name, key, value) ⇒ Object



92
93
94
# File 'lib/canery/backend.rb', line 92

def update(name, key, value)
  namespace(name).where(:key => build_key(key)).limit(1).update(:value => dump(value)) && build_key(key)
end

#values(name) ⇒ Object



104
105
106
# File 'lib/canery/backend.rb', line 104

def values(name)
  namespace(name).map{ |dataset| load(dataset[:value]) }
end