Class: Rhoconnect::Model

Inherits:
Object
  • Object
show all
Defined in:
lib/rhoconnect/model.rb

Overview

Taken from github.com/voloko/redis-model

Simple models for redis-rb.

Direct Known Subclasses

ApiToken, App, BulkData, Client, ReadState, User

Defined Under Namespace

Modules: Marshal Classes: FieldProxy, ListProxy, SetProxy

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id = nil) ⇒ Model

Returns a new instance of Model.



9
10
11
# File 'lib/rhoconnect/model.rb', line 9

def initialize(id=nil)
  self.id = id
end

Class Attribute Details

.prefixObject

Defaults to model_name.dasherize



79
80
81
# File 'lib/rhoconnect/model.rb', line 79

def prefix
  @prefix
end

.validates_presenceObject

Returns the value of attribute validates_presence.



80
81
82
# File 'lib/rhoconnect/model.rb', line 80

def validates_presence
  @validates_presence
end

Instance Attribute Details

#idObject

Returns the value of attribute id.



7
8
9
# File 'lib/rhoconnect/model.rb', line 7

def id
  @id
end

Class Method Details

._field_key(p, i, n) ⇒ Object

:nodoc:



86
87
88
# File 'lib/rhoconnect/model.rb', line 86

def _field_key(p,i,n) #:nodoc:
  "#{p}:#{i}:#{n}"
end

._prefixObject



82
83
84
# File 'lib/rhoconnect/model.rb', line 82

def _prefix
  class_prefix(self)
end

.class_prefix(classname) ⇒ Object



90
91
92
93
94
95
96
# File 'lib/rhoconnect/model.rb', line 90

def class_prefix(classname)
  classname.to_s.
    sub(%r{(.*::)}, '').
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z\d])([A-Z])/,'\1_\2').
    downcase
end

.create(params = {}, attributes = {}) ⇒ Object Also known as: with_next_key

Creates new model instance with new uniqid NOTE: “sequence:model_name:id” key is used

Raises:

  • (ArgumentError)


100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/rhoconnect/model.rb', line 100

def create(params = {}, attributes = {})
  raise ArgumentError.new("Record already exists for '#{params[:id]}'") if self.is_exist?(params[:id])
  if self.validates_presence
    self.validates_presence.each do |field|
      raise ArgumentError.new("Missing required field '#{field}'") unless params[field]
    end
  end
  o = self.new
  o.id = params[:id].nil? ? o.next_id : params[:id]
  params[:rho__id] = params[:id]
  populate_model(o,params)
  populate_attributes(o,attributes)
end

.field(name, type = :string) ⇒ Object Also known as: value

Defines marshaled rw accessor for redis string value



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/rhoconnect/model.rb', line 137

def field(name, type = :string)
  if @fields.nil?
    @fields = []
    field :rho__id, :string
  end        
  type = type.to_sym
  type = :integer if type == :int

  class_name = marshal_class_name(name, type)

  fields << {:name => name.to_s, :type => type}
  if type == :string
    class_eval "def #{name}; @#{name} ||= redis[field_key('#{name}')]; end"
    class_eval "def #{name}=(value); @#{name} = redis[field_key('#{name}')] = value; end"
  else
    class_eval "def #{name}; @#{name} ||= Marshal::#{class_name}.load(redis[field_key('#{name}')]); end"
    class_eval "def #{name}=(value); @#{name} = value; redis[field_key('#{name}')] = Marshal::#{class_name}.dump(value); end"
  end
end

.fieldsObject

:nodoc:



185
186
187
# File 'lib/rhoconnect/model.rb', line 185

def fields #:nodoc:
  @fields ||= []
end

.is_exist?(id) ⇒ Boolean

Returns:

  • (Boolean)


50
51
52
# File 'lib/rhoconnect/model.rb', line 50

def self.is_exist?(id)
  !redis.get(self._field_key(self._prefix,id,'rho__id')).nil?
end

.list(name, type = :string) ⇒ Object

Defines accessor for redis list



159
160
161
162
163
164
165
# File 'lib/rhoconnect/model.rb', line 159

