Serialize Params to store in Database for Logging - ruby-on-rails

I am processing the payment and looking to dump the content i receive from the Gateway into my DB for logging.
#order[:payment_details] = params.to_json.to_s
Getting the following error
no implicit conversion of Symbol into Integer

This error means that #order is an array - the keys must be integers. This sounds like you expected #order to be a hash or activerecord object - review where #order is created.

I think you have no need to explicitly convert params to JSON just declare you params details as
serialize :payment_details
in your model it automatically serialize you params hash and on time of fetching deserialize your hash for reading.
An above error is due to you are trying to convert symbol i.e key in params to integer.

Related

Cannot access specific value of a hash - Rails

Hello i have been trying to access the token value of the following hash with no avail
email.to[{:token=>"example", :host=>"HOSTNAME here", :email=>"example email", :full=>"example#email.com", :name=>nil}]
does it not email.to[:token] give me the value of token?
when i do that i get this
TypeError (no implicit conversion of Symbol into Integer):
if not what is the correct way to do it. Is there any point in doing a loop when i just need one value?
email.to method returns an Array that contains a Hash
[{:a=>"a", :b=>"b"}]
so you have to specify the index of an element in that array first
email.to[0][:a]
or
email.to.first[:a]
In order to access the Hash without an index, email.to method would have to return a Hash and not an Array type. So it would have to be something likes this
def to
{:a=>"a", :b=>"b"}
end

Rails serialize not storing correctly

I am setting up stripe connect with the example from https://github.com/rfunduk/rails-stripe-connect-example and am running into a problem using serialize to store stripe_account_status which should be stored as an array.
This is how it should be stored (Generated from the above example link)
{"details_submitted"=>false, "charges_enabled"=>true, "transfers_enabled"=>false, "fields_needed"=>["legal_entity.first_name", "legal_entity.last_name", "legal_entity.dob.day", "legal_entity.dob.month", "legal_entity.dob.year", "legal_entity.address.line1", "legal_entity.address.city", "legal_entity.address.postal_code", "bank_account"], "due_by"=>nil}
And this is how my application is storing it
{:details_submitted=>false, :charges_enabled=>true, :transfers_enabled=>false, :fields_needed=>["legal_entity.first_name", "legal_entity.last_name", "legal_entity.dob.day", "legal_entity.dob.month", "legal_entity.dob.year", "legal_entity.address.line1", "legal_entity.address.city", "legal_entity.address.postal_code", "bank_account"], :due_by=>nil}
As far as I am concerned everything is set up the same. The only difference is that the first example uses
serialize :stripe_account_status, JSON
and my app just has
serialize :stripe_account_status
The reason for this is that when I add JSON I this error:
JSON::ParserError - 795: unexpected token at '':
I have tried finding out the JSON error including changing the config/initializers/cookies_serializer.rb to use :hybrid but this is giving me the same error.
Could someone point me into the right direction of either fixing the JSON issue OR finding a way to make sure the stripe_account_status is stored as an array correctly.
Below is the methods used to store the array:
if #account
user.update_attributes(
currency: #account.default_currency,
stripe_account_type: 'managed',
stripe_user_id: #account.id,
secret_key: #account.keys.secret,
publishable_key: #account.keys.publishable,
stripe_account_status: account_status
)
end
def account_status
{
details_submitted: account.details_submitted,
charges_enabled: account.charges_enabled,
transfers_enabled: account.transfers_enabled,
fields_needed: account.verification.fields_needed,
due_by: account.verification.due_by
}
end
Thanks I really appreciate any direction you could point me!
When you ask Rails to serialize an attribute on a model, it will default to storing the object as YAML string.
You can ask Rails to serialize differently, as you have noticed by providing a class to do the serialization e.g
serialize :stripe_account_status, JSON
The reason why this isn't working when you add it is because you presumably already have a record in the database using the YAML and so Rails can't parse this as a valid JSON string when reading from the DB. If it's just development data that you don't need, you can delete the records and then use JSON, otherwise you will need to convert the current YAML strings to JSON.
Rails will also symbolize the keys of a hash when parsing a serialized string in the database. This is the only difference between the hashes in your question and shouldn't matter in practise. Should you need String keys for some reason, you can use the #stringify_keys method on the hash provided by Rails.

Iterate to every element of the multidimension array in ruby

