What's the best way to allow users to input fields that will be serialized as hashes or arrays? - ruby-on-rails

I have a field that is stored like this:
serialize :value
And, I'd like to store it as an array/hash/string depending on the input format. Is there an accepted best practice about how to handle this? The input will always come from the user.

If I understand your problem correctly, you are talking about the opposite of serialization, which is parsing or tokenzing (converting a string into meaningful pieces)... That's a very generic problem, but take a look at the String.match and String.scan to get you started. Here are some stack overflow quetions that could be helpful (remember to search for things like this first!)
What's the "ruby way" to parse a string for a single key/value?
How do I tokenize this string in Ruby?

The best practice is to serialize Arrays and Hashes. When it comes to string there is no need for serialization. HTML form elements like checkboxes posts the array, which you can be serialized and saved directly in table. For Hashes, you should manipulate yourself accordingly and apply to the attribute.

Related

Partial deserialization with Apache Avro

Is it possible to deserialize a subset of fields from a large object serialized using Apache Avro without deserializing all the fields? I'm using GenericDatumReader and the GenericRecord contains all the fields.
I'm pretty sure you can't do it using GenericDatumReader, but my question is whether it is possible given the binary format of Avro.
Conceptually, binary serialization of Avro data is in-order and depth-first. As you traverse the data, record fields are serialized one after the other, lists are serialized from the top to the bottom, etc.
Within one object, there no markers to separate fields, no tags to identify specific fields, and no index into the binary data to help quickly scan to specific fields.
Depending on your schema, you could write custom code to skip some kinds of data ... for example, if a field is a LIST of FIXED bytes, you could read the size of the list and just jump over the data to the next field. This is pretty specific and wouldn't work for most Avro types though (notably integers are variable length when encoded).
Even in that unlikely case, I don't believe there are any helpers in the Java SDK that would be useful.
In brief, Avro isn't designed to do that, and you're probably not going to find a satisfactory way to do a projection on your Schema without deserializing the entire object. If you have a collection, column-oriented persistence like Parquet is probably the right thing to do!
It is possible if the fields you want to read occur first in the record. We do this in some cases where we want to read only the header fields of an object, not the full data which follows.
You can create a "subset" schema containing just those first fields, and pass this to GenericDatumReader. Avro will deserialise those fields, and anything which comes after will be ignored, because the schema doesn't "know" about it.
But this won't work for the general case where you want to pick out fields from within the middle of a record.

Rails: storing datatype in a column?

Im working on a database table that consists of two columns - one for all the values I'd like to store converted to strings. And as for the other one, I'd like to store their original datatypes.
I understand that I can store their types in strings (e.g. "string", "fixnum" etc). However, when I need to retrieve and process that data later on I'll have to switch the types (I'd like to avoid that and to be able to convert the values back to their original types immediately.) Is there any way to store what we get from the .class call to a database column? And if so, of what type should the column be?
Thanks.
You can use the constantize method. It takes a string and tries to convert it to a constant name:
"String".constantize #becomes String
Now, the string has to be correctly capitalized for it to work. And if something is wrong, it throws an error. Use safe_constantize to make it return nil when it fails.

Dealing with single value hash or multiple value array in JSON data

I have a JSON data feed where the value is a hash if single value and is an array if there are multiple values (see JSON data below).
JSON data:
# multiple values in option
{"options":{"option":[{"$t":"hasShots"},{"$t":"housebroken"}]}
# single value in option
{"options":{"option":{"$t":"hasShots"}}
I can do a check to see if the value is a hash or array using is_a? in Ruby, then extract the data accordingly and convert it to an object. Is this how it would typically be done or is there a better, more elegant way to code it in Ruby?
(NB: I figure this is such a common thing that there might be good solution to handling it. I google but it kept giving me how to parse JSON data's and creating JSON in Rails.)
I can do a check using is_a?. Is this how it would typically be done?
That's how I would do it! I think the more common scenario is for the JSON (or whatever) to have a consistent design, and have the objects in an array even if there's just one.

List of Model's Field in Rails

I've been looking at the Rails documentation and can't find this.
Lets say I have a Model User with field strength.
How do I get a list of all strengths for every instance of the model object in an array?
list_of_str = [1, 2, 3, 4, etc..]
I know that you can call User.all and iterate through each of their strength fields and append them to a list but is there a more elegant way of doing this?
User.pluck 'strength'
New in rails 3.2 if my memory is correct
You can use
User.uniq.pluck 'strength'
If you need to avoid duplicates, and you can also combine this with scopes and conditions, for example
User.where(...).pluck 'strength'
If you're really after the distinct strengths then:
User.select('distinct strength').pluck(:strength)
will get them. If you don't care about duplicates then Frederick Cheung's plain pluck would be a good idea.
You can use the select method for that, it generates a query where only the values of the desired field are retrieved (which is faster than loading all model data from the database):
User.select(:strength)
This still returns an array of model-objects, so you have to use map to get an array of the values only:
User.select(:strength).map(&:strength)
The creation of the model object will be slower than just querying the database for the values, but using raw SQL should be avoided if performance is not critical in this place.
Edit: There is an even better way (pluck), see the accepted answer.

Concatenating JSON strings for POST request

I'm attempting to submit a large database containing many tables to a web service by sending the data via JSON. Extracting the data and converting it to a JSON string is working fine but so far I have only implemented it to send one table at a time each with its own ASIHTTPRequest. My question is whether or not concatenating all the JSON strings generated from each table is a good idea or if I should first combine the tables in their abstract data form, before converting all of them together to JSON?
Alternatively if there is any other suggestion that would be good too.
It entirely depends on your needs. If the tables are unrelated, multiple requests may be more appropriate because if a request fails (timeouts or loss of connection), it won't affect any other requests. However if you have tables with associations with one another, it would be better to send it all in one go so either all the data transmitted wholly or did not so you don't end up with broken associations.
You can't just "concatenate" JSON strings. The result will not be legal JSON. You need to somehow "splice" them.
And, of course, the server on the other end must be capable of parsing the resulting JSON -- it may only expect one table at a time, eg.
I dont see any issue in doing any one of the two choices you proposed
But i would suggest concatenate the tables in the database before converting so that you dont deal with string concatenations and other form of processes

Resources