Update multiple records in the BD, 1 time per record in Rails

1

I have a code that is updating user registries in a DB, but it is updating the registration of each user the number of times there are users in the database, eg. I have 3 users = > medic1, medic2, medic4 in the SQL you can see that it is updating them 3 times when it should be 1 time per record.

What my code should do is extract from the DB the users with the nested attribute period_end_date and save them in a hash, which will query the Openpay API about the status of the subscription; in the response_hash I receive the data of each user and depending on the 'status' I update the values in the database with the results of the response_hash, this should be per user. I can not see what I'm doing wrong, can you help me achieve it?

Here is the code:

namespace :premium_users do
  desc 'Get the user id & data in a hash'
  task get_users: :environment do 
    users = Medic.includes(:payment_methods).where.not payment_methods: { period_end_date: nil }
    request_hash = {}

    users.each do |user|
      period_end_date = user.payment_methods.last.period_end_date

      if Date.today - period_end_date <= 172_800
        openpay_customer_id = user.payment_methods.last.openpay_customer_id
        openpay_subscription_id = user.payment_methods.last.openpay_subscription_id
        medic_id = user.payment_methods.last.medic_id
        user_hash = {}
        user_hash[medic_id] = [openpay_customer_id, openpay_subscription_id]
      else
        user_hash = {}
      end

      request_hash.merge!(user_hash) # If no users is empty => {}

      if request_hash.empty?
       puts 'No User to check!'
      else
        request_hash.each_value do |value|
          openpay_customer_id = value[0]
          openpay_subscription_id = value[1]

          @openpay = OpenpayApi.new(ENV['MERCHANT_ID_OPENPAY'], ENV['SECRET_KEY_OPENPAY'])
          @subscriptions = @openpay.create(:subscriptions)
          response_hash = @subscriptions.get(openpay_subscription_id, openpay_customer_id)

          @charge_date, @creation_date, @current_period_number, @period_end_date, @status, @trial_end_date = response_hash.values_at('charge_date', 'creation_date', 'current_period_number', 'period_end_date', 'status', 'trial_end_date')

          case @status
          when 'past_due'
            @premium = false
            @cancelled = Time.now
          when 'unpaid'
            @premium = false
            @cancelled = Time.now
          when 'cancelled'
            @premium = false
            @cancelled = Time.now
          else
            @premium = true
            @cancelled = nil
          end

        end

        @payment_method = PaymentMethod.update(
          premium: @premium,
          charge_date: @charge_date,
          creation_date: @creation_date,
          current_period_number: @current_period_number,
          period_end_date: @period_end_date,
          status: @status,
          trial_end_date: @trial_end_date,
          cancelled_on: @cancelled
        )

        puts "User #{user.email} update, Complete!"

      end
    end
  end
end

My models:

class Medic < ApplicationRecord
  has_many :payment_methods, dependent: :destroy
end

class PaymentMethod < ApplicationRecord
  belongs_to :medic, optional: true 
end

Rake result premium_users: get_users:

