[英]Update multiple records in the DB, one time per record in Rails
I have a code that is updating user records in a DB, but is updating the record of each user, the number of times there are users in the database, example, 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 user. 我有一个代码正在更新数据库中的用户记录,但正在更新每个用户的记录,即数据库中有用户的次数,例如,我在SQL中有3个用户=> medic1,medic2,medic4可以看到它正在对它们进行3次更新,而每个用户应该更新1次。
What my code should do is extract the users with the nested attribute period_end_date from the DB and save them in a hash, which will query the Openpay API about the status of the subscription; 我的代码应该做的是从数据库中提取具有嵌套属性period_end_date的用户,并将其保存在哈希中,该哈希将查询Openpay API的订阅状态; 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.
在响应哈希中,我接收每个用户的数据,并根据“状态”,使用response_hash的结果更新数据库中的值,该值应针对每个用户。 I can not see what I'm doing wrong, can you help me achieve it?
我看不到我在做什么错,您能帮我解决吗?
Here is the code, rake premium_users:get_users (lib/tasks/premium_users.rake): 以下是代码rake premium_users:get_users(lib / tasks / premium_users.rake):
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 = {}
# Get users in a 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 for subscription status to Openpay
request_hash.each_value do |value|
openpay_customer_id = value[0]
openpay_subscription_id = value[1]
# Openpay API connection
@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)
# Extract values from response
@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
# Update user payment record with response from Openpay
@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
The SQL: SQL:
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 medic1@mail.com 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 medic2@mail.com 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 medic4@mail.com update, Complete!
Models: 楷模:
class Medic < ApplicationRecord
has_many :payment_methods, dependent: :destroy
end
class PaymentMethod < ApplicationRecord
belongs_to :medic, optional: true
end
Thanks for your answers, they finally helped me to realize that I have to update each object, so I did it by going through PaymentMethod.where(id: @subscription_id, medic_id: @medic_id).update()
感谢您的回答,他们终于帮助我意识到我必须更新每个对象,因此我通过
PaymentMethod.where(id: @subscription_id, medic_id: @medic_id).update()
做到了这一点。
namespace :premium_users do
desc 'Get the user id & data in a hash'
task get_users: :environment do
# Get the user and association payment_method where period_end_date not nil, means that this user has a payment_method
users = Medic.includes(:payment_methods).where.not payment_methods: { period_end_date: nil }
request_hash = {}
users.each do |user|
# Set to compare period end date with date today
period_end_date = user.payment_methods.last.period_end_date
# Create a user hash if period_end_date is 2 days from date today
if Date.today - period_end_date <= 172_800
medic_id, subscription_id, openpay_customer_id, openpay_subscription_id = user.payment_methods.last.medic_id, user.payment_methods.last.id, user.payment_methods.last.openpay_customer_id, user.payment_methods.last.openpay_subscription_id
user_hash = {}
user_hash[medic_id] = [subscription_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 do |key, value|
@medic_id, @subscription_id, openpay_customer_id, openpay_subscription_id = key, value[0], value[1], value[2]
# Openpay API connection and request
@openpay = OpenpayApi.new(ENV['MERCHANT_ID_OPENPAY'], ENV['SECRET_KEY_OPENPAY'])
@subscriptions = @openpay.create(:subscriptions)
# @subscriptions.get(subscription_id,customer_id)
response_hash = @subscriptions.get(openpay_subscription_id, openpay_customer_id)
# Split values
@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')
# Status conditions
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
# Update each subscription with data from API response
@payment_method = PaymentMethod.where(id: @subscription_id, medic_id: @medic_id).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 #{@medic_id} update, Complete!"
end
end
end
end
Result: 结果:
PaymentMethod Load (0.5ms) SELECT `payment_methods`.* FROM `payment_methods` WHERE `payment_methods`.`id` = 1 AND `payment_methods`.`medic_id` = 1
(0.2ms) BEGIN
SQL (0.4ms) UPDATE `payment_methods` SET `premium` = 1, `current_period_number` = 0, `status` = 'trial', `updated_at` = '2018-06-20 17:40:20' WHERE `payment_methods`.`id` = 1
(12.1ms) COMMIT
User 1 update, Complete!
PaymentMethod Load (0.5ms) SELECT `payment_methods`.* FROM `payment_methods` WHERE `payment_methods`.`id` = 2 AND `payment_methods`.`medic_id` = 3
(0.2ms) BEGIN
SQL (0.4ms) UPDATE `payment_methods` SET `premium` = 1, `status` = 'trial', `cancelled_on` = NULL, `updated_at` = '2018-06-20 17:40:22' WHERE `payment_methods`.`id` = 2
(11.8ms) COMMIT
User 3 update, Complete!
0.040000 0.010000 0.050000 ( 1.741126)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.