Как работать с формой rails и jsonb postgres

Я рассматриваю возможность использования новой возможности jsonb в Rails4.2 и Postgres4.1.

Я хотел создать модель, которая представляет профиль пользователя (например, наборы навыков и т. д.), и сохранить все это в одном наборе данных jsonb.

Таким образом, таблица будет иметь:

id int
profile jsonb
timestamps

Я думал, что могу хранить все данные профиля в структуре jsonb следующим образом (это всего лишь пример/концепция):

{
  "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"
  }],
}

Мой вопрос: как мне создать базовую форму рельсов, которая будет писать/читать в эту структуру? Я понимаю, как это сделать с традиционным реляционным набором таблиц, но не знаю, как подойти, когда все это может быть объединено в гибкую структуру, как показано ниже?

Что произойдет в _form.html.erb и в действиях контроллера new/create/edit?


person cman77    schedule 07.02.2015    source источник
comment
Я в такой же ситуации. Вы нашли какое-нибудь решение?   -  person medBouzid    schedule 05.04.2015


Ответы (2)


Используйте store_accessors. Данные формы — это всего лишь объект Hash, который можно легко преобразовать в объект JSON и сохранить в postgresql без особых проблем.

Предположим, что ваша форма отправляет все данные профиля в виде хэша profile[], а ваши модели выглядят примерно так:

class User < ActiveRecord::Base
  has_one :profile
end

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

Вы можете просто сделать что-то вроде:

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

В вашем контроллере (или где-либо еще) и он должен работать.

person lsdr    schedule 04.05.2015
comment
Потрясающие! какие-либо недостатки или ошибки, на которые следует обратить внимание? - person cman77; 08.05.2015
comment
@ cman77 Rails выполняет большую сериализацию/десериализацию для вас без вашего ведома. Как обычно с Rails, когда он работает, это выглядит как волшебство, но может вызвать некоторые проблемы. Остерегайтесь нестандартных структур данных. Однако все, что можно безопасно сериализовать в JSON, должно работать нормально. - person lsdr; 11.05.2015

Я не знаю о предыдущих версиях, но в Rails 6 из документа: https://api.rubyonrails.org/classes/ActiveRecord/Store.html

вы можете использовать магазин следующим образом:

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

Теперь, если у вас есть форма с <%= form.text_field :property1 %> и <%= form.text_field :property2 %>, они будут автоматически сопоставлены с вашим полем json/jsonb, и вы сможете обращаться с ними так, как если бы они были обычными полями (varchar/string).

Не забудьте разрешить :property1 и property2 и т. д. в ваших сильных параметрах, то есть:

params.require(:my_model).permit(:title, [...], :property1, :property2)
person medBouzid    schedule 04.09.2020
comment
Хороший! Это также работает на Rails 5.0. - person DaniG2k; 17.02.2021