简体   繁体   中英

Ruby on Rails sneakily changing nested hash keys from symbols to strings

I'm encountering something strange in Ruby on Rails. I am working on a website that allows users to purchase certain things and go through a multi-step checkout process. I use a session object as a hash to carry data over to other actions in the controller.

Here's what it basically looks like

class CheckoutController < ApplicationController
  def index
    #stuff
  end
  def create
    #stuff

    session[:checkout_data] = {} #initialize all the checkout data as hash
    # Insert the :items_to_purchase key with the value as a new Items model instance
    session[:checkout_data][:items_to_purchase] = Items.new(post_data_params) #as an example

    redirect_to :action => 'billing_info'
  end

So I've created some data in the first POST request of the form using the Items model. Let's go to the next page where the user enters billing info.

  def billing_info
    if request.get?
      @items_to_purchase = session[:checkout_data][:items_to_purchase]
    end
    if request.post?
      # ...
    end
  end
end

My problem is on the line

@items_to_purchase = session[:checkout_data][:items_to_purchase]. 

The key :items_to_purchase doesn't exist, and instead, 'items_to_purchase' is the key. What happened? I specifically initialized that key to be a symbol instead of string! Ruby changed it behind my back! It doesn't seem to do this if I only have one flat hash, but with these nested hashes, this problem occurs.

Anybody have any insight to what is happening?

Sessions, if you're using cookie ones, do not live in Ruby - they are transmitted back and forth across the network. The session object you stored your data in is not the same session object that you tried to read it from. And while in cookie form, there is no difference between strings and symbols. Use Hash#symbolize_keys! to be sure you have your keys as you wish, or just use the string keys consistently.

session[:checkout_data] = {} #initialize all the checkout data as hash

您在这里分配一个普通的Hash而不是ActionDispatch :: Request :: Session(该对象由session方法返回)。

I ran into this problem today. Here is how I was able to solve it... hope this helps!

 def first_method
   session[:thing_to_store] = ThingToStore.new(params)).to_yaml
  end

 def second_method
   session[:thing_to_store] = YAML.load(session[:thing_to_store])
 end

它似乎取决于你的rails版本,当我使用4.1.0时,我有同样的问题,但我们的旧系统使用4.0.3,使用符号作为检索会话的密钥工作。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM