Class: ActiveRecord::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/core_ext/active_record.rb

Overview

Add Edgar specific methods.

Direct Known Subclasses

Edgar::Address, Edgar::ModelPermission, Edgar::Sssn, Edgar::User, Edgar::UserGroup, Edgar::UserGroupUser, Edgar::ViewStatus, Edgar::ZipAddress

Constant Summary

@@_edgar_cache =

cache several kind of information for each (class x kind) during runtime, for example, result of edgar_address? method.

{}

Class Method Summary (collapse)

Instance Method Summary (collapse)

Class Method Details

+ (Object) _edgar_cache

just for dump purpose



224
225
226
# File 'lib/core_ext/active_record.rb', line 224

def self._edgar_cache
  @@_edgar_cache
end

+ (Object) belongs_to_AR(column)

return AR class which the column belongs to. nil if not exist



20
21
22
23
24
25
26
27
28
# File 'lib/core_ext/active_record.rb', line 20

def self.belongs_to_AR(column)
  for parent_assoc in reflect_on_all_associations(:belongs_to) do
    if !parent_assoc.options[:polymorphic] &&
        parent_assoc.foreign_key == column.name
      return parent_assoc.klass
    end
  end
  nil
end

+ (Object) columns_for(list)

return array of model columns (ActiveRecord::ConnectionAdapters::X_Column type). This is usually used as follows:

Model.columns_for(Model.view_popup_columns)

INPUTS

list

column name list

FIXME: inefficient



39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/core_ext/active_record.rb', line 39

def self.columns_for(list)
  # build hash: {col.name => col}
  hash = {}
  for col in self.columns do
    hash[col.name] = col
  end
  result = []
  for col_name in list do
    result << hash[col_name] if hash[col_name]
  end
  result
end

+ (Object) edgar_address(name)

make 'belongs_to' relation from the name to address.

This directive makes a 'belongs_to' relation from the specified integer column to Edgar::Address model.

Rails 'nested_attributes' feature cannot be used to assign address part because here is child side. So, 'before_save' call back is used.

EXAMPLE

Declaration following in AR:

edgar_address :adrs_00

is equivalent to:

belongs_to :adrs_00, :class_name=>'Edgar::Address', :foreign_key=>:adrs_00, :dependent=>:destroy
attr_protected :adrs_00


202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/core_ext/active_record.rb', line 202

def self.edgar_address(name)
  column  = name.to_s + '_id'
  attr_protected(column)
  belongs_to(name,
      class_name:   'Edgar::Address',
      foreign_key:  column,
      dependent:    :destroy)
  class_eval <<-EOS, __FILE__, __LINE__ + 1
    def #{name}_attributes=(attrs)
      self.#{column} = Edgar::Address.intern(attrs).id
    end
  EOS
end

+ (Boolean) edgar_address?(col_or_sym)

column is declared as edgar_address?

Returns:

  • (Boolean)


229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/core_ext/active_record.rb', line 229

def self.edgar_address?(col_or_sym)
  cache     = edgar_cache(:edgar_address)
  col_name  = get_column_name(col_or_sym).to_s
  if !cache[col_name].nil?
    return cache[col_name]
  end

  for assoc in reflect_on_all_associations(:belongs_to) do
    if assoc.foreign_key.to_s == col_name &&
       assoc.class_name == 'Edgar::Address'

      cache[col_name] = true
      return true
    end
  end
  cache[col_name] = false
  false
end

+ (Object) edgar_cache(kind)

initialize cache per (class x kind) on the fly



217
218
219
220
221
# File 'lib/core_ext/active_record.rb', line 217

def self.edgar_cache(kind)
  @@_edgar_cache[self] = {}       if !@@_edgar_cache[self]
  @@_edgar_cache[self][kind] = {} if !@@_edgar_cache[self][kind]
  @@_edgar_cache[self][kind]
end

+ (Object) edgar_file(*args)

define file upload/download columns.

EXAMPLE

Declaration following in AR:

edgar_file :file_00, :file_01

is equivalent to:

