我有一个自定义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值更新相关订单。
我已将以下内容添加到自定义佣金任务
中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)
答案 0 :(得分: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