I have a Ruby on Rails form that takes the input and saves it as model attributes. One of the attributes, though, holds json data. I would like to be able to take the data entered into multiple fields and save it as a single JSON object in my models attribute. Is there a way I could do this?
If it helps, I could also make a Hash and convert it to json. Basically I just want to combine multiple input fields into one, then hand it off from there.
Thanks!
There are multiple things to consider here.
The first problem is to get your data out of the HTML form. If you use the standard Rails way of naming your form inputs, it's quite simple.
<input name="my_fields[value1]">
<input name="my_fields[value2]">
<input name="my_fields[sub1][value1]">
<input name="my_fields[sub1][value2]">
If you name them like that they can be accessed "en bloc" using the params hash via params[:my_fields], which gives you another hash containing your data.
Then you have to choose which way to save this data in your model. There are several options:
1. Use a string attribute
Just use a string or text column and assign a JSON string:
#my_model.my_data = params[:my_fields].to_json
Pro: A very simple solution.
Contra: SQL queries virtually impossible. Processing with Rails requires manually parsing of the data string.
2. Use a serialized hash
Use a string or text column and declare it as serializable on your model
serialize :my_data, Hash
Then you can use this column as it was a simple hash and Rails will perform the reading and writing operations.
#my_model.my_data = params[:my_fields]
Pro: Still a simple solution. No messing with JSON strings. Processing with Rails much easier.
Contra: SQL queries virtually impossible. A call to to_json is necessary if you need a real JSON string.
3. Use specialized JSON database types
In case you need to be able to query the database using SQL the solutions above won't work. You have to use specialized types for that.
Many DBMS provide structured datatypes in form of XML or even JSON types. (PostgreSQL for example)
Pro: Database queries are possible.
Contra: Custom parsing and serialization necessary, migrations ditto. This solution might be over-engineered.
Update: Since Rails 5 JSON column types are supported. If you are using PostgreSQL or MySQL just use t.json (or t.jsonb) in your migration and use that attribute like a regular hash.
You can save all multiple files as text in JSON format and when you need parse the field.
Ex:
a = JSON.parse('{"k1":"val1"}')
a['k1'] => "val1"
You will probably looking for an before_save that takes all your model attributes and create a JSON format using .to_json method.
You should probably look into the new JSONB format of Postgres. I think this gets you all the PROS, and none of the CONS:
http://robertbeene.com/rails-4-2-and-postgresql-9-4/
Related
I have SPA and few models, I want to create form for REST api, but I don't want to duplicate validators data in JS and Ruby.
All I want is to get validators data(required, read-only, type, default, choices, name, label, help_text) from rails and render form from it.
The problem is I don't see any solution to serialize model into json. With Python, Django REST Framework, I can make OPTIONS request and it will give me full information about model fields, parsers, methods, etc. Is there any similar solution for Rails?
There is validation reflection available in Rails 3 and Rails 4: MyModel.validators (railscast). This will give you an array containing all validators with options, e.g.:
[
[0] #<ActiveRecord::Validations::PresenceValidator:0x007fe542431b40 #attributes=[:name], #options={}>,
[1] #<UrlValidator:0x007fe542431050 #attributes=[:url], #options={:allow_blank=>true}>
]
If you want to get validation errors, the option is to pass #object.errors.messages through json response.
Additionally you may use AMS to serialize model data into json (railscast).
Hope it helps.
I have a ruby on rails 4 app and I'm using omniauth-facebook gem for authentication. I have
#omniauth = request.env["omniauth.auth"]
Now I'd like to save a user's education history (#omniauth[:extra][:raw_info][:education]) in the education column of Auth table in the database. #omniauth[:extra][:raw_info][:education] is an Array object which contains OmniAuth::AuthHash objects (i.e. #omniauth[:extra][:raw_info][:education][0].class returns OmniAuth::AuthHash).
Rails api says that "Active Record can serialize any object in text columns using YAML. To do so, you must specify this with a call to the class method serialize. This makes it possible to store arrays, hashes, and other non-mappable objects without doing any additional work." So I did the following and it seems to be working:
auth.education = #omniauth[:extra][:raw_info][:education]
auth.save
Is there any downside to this? Is there a better way (like using json, etc)? One downside I can think is that saving data this way makes it difficult for search and query which I probably won't be needing.
Thanks a lot.
I am currently working on a simple rails4 app. As part of the app, I am creating a form to populate the database and a particular column (:additional), I would like to populate with a hash where the key is a string (heading) and the value an array of strings (paragraphs below heading). So, for example: {"Heading" => ["Paragraph1", "Paragraph2"]} etc.
I am confused how I would now set up a form using rails to populate this column. I was thinking of creating a text_field for the title and then one or more text_areas underneath for the paragraphs and then somehow merging them in the controller but when creating the fields, I have to give the object as :additional which leads to problems.
How would I go about best accomplishing this? Is it even possible or should I restructure my database somehow?
Any advice is much appreciated.
If you're using postgres, ActiveRecord has support for using :hstore as the column type. If you're not, you can use serialize.
Here's my challenge. I have a key/value set that I want to tie to a model. These are my specific requirements:
I want the hash to be stored as a serialized JSON object in the model's table instead of in a separate table
I want to be able to pre-define the valid keys within the model itself
I want to be able to set a strong type for each key and automatically perform validations. I don't want to have to write validation functions for each individual attribute unless it needs a validation out of the basic data type scope.
I would LOVE to be able to magically access the attributes inside a form generator (f.input :my_key) and have the form generator recognize that :my_key is of type :boolean and create a checkbox instead of a generic text input. The same for other data types.
There are a few different ways to solve this problem, and lots of opinions for both. I read over this answer from 5 years ago:
Best approach to save user preferences?
It seems that many/most of those plugins have been abandoned. Anything else come out in the last 5 years that matches my criteria?
Your question is a bit open-ended, but as far as I can see your needs, they should be met with using Hashie gem.
I want to send a very vague and dynamic JSON as a response from a client to server.
for backend I'm using rails + mongoid.
What I know from mongoid is I have to create a model class corresponding to my collection structure so that I can call it from my controller to store data to it this way reminds me traditional RDBMS (still can't figure it out why people are happy with it!!!!)
I don't want to do that , I want to send a JSON (which I don't know about its structure) back to my server and mongoid stores the JSON as it is on the server in other words I don't have any preference structure to storing them and I don't want to have any.
Is there a way to that in rails + mongoid?
Generally Mongoid expects you to specify the fields of your model because there is no underlying schema to infer those fields from in the way that ActiveRecord does. But if you just want to store an arbitrary JSON object you can parse it into a Ruby Hash and store it using Mongoid's hash datatype.
field :untyped_data, type: Hash
There are a few caveats about key names, see http://mongoid.org/en/mongoid/docs/documents.html#fields