SQL (0.5ms) SELECT medics . id AS t0_r0, medics . email AS t0_r1, medics . encrypted_password AS t0_r2, medics . reset_password_token AS t0_r3, medics . reset_password_sent_at AS t0_r4, medics . remember_created_at AS t0_r5, medics . sign_in_count AS t0_r6, medics . current_sign_in_at AS t0_r7, medics . last_sign_in_at AS t0_r8, medics . current_sign_in_ip AS t0_r9, medics . last_sign_in_ip AS t0_r10, medics . created_at AS t0_r11, medics . updated_at AS t0_r12, medics . full_name AS t0_r13, medics . clinic_name AS t0_r14, medics . clinic_address AS t0_r15, medics . medic_specialty AS t0_r16, medics . contact_phone AS t0_r17, medics . emergency_contact_phone AS t0_r18, medics . professional_licence AS t0_r19, medics . customer_service_hours AS t0_r20, medics . confirmation_token AS t0_r21, medics . confirmed_at AS t0_r22, medics . confirmation_sent_at AS t0_r23, medics . failed_attempts AS t0_r24, medics . unlock_token AS t0_r25, medics . locked_at AS t0_r26, payment_methods . id AS t1_r0, payment_methods . premium AS t1_r1, payment_methods . cancel_at_period_end AS t1_r2, payment_methods . charge_date AS t1_r3, payment_methods . creation_date AS t1_r4, payment_methods . current_period_number AS t1_r5, payment_methods . period_end_date AS t1_r6, payment_methods . status AS t1_r7, payment_methods . trial_end_date AS t1_r8, payment_methods . openpay_subscription_id AS t 1_r9, payment_methods . openpay_customer_id AS t1_r10, payment_methods . cancelled_on AS t1_r11, payment_methods . medic_id AS t1_r12, payment_methods . created_at AS t1_r13, payment_methods . updated_at AS t1_r14 FROM medics LEFT OUTER JOIN payment_methods ON payment_methods . medic_id = medics . id WHERE ( payment_methods . period_end_date IS NOT NULL)   PaymentMethod Load (0.4ms) SELECT payment_methods . * FROM payment_methods        (0.1ms) BEGIN

  SQL (0.3ms)  UPDATE 'payment_methods' SET 'creation_date' = '2018-06-15 19:15:13', 'updated_at' = '2018-06-15 21:01:19' WHERE 'payment_methods'.'id' = 1
   (11.9ms)  COMMIT
   (0.1ms)  BEGIN

  SQL (0.3ms)  UPDATE 'payment_methods' SET 'creation_date' = '2018-06-15 19:15:13', 'updated_at' = '2018-06-15 21:01:19' WHERE 'payment_methods'.'id' = 2
   (2.7ms)  COMMIT
   (0.1ms)  BEGIN

  SQL (0.2ms)  UPDATE 'payment_methods' SET 'creation_date' = '2018-06-15 19:15:13', 'updated_at' = '2018-06-15 21:01:19' WHERE 'payment_methods'.'id' = 3
   (2.6ms)  COMMIT
User [email protected] update, Complete!

  PaymentMethod Load (0.3ms)  SELECT 'payment_methods'.* FROM 'payment_methods'
   (0.1ms)  BEGIN

  SQL (0.3ms)  UPDATE 'payment_methods' SET 'creation_date' = '2018-06-15 19:16:24', 'updated_at' = '2018-06-15 21:01:20' WHERE 'payment_methods'.'id' = 1
   (11.9ms)  COMMIT
   (0.1ms)  BEGIN

  SQL (0.3ms)  UPDATE 'payment_methods' SET 'creation_date' = '2018-06-15 19:16:24', 'updated_at' = '2018-06-15 21:01:20' WHERE 'payment_methods'.'id' = 2
   (2.7ms)  COMMIT
   (0.1ms)  BEGIN

  SQL (0.3ms)  UPDATE 'payment_methods' SET 'creation_date' = '2018-06-15 19:16:24', 'updated_at' = '2018-06-15 21:01:20' WHERE 'payment_methods'.'id' = 3
   (2.5ms)  COMMIT
User [email protected] update, Complete!

  PaymentMethod Load (0.3ms)  SELECT 'payment_methods'.* FROM 'payment_methods'
   (0.1ms)  BEGIN

  SQL (0.2ms)  UPDATE 'payment_methods' SET 'creation_date' = '2018-06-15 19:18:30', 'updated_at' = '2018-06-15 21:01:22' WHERE 'payment_methods'.'id' = 1
   (2.6ms)  COMMIT
   (0.1ms)  BEGIN

  SQL (0.2ms)  UPDATE 'payment_methods' SET 'creation_date' = '2018-06-15 19:18:30', 'updated_at' = '2018-06-15 21:01:22' WHERE 'payment_methods'.'id' = 2
   (2.6ms)  COMMIT
   (0.1ms)  BEGIN

  SQL (0.3ms)  UPDATE 'payment_methods' SET 'creation_date' = '2018-06-15 19:18:30', 'updated_at' = '2018-06-15 21:01:22' WHERE 'payment_methods'.'id' = 3
   (2.6ms)  COMMIT
User [email protected] update, Complete!
    
asked by Carlos Gómez 19.06.2018 в 19:04
source

1 answer

0

Without having gone into the logic of your code, I think you should be using user.payment_methods.update instead of PaymentMethod.update .
The latter updates all the records in the payment_methods table with the values that you are passing in each iteration. I "assume" that you should only update the payment methods that the doctor has for the current iteration and not the entire table.

    
answered by 20.06.2018 / 19:09
source