Обновите значение хеша в итераторе, и все значения будут последней итерацией в рельсах - PullRequest
0 голосов
/ 05 апреля 2019

Я попытался использовать итератор для обновления значения в хэше, так как хэш, который я создал:

@period = Date.new(2019,3,1)..Date.new(2019,3,31)

@deals = Deal.includes(:staff).where(shop_id:1, created_at:@period).group_by{|t| t.staff}

data = {}
 staff_id_container = {
  total:{item1: 0, item2: 0, item3: 0}
 }

 Staff.where(shop_id: 1).select(:id).each do |staff|
  staff_id_container[staff.id] = {item1:0, item2:0, item3:0}
 end

 @period.each do |date|
  data[date] = staff_id_container.dup
 end

, и существует три способа обновить двухслойную структуру гнезда:

1.Замена значения непосредственно

@deals.each do |staff, deals_by_staff|
  deals_by_staff.group_by{|t| t.created_at.to_date}.each do |date, selected_deals|
   data[date][staff.id] = {
    item1: select_deals.select{|deal| deal.item == "item1"}.count
    item2: select_deals.select{|deal| deal.item == "item2"}.count
    item3: select_deals.select{|deal| deal.item == "item3"}.count
   }
  end
 end

2. Использование слияния

@deals.each do |staff, deals_by_staff|
  deals_by_staff.group_by{|t| t.created_at.to_date}.each do |date, selected_deals|
   data[date][staff.id].merge!({
    item1: select_deals.select{|deal| deal.item == "item1"}.count
    item2: select_deals.select{|deal| deal.item == "item2"}.count
    item3: select_deals.select{|deal| deal.item == "item3"}.count
   })
  end
 end

3. Использование "=" для объявления

@deals.each do |staff, deals_by_staff|
  deals_by_staff.group_by{|t| t.created_at.to_date}.each do |date, selected_deals|
    data[date][staff.id][:item1] = select_deals.select{|deal| deal.item == "item1"}.count
    data[date][staff.id][:item2] = select_deals.select{|deal| deal.item == "item2"}.count
    data[date][staff.id][:item3] = select_deals.select{|deal| deal.item == "item3"}.count
  end
 end

первый способ работает, но еслиначальное значение data[date][staff.id] равно {item1: 0,item2: 0,item3: 0, item4: 0}, а item4 будет перезаписано.

Второй и третий способ возвращают неверное значение, они оба позволяют каждому значению каждой даты стать дубликатом последней даты.

как показано выше:

{
 2019-03-01:{
  staff_1:{item1: 0, item2: 3, item3: 1, item4: 5},
  staff_2:{item1: 1, item2: 4, item3: 2, item4: 7},
 },
 2019-03-02:{
  staff_1:{item1: 0, item2: 3, item3: 1, item4: 5},
  staff_2:{item1: 1, item2: 4, item3: 2, item4: 7},
 }
} 

Если я просто хочу изменить один ключ data[date][staff_id], например data[date][staff_id][:item1], или добавить новый ключ в data[date][staff_id], мне нужно использовать способвторой или третий.

в чем проблема пути второго и третьего?

Ответы [ 2 ]

0 голосов
/ 13 апреля 2019

В следующем порядке:

@deals.each do |staff, deals_by_staff|
  deals_by_staff.group_by{|t| t.created_at.to_date}.each do |date, selected_deals|
   data[date][staff.id] = {
    item1: select_deals.select{|deal| deal.item == "item1"}.count
    item2: select_deals.select{|deal| deal.item == "item2"}.count
    item3: select_deals.select{|deal| deal.item == "item3"}.count
   }
  end
 end

Если вы хотите добавить или изменить значение в глубоком хеше, я рекомендую этот способ:

@deals.each do |staff, deals_by_staff|
  deals_by_staff.group_by{|t| t.created_at.to_date}.each do |date, selected_deals|
   temp = data[date][staff.id].dup
   temp[:item4] = selected_deals.select{|deal| deal.item == "item4"}.count
   data[date][staff.id] = temp
  end
 end
0 голосов
/ 05 апреля 2019

Попробуйте заменить dup на deep_dup при построении таких данных, как

data[date] = staff_id_container.deep_dup

https://apidock.com/rails/Hash/deep_dup

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...