Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to work with rails form and jsonb postgres

I'm looking at using the new jsonb capability in Rails4.2 and Postgres4.1.

I was looking at creating a model which represents a user profile (i.e. skill sets, etc) and storing the whole thing in a single jsonb dataset.

So the table would have:

id int
profile jsonb
timestamps

I was thinking I could basically store all the profile data in the jsonb structure as follows (this is just an example/concept):

{
  "basics": {
    "name": "John Doe",
    "label": "Programmer",
    "picture": "",
    "email": "[email protected]",
    "phone": "(912) 555-4321",
    "website": "http://johndoe.com",
    "summary": "A summary of John Doe...",
    "location": {
      "address": "2712 Broadway St",
      "postalCode": "CA 94115",
      "city": "San Francisco",
      "countryCode": "US",
      "region": "California"
    },
    "profiles": [{
      "network": "Twitter",
      "username": "john",
      "url": "http://twitter.com/john"
    }]
  },
"skills": [{
    "name": "Web Development",
    "level": "Master",
    "keywords": [
      "HTML",
      "CSS",
      "Javascript"
    ]
  }],
  "languages": [{
    "language": "English",
    "fluency": "Native speaker"
  }],
}

My question is how would I create a basic rails form that would write/read to this structure? I understand how to do it to a traditional relational set of tables, but not sure how to approach when it could all go into a flexible structure like the below?

What would happen at the _form.html.erb and in the controller new/create/edit actions?

like image 580
cman77 Avatar asked Feb 07 '15 16:02

cman77


2 Answers

Use store_accessors. Form data is just a Hash, that could be easily converted to a JSON object and persisted in postgresql without major problems.

Assuming your form submits all profile data in a profile[] hash and your models look something like this:

class User < ActiveRecord::Base
  has_one :profile
end

class Profile < ActiveRecord::Base
  belongs_to :user
  store_accessor :profile
end

You could simply do something like:

user.profile = params[:profile]
user.profile.save

In your controller (or anywhere else) and it should work.

like image 178
lsdr Avatar answered Oct 24 '22 19:10

lsdr


I don't know about the previous versions but in Rails 6 from the doc: https://api.rubyonrails.org/classes/ActiveRecord/Store.html

you can use store like this:

class MyModel < ApplicationRecord
    store :my_jsonb_field_name, accessors: [:property1, :property2]
end

Now if you have a form with <%= form.text_field :property1 %> and <%= form.text_field :property2 %> they will be automatically mapped to your json/jsonb field and you will be able to treat them like if they were a regular (varchar/string) fields.

Do Not forget to permit :property1 and property2 etc in your strong parameters, i.e:

params.require(:my_model).permit(:title, [...], :property1, :property2)
like image 10
medBouzid Avatar answered Oct 24 '22 19:10

medBouzid