Можно ли использовать postgresql 9.3 json type в ассоциациях (принадлежит_to) как foreign_key

У меня есть ruby ​​on rails 4.0 и postgresql 9.3.

У меня две модели:

class Person < ActiveRecord::Base
       belongs_to :address_city, :class_name =>'City', :foreign_key => "address['city_id']"
end

class City < ActiveRecord::Base
   has_many: :address_cities, :class => "Person", :foreign_key => "address['city_id']"
end

Поле address в таблице Person относится к типу JSON, а city_id является одним из возможных ключей в этом поле JSON.

Итак, могу ли я установить связь между двумя моделями, используемыми как Person.first.address_city?

Ответ 1

Рельсы по умолчанию используют foreign_key в стороне own_to для выполнения SQL. Присоединение между двумя связанными таблицами. Поэтому он не входит в поле JSON, ища значения foreign_key.

Что вы можете сделать, так это построить расширение ассоциации, чтобы заглянуть в ваше поле json. Вы можете посмотреть здесь в руководствах по связям с рельсами о том, как это сделать: http://guides.rubyonrails.org/association_basics.html#association-extensions

По-моему, это противоречит правилам рельсов, и вы не должны этого делать. Вместо этого вы можете создать новый столбец с именем city_id в таблице лиц. Затем вы выполняете работу, которая выполняет итерацию таблицы лиц, чтобы извлечь city_id из json и обновить столбец city_id. После этого вы можете сделать обычную связь 1 между людьми между таблицей лиц и городов. Если я, где вы, я также извлечу другое поле, мне может понадобиться. Затем вы можете добавлять индексы в базу данных для скорости.

Update:

В Rails 4.2 и Postgres вы можете поместить содержимое json прямо в столбец, а затем вы можете легко запросить его, используя синтаксис запроса postgres json в rails.

Итак, я думаю, вы могли бы построить расширение ассоциации, которое могло бы выглядеть внутри json-контента, хотя я бы не рекомендовал это, потому что это противоречит соглашениям.

Литература:

Пример использования json-запросов с моделями рельсов: http://robertbeene.com/rails-4-2-and-postgresql-9-4/

Активная запись json Тип данных: http://edgeguides.rubyonrails.org/active_record_postgresql.html#json

Синтаксис запроса postgres json: http://www.postgresql.org/docs/9.4/static/functions-json.html

Ответ 2

У меня была такая же проблема.

На данный момент есть методы, выполняющие запросы, и это работает для меня.

С Rails 4.2.6 и Postgres 9.5 он должен работать следующим образом:

class Person < ActiveRecord::Base

  def address_city
    City.find_by(id: address['city_id'])
  end

end

class City < ActiveRecord::Base

  def address_cities
    Person.where(["(address->>'city_id')::int = ?", id])
  end

end

Я исследовал далее, чтобы решить мою проблему, и Sequel ORM, похоже, поддерживает это:

https://github.com/jeremyevans/sequel/blob/master/doc/association_basics.rdoc#associations-based-on-sql-expressions-options

Подумайте о том, чтобы использовать его вместо Active Record, я планирую сделать это в ближайшем будущем