Class: Engine2::TypeInfo

Inherits:
Object show all
Defined in:
lib/engine2/type_info.rb

Instance Method Summary collapse

Constructor Details

#initialize(model) ⇒ TypeInfo

Returns a new instance of TypeInfo.



6
7
8
9
# File 'lib/engine2/type_info.rb', line 6

def initialize model
    @model = model
    @info = model.type_info
end

Instance Method Details

#any_field(field) ⇒ Object



47
48
49
50
# File 'lib/engine2/type_info.rb', line 47

def any_field field
    define_field field, :any do |info|
    end
end

#blob_field(field, length) ⇒ Object



59
60
61
62
63
# File 'lib/engine2/type_info.rb', line 59

def blob_field field, length
    define_field field, :blob do |info|
        info[:length] = length
    end
end

#blob_store_field(name, name_field, mime_field) ⇒ Object



277
278
279
280
281
282
283
284
285
# File 'lib/engine2/type_info.rb', line 277

def blob_store_field name, name_field, mime_field
    optional name
    define_field :"#{name}_blob", :blob_store do |info|
        info[:bytes_field] = name
        info[:name_field] = name_field
        info[:mime_field] = mime_field
        info[:transaction] = true
    end
end

#boolean(field, true_value = true, false_value = false) ⇒ Object



76
77
78
79
80
81
82
83
# File 'lib/engine2/type_info.rb', line 76

def boolean field, true_value = true, false_value = false
    modify_field field do |info|
        info[:type] = :boolean
        info[:true_value] = true_value
        info[:false_value] = false_value
        info[:validations][:boolean] = true
    end
end

#boolean_field(field) ⇒ Object



71
72
73
74
# File 'lib/engine2/type_info.rb', line 71

def boolean_field field
    define_field field, :boolean do |info|
    end
end

#currency(field, symbol = ) ⇒ Object



269
270
271
272
273
274
275
# File 'lib/engine2/type_info.rb', line 269

def currency field, symbol = LOCS[:currency_symbol]
    modify_field field do |info|
        info[:type] = :currency
        info[:symbol] = symbol
        info[:validations][:currency] = true
    end
end

#date_field(field, format, model_format) ⇒ Object



85
86
87
88
89
90
91
# File 'lib/engine2/type_info.rb', line 85

def date_field field, format, model_format
    define_field field, :date do |info|
        info[:format] = format
        info[:model_format] = model_format
        info[:validations][:date] = true
    end
end

#date_range(from, to) ⇒ Object



252
253
254
255
256
257
258
259
# File 'lib/engine2/type_info.rb', line 252

def date_range from, to
    depends_on(from, to)
    modify_field from do |info|
        # info[:type] = :date_range
        info[:other_date] = to
        info[:validations][:date_range] = true
    end
end

#date_time(date, time) ⇒ Object



261
262
263
264
265
266
267
# File 'lib/engine2/type_info.rb', line 261

def date_time date, time
    depends_on(date, time)
    modify_field date do |info|
        info[:other_time] = time
        info[:validations][:date_time] = true
    end
end

#datetime_field(field, date_format, time_format, date_model_format, time_model_format) ⇒ Object



108
109
110
111
112
113
114
115
116
# File 'lib/engine2/type_info.rb', line 108

def datetime_field field, date_format, time_format, date_model_format, time_model_format
    define_field field, :datetime do |info|
        info[:date_format] = date_format
        info[:time_format] = time_format
        info[:date_model_format] = date_model_format
        info[:time_model_format] = time_model_format
        info[:validations][:datetime] = true
    end
end

#decimal_date(field, format = , model_format = "yyyyMMdd") ⇒ Object



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

def decimal_date field, format = LOCS[:default_date_format], model_format = "yyyyMMdd"
    modify_field field do |info|
        info[:type] = :decimal_date
        info[:format] = format
        info[:model_format] = model_format
        info[:validations][:decimal_date] = true
    end
end