belongs_to :file_00_info, :class_name=>'FileInfo', :foreign_key=>:file_00, :dependent=>:destroy
belongs_to :file_01_info, :class_name=>'FileInfo', :foreign_key=>:file_01, :dependent=>:destroy
attr_protected :file_00, :file_01


262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/core_ext/active_record.rb', line 262

def self.edgar_file(*args)
  attr_protected(*args)
  for arg in args do
    if arg.is_a?(Symbol)
      belongs_to "#{arg.to_s}_info".to_sym,
          :class_name   => 'FileInfo',
          :foreign_key  => arg,
          :dependent    => :destroy
    else
      raise "edgar_file argument must be a symbol"
    end
  end
end

+ (Boolean) edgar_file?(col_or_sym)

column is declared as edgar_file?

Returns:

  • (Boolean)


287
288
289
290
291
292
293
294
295
296
297
# File 'lib/core_ext/active_record.rb', line 287

def self.edgar_file?(col_or_sym)
  col_name = get_column_name(col_or_sym).to_s
  for assoc in reflect_on_all_associations(:belongs_to) do
    if assoc.foreign_key.to_s == col_name &&
       assoc.class_name == 'FileInfo'

      return true
    end
  end
  false
end

+ (Object) get_belongs_to_name(col_or_sym)

get belongs_to association name from column.

Example: get_assoc_name(:adrs_id) -> :adrs



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/core_ext/active_record.rb', line 167

def self.get_belongs_to_name(col_or_sym)
  cache     = edgar_cache(:belongs_to_name)
  col_name  = get_column_name(col_or_sym).to_s
  if !cache[col_name].nil?
    return cache[col_name]
  end

  for reflection in reflect_on_all_associations(:belongs_to) do
    if reflection.foreign_key == col_name
      cache[col_name] = reflection.name
      return reflection.name
    end
  end
  nil
end

+ (Object) get_column_name(col_or_sym)

get column name from column object or symbol



277
278
279
280
281
282
283
284
# File 'lib/core_ext/active_record.rb', line 277

def self.get_column_name(col_or_sym)
  case col_or_sym
  when String, Symbol
    col_or_sym
  else
    col_or_sym.name
  end
end

+ (Object) human_const_name(_module, const)

Human name for 'const' in namespace of the '_module'.

I18n fallbacks is as follows (Question::Priority::HIGH as example):

  1. t('activerecord.enums.question/priority.HIGH')

  2. t('high')

  3. 'High'



150
151
152
153
154
# File 'lib/core_ext/active_record.rb', line 150

def self.human_const_name(_module, const)
  lower = const.downcase
  I18n.t("activerecord.enums.#{_module.name.underscore}.#{const}",
         :default => I18n.t(lower, :default=>lower.to_s.humanize))
end

+ (Object) human_name

Fallback is as follows (Author model is an example):

  1. t('activerecord.author')

  2. t('author')

  3. human()



11
12
13
14
15
16
17
# File 'lib/core_ext/active_record.rb', line 11

def self.human_name
  name = self.model_name
  I18n.t(name.underscore,
      scope:    :activerecord,
      default:  I18n.t(name.underscore,
          default: name.human))
end

+ (Object) view_columns

define model-wide default columns selection on view.

If you need to customize at model, overwrite it at derived model class. Example:

def self.view_columns
  %w(id name email updated_at)
end

SEE ALSO

view_list_columns

define list columns

view_popup_columns

define popup columns

view_form_columns

define form columns

view_search_form_columns

define search form columns

DESIGN ISSUE

view_* methods might have to be in view. However, helper method is static so it is not possible to provide default method and overwriting on demand. This is the reason why view_* is here so far.



71
72
73
# File 'lib/core_ext/active_record.rb', line 71

def self.view_columns
  columns.map{|c| c.name}
end

+ (Object) view_form_columns

This defines form columns. You can overwrite this method at each model if it is different from view_columns. Default is calling view_columns().

SEE ALSO

view_columns

define default columns

view_list_columns

define list columns

view_popup_columns

define popup columns

view_search_form_columns

