Different behavior between production and development environments?


#1

I have a yaml file that I am trying to import. If I am in the
development environment it works perfectly, but when I am in the
production environment it fails.

The line “records = YAML::load( params[:importfile] )” is where things
get weird.

production environment gets this "#<Contract sdc_ref: “ST-20080515”,
description: “8x…”

development environment gets this “#<YAML::Object:0xb6373744
@ivars={“attributes”=>{“discount_ce_day”=>0…”

So “contract_ary.ivars[‘attributes’].update(options)” works in the
development environment but fails in the production environment.

Can anyone please tell me why this is happening?

Ubuntu 8.04
ruby 1.8.6
rails 2.1.1

Thanks

##import_controller.rb
def create()
debugger
records = YAML::load( params[:importfile] ) #<< Problem occurs
here
#Separate out the data

contract_ary = records[0]
line_items_ary = records[1..-1]
aryAcct = params[:account_id].split('|')
arySales = params[:sales_office].split('|')
arySupport = params[:support_office].split('|')
options = {'account_id' => aryAcct[0], 'account_name' =>

aryAcct[1], ‘sales_rep_id’ => params[:sales_rep_id], ‘sales_office’ =>
arySales[0], ‘sales_office_name’ => arySales[1], ‘support_office’ =>
arySupport[0], ‘support_office_name’ => arySupport[1], ‘platform’ =>
params[:platform], ‘contract_type’ => params[:contract_type]}
contract_ary.ivars[‘attributes’].update(options)

#Cleanup
records = nil

#Save new contract
if params[:contract] != ""
  @contract = Contract.find(params[:contract])
  @contract.hw_support_level_id = contract_ary.ivars['attributes']

[‘hw_support_level_id’]
@contract.sw_support_level_id = contract_ary.ivars[‘attributes’]
[‘sw_support_level_id’]
@contract.updates = contract_ary.ivars[‘attributes’][‘updates’]
@contract.said = contract_ary.ivars[‘attributes’][‘said’]
else
@contract = Contract.new(contract_ary.ivars[‘attributes’])
end

#if Contract successfully saves then import
#associated line items
if @contract.save
  line_items_ary.each do |item|
    @line_item =

@contract.line_items.new(item.ivars[‘attributes’])
@line_item.save
end
end

respond_to do |format|
  if !@contract.new_record?
    flash[:notice] = 'Contract was successfully created.'
    format.html { redirect_to(@contract) }
    format.xml  { render :xml => @contract, :status

=> :created, :location => @contract }
else
flash[:notice] = ‘Contract was not successfully created.’
format.html { render :action => “new” }
format.xml { render :xml => @contract.errors, :status
=> :unprocessable_entity }
end
end
end

YAML file to import

  • !ruby/object:Contract
    attributes:
    sdc_ref: ST-20080515
    said: ABC Co.
    description: 8x rp34xx, 2x rx2620, rx3600, EVA8K
    cust_po_num: 243422
    payment_terms: Quarterly
    revenue: 108933.323333333
    annual_hw_rev: 73904.9294117647
    annual_sw_rev: 2989.18117647059
    annual_ce_rev: 0
    annual_sa_rev: 0
    annual_dr_rev: 0
    start_date: 8/1/2008
    end_date: 12/31/2009
    multiyr_end: 8/1/2009
    hw_support_level_id: SDC 24x7
    sw_support_level_id: SDC SW 24x7
    updates: Yes
    ce_days: 0
    sa_days: 0
    discount_pref_hw: 0.3
    discount_pref_sw: 0.3
    discount_pref_srv: 0
    discount_prepay: 0.05
    discount_multiyear: 0
    discount_ce_day: 0
    discount_sa_day: 0
  • !ruby/object:LineItem
    attributes:
    support_type: HW
    product_num: LABEL
    serial_num:
    description: HPORAPPQ
    begins: 12:00:00 AM
    ends: 12:00:00 AM
    qty:
    list_price:
    position: 1
    support_provider: XYZ
  • !ruby/object:LineItem
    attributes:
    support_type: HW
    product_num: A9953A
    serial_num: USL530SKTB
    description: rp3440 PA8900 1GHz 1 Way Server
    begins: 2/1/2009
    ends: 12/31/2009
    qty: 1
    list_price: 105
    position: 2
    support_provider: XYZ

#2

Even more specifically, it happens when config.cache_classes = true.
Other caching has no effect. Is there a way to turn class caching off
for just this one class/action?

Thanks


#3

On 22 Oct 2008, at 07:53, Troy wrote:

Even more specifically, it happens when config.cache_classes = true.
Other caching has no effect. Is there a way to turn class caching off
for just this one class/action?

Your YAML file contains serialized ruby objects - the !ruby/
object:LineItem bits indicate that.
In dev mode, constants are removed after requests (this is part of the
reloading of source in dev mode, which is exactly what
config.cache_classes does).
Odds are that when you hit your create action the LineItem and
Contract classes have not yet been loaded. YAML’s loading does not
apparently hit const_missing so when it sees a constant (ie Contract)
that does not exist you just get something generic (ie YAML::Object).
In production mode classes are never cleared out like this so unless
the server is serving its very first request odds are the Contract
class is loaded so you get back an instance of Contract. YAML::Object
has an ivars method that gets you something like a hash of instance
variables, but other objects don’t (everyone has instance_variable_get
though, but that’s not very nice)

It is the dev mode behavious which is weird, you can work around it by
using require_dependency to load contract, line_item and whatever else
you need. Personally I wouldn’t store the active record objects
themselves - just their hash of attributes.

Fred


#4

Thanks Fred, that makes perfect sense now. Now I can turn the
cache_classes back on.

On Oct 22, 9:23 pm, Frederick C. removed_email_address@domain.invalid