Redis-rb pushing hash into list - ruby

Using redis-rb, how can I push a hash into a list? Do I have to JSON encode it or is this natively supported? If so, how can I do it? I only see hset method with a key and key/value pairs.
Thanks

Storing any object (not just hash) as a JSON encoded string is one way to do it.
If your use case allows it you can also store hash IDs within the list and use SORT GET to retrieve additional values.
Example:
r.hmset('person:1', 'name','adam','age','33')
r.hmset('person:2', 'name','eva','age','28')
r.lpush('occupants', 'person:1')
r.lpush('occupants', 'person:2')
r.sort('occupants', :get => ['*->name'])
To get list names from hashes which IDs are stored within occupants list. You can retrieve multiple fields, but you will get only array back.
For more information check SORT command

A Redis list is analogous to a Ruby Array. It has no keys.
As discussed in the redis-rb documentation, if you want to store a Ruby object in a Redis value you'll need to serialize it first using e.g. JSON:
Storing objects
Redis only stores strings as values. If you want to store an object inside a key, you can use a serialization/deseralization mechanism like JSON:
>> redis.set "foo", [1, 2, 3].to_json
=> OK
>> JSON.parse(redis.get("foo"))
=> [1, 2, 3]
Your other option would be to store it as a Redis hash, as you mentioned, using e.g. HMSET, but if your only goal is to store and retrieve the object (rather than perform Redis operations on it), that's superfluous.

Related

How can I store raw json string in redis cache using laravel without php serialization?

When I cache json string like so cache()->rememberForever('globals', fn() => json_encode(['foo' => 'bar']));.
The value stored in cache is actually "s:13:\"{\"foo\":\"bar\"}\";" rather than "{\"foo\":\"bar\"}"?
Is there a way I can store string without php serialisation?
You would need to use the true cache storage like Redis::put(...). The cache facade(s) have a pretty helpful way of getting complex data in and out of cache. For instance you can cache models or associative arrays thru that facade and not worry about how it gets stringified behind the scenes. However, if you don't want that kind of helper/handling to cache and restore your variables - then use the caching storage directly.
You should be able to store the string using the Cache::forever function. From Laravel docs Storing Items Forever:
The forever method may be used to store an item in the cache permanently. Since these items will not expire, they must be manually removed from the cache using the forget method:
Cache::forever('key', 'value');
Given that, I would change your code to something like the following:
cache()->forever('globals', json_encode(['foo' => 'bar']));

Ruby Find a value in a complex JSON object

I need to find the value of a particular key (say "key") in a JSON object. Since I am getting the JSON object dynamically, I do not know the structure of the JSON object.
Could anyone tel me an easy way to find the value of a key in such a JSON object?
If you dont know the structure of the JSON then you will need to do more work to inspect all possible keys.
You might just have to do a recursive descent and iterate over all keys until you find the key whose name matches key and then grab its value.

How can I turn a mongoid document into JSON stripping out embedded document ids, but keeping the main document id?

I have a document that has some embedded documents (and some of those have further embedded documents).
I want to return the document content as JSON but without all the IDs for the embedded documents.
I can do this: mydoc.to_json(:except => :_id)
but that strips all BSON IDs, including the one for mydoc.
Is there some other way to only strip the embedded document IDs?
Keep in mind that to_json is actually two steps here:
Call as_json to get a Hash.
Convert that Hash to a string of JSON.
So you could use as_json instead of to_json to build a Hash without any _ids, then put the _id you care about back in, and finally convert to JSON:
mydoc.as_json(:except => :_id).merge('_id' => mydoc.id).to_json

How can request params be validated to ensure they include required params and don’t include unsupported params?

This is particularly in the context of a REST API built with Ruby and Sinatra.
It's easy enough to manually check to make sure that the required params are not nil. And it's easy to iterate through a flat params hash to see if it's allowed in a whitelist.
However, when the params hash also include hashes it becomes more difficult.
One way of handling this I've thought of is converting the params hash to JSON and using a library to validate it against a JSON schema.
I have come across the sinatra-param gem but I haven't had a chance to see if it can validate sub-hashes or check for unsupported params.
Edit: Another possible way, that might make more sense is passing params directly to the model (I'm using DataMapper) and using its validation and errors instead of rewriting validations.
If each of your routes are going to take the same 4 params (IE :one, :two, :three, :four), you could set up a before filter, store an array of those four params as an instance variable in the before (which is accessible to all routes) and use a sexy little method from class Enumerable called all?:
before do
#base_params = [params[:one], params[:two], params[:three], params[:four]]
unless #base_params.all?
redirect '/error_route'
end
end
Enumerable#all? will return true only if all values in your 'collection' are not false or nil. Documentation can be found here for Ruby 1.9
Additionally if you find that you have different sets of params, you can create a hash instead of just an array of #base_params where they keys are the string value of request.request_method:
before do
#base_params = {"GET" => [params[:one], params[:two], params[:three], params[:four]],
"POST" => [params[:five], params[:six], params[:seven]],
"PUT" => [params[:one], params[:five], params[:six]]}
unless #base_params[request.request_method].all?
redirect '/error_route'
end
end

How to pass an array of hashes to controller WITHOUT form?

What I have so far is an array of hashes I'm pulling from a Website via RestClient:
def self.all_galleries
JSON.parse(RestClient.get ENV["GALLERY_API"], {:accept => :json})
end
I wanted to then pass this array to my controller, and create and save a new object for every hash to my database ONLY IF it doesn't exist without using any sort of form. What's the cleanest way of doing this?

Resources