define search form columns



113
114
115
# File 'lib/core_ext/active_record.rb', line 113

def self.view_form_columns
  view_columns
end

+ (Object) view_list_columns

This defines list columns. You can overwrite this method at each model if it is different from view_columns. Default is calling view_columns().

SEE ALSO

view_columns

define default columns

view_popup_columns

define popup columns

view_form_columns

define form columns

view_search_form_columns

define search form columns



85
86
87
# File 'lib/core_ext/active_record.rb', line 85

def self.view_list_columns
  view_columns
end

+ (Object) view_popup_columns

This defines popup list columns. You can overwrite this method at each model if it is different from view_columns. Default is calling view_columns().

SEE ALSO

view_columns

define default columns

view_list_columns

define list columns

view_form_columns

define form columns

view_search_form_columns

define search form columns



99
100
101
# File 'lib/core_ext/active_record.rb', line 99

def self.view_popup_columns
  view_columns
end

+ (Object) view_search_form_columns

This defines search-form columns. You can overwrite this method at each model if it is different from view_columns. Default is calling view_columns().

SEE ALSO

view_columns

define default columns

view_list_columns

define list columns

view_popup_columns

define popup columns

view_form_columns

define form columns



127
128
129
# File 'lib/core_ext/active_record.rb', line 127

def self.view_search_form_columns
  view_columns
end

Instance Method Details

- (Object) belongs_to_AR(column)

return AR object which the column belongs to. return nil if the column is not 'belongs_to'



133
134
135
136
137
138
139
140
# File 'lib/core_ext/active_record.rb', line 133

def belongs_to_AR(column)
  for parent_assoc in self.class.reflect_on_all_associations(:belongs_to) do
    if parent_assoc.foreign_key == column.name
      return self.send(parent_assoc.name)
    end
  end
  nil
end

- (Object) err_on(attr, message_key)

short-cut of:

errors.add(attr, I18n.t(message_key, :scope=>'activerecord.errors.messages')


158
159
160
161
162
# File 'lib/core_ext/active_record.rb', line 158

def err_on(attr, message_key)
  errors.add(
      attr,
      I18n.t(message_key, :scope=>'activerecord.errors.messages'))
end

- (Object) upsert_files(file_info_params, model_params)

insert/update uploaded file

A B C
- - -
n n n   do nothing
n n y   n/a
n y *   1) FileInfo.new & set file_NN the id
y n n   2) delete file_info, update file_NN = null
y n y   do nothing
y y *   3) update file_info by C

Where,

A

file exist (rec.file_NN has value?)

B

params[:file_NN] (or file_info_params)

C

params[:file_NN] (or model_params)

FIXME: what happens when file_NN is required field and value is nil??

INPUTS

model_params

model specific hash values

file_info_params

uploaded file parameters

RESULT

filtered_params

SEE ALSO

edgar_file()

model API to declare file upload/download columns

draw_file()

helper for file field



327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
# File 'lib/core_ext/active_record.rb', line 327

def upsert_files(file_info_params, model_params)
  if file_info_params
    for file_col in file_info_params.keys do
      file_info = nil
      if file_info_id = self.send(file_col)
        # 3) update file_info by C
        file_info = FileInfo.safe_find(file_info_id)
        if file_info
          file_info.uploaded_data = file_info_params[file_col][:uploaded_data]
          file_info.save!
        end
        # FIXME: need to update updated_at even in this case
      else
        # 1) FileInfo.create & set file_NN the id
        file_info = FileInfo.create!(file_info_params[file_col])
        update_attribute(file_col, file_info.id)  # assume file_NN is protected
      end
    end
  end

  # 2) delete file_info, update file_NN = null
  if model_params
    for col in model_params.keys do
      if self.class.edgar_file?(col) &&
         (file_info_params.blank? || file_info_params[col].blank?) &&
         model_params[col].blank?

        file_info = FileInfo.safe_find(self.send(col))
        file_info.destroy if file_info
        update_attribute(col, nil)
      end
    end
  end
  
  # otherwise -> do nothing
end