【问题标题】:How to check if a value has changed and update that value in the database?如何检查值是否已更改并更新数据库中的值?
【发布时间】:2023-03-24 00:45:01
【问题描述】:

我有一个自定义 rake 任务 (Mechanize),它(每小时)从某个网站获取订单信息,例如订单 ID、客户名称和订单状态,并将其保存到数据库中。

代码如下:

desc "Login to exampleShop, fetch all the order information, save it to the database"
task :task_1 => :environment do
    require 'mechanize'

    puts "BEGIN - Task 1 - Checking exampleShop for new orders"

    a = Mechanize.new

    a.get('http://exampleshop.nl/admin/') do |page|

        # Select the login form
        login_form = page.forms.first

        # Insert the username and password
        login_form.username = 'username'
        login_form.password = 'password'

        # Submit the login information
        dashboard_page = a.submit(login_form, login_form.buttons.first)

        # Check if the login was successfull
        puts check_1 = dashboard_page.title == 'Dashboard' ?  "CHECK 1 DASHBOARD SUCCESS" : "CHECK 1 DASHBOARD FAIL"

        # Visit the orders index page to scrape some standard information
        orders_page = a.click(dashboard_page.link_with(:text => /Bestellingen/))

        # pp orders_page # => http://pastebin.com/L3zASer6

        # Check if the visit is successful
        puts check_2 = orders_page.title == 'Bestellingen' ?  "CHECK 2 ORDERS SUCCESS" : "CHECK 2 ORDERS FAIL"

        # Search for all #singleOrder table row's and put them in variable all_single_orders
        all_single_orders = orders_page.search("#singleOrder") 

        # Print information to the console
        puts "START fetching and saving information"

        # Scrape the needed information (the actual save to database is omitted)
        all_single_orders.each do |order|
            # Set links for each order
            order_link = order.at_css("a")['href']  #Assuming first link in row

            order_id = order.search("#orderId").text                    
            order_status = order.search("#orderStatus").text        
            order_revenue = order.search("#orderAmount").text       

            # Visit a single order page to fetch more detailed information
            single_order_page = orders_page.link_with(:href => order_link).click

            first_name = single_order_page.search(".firstName").text
            last_name = single_order_page.search(".lastName").text
            city = single_order_page.search(".city").text
            postal_code = single_order_page.search(".postalCode").text
            address = single_order_page.search(".address").text
            email = single_order_page.search(".email").text
            order_quantity = single_order_page.search(".orderQuantity").text

            single_order = Order.create(    order_id: order_id, first_name: first_name, last_name: last_name, city: city,
                                                        email: email, postal_code: postal_code, address: address, order_quantity: order_quantity,
                                                        order_revenue: order_revenue, order_status: order_status)


        end

        # Print information to the console
        puts "DONE fetching and saving information"
    end

    puts "END - Task 1 - Checking exampleShop for new orders"
end

我不希望数据库变得混乱并设置唯一性验证器。这是当前的Order 模型:

class Order < ActiveRecord::Base
    validates :order_id, uniqueness: true
end

这是一个场景草图:

# Point in time 1
order_status = "Order received"

# Point in time 2
order_status = "Order shipped"

当在时间点 1 时,rake 任务将获取所有相关的订单信息,order_status 将是“收到订单”。

在第 2 点时,rake 任务再次开始获取订单信息。但这次我希望它检查order_status 是否发生了变化,如果是,它必须在不向数据库添加新订单的情况下更新订单。

完成这项工作的最佳方法是什么?我正在使用 Rails 4.0.1 和 Ruby 2.0.0。

更新

问题是关于第二部分的。我希望代码检查 order_status 是否已更改,如果是,则必须使用新的 order_status 值更新相关订单。

更新 2

我已将以下内容添加到我的自定义 rake 任务中

single_order = Order.find_or_create_by(order_id: order_id, first_name: first_name, last_name: last_name, city: city,
                                            email: email, postal_code: postal_code, address: address, order_quantity: order_quantity,
                                            order_revenue: order_revenue, order_status: order_status)

unless single_order.valid?
    single_order.order_status = order_status
    puts single_order.save!
end

这给了我以下输出:

