How to store array on a cookie rails 4? - ruby-on-rails

I am trying to store an array on rails an getting error on the decoding.
I use cookies[:test] = Array.new
And when I am trying to decode
#test = ActiveSupport::JSON.decode(cookies[:test])
I am getting an error.
Whats the proper way to achieve what I am trying to ?

When writing to the cookie I usually convert the array to a string.
def save_options(options)
cookies[:options] = (options.class == Array) ? options.join(',') : ''
end
Then I convert back into an array when reading the cookie.
def options_array
cookies[:options] ? cookies[:options].split(",") : []
end
I'm not sure if this is "the right way" but it works well for me.

The "Rails way" is to use JSON.generate(array), since it's what is used in the second example in the Cookies docs:
# Cookie values are String based. Other data types need to be serialized.
cookies[:lat_lon] = JSON.generate([47.68, -122.37])
Source: http://api.rubyonrails.org/classes/ActionDispatch/Cookies.html
When you want to read it back, just use JSON.parse cookies[:lat_lon] for example, and it'll provide you an array.

Use session, not cookies. You don't have to decode it, rails handles that for you. Create the session the same way you already are:
session[:test] = Array.new
and when you need it, access it like normal
session[:test]
# => []

Related

Storing/Retrieving values in a Rails cookie and in different controller [duplicate]

I am trying to store an array on rails an getting error on the decoding.
I use cookies[:test] = Array.new
And when I am trying to decode
#test = ActiveSupport::JSON.decode(cookies[:test])
I am getting an error.
Whats the proper way to achieve what I am trying to ?
When writing to the cookie I usually convert the array to a string.
def save_options(options)
cookies[:options] = (options.class == Array) ? options.join(',') : ''
end
Then I convert back into an array when reading the cookie.
def options_array
cookies[:options] ? cookies[:options].split(",") : []
end
I'm not sure if this is "the right way" but it works well for me.
The "Rails way" is to use JSON.generate(array), since it's what is used in the second example in the Cookies docs:
# Cookie values are String based. Other data types need to be serialized.
cookies[:lat_lon] = JSON.generate([47.68, -122.37])
Source: http://api.rubyonrails.org/classes/ActionDispatch/Cookies.html
When you want to read it back, just use JSON.parse cookies[:lat_lon] for example, and it'll provide you an array.
Use session, not cookies. You don't have to decode it, rails handles that for you. Create the session the same way you already are:
session[:test] = Array.new
and when you need it, access it like normal
session[:test]
# => []

rails: how to get all key-values from Rails.cache