I have a array i getting through an xml .i want to iterate every element to the array which is hash and get the every hash element value using key.
I want to someting like this>>
array>>
education_split = [{"University"=>"Institute Of Engineering And Emerging Technologies", "Degree"=>"MBA", "Year"=>"2007"}, {"University"=>"H.N.B. Garhwal University", "Degree"=>"MSC", "Year"=>"2005"}, {"University"=>"H.P. University", "Degree"=>"Med", "Year"=>"2003"}, {"University"=>nil, "Degree"=>"12th", "Year"=>"1999"}, {"University"=>nil, "Degree"=>"10th", "Year"=>nil}]
now i want to iterate to every element of the array and get the value of university ,degree,year in iteration. something like that..
education_split.each do |edu|
//here are some other things also like creating object
edu["University"]
edu ["Degree"]
edu["Year"]
end
This is also working but in some cases it is though error >> TypeError (no implicit conversion of String into Integer)
here all fields are string and values i am getting are also string.
Just need to check a hash :
education_split.each do |edu|
//here are some other things also like creating object
if edu.is_a? Hash
edu["University"]
edu ["Degree"]
edu["Year"]
end
end
Reading the error, I am sure your collection education_split contains also arrays with hashes. Now to prevent the error and as you interested only to hash that part of the code, just do a check if edu in any particular iteration, is a hash or not. if hash, do your operation or skip it.
TypeError (no implicit conversion of String into Integer) only comes, when you would try to get array elements using strings, instead of integers. Like a = [1, 2], and now do a['x'], and see you would get the exact error you are now getting.

Symbols used as Hash keys get converted to Strings when serialized

When I assign an Array or Hash to an attribute of a Mongo document, it gets properly
serialized except for Symbols when they are used as Hash keys. Simple example:
irb>MyMongoModel.create :some_attr => {:a => [:b,:c]}
=> #<MyMongoModel _id: 4d861c34c865a1f06a000001, some_attr: {:a=>[:b, :c]}>
irb>MyMongoModel.last
=> #<MyMongoModel _id: 4d861c34c865a1f06a000001, some_attr: {"a"=>[:b, :c]}>
Please, note that some_attr is retrieved as {"a"=>[:b, :c]}, not as
{:a=>[:b, :c]}
This also happens for nested Hashes (e.g., inside of Arrays or other Hashes). Is there a way to preserve Symbols in such cases?
Solution
I'm using YAML to manually serialize some_attr - YAML.dump (or Object#to_yaml) before storing, and YAML::load after reading the attribute. YAML preserves the serialized object better. ActiveRecord is using YAML to implement its serialize class method on ActiveRecord::Base.
More than likely this has to do with the ORM you are using to provide the persistance layer for the model. You can probably wrap some_attr with a method that returns it in the form of a HashWithIndifferentAccess which you can then access with either strings or arrays. Since you are using Rails, this functionality can be activated by calling the with_indifferent_access method on the Hash object. (If you have an array of Hash objects, you'll need to call it on each one of course) The method will return the same hash, but then symbol lookups will work.
From your code:
new_hash = MyMongoModel.last.some_attr.with_indifferent_access
new_hash[:a] # Will return the same as new_hash['a']
Hope this helps!
the culprit here is the BSON serialization. when you serialize a symbol used as a key for hashes, it is actually translated to a string and when you ask it back you get the string instead of the symbol.
i'm having the same problem as you and i'm thinking of extending the Hash class to include a method to convert all the "string" keys to :symbols.
unfortunately i'm not on Rails so i cannot use the with_indifferent_access as suggested by ctcherry.
I'm not sure about preserving symbols but you can convert the strings back to symbols.
str.to_sym
Found this, works well and you have define the field as Hash:
https://github.com/mindscratch/mongoid-indifferent-access

Rails JSON conversion error

I'm getting a strange error when trying to convert my object to json for an API connection. The following details my experience.
If I call
JSON.generate(self)
the output is
{"validation_context":null,"errors":{},"params":{"number":"123","name":"test"}}
I only need the params in my json object and when I call
JSON.generate(self.params) # or the next line
JSON.generate(#params) #params has been set on the object as an accessor
I get
undefined method `merge' for #<JSON::Ext::Generator::State:0x1043f1a38>
For some reason params is not considered a Hash. It serializes ok when I'm getting the parent object but fails otherwise. How can I serialize just the params?
Turns out I found a relatively simple solution.
Rather than
JSON.generate(object_to_serialize)
Using
object_to_serialize.to_json
Will work as intended.

Resources