Class: Sequel::Model

Inherits:
Object show all
Includes:
Fossil::NumberHelper, Serialization
Defined in:
lib/sequel/model_patch.rb

Constant Summary collapse

PK_KEYS =

Using this order for keys because it makes it easier to query fos records. If you had a key like “MERE.0.8.40443.1259” for a trip leg and you did this: TripLeg, you would get a trip leg You still have to massage this key alittle to make the query: see Sequel.fos_id_to_lookup_key in core_patch.rb

[:"kid - user", :"kid - mult", :"kid - comm", :"kid - date", :"kid - time"]

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Fossil::NumberHelper

#number_to_currency, #number_to_percentage, #number_to_phone, #number_with_delimiter, #number_with_precision

Methods included from Serialization

#from_xml, included, #to_fos_json, #to_fos_xml, #to_json, #to_xml

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

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



54
55
56
57
58
59
60
61
62
63
# File 'lib/sequel/model_patch.rb', line 54

def method_missing(method, * args, & block)
  if method.to_s.split(/__/).size > 1
    generate_delegator(method)
    send(method.to_s.gsub('__', '_').to_sym)
  elsif self.class.instance_variable_get("@aliases").values.include? method
    send(:[],method)
  else
    super(method, * args, & block)
  end
end

Class Attribute Details

.aliasesObject

Returns the value of attribute aliases.



82
83
84
# File 'lib/sequel/model_patch.rb', line 82

def aliases
  @aliases
end

.datatypesObject

Returns the value of attribute datatypes.



82
83
84
# File 'lib/sequel/model_patch.rb', line 82

def datatypes
  @datatypes
end

Class Method Details

.association(assoc_type, assoc_name, options) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/sequel/model_patch.rb', line 98

def association(assoc_type, assoc_name, options)
  class_name = options[:class]
  prefix = options[:prefix]
  case assoc_type
    when :one_to_many
      key = options[:key] || primary_key
      primary_key = options[:primary_key] || key
      extra_dataset_conditions = options[:extra_conditions] || {}
      graph_conditions = {:"#{prefix} kid - date" => :'kid - date',
                          :"#{prefix} kid - time" => :'kid - time',
                          :"#{prefix} kid - user" => :'kid - user',
                          :"#{prefix} kid - mult" => :'kid - mult',
                          :"#{prefix} kid - comm" => :'kid - comm'}.
          merge(extra_dataset_conditions)
      dataset_filter = proc {
        class_name.to_s.constantize.filter(
        {:"#{prefix} kid - date"=>self[:'kid - date'],
         :"#{prefix} kid - time"=>self[:'kid - time'],
         :"#{prefix} kid - user"=>self[:'kid - user'],
         :"#{prefix} kid - mult"=>self[:'kid - mult'],
         :"#{prefix} kid - comm"=>self[:'kid - comm']}.
          merge(extra_dataset_conditions)
        )
      }
    when :many_to_one
      key = nil
      graph_conditions = {:'kid - date'=>:"#{prefix} kid - date", :'kid - time'=>:"#{prefix} kid - time", :'kid - user'=>:"#{prefix} kid - user", :'kid - mult'=>:"#{prefix} kid - mult", :'kid - comm'=>:"#{prefix} kid - comm"}
      extra_dataset_conditions = options[:dataset_conditions] || {}
      dataset_filter = proc { class_name.to_s.constantize.filter({:"kid - date"=>self[:"#{prefix} kid - date"], :"kid - time"=>self[:"#{prefix} kid - time"], :"kid - user"=>self[:"#{prefix} kid - user"], :"kid - mult"=>self[:"#{prefix} kid - mult"], :"kid - comm"=>self[:"#{prefix} kid - comm"]}.merge(extra_dataset_conditions)) }
  end
  graph_conditions.merge!(options[:graph_only_conditions]) if options[:graph_only_conditions]
  send(assoc_type, assoc_name, :key=> key, :primary_key=>primary_key, :class => class_name, :dataset=> dataset_filter, :graph_only_conditions=>graph_conditions)
end

.clear_schemaObject



84
85
86
87
88
# File 'lib/sequel/model_patch.rb', line 84

def clear_schema
  db_schema.clear
  @datatypes = {}
  @aliases = {}
end

.code_association(assoc_name, column_name_holding_code, code_group_name) ⇒ Object

for creating an association to the ‘Codes’ table



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/sequel/model_patch.rb', line 133