def list(name, type = :string)
  class_name = marshal_class_name(name, type)

  fields << {:name => name.to_s, :type => :list}
  class_eval "def #{name}; @#{name} ||= ListProxy.new(self.redis, field_key('#{name}'), Marshal::#{class_name}); end"
  eval_writer(name)
end

.load(id, params = {}) ⇒ Object



114
115
116
# File 'lib/rhoconnect/model.rb', line 114

def load(id, params={})
  populate_attributes(self.with_key(id),params) if self.is_exist?(id)
end

.marshal_class_name(name, type) ⇒ Object



176
177
178
# File 'lib/rhoconnect/model.rb', line 176

def marshal_class_name(name, type)
  Marshal::TYPES[type] or raise ArgumentError.new("Unknown type #{type} for field #{name}")
end

.populate_attributes(obj, attribs) ⇒ Object



118
119
120
121
122
123
# File 'lib/rhoconnect/model.rb', line 118

def populate_attributes(obj,attribs)
  attribs.each do |attrib,value|
    obj.send "#{attrib.to_s}=".to_sym, value
  end
  obj
end

.redisObject

Redefine this to change connection options



181
182
183
# File 'lib/rhoconnect/model.rb', line 181

def redis
  @@redis ||= Store.db
end

.set(name, type = :string) ⇒ Object

Defines accessor for redis set



168
169
170
171
172
173
174
# File 'lib/rhoconnect/model.rb', line 168

def set(name, type = :string)
  class_name = marshal_class_name(name, type)

  fields << {:name => name.to_s, :type => :set}
  class_eval "def #{name}; @#{name} ||= SetProxy.new(self.redis, field_key('#{name}'), Marshal::#{class_name}); end"
  eval_writer(name)
end

.validates_presence_of(*names) ⇒ Object



125
126
127
128
129
130
# File 'lib/rhoconnect/model.rb', line 125

def validates_presence_of(*names)
  self.validates_presence ||= []
  names.each do |name|
    self.validates_presence << name
  end
end

Instance Method Details

#decrement!(name, amount = 1) ⇒ Object

Decrement the specified integer field by 1 or the specified amount.

Raises:

  • (ArgumentError)


41
42
43
44
# File 'lib/rhoconnect/model.rb', line 41

def decrement!(name,amount=1)
  raise ArgumentError, "Only integer fields can be decremented." unless self.class.fields.include?({:name => name.to_s, :type => :integer})
  redis.decrby(field_key(name), amount)
end

#delete(name = nil) ⇒ Object

Issues delete commands for all defined fields



18
19
20
21
22
23
24
25
26
# File 'lib/rhoconnect/model.rb', line 18

def delete(name = nil)
  if name
    redis.del field_key(name.to_s)
  else
    self.class.fields.each do |field|
      redis.del field_key(field[:name])
    end
  end
end

#field_key(name) ⇒ Object

:nodoc:



28
29
30
# File 'lib/rhoconnect/model.rb', line 28

def field_key(name) #:nodoc:
  self.class._field_key(prefix,id,name)
end

#increment!(name, amount = 1) ⇒ Object

Increment the specified integer field by 1 or the specified amount.

Raises:

  • (ArgumentError)


34
35
36
37
# File 'lib/rhoconnect/model.rb', line 34

def increment!(name,amount=1)
  raise ArgumentError, "Only integer fields can be incremented." unless self.class.fields.include?({:name => name.to_s, :type => :integer})
  redis.incrby(field_key(name), amount)
end

#next_idObject

:nodoc:



46
47
48
# File 'lib/rhoconnect/model.rb', line 46

def next_id #:nodoc:
  redis.incr "sequence:#{self.prefix}:id"
end

#redisObject

:nodoc:



13
14
15
# File 'lib/rhoconnect/model.rb', line 13

def redis #:nodoc:
  self.class.redis
end

#to_arrayObject



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

def to_array
  res = []
  self.class.fields.each do |field|
    res << field.merge!(:value => send(field[:name].to_sym))
  end
  res
end