BEGIN - Task 1 - Checking exampleShop for new orders
CHECK 1 DASHBOARD SUCCESS
CHECK 2 ORDERS SUCCESS
START fetching and saving information
rake aborted!
Validation failed: Order has already been taken
/Users/username/.rvm/gems/ruby-2.0.0-p353@global/gems/activerecord-4.0.1/lib/active_record/validations.rb:57:in `save!'
/Users/username/.rvm/gems/ruby-2.0.0-p353@global/gems/activerecord-4.0.1/lib/active_record/attribute_methods/dirty.rb:41:in `save!'
/Users/username/.rvm/gems/ruby-2.0.0-p353@global/gems/activerecord-4.0.1/lib/active_record/transactions.rb:275:in `block in save!'
/Users/username/.rvm/gems/ruby-2.0.0-p353@global/gems/activerecord-4.0.1/lib/active_record/transactions.rb:326:in `block in with_transaction_returning_status'
/Users/username/.rvm/gems/ruby-2.0.0-p353@global/gems/activerecord-4.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:202:in `block in transaction'
/Users/username/.rvm/gems/ruby-2.0.0-p353@global/gems/activerecord-4.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:210:in `within_new_transaction'
/Users/username/.rvm/gems/ruby-2.0.0-p353@global/gems/activerecord-4.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:202:in `transaction'
/Users/username/.rvm/gems/ruby-2.0.0-p353@global/gems/activerecord-4.0.1/lib/active_record/transactions.rb:209:in `transaction'
/Users/username/.rvm/gems/ruby-2.0.0-p353@global/gems/activerecord-4.0.1/lib/active_record/transactions.rb:323:in `with_transaction_returning_status'
/Users/username/.rvm/gems/ruby-2.0.0-p353@global/gems/activerecord-4.0.1/lib/active_record/transactions.rb:275:in `save!'
/Users/username/Dropbox/Development/Rails/fstool/lib/tasks/task_1.rake:64:in `block (3 levels) in <top (required)>'
/Users/username/.rvm/gems/ruby-2.0.0-p353@global/gems/nokogiri-1.6.0/lib/nokogiri/xml/node_set.rb:237:in `block in each'
/Users/username/.rvm/gems/ruby-2.0.0-p353@global/gems/nokogiri-1.6.0/lib/nokogiri/xml/node_set.rb:236:in `upto'
/Users/username/.rvm/gems/ruby-2.0.0-p353@global/gems/nokogiri-1.6.0/lib/nokogiri/xml/node_set.rb:236:in `each'
/Users/username/Dropbox/Development/Rails/fstool/lib/tasks/task_1.rake:39:in `block (2 levels) in <top (required)>'
/Users/username/.rvm/gems/ruby-2.0.0-p353@global/gems/mechanize-2.7.2/lib/mechanize.rb:434:in `get'
/Users/username/Dropbox/Development/Rails/fstool/lib/tasks/task_1.rake:9:in `block in <top (required)>'
/Users/username/.rvm/gems/ruby-2.0.0-p353@global/bin/ruby_executable_hooks:15:in `eval'
/Users/username/.rvm/gems/ruby-2.0.0-p353@global/bin/ruby_executable_hooks:15:in `<main>'
Tasks: TOP => task_1
(See full trace by running task with --trace)

【问题讨论】:

  • 这里只是一个快速的警察检查。为什么要在循环中使用 @order_quantity 等实例变量。这不是一个好习惯,您正在破坏那里的可见性。
  • 因为我是初学者,所以总是欢迎好的练习技巧。谢谢。

标签: ruby-on-rails ruby activerecord ruby-on-rails-4


【解决方案1】:

嗯,

你可以的

order = Order.new(order_params)
if order.valid? #no error on uniq
   order.save
end

我不太确定你提到的最后一部分。 但您可以检查 order_status 是否更改为

@order.order_status_changed?

这里是文档:

http://api.rubyonrails.org/classes/ActiveModel/Dirty.html

single_order = Order.create(order_id: order_id, first_name: first_name, last_name: last_name, city: city, email: email, postal_code: postal_code, address: address, order_quantity: order_quantity, order_revenue: order_revenue, order_status: order_status)

if single_order.valid?
  single_order.save
else
  order = Order.find(order_id)
  order.order_status = "SOMETHING"
  order.save!
end

【讨论】:

  • 是的,你可以使用find_or_create_by
  • 问题主要是关于第二部分。我希望代码检查 order_status 是否已更改,如果是,则必须使用新的 order_status 值更新相关订单。
  • @Nich,validates :order_id, uniqueness: true 可防止将重复订单保存到数据库中。在task_1.rake 中使用您建议的代码有什么好处?
  • 我认为当你保存并且它在 rake 任务中达到相同的记录时,它会抛出错误并打破循环(你的 rake 任务)。您需要检查是否有效然后保存。 @narzero 那么您是否正在检查特定订单 order_Status 是否已更改?如果是这样,你可以使用我的建议,否则我不确定你能做什么..
  • 如果你使用 find_or_create_by 和唯一的 order_id 你不会有这个问题,伙计!
猜你喜欢
  • 2013-08-11
  • 1970-01-01
  • 2014-04-15
  • 1970-01-01
  • 2018-11-10
  • 2016-11-03
  • 1970-01-01
  • 1970-01-01
  • 2011-02-20
相关资源
最近更新 更多