def code_association(assoc_name, column_name_holding_code, code_group_name)
  # create the many to one association
  send(:many_to_one, assoc_name, :class=>:Code, :key=>nil,
       # dataset adds
       :dataset=>proc {
         value = self[column_name_holding_code] || send(column_name_holding_code)
         Code.filter(:'value'=> value, :name=>CodeGroup.send(code_group_name))
       },
       # graph_only_conditions add the join conditions when using eager_graph in query
       :graph_only_conditions => {:'value'=> column_name_holding_code, :name=>CodeGroup.send(code_group_name)}
  )

  # create the :get_all method to find all codes of the code group name
  meta_def "get_all_#{assoc_name.to_s.pluralize}" do
    Code.get_codes(CodeGroup.send(code_group_name))
  end
  # add a delegator that calls for the code, and one for description  
  delegate :code, :to=> assoc_name, :prefix=>true, :allow_nil => true
  delegate :description, :to=> assoc_name, :prefix=>true, :allow_nil => true
end

.column_alias(new_column_name, old_column_name, options = {}) ⇒ Object

column_alias :‘bad_name’, :‘bad name’, :type=>:date # can set type here if you like



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/sequel/model_patch.rb', line 164

def column_alias(new_column_name, old_column_name, options={})
  @aliases ||= {}
  @aliases[new_column_name]= old_column_name

  # define a getter method on the model class for the aliased column name
  # will get value from old_column_name
  inst_def new_column_name do
    send(:[], old_column_name)
  end
  # define a setter method on the model class with the aliased column name
  # will actually set value to old_column_name
  inst_def "#{new_column_name}=" do |value|
    send(:[]=, old_column_name, value)
  end

  if options[:type]
    column_type(new_column_name, options[:type])
    column_type(old_column_name, options[:type])
  else
    column_type(new_column_name, :string)
  end
end

.column_def_datetime(datetime_column_name, date_column, time_column) ⇒ Object

date_column,time_column should be a Fixnum because fos stores dates,times as numbers



155
156
157
158
159
160
161
# File 'lib/sequel/model_patch.rb', line 155

def column_def_datetime(datetime_column_name, date_column, time_column)
  inst_def datetime_column_name do
    days = send(:[], date_column) || 0 # nil defaults to 0 days
    minutes = send(:[], time_column) || 0 # nil defaults to 0 minutes
    DateTime.from_fos_date_time(days, minutes) # returns utc datetime
  end
end

.column_type(name, type) ⇒ Object

set the column type to an existing column column_type :‘bad name’, :datetime



189
190
191
192
193
194
195
# File 'lib/sequel/model_patch.rb', line 189

def column_type(name, type)
  @datatypes = model.db_schema
  # if things went wrong and the db_schema could not load up
  # have to set up the datatypes entry manually
  @datatypes[name] = {} unless @datatypes[name]
  @datatypes[name][:type] = type
end

.column_view(column_name, type, custom_method_name = nil) ⇒ Object

define a method to get the value of set the column as a certain type Used like this in a Model class.

column_view :'column_name', :date
column_view :'column_name', :time
column_view :'column_name', :time,     :custom_method_name
column_view :'column_name', :currency
column_view :'column_name', :boolean

defines methods for getting new value in the type you requested from the column_name. The type should be :time, :date, :currency, or :boolean

For example: column_name :eta_local, :date, the methods created are:

eta_local_date               =>  returns a Date
eta_local_date_view          =>  returns a Date formatted   y-m-d
eta_local_date_view_mdy      =>  returns a Date formatted   m/d/y
eta_local_date_view_mdy_ipc  =>  returns a Date formatted   m/d/y with first 0 chopped
   ie.  instead of 08/07/2009  .. it will be 8/07/2009

column_name :eta_local, :time, the methods created are:

eta_local_time       =>  returns a Time
eta_local_time_view  =>  returns a Time formatted  H:M

column_name :price, :currency, the method created is:

price_currency       => which returns a currecy formatted value 12.15 ( no dollar sign )

column_name :item_total, :delimited, the method created is:

item_total_delimited => which returns a delimited formatted value 12.15 ( no dollar sign )

column_name :paid, :boolean, the method created is:

paid_boolean         => which returns a string ("False" / "True") for values ( 0 / 1 )

Raises:

  • (StandardError)


235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# File 'lib/sequel/model_patch.rb', line 235

def column_view(column_name, type, custom_method_name=nil)
  raise(StandardError, "Expect the type to be either :date, :datetime, :time, :currency, :precision or :boolean") unless [:date, :time, :datetime, :currency, :precision, :boolean].include? type
  # will get value from old_column_name
  method_name = custom_method_name || "#{column_name}_#{type.to_s}"

  # the method that returns the column value as a Date or Time value
  inst_def method_name do
    column_value = send(column_name)
    case type
      when :date
        Date.from_fos_days(column_value) if column_value
      when :time
        DateTime.from_fos_time(column_value) if column_value
      when :currency
