Different behavior between production and development environments?

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

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

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

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