I want to maintain an user online/offline list with Rails.cache(memory_store).
Basically if a request /user/heartbeat?name=John reached Rails server, it will simply:
def update_status
name = params.require(:name)
Rails.cache.write(name, Time.now.utc.iso8601, expires_in: 6.seconds)
end
But how could I get all the data stored in Rails.cache similarly as following?
def get_status
# wrong codes, as Rails.cache.read doesn't have :all option.
ary = Rails.cache.read(:all)
# deal with array ...
end
I googled for a while, it seems Rails.cache doesn't provide the method to get all the data directly. Or there is better way to store the data?
I'm using Rails 5.0.2.
Thanks for your time!
If you have redis you can use sth like Rails.cache.redis.keys
You can get all keys with code:
keys = Rails.cache.instance_variable_get(:#data).keys
In addition, you can iterate on the keys to get their values and display them all
keys = Rails.cache.instance_variable_get(:#data).keys
keys.each{|key| puts "key: #{key}, value: #{Rails.cache.fetch(key)}"}
or map them all directly as such:
key_values = Rails.cache.instance_variable_get(:#data).keys.map{|key| {key: key, value: Rails.cache.fetch(key)}}
In addition I would check beforehand the amount of keys to make sure I would not come up with a gigantic object (and if so, restrict the key_value array generated to the first 1000 items for instance).
You could use:
Rails.cache.instance_variable_get(:#data).keys.count
or just look at the last line of the stats command:
Rails.cache.stats
None of the answers seem to work if you're using Redis. Instead, you will have to use redis-rb:
redis = Redis.new(url: ENV["REDIS_URL"])
redis.keys("*")
The above answeres helped me. The existing cache values can been seen by looping
Rails.cache.redis.keys.each{ |k| puts k if Rails.cache.exist?(k)}
If you have connection pooling, try:
Rails.cache.redis.with do |conn|
conn.keys
end

Rails: Converting URL strings to params?

I know Rails does this for you, but I have a need to do this myself for examples. Is there a simple, non-private method available that takes a string and returns the hash of params exactly as Rails does for controllers?
Using Rack::Utils.parse_nested_query(some_string) will give you better results since CGI will convert all the values to arrays.
I found a way after a more intense Google search.
To convert url string to params:
hash = CGI::parse(some_string)
And (as bonus) from hash back to url string:
some_string = hash.to_query
Thanks to: https://www.ruby-forum.com/topic/69428
In model you can write a query like
def to_param
"-#{self.first_name}" +"-"+ "#{self.last_name}"
end
More info
http://apidock.com/rails/ActiveRecord/Base/to_param
It will generate a url like http://ul.com/12-Ravin-Drope
More firendly url you can consult
https://gist.github.com/cdmwebs/1209732

JSON to Ruby on Rails Create Action

I am using an API for movies, for the most part I use a gem, but in order to get certain information, I have to use RestClient.get methods.
response = RestClient.get "http://api.themoviedb.org/3/movie/8699/keywords", headers
puts response
If I run this code, it returns this JSON "extract"
{"id":8699,"keywords":[{"id":917,"name":"journalism"},{"id":4411,"name":"sexism"},{"id":6198,"name":"ladder"},{"id":8531,"name":"panda"},{"id":18290,"name":"1970s"},{"id":18298,"name":"tv show in film"},{"id":41390,"name":"mustache"},{"id":165288,"name":"misogynist"},{"id":167241,"name":"newsroom"},{"id":167250,"name":"teleprompter"},{"id":167252,"name":"what happened to epilogue"},{"id":167254,"name":"gang warfare"},{"id":167256,"name":"multiple cameos"},{"id":179430,"name":"aftercreditsstinger"},{"id":179431,"name":"duringcreditsstinger"},{"id":185281,"name":"news spoof"}]}
Now what I need to do is be able to do is turn the above into a rails readable piece of code, so that I can then put it into a database.
More specifically, I would like to take the above information and be able to execute it as such
keywords.each do |keyword|
Keyword.create(name: keyword.name, tmdbid: keyword.id)
end
So that it creates a new Keyword based on each keyword and its name & id based on the JSON File
You can use JSON.parse to turn it into a hash
keywords = JSON.parse(response)["keywords"]
It will be faster if you create all keywords at once by first create correct array of values to be saved. Here is what I will do
keywords = JSON.parse(response)["keywords"].map do |k|
{ name: k["name"], tmdbid: k["id"] }
end
Keyword.create(keywords) #one SQL statement only
Regards

Serialization to blob in rails 3

I have an rails app where one of the attributes on an object is a data set which consists of an array of x,y coordinates. I am currently storring this in the sql database using the rails serialize helper :
serialize :data, Array
This converts the array to yaml and then stores it in a string field in the sql database. The problem is that our database is getting really big doing this and we need to keep it smaller. Is it possible to serialize to raw binary instead of a string and store in a blob?, this would dramatically reduce the size and help our problem.
I have had a search for a gem to do this, or even a ruby method that will turn an array in to binary data without much help. Any suggestions would be appreciated.
You may be interested in Array.pack and String.unpack methods. See ruby documentation for it: type ri Array.pack
You may want to use a 'packed_data' attribute in your database, then add accessors to pack/unpack it:
def data
packed_data.unpack('....')
end
def data=(v)
self.packed_data = v.pack('....')
end
To make it more useful, you may store the unpacked form in a variable, but you have to remember to clear it when the packed_data attribute changes, like when you call .reload
before_validation :pack_data
UNPACK_FORMAT = '.....' # See ri Array.pack
def data
#data ||= packed_data.unpack(UNPACK_FORMAT)
end
def data=(v)
#data = v
end
def reload(options=nil)
#data = nil
super
end
def pack_data
self.packed_data = self.data.pack(UNPACK_FORMAT)
true # Because we are in a before_.. callback
end
The format of the magic string used to pack/unpack the data depends on the data you have in your array. The documentation will help you to choose the right one.
I believe the format for pack and unpack will be the same, but don't trust me too much. ;)

Resources