Class: Kiss::Model

Inherits:
Sequel::Model
  • Object
show all
Extended by:
ControllerAccessors, RequestAccessors
Includes:
ControllerAccessors, RequestAccessors
Defined in:
lib/kiss/model.rb

Overview

This class adds functionality to Sequel::Model and automatically loads model class definitions from model_dir. It also uses Kiss#file_cache to cache database model classes, unless no model_dir is specified.

Class Method Summary collapse

Instance Method Summary collapse

Methods included from RequestAccessors

app, cookies, debug, env, file_cache, host, login, models, path_info, protocol, pub, query_string_with_params, redirect_action, redirect_url, request_url_with_params, response, send_file, send_response, session, set_cookie, set_exception_cache, start_benchmark, stop_benchmark

Methods included from ControllerAccessors

environment, models, public_dir, upload_dir

Methods included from KissAccessors

#html_escape, #url_escape

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args, &block) ⇒ Object

Raises:

  • (NoMethodError)


203
204
205
206
207
208
209
210
211
212
# File 'lib/kiss/model.rb', line 203

def method_missing(meth, *args, &block)
  if meth.to_s =~ /(\w+)\?\Z/
    column = $1.to_sym
    if respond_to?(column)
      val = self.send(column, *args, &block)
      return !(val.nil? || val.zero?)
    end
  end
  raise NoMethodError, "undefined method `#{meth}' for database model `#{self.class.name.pluralize}'"
end

Class Method Details

.alias_association(new_name, old_name) ⇒ Object Also known as: alias_assoc



25
26
27
28
# File 'lib/kiss/model.rb', line 25

def alias_association(new_name, old_name)
  alias_method new_name, old_name
  alias_method :"#{new_name}_dataset", :"#{old_name}_dataset"
end

.associate(type, name, opts = {}, &block) ⇒ Object

TODO: Fix has_many and many_to_many associations



63
64
65
66
67
68
69
70
71
72
73
# File 'lib/kiss/model.rb', line 63

def associate(type, name, opts = {}, &block)
  opts = opts.clone
  
  unless opts[:class] || opts[:class_name]
    opts[:class_name] = name.to_s.pluralize
  end
  
  super(type, name, opts, &block)
  
  association_reflections[name]
end

.belongs_to(*args) ⇒ Object



17
18
19
# File 'lib/kiss/model.rb', line 17

def belongs_to(*args)
  many_to_one(*args)
end

.controllerObject



37
38
39
# File 'lib/kiss/model.rb', line 37

def controller
  db.kiss_controller
end

.default_foreign_keyObject

Name symbol for default foreign key



54
55
56
# File 'lib/kiss/model.rb', line 54

def default_foreign_key
  :"#{name.singularize.demodulize.underscore}_id"
end

.find_or_new(cond) ⇒ Object



58
59
60
# File 'lib/kiss/model.rb', line 58

def find_or_new(cond)
  find(cond) || new(cond)
end

.has_and_belongs_to_many(*args) ⇒ Object



21
22
23
# File 'lib/kiss/model.rb', line 21

def has_and_belongs_to_many(*args)
  many_to_many(*args)
end

.has_many(*args) ⇒ Object



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

def has_many(*args)
  one_to_many(*args)
end

.nameObject

This method is called by Sequel::Model’s association def methods. Must return singularized table name for correct association key names.



33
34
35
# File 'lib/kiss/model.rb', line 33

def name
  @_table.to_s.singularize
end

.requestObject



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

def request
  db.kiss_request || controller
end

.set_dataset(source) ⇒ Object



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

def set_dataset(source)
  super(source)
end

.tableObject



45
46
47
# File 'lib/kiss/model.rb', line 45

def table
  @_table.to_sym
end

.table=(table) ⇒ Object



49
50
51
# File 'lib/kiss/model.rb', line 49

def table=(table)
  @_table = table
end

Instance Method Details

#add_associated_object(opts, o) ⇒ Object



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

def add_associated_object(opts, o)
  need_missing_opk = opts.need_associated_primary_key? && !o.pk
  if !pk || need_missing_opk
    double_defer = !pk && need_missing_opk
    # TODO: add :uniq check here (and patch this in Sequel as well)
    (deferred_associations[opts[:name]] ||= []).push(o)
    
    method_call = [double_defer, [self, opts.add_method, o]]
    deferred_association_method_calls << method_call unless pk
    o.deferred_association_method_calls << method_call if need_missing_opk
    
    add_deferred_reciprocal_object(opts, o)
    o
  else
    deferred_associations[opts[:name]].delete(o) if deferred_associations[opts[:name]]
    super
  end
end

#add_deferred_reciprocal_object(opts, o) ⇒ Object

Add/Set the current object to/as the given object’s reciprocal association.



127
128
129
130
131
132
133
134
135
136
# File 'lib/kiss/model.rb', line 127

