Class: StrsubcatRuntimeTables

Inherits:
Object
  • Object
show all
Defined in:
lib/c80_yax/strsubcat_runtime_tables.rb

Overview

В задачи класса входят:

* создавать
* уничтожать
* заполнять
* обновлять записи

таблиц вида `c80_yax_strcat_#{NN}_items".

Class Method Summary collapse

Class Method Details

.check_and_clean_item_props(strsubcat) ⇒ Object

удаляем из таблицы item_props те строки, у которых strsubcat_id == ID и чьё prop_name_id входит в список свойств LIST вызывается только в методе StrsubcatSweeper.after_update



324
325
326
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
363
364
365
366
367
368
369
370
371
372
373
# File 'lib/c80_yax/strsubcat_runtime_tables.rb', line 324

def self.check_and_clean_item_props(strsubcat) # strh_check_and_clean_item_props
  list = strsubcat.get_list_removed_props

  if list.count > 0
    Rails.logger.debug '[TRACE] <StrsubcatRuntimeTables.check_and_clean_item_props> Чистим item_props.'
    # 1.1. Сначала составим список свойств, которые надо удалить.

    sql = "
    SELECT
      `c80_yax_item_props`.`id`,
      `c80_yax_item_props`.`prop_name_id`,
      `c80_yax_prop_names`.`title` AS prop_name_title,
      `c80_yax_item_props`.`value`,
      `c80_yax_items`.`id` AS item_id,
      `c80_yax_items`.`title` as item_title,
      `c80_yax_items`.`is_main`,
      `c80_yax_items`.`is_hit`,
      `c80_yax_items`.`is_sale`,
      `c80_yax_strsubcats`.`id` AS strsubcat_id,
      `c80_yax_strsubcats`.`slug` AS strsubcat_slug
    FROM `c80_yax_items`
      INNER JOIN `c80_yax_strsubcats` ON `c80_yax_strsubcats`.`id` = `c80_yax_items`.`strsubcat_id`
      LEFT JOIN `c80_yax_item_props` ON `c80_yax_item_props`.`item_id` = `c80_yax_items`.`id`
      LEFT JOIN `c80_yax_prop_names` ON `c80_yax_prop_names`.`id` = `c80_yax_item_props`.`prop_name_id`
    WHERE `c80_yax_strsubcats`.`id` = #{ strsubcat.id }
    AND `prop_name_id` IN (#{ list.join(',')})
  "

    records = ActiveRecord::Base.connection.execute(sql)

    # 1.2. Составим список айдишников свойств для удаления
    item_props_ids = []
    records.each do |row|
      item_props_ids << row[0]
    end

    # 2. Теперь на основе списка свойств, которые надо удалить, составим запрос, который удалит эти свойства.
    if item_props_ids.count > 0
      sql = "
    DELETE FROM `c80_yax_item_props`
    WHERE `id` IN (#{ item_props_ids.join(',') })
  "

      ActiveRecord::Base.connection.execute(sql)
    end

    Rails.logger.debug '[TRACE] <StrsubcatRuntimeTables.check_and_clean_item_props> END'
  end

end

.item_drop(strsubcat_id, item_id) ⇒ Object

из таблицы типа strcat_111_items удалить строку, описывающую вещь item_id



376
377
378
379
380
381
382
383
384
385
386
387
# File 'lib/c80_yax/strsubcat_runtime_tables.rb', line 376

def self.item_drop(strsubcat_id, item_id) # strh_item_drop
  runtime_table_name = "c80_yax_strcat_#{strsubcat_id}_items"
  Rails.logger.debug "[TRACE] <StrsubcatRuntimeTables.item_drop> Удаляем вещь id = #{item_id} из таблицы `#{runtime_table_name}`."
  if ActiveRecord::Base.connection.table_exists?(runtime_table_name)
    sql = "
    DELETE FROM #{runtime_table_name}
    WHERE item_id = #{item_id}
    "

    ActiveRecord::Base.connection.execute(sql)
  end
end

.item_update(strsubcat_id, item_id) ⇒ Object

в таблице типа strcat_111_items обновить поля строки, описывающую вещь item_id



390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
# File 'lib/c80_yax/strsubcat_runtime_tables.rb', line 390

