Domanda

I have a method that loads from xml file customers. Before the file download all customers that are not in xml file is put in the validity false. Then begins loading and updating of existing customers . I wrapped the whole method in a transaction. But if you try to make the download client deliberately wrong ( which does not pass validation) I have not the entire transaction is rolled back. Prompt what am I doing wrong ? How to work in a transaction rails?

Code:

if customers_upload
  EXCHANGE_LOGGER.info("Start customers exchange")
  Customer.transaction do
    begin
      customers = xml.elements.to_a("//customer")

      customers_external_keys = []
      customers.each do |customer| 
        customers_external_keys << customer.elements['external_key'].text
      end          
      customers_false = Customer.where("external_key NOT IN (?)", customers_external_keys)
      customers_false.each do |customer_false|
        if customer_false.validity
          customer_false.update_attributes(validity: false)              
        end
      end
      EXCHANGE_LOGGER.info("#{customers_false.count} update validity in false")

      customers.each do |customer| 
        customer_name = customer.elements['name'].text
        customer_external_key = customer.elements['external_key'].text
        customer_address = customer.elements['address'].text
        customer_debt = customer.elements['debt'].text
        customer_db = Customer.find_by_external_key(customer_external_key)
        if !customer_db
          new_customer = Customer.create(name: customer_name, external_key: customer_external_key, address: customer_address, debt: customer_debt)
          EXCHANGE_LOGGER.info("#Create new customer #{customer_name}")
        else 
          if !customer_db.validity
            customer_db.update_attributes(name: customer_name, address: customer_address, debt: customer_debt, validity: true)
            EXCHANGE_LOGGER.info("#Change validity true and update customer #{customer_name}")            
          else
            customer_db.update_attributes(name: customer_name, address: customer_address, debt: customer_debt)
            EXCHANGE_LOGGER.info("#Update customer #{customer_name}")
          end        
        end
      end

    rescue => e
      if e.present?
        EXCHANGE_LOGGER.error("Customers not exchanged, message: #{e}")
        raise ActiveRecord::Rollback, "Call tech support!"
      end          
    end        
  end  
end

Here are the contents in exchange.log:

2013-11-29 10:53:23 INFO Start customers exchange
2013-11-29 10:53:33 INFO 3981 update validity in false
2013-11-29 10:53:33 ERROR Customers not exchanged, message: undefined method `text 'for nil: NilClass

Here are the contents development.log:

 

 Customer Exists (0.2ms) SELECT 1 AS one FROM customers WHERE (customers. External_key = 'CB001820' AND customers. Id! = 3979 ) LIMIT 1    (0.1ms) UPDATE customers SET validity = 0 , updated_at = '2013- 11 -29 10:53:33 'WHERE customers. Id = 3979   Customer Exists (0.2ms) SELECT 1 AS one FROM customers WHERE (customers. External_key = 'CB001826' AND customers. Id! = 3980 ) LIMIT 1    (0.1ms) UPDATE customers SET validity = 0 , updated_at = '2013- 11 -29 10:53:33 'WHERE customers. Id = 3980   Customer Exists (0.2ms) SELECT 1 AS one FROM customers WHERE (customers. External_key = 'CB001822' AND customers. Id! = 3981 ) LIMIT 1    (0.1ms) UPDATE customers SET validity = 0 , updated_at = '2013- 11 -29 10:53:33 'WHERE customers. Id = 3981    (2.2ms) SELECT COUNT (*) FROM customers WHERE (external_key NOT IN ('12312 '))    (0.1ms) ROLLBACK

Like ROLLBACK appears at the end , but all clients will still remain valid : (

È stato utile?

Soluzione

You must use a table in the database that supports transactions. For example InnoDB

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top