def add_deferred_reciprocal_object(opts, o)
  return unless reciprocal = opts.reciprocal
  if opts.reciprocal_array?
    if array = o.deferred_associations[reciprocal] and !array.include?(self)
      array.push(self)
    end
  else
    o.deferred_associations[reciprocal] = self
  end
end

#after_createObject



188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/kiss/model.rb', line 188

def after_create
  deferred_association_method_calls.each do |call|
    if call[0]
      # call[0] (double_defer) is true
      # now set it to false, do nothing else
      # (defer again until other side is created)
      call[0] = false
    else
      m = call[1]
      m.shift.send(*m) if m
    end
  end
  @deferred_association_method_calls = []
end

#controllerObject



214
215
216
# File 'lib/kiss/model.rb', line 214

def controller
  self.class.controller
end

#deferred_association_method_callsObject



84
85
86
# File 'lib/kiss/model.rb', line 84

def deferred_association_method_calls
  @deferred_association_method_calls ||= []
end

#deferred_associationsObject



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

def deferred_associations
  @deferred_associations ||= {}
end

#load_associated_objects(opts, reload = false) ⇒ Object



138
139
140
141
142
143
144
# File 'lib/kiss/model.rb', line 138

def load_associated_objects(opts, reload=false)
  if d = deferred_associations[opts[:name]]
    opts.returns_array? ? super + d : d
  else
    super || set_associated_object(opts, opts.associated_class.new)
  end
end

#nameObject



222
223
224
# File 'lib/kiss/model.rb', line 222

def name
  self[:name] || self.class.table.to_s.singularize.titleize
end

#new_email(options = {}) ⇒ Object

Creates and invokes new Kiss::Mailer instance to send email message via SMTP.



227
228
229
230
231
# File 'lib/kiss/model.rb', line 227

def new_email(options = {})
  request.new_email({
    :data => self
  }.merge(options))
end

#remove_all_associated_objects(opts) ⇒ Object

Remove all associated objects from the given association



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/kiss/model.rb', line 147

def remove_all_associated_objects(opts)
  ret = super
  if deferred_associations.include?(opts[:name])
    def_ret = deferred_associations[opts[:name]].each do |o|
      method_call = [self, opts.add_method, o]
      deferred_association_method_calls.delete_if {|c| c[1] == method_call }
      o.deferred_association_method_calls.delete_if {|c| c[1] == method_call }
      remove_deferred_reciprocal_object(opts, o)
    end
    deferred_associations[opts[:name]] = []
    (ret || []) + def_ret
  else
    ret
  end
end

#remove_associated_object(opts, o) ⇒ Object

Remove the given associated object from the given association



164
165
166
167
168
169
170
171
172
173
174
# File 'lib/kiss/model.rb', line 164

def remove_associated_object(opts, o)
  if (array = deferred_associations[opts[:name]]) and array.delete(o)
    method_call = [self, opts.add_method, o]
    deferred_association_method_calls.delete_if {|c| c[1] == method_call }
    o.deferred_association_method_calls.delete_if {|c| c[1] == method_call }
    remove_deferred_reciprocal_object(opts, o)
  else
    super
  end
  o
end

#remove_deferred_reciprocal_object(opts, o) ⇒ Object

Remove/unset the current object from/as the given object’s reciprocal association.



177
178
179
180
181
182
183
184
185
186
# File 'lib/kiss/model.rb', line 177

def remove_deferred_reciprocal_object(opts, o)
  return unless reciprocal = opts.reciprocal
  if opts.reciprocal_array?
    if array = o.deferred_associations[reciprocal]
      array.delete_if{|x| self === x}
    end
  else
    o.deferred_associations[reciprocal] = nil
  end
end

#requestObject



218
219
220
# File 'lib/kiss/model.rb', line 218

def request
  self.class.request
end

#send_email(options = {}) ⇒ Object



233
234
235
# File 'lib/kiss/model.rb', line 233

def send_email(options = {})
  new_email(options).send
end

#set_associated_object(opts, o) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/kiss/model.rb', line 88

def set_associated_object(opts, o)
  if o && !o.pk
    if (da = deferred_associations[opts[:name]]) != o
      if da
        da.deferred_association_method_calls.delete_if {|c| c[1] == [self, opts.setter_method, da] }
        remove_deferred_reciprocal_object(opts, o)
      end
      
      deferred_associations[opts[:name]] = o
      o.deferred_association_method_calls << [false, [self, opts.setter_method, o]]
      add_deferred_reciprocal_object(opts, o)
    end
    o
  else
    deferred_associations.delete(opts[:name])
    super
  end
end

#to_hashObject



237
238
239
240
241
242
243
# File 'lib/kiss/model.rb', line 237

def to_hash
  result = {}
  keys.each do |key|
    result[key] = values[key]
  end
  result
end