#decimal_field(field, size, scale) ⇒ Object



118
119
120
121
122
123
124
125
126
# File 'lib/engine2/type_info.rb', line 118

def decimal_field field, size, scale
    define_field field, :decimal do |info|
        info[:validations][:decimal] = {
            scale: scale,
            size: size,
            regexp: (scale && size) ? /^\d{,#{size - scale}}(?:\.\d{,#{scale}})?$/ : nil
        }
    end
end

#decimal_time(field, format = , model_format = "HHmmss", model_regexp = /^(\d{2})(\d{2})(\d{2})$/) ⇒ Object



142
143
144
145
146
147
148
149
150
# File 'lib/engine2/type_info.rb', line 142

def decimal_time field, format = LOCS[:default_time_format], model_format = "HHmmss", model_regexp = /^(\d{2})(\d{2})(\d{2})$/
    modify_field field do |info|
        info[:type] = :decimal_time
        info[:format] = format
        info[:model_format] = model_format
        info[:model_regexp] = model_regexp
        info[:validations][:decimal_time] = true
    end
end

#decode(name, dinfo = {form: {scaffold: true}, search: {scaffold: true}}) ⇒ Object



350
351
352
353
354
355
356
357
358
# File 'lib/engine2/type_info.rb', line 350

def decode name, dinfo = {form: {scaffold: true}, search: {scaffold: true}}
    modify_field name do |info|
        raise E2Error.new("Field type of '#{name}' in model '#{@model}' needs to be 'many_to_one'") unless info[:type] == :many_to_one
        dec = info[:decode] ||= {}
        dec[:search].clear if dinfo[:search] && dec[:search]
        dec[:form].clear if dinfo[:form] && dec[:form]
        info[:decode].rmerge!(dinfo)
    end
end

#default(field, value) ⇒ Object



152
153
154
155
156
# File 'lib/engine2/type_info.rb', line 152

def default field, value
    modify_field field do |info|
        info[:default] = value
    end
end

#define_field(field, type) {|info| ... } ⇒ Object

Yields:

  • (info)

Raises:



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/engine2/type_info.rb', line 11

def define_field field, type
    info = @info[field]
    raise E2Error.new("Field '#{field}' already defined in model '#{@model}'") if info && info[:type]

    unless info
        @info[field] = info = {dummy: true}
        @model.dummies << field
    end

    info.merge!({
        name: field,
        otype: type,
        type: type,
        validations: {}
    })
    yield info
end

#depends_on(what, *on) ⇒ Object



35
36
37
38
39
# File 'lib/engine2/type_info.rb', line 35

def depends_on what, *on
    modify_field what do |info|
        (info[:depends] ||= []).concat(on)
    end
end

#dont_strip(field) ⇒ Object



177
178
179
180
181
# File 'lib/engine2/type_info.rb', line 177

def dont_strip field
    modify_field field do |info|
        info[:dont_strip] = true
    end
end

#email(field, message = ) ⇒ Object



213
214
215
216
217
218
# File 'lib/engine2/type_info.rb', line 213

def email field, message = LOCS[:invalid_email_format]
    modify_field field do |info|
        info[:type] = :email
    end
    format field, /\w+\@\w+\.\w+/, message
end

#file_store_field(field, multiple = true, table = :files, store = {}) ⇒ Object



226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/engine2/type_info.rb', line 226

def file_store_field field, multiple = true, table = :files, store = {}
    # string_field field, 1000
    any_field field
    modify_field field do |info|
        info[:type] = :file_store
        info[:multiple] = multiple
        info[:table] = table
        info[:store] = store
        info[:store][:upload] ||= "#{Engine2::SETTINGS[:path]}/store/upload"
        info[:store][:files] ||= "#{Engine2::SETTINGS[:path]}/store/files"
        info[:transaction] = true
    end
end

#fix_decimal(field, size, scale) ⇒ Object



189
190
191
192
193
194
195
196
197
# File 'lib/engine2/type_info.rb', line 189

def fix_decimal field, size, scale
    modify_field field do |info|
        info[:validations][:decimal] = {
            scale: scale,
            size: size,
            regexp: /^\d{,#{size - scale}}(?:\.\d{,#{scale}})?$/
        }
    end
end

#foreign_blob_store_field(assoc_name, name, name_field, mime_field) ⇒ Object

Raises:



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

def foreign_blob_store_field assoc_name, name, name_field, mime_field
    assoc = @model.many_to_one_associations[assoc_name]
    raise E2Error.new("'many_to_one' association '#{assoc_name}' not found for model '#{@model}'") unless assoc
    define_field :"#{assoc[:key]}_blob", :foreign_blob_store do |info|
        info[:assoc_name] = assoc_name
        info[:bytes_field] = name
        info[:name_field] = name_field
        info[:mime_field] = mime_field
        info[:transaction] = true
    end
end

#format(field, pattern, message = ) ⇒ Object



240
241
242
243
244
# File 'lib/engine2/type_info.rb', line 240

def format field, pattern, message = LOCS[:invalid_format]
    modify_field field do |info|
        info[:validations][:format] = {pattern: pattern, message: message}
    end
end

#integer_field(field) ⇒ Object



65
66
67
68
69
# File 'lib/engine2/type_info.rb', line 65

def integer_field field
    define_field field, :integer do |info|
        info[:validations][:integer] = true
    end
end

#length(field, len) ⇒ Object



246
247
248
249
250
# File 'lib/engine2/type_info.rb', line 246

def length field, len
    modify_field field do |info|
        info[:length] = len
    end
end

#list_select(name, options) ⇒ Object



326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# File 'lib/engine2/type_info.rb', line 326

def list_select name, options
    modify_field name do |info|
        info[:type] = :list_select
        values = options[:values]

        if options[:multiselect]
            info[:multiselect] = true
            case info[:otype]
            when :string
                info[:separator] = options[:separator] || ';'
                info[:validations].delete(:string_length)
            when :integer
                info[:validations].delete(:integer)
            end
            info[:max_length] = options[:max_length] || 3
            info[:max_length_html] = options[:max_length_html] || LOCS[:list_select_selected]
        end

        raise E2Error.new("type '#{values.class}' not supported for list_select modifier for field #{name}") unless values.is_a?(Hash)
        info[:values] = values.to_a
        info[:validations][:list_select] = true unless values.empty?
    end
end

#list_select_bits(values) ⇒ Object



322
323
324
# File 'lib/engine2/type_info.rb', line 322

def list_select_bits values
    values.each_with_index.map{|a, i|[1 << i, a]}.to_h
end

#many_to_one_field(assoc_name) ⇒ Object

Raises:



299
300
301
302
303
304
305
306
307
308
# File 'lib/engine2/type_info.rb', line 299

def many_to_one_field assoc_name
    assoc = @model.many_to_one_associations[assoc_name]
    raise E2Error.new("'many_to_one' association '#{assoc_name}' not found for model '#{@model}'") unless assoc
    keys = assoc[:keys]
    modify_field keys.first do |info|
        info[:type] = :many_to_one
        info[:keys] = keys
        info[:assoc_name] = assoc_name
    end
end

#modify_field(field) {|info| ... } ⇒ Object

Yields:

  • (info)

Raises:



29
30
31
32
33
# File 'lib/engine2/type_info.rb', line 29

def modify_field field
    info = @info[field]
    raise E2Error.new("No field '#{field}' defined for model '#{@model}'") unless info
    yield info
end

#null_value(field, value) ⇒ Object



41
42
43
44
45
# File 'lib/engine2/type_info.rb', line 41

def null_value field, value
    modify_field field do |info|
        info[:null_value] = value
    end
end

#optional(field) ⇒ Object



166
167
168
169
170
171
# File 'lib/engine2/type_info.rb', line 166

def optional field
    modify_field field do |info|
        info.delete(:required)
        info[:optional] = true
    end
end

#optionals(*fields) ⇒ Object



173
174
175
# File 'lib/engine2/type_info.rb', line 173

def optionals *fields
    fields.each{|f|optional f}
end

#password(field) ⇒ Object



220
221
222
223
224
# File 'lib/engine2/type_info.rb', line 220

def password field
    modify_field field do |info|
        info[:type] = :password
    end
end

#primary_key(field) ⇒ Object



183
184
185
186
187
# File 'lib/engine2/type_info.rb', line 183

def primary_key field
    modify_field field do |info|
        info[:primary_key] = true
    end
end

#required(field, message = , &blk) ⇒ Object



158
159
160
161
162
163
164
# File 'lib/engine2/type_info.rb', line 158

def required field, message = LOCS[:field_required], &blk
    modify_field field do |info|
        raise E2Error.new("Required condition already provided for field #{field} in model #{@model}") if blk && info[:required] && info[:required][:if]
        info[:required] = {message: message}
        info[:required][:if] = blk if blk
    end
end

#sequence(name, seq_name) ⇒ Object



367
368
369
370
371
# File 'lib/engine2/type_info.rb', line 367

def sequence name, seq_name
    modify_field name do |info|
        info[:sequence] = seq_name
    end
end

#star_to_many_field(assoc_name, schemes = Schemes::STMF_LINK) ⇒ Object

Raises:



310
311
312
313
314
315
316
317
318
319
320
# File 'lib/engine2/type_info.rb', line 310

def star_to_many_field assoc_name, schemes = Schemes::STMF_LINK
    assoc = @model.one_to_many_associations[assoc_name] || @model.many_to_many_associations[assoc_name]
    raise E2Error.new("'*_to_many' association '#{assoc_name}' not found for model '#{@model}'") unless assoc
    define_field assoc_name, :string do |info|
        info[:type] = :star_to_many_field
        info[:schemes] = schemes
        info[:keys] = assoc[:keys]
        info[:assoc_name] = assoc_name
        info[:transaction] = true
    end
end

#string_field(field, length) ⇒ Object



52
53
54
55
56
57
# File 'lib/engine2/type_info.rb', line 52

def string_field field, length
    define_field field, :string do |info|
        info[:length] = length
        info[:validations][:string_length] = true
    end
end

#text_field(field) ⇒ Object



128
129
130
131
# File 'lib/engine2/type_info.rb', line 128

def text_field field
    define_field field, :text do |info|
    end
end

#time(field, format, model_format) ⇒ Object



99
100
101
102
103
104
105
106
# File 'lib/engine2/type_info.rb', line 99

def time field, format, model_format
    modify_field field do |info|
        info[:type] = :time
        info[:format] = format
        info[:model_format] = model_format
        info[:validations][:time] = true
    end
end

#time_field(field, format, model_format) ⇒ Object



93
94
95
96
97
# File 'lib/engine2/type_info.rb', line 93

def time_field field, format, model_format
    define_field field, :time do |info|
    end
    time field, format, model_format
end

#unique(field, *with) ⇒ Object

def validation field, name, opts = true

modify_field field do |info|
    info[:validations][name] = opts
end

end



205
206
207
208
209
210
211
# File 'lib/engine2/type_info.rb', line 205

def unique field, *with
    depends_on(field, *with)
    modify_field field do |info|
        info[:transaction] = true
        info[:validations][:unique] = {with: with}
    end
end

#validate(name, validation_name = nil, &blk) ⇒ Object

Raises:



360
361
362
363
364
365
# File 'lib/engine2/type_info.rb', line 360

def validate name, validation_name = nil, &blk
    raise E2Error.new("Local validation '#{validation_name}' in model '#{@model}' conflicts with builtin validation") if validation_name && Validations[validation_name]
    modify_field name do |info|
        info[:validations][validation_name || :"#{@model.table_name}_#{name}_#{info[:validations].size}"] = {lambda: blk}
    end
end