#            (column_value || 0).to_currency
        number_to_currency((column_value || 0).to_f/100, :unit=>'', :precision=>2)
      when :precision
#            (column_value || 0).to_currency
#            precision wont do delimiter .. so send to currency
        number_to_currency((column_value || 0).to_f/100, :unit=>'', :precision=>2)
      when :boolean
        return "True" if column_value and (column_value == 1 or column_value == true)
        "False"
    end
  end

  method_view_name = method_name.to_s + "_view"
  case type
    when :boolean, :currency, :precision
      inst_def method_view_name do
        value = send(method_name)
        value.to_s if value
      end

    when :time
      inst_def method_view_name do
        value = send(method_name)
        value.strftime('%H:%M') if value
      end

    when :date
      inst_def method_view_name do
        value = send(method_name)
        value.to_s if value
      end
      
      # extra view methods for date type
      method_view_name = method_name.to_s + "_view_mdy"
      # method that returns the column value as a Date in mdy format
      inst_def method_view_name do
        column_value = send(column_name)
        return nil unless column_value
        Date.from_fos_days(column_value).strftime('%m/%d/%Y')
      end
      method_view_name = method_name.to_s + "_view_mdy_ipc"
      # method that returns the column value as a Date in mdy format
      inst_def method_view_name do
        column_value = send(column_name)
        return nil unless column_value
        date_str = Date.from_fos_days(column_value).strftime('%m/%d/%Y')
        date_str.slice!(3) if date_str[3] == 48 # if the fourth char is 0 ( ascii value 48 ) remove it
        date_str.slice!(0) if date_str[0] == 48 # if the first char is 0 ( ascii value 48 ) remove it
        date_str
      end
    end
end

.find_childrenObject



10
11
12
13
14
15
16
# File 'lib/sequel/model_patch.rb', line 10

def self.find_children
  Module.constants.find_all do |c_klass|
    if c_klass!=c_klass.upcase
      self > (Object.const_get c_klass) rescue nil
    end
  end
end

.n_to_o(assoc_name, options) ⇒ Object



90
91
92
# File 'lib/sequel/model_patch.rb', line 90

def n_to_o(assoc_name, options)
  association(:many_to_one, assoc_name, options)
end

.o_to_n(assoc_name, options) ⇒ Object



94
95
96
# File 'lib/sequel/model_patch.rb', line 94

def o_to_n(assoc_name, options)
  association(:one_to_many, assoc_name, options)
end

.select_fields(table, *fields) ⇒ Object



302
303
304
# File 'lib/sequel/model_patch.rb', line 302

def select_fields(table, * fields)
  dataset.select_fields(table, * fields)
end

Instance Method Details

#fill_hash(attributes) ⇒ Object

Passing in an array of attribute / method names, fills a hash with values from the model. Can pass in attributes with __ like :passenger__name and the ‘name’ value will be delegated to ‘passenger’ with the delegator being created on the fly. Can also pass in a hash of attributes, with the key being the key you want for the hash and the value being the value you want from the model. So you could pass in :pax_name=>:passenger__name and the hash returned will be :pax_name=>‘Bob’



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/sequel/model_patch.rb', line 35

def fill_hash(attributes)
  if attributes.is_a? Array
    attributes.inject({}) do |hash, attribute|
      attribute_name = attribute.to_s.gsub('__', '_').to_sym
      generate_delegator(attribute) unless respond_to? attribute_name
      hash[attribute_name] = send(attribute_name) if respond_to? attribute_name
      hash
    end
  elsif attributes.is_a? Hash
    hash = {}
    attributes.each do |key, attribute|
      attribute_name = attribute.to_s.gsub('__', '_').to_sym
      generate_delegator(attribute) unless respond_to? attribute_name
      hash[key] = send(attribute_name) if respond_to? attribute_name
    end
    hash
  end
end

#fos_idObject



25
26
27
# File 'lib/sequel/model_patch.rb', line 25

def fos_id
  PK_KEYS.collect { |key| value=send(key); value.strip! if value.is_a?(String); value }.join('-')
end

#generate_delegator(method) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/sequel/model_patch.rb', line 65

def generate_delegator(method)
  arr = method.to_s.split(/__/)
  # check to see if method_name ( delegator )  exists first to ensure its not created again
  unless respond_to? arr.join('_')
    # create delegator on the fly
    method_call = arr.shift
    arr.each do |next_call|
      unless respond_to?(method_call + "_" + next_call)
        self.class.delegate next_call.to_sym, :to => method_call.to_sym, :prefix => true, :allow_nil => true
      end
      method_call = method_call + "_" + next_call
    end
  end
end