def self.item_update(strsubcat_id,item_id) # strh_item_update
  runtime_table_name = "c80_yax_strcat_#{strsubcat_id}_items"
  Rails.logger.debug "[TRACE] <StrsubcatRuntimeTables.item_update> В таблице `#{runtime_table_name}` обновим данные о товаре id = #{item_id}."

  # <editor-fold desc="# сначала соберём все свойства вещи">
  # NOTE:: [columns] эти столбцы должны соответствовать (запрос при обновлении предмета)
  sql = "
        SELECT
          `c80_yax_item_props`.`prop_name_id`,
          `c80_yax_prop_names`.`title` AS prop_name_title,
          `c80_yax_item_props`.`value`,
          `c80_yax_items`.`id` AS item_id,
          `c80_yax_items`.`title` as item_title,
          `c80_yax_items`.`is_main`,
          `c80_yax_items`.`is_hit`,
          `c80_yax_items`.`is_sale`,
          `c80_yax_strsubcats`.`id` AS strsubcat_id,
          `c80_yax_strsubcats`.`slug` AS strsubcat_slug,
          `c80_yax_vendors`.`id` as vendor_id,
          `c80_yax_vendors`.`title` as vendor_title,
          `c80_yax_items`.`full_desc`,
          `c80_yax_items`.`image`,
          `c80_yax_items`.`is_ask_price`,
          `c80_yax_items`.`is_gift`,
          `c80_yax_items`.`is_starting`,
          `c80_yax_items`.`is_available`
        FROM `c80_yax_items`
          INNER JOIN `c80_yax_strsubcats` ON `c80_yax_strsubcats`.`id` = `c80_yax_items`.`strsubcat_id`
          LEFT JOIN `c80_yax_item_props` ON `c80_yax_item_props`.`item_id` = `c80_yax_items`.`id`
          LEFT JOIN `c80_yax_prop_names` ON `c80_yax_prop_names`.`id` = `c80_yax_item_props`.`prop_name_id`
          LEFT JOIN `c80_yax_items_vendors` ON `c80_yax_items_vendors`.`item_id` = `c80_yax_items`.`id`
          LEFT JOIN `c80_yax_vendors` ON `c80_yax_vendors`.`id` = `c80_yax_items_vendors`.`vendor_id`
        WHERE (`c80_yax_strsubcats`.`id` = #{strsubcat_id})
        AND `c80_yax_items`.`id` = #{item_id};
  "
  records = ActiveRecord::Base.connection.execute(sql)
  # </editor-fold>

  # составим SQL команду
  hash_sql = self.hash_sql_make(records, strsubcat_id)

  #-> удалим старую строку
  sql = "DELETE FROM `#{runtime_table_name}` WHERE item_id = #{item_id}"
  ActiveRecord::Base.connection.execute(sql)

  #-> выполним SQL команду : вставим строку с обновлёнными значениями
  self.hash_sql_execute(hash_sql)

  Rails.logger.debug '[TRACE] <StrsubcatRuntimeTables.strh_item_update> END'
end

.table_check_and_build(strsubcat) ⇒ Object

создаёт таблицу под все вещи подкатегории, если такой таблицы нету в базе



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
# File 'lib/c80_yax/strsubcat_runtime_tables.rb', line 201

def self.table_check_and_build(strsubcat) # strh_table_check_and_build

  # по-умолчанию в результате исполнения метода - таблицу создавать не надо
  # noinspection RubyUnusedLocalVariable
  mark_create_table = false

  runtime_table_name = "c80_yax_strcat_#{strsubcat.id}_items"

  # <editor-fold desc="# Сначала составим список айдишников всех свойств, присущих данной категории">
  # выбрать из базы айдишники всех свойств, присущих данной категории
  # по сути дела, тоже самое, что и strsubcat.prop_names
  sql = "
      SELECT `c80_yax_prop_names`.`id`
      FROM `c80_yax_prop_names`
      INNER JOIN `c80_yax_prop_names_strsubcats` ON `c80_yax_prop_names`.`id` = `c80_yax_prop_names_strsubcats`.`prop_name_id`
      WHERE `c80_yax_prop_names_strsubcats`.`strsubcat_id` = #{strsubcat.id}
  "
  records = ActiveRecord::Base.connection.execute(sql)

  propnames_ids = []
  records.each do |r|
    propnames_ids << r[0].to_i
  end
  # </editor-fold>

  # Теперь определимся, нужно ли дропнуть и создать таблицу
  if ActiveRecord::Base.connection.table_exists? runtime_table_name
    Rails.logger.debug "[TRACE] <StrsubcatRuntimeTables.table_check_and_build> Таблица уже существует: #{runtime_table_name}"

    # <editor-fold desc="# совпадают ли столбцы runtime таблицы и свойства?">
    # проверим, совпадают ли столбцы свойств в runtime таблице со списком свойств, присущих данной категории:
    # если какого-то свойства нет в столбцах - дропнем таблицу и создадим её заново
    # если есть лишний столбец в таблице - дропнем таблицу и создадим её заново
    Rails.logger.debug '[TRACE] <StrsubcatRuntimeTables.table_check_and_build> Проверим соответствие столбцов свойствам.'

    # получим список столбцов и извлечём из него айдишники свойств в массив +actual_props_ids+
    sql_describe = "DESCRIBE #{runtime_table_name}"
    records = ActiveRecord::Base.connection.execute(sql_describe)
    actual_props_ids = []
    records.each do |row|
      actual_props_ids << row[0][/\d+/].to_i if row[0]['prop_']
    end

    mark_create_table = actual_props_ids.sort != propnames_ids.sort
    Rails.logger.debug "[TRACE] <StrsubcatRuntimeTables.table_check_and_build> Сравним propnames_ids = #{propnames_ids} и actual_props_ids = #{actual_props_ids}."
    Rails.logger.debug "[TRACE] <StrsubcatRuntimeTables.table_check_and_build> mark_create_table = #{mark_create_table}."
    # </editor-fold>

    # если не совпадают - дропнем таблицу
    if mark_create_table
      self.table_drop(strsubcat)
    end

  else
    Rails.logger.debug "[TRACE] <check_and_build_table> Таблица не существует, создаём: #{runtime_table_name}"
    mark_create_table = true
  end

  # Если таблицу надо создать - создаём
  if mark_create_table
    self.table_create(runtime_table_name, propnames_ids)
  end

end

.table_create(runtime_table_name, propnames_ids) ⇒ Object

враппер метода ActiveRecord::Migration.create_table создаёт таблицу с именем strcat_#strsubcat_id_items со столбцами, описанными в массиве props_names_list (имя столбца вида prop_#item)



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
301
302
303
304
305
306
307
308
309
310
# File 'lib/c80_yax/strsubcat_runtime_tables.rb', line 269

def self.table_create(runtime_table_name, propnames_ids) # strh_table_create
  Rails.logger.debug "[TRACE] <StrsubcatRuntimeTables.table_create> BEGIN. propnames_ids = #{propnames_ids}"

  ActiveRecord::Migration.create_table(runtime_table_name, :options => 'COLLATE=utf8_unicode_ci') do |t|

    # NOTE:: [columns] эти столбцы должны соответствовать (создание новой таблицы)

    t.integer :item_id
    t.string :item_title
    t.boolean :is_main
    t.boolean :is_hit
    t.boolean :is_sale
    t.integer :strsubcat_id
    t.string :strsubcat_slug
    t.integer :vendor_id
    t.text :full_desc
    t.string :image
    t.boolean :is_ask_price
    t.boolean :is_gift
    t.boolean :is_starting
    t.boolean :is_available

    t.index :item_id, unique: true

    # т.к. сортировка средствами SQL (ORDER BY) нам
    # нужна только для цен, то только столбцы для
    # цен делаем числами. Остальное - храним, как строки.
    propnames_ids.each do |prop_name_id|
      is_decimal_column = C80Yax::PropName.find(prop_name_id).is_normal_price
      if is_decimal_column
        t.decimal "prop_#{prop_name_id}", :precision => 8, :scale => 2
      else
        t.string "prop_#{prop_name_id}"
      end

    end

  end

  Rails.logger.debug '[TRACE] <StrsubcatRuntimeTables.table_create> END'

end

.table_drop(strsubcat) ⇒ Object

strh_table_drop



312
313
314
315
316
317
318
319
# File 'lib/c80_yax/strsubcat_runtime_tables.rb', line 312

def self.table_drop(strsubcat) # strh_table_drop
  runtime_table_name = "c80_yax_strcat_#{strsubcat.id}_items"
  if ActiveRecord::Base.connection.table_exists?(runtime_table_name)
    Rails.logger.debug "[TRACE] <StrsubcatRuntimeTables.table_drop> Удаляем таблицу: table_name = #{runtime_table_name}"
    ActiveRecord::Migration.drop_table(runtime_table_name)
    Rails.logger.debug '[TRACE] <StrsubcatRuntimeTables.table_drop> END'
  end
end

.table_fill(strsubcat_id) ⇒ Object

strh_table_fill



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/c80_yax/strsubcat_runtime_tables.rb', line 12

def self.table_fill(strsubcat_id) # strh_table_fill

  # NOTE:: [columns] эти столбцы должны соответствовать (комментарий как wiki)

  # [0] item_props.prop_name_id,
  # [1] prop_names.title AS prop_name_title,
  # [2] item_props.value,
  # [3] items.id AS item_id,
  # [4] items.title as item_title,
  # [5] items.is_main,
  # [6] items.is_hit,
  # [7] items.is_sale,
  # [8] strsubcats.id AS strsubcat_id,
  # [9] strsubcats.slug AS strsubcat_slug
  # [10] vendors.id as vendor_id
  # [11] vendors.title as vendor_title - дублирующий столбец: чтобы не совершать
  #                                      лишних запросов за vendor.title в методе hash_sql_make
  # [12] items.full_desc
  # [13] items.image
  # [14] items.is_ask_price
  # [15] `c80_yax_items`.`is_gift`,
  # [16] `c80_yax_items`.`is_starting`,
  # [17] `c80_yax_items`.`is_available`
  # выбираем свойства предметов вместе с инфой о предметах, которым они принадлежат

  # <editor-fold desc="# составляем и выполняем sql запрос">

  # NOTE:: [columns] эти столбцы должны соответствовать (запрос при заполнении таблицы)

  sql = "
        SELECT
          `c80_yax_item_props`.`prop_name_id`,
          `c80_yax_prop_names`.`title` AS prop_name_title,
          `c80_yax_item_props`.`value`,
          `c80_yax_items`.`id`         AS item_id,
          `c80_yax_items`.`title`      AS item_title,
          `c80_yax_items`.`is_main`,
          `c80_yax_items`.`is_hit`,
          `c80_yax_items`.`is_sale`,
          `c80_yax_strsubcats`.`id`    AS strsubcat_id,
          `c80_yax_strsubcats`.`slug`  AS strsubcat_slug,
          `c80_yax_vendors`.`id`       AS vendor_id,
          `c80_yax_vendors`.`title`    AS vendor_title,
          `c80_yax_items`.`full_desc`,
          `c80_yax_items`.`image`,
          `c80_yax_items`.`is_ask_price`,
          `c80_yax_items`.`is_gift`,
          `c80_yax_items`.`is_starting`,
          `c80_yax_items`.`is_available`
        FROM `c80_yax_items`
          INNER JOIN `c80_yax_strsubcats` ON `c80_yax_strsubcats`.`id` = `c80_yax_items`.`strsubcat_id`
          LEFT JOIN `c80_yax_item_props` ON `c80_yax_item_props`.`item_id` = `c80_yax_items`.`id`
          LEFT JOIN `c80_yax_prop_names` ON `c80_yax_prop_names`.`id` = `c80_yax_item_props`.`prop_name_id`
          LEFT JOIN `c80_yax_items_vendors` ON `c80_yax_items_vendors`.`item_id` = `c80_yax_items`.`id`
          LEFT JOIN `c80_yax_vendors` ON `c80_yax_vendors`.`id` = `c80_yax_items_vendors`.`vendor_id`
        WHERE (`c80_yax_strsubcats`.`id` = #{strsubcat_id})
  "
    records = ActiveRecord::Base.connection.execute(sql)
    records
  # </editor-fold>

  # 1. заполняем хэш объектами для составления sql-команд INSERT
  hash_sql = self.hash_sql_make(records, strsubcat_id)

  Rails.logger.debug '[TRACE] <StrsubcatRuntimeTables.table_fill> Начинаем заполнять таблицу:'
  self.hash_sql_execute(hash_sql)
  Rails.logger.debug '[TRACE] <StrsubcatRuntimeTables.table_fill> END'

end