0

У меня есть Rails API, который взаимодействует с приложением Ember. Мне нужно иметь возможность сериализовать модель с двумя первичными ключами вместо идентификатора по умолчанию.Сериализация модели с несколькими первичными ключами

Это то, что это выглядит как прямо сейчас:

Модели

# This is the problem model: 
class Value < ActiveRecord::Base 
    self.primary_keys = :foreign_id, :type_id 
    belongs_to :type, foreign_key: :type_id 
end 

class Type < ActiveRecord::Base 
    has_many :codes, foreign_key: :code_type_id 
    has_many :values, foreign_key: :type_id 
end 

class Code < ActiveRecord::Base 
    belongs_to :type, foreign_key: :code_type_id 
end 

class Activity < ActiveRecord::Base 
    has_many :values, -> (object){ where("type_subject_area = ?", "Activity") }, foreign_key: :foreign_id 
end 

Схема

create_table "values", id: false, force: :cascade do |t| 
    t.integer "foreign_id" 
    t.string "type_subject_area" 
    t.integer "code_id" 
    t.integer "type_id" 
    t.string "type_title" 
    t.text  "text" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
end 

add_index "values", ["foreign_id", "type_id"], name: "index_values_on_foreign_id_and_type_id", unique: true, using: :btree 

create_table "types", force: :cascade do |t| 
    t.integer "id" 
    t.string "title" 
    t.string "subject_area" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
end 

add_index "types", ["id"], name: "index_types_on_id", unique: true, using: :btree 

create_table "activities", force: :cascade do |t| 
    t.integer "id" 
    t.datetime "created_at" 
    t.string "name" 
end 

add_index "activities", ["activity_type"], name: "index_activities_on_activity_type", using: :btree 
add_index "activities", ["id"], name: "index_activities_on_id", unique: true, using: :btree 

create_table "codes", force: :cascade do |t| 
    t.integer "id" 
    t.string "description" 
    t.string "code_value" 
    t.integer "code_type_id" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
end 

add_index "codes", ["id"], name: "index_codes_on_id", unique: true, using: :btree 

сериализаторы

class ActivitySerializer < ActiveModel::Serializer 
    attributes :id, :name 
    has_many :values 
end 

class UDFValuesSerializer < ActiveModel::Serializer 
    attributes :foreign_id, :type_subject_area, :type_id, :text, :type_title 
end 

Как вы можете видеть, тип имеет много значений и кодов. Активность имеет много значений, хотя она относится только к значениям, которые имеют предметную область «Активность». Поскольку значения не имеют индивидуального первичного ключа, я не уверен, как его форматировать таким образом, чтобы он работал в Ember. Насколько я понимаю, Ember должен иметь идентификатор, доступный для получения значений.

Мысли? Идеи? Я боюсь, что это должно быть в этом формате, потому что Rails API взаимодействует и синхронизируется с другим, более крупным API.

ответ

0

У вас может быть только один первичный ключ на столе. Вы можете создать composite primary key, но поскольку ActiveRecord не поддерживает это, вам нужно найти способ сделать это. Есть composite_primary_keys gem, который утверждает, что добавляет эту поддержку, но я ее не использовал.

Однако, я не думаю, что это то, что вы хотите сделать здесь. Если foreign_id должен ссылаться на идентификатор в API, то это будет внешний ключ, а не первичный ключ, поскольку он относится к первичному ключу в другой таблице. Если вы хотите, чтобы гарантировать уникальность foreign_id на уровне SQL (в дополнение к использованию validates_uniqueness_of), добавьте индекс в миграции, как так:

add_index :values, :foreign_id, unique: true 

Если API использует как foreign_id и type_id в Составной ключ, возможно, вы хотите индексировать и как уникальный:

add_index :values, [:foreign_id, :type_id], unique: true 

Опять же, вы хотели бы добавить проверку на рельсах уровне, а также:

validates_uniqueness_of :foreign_id, scope: :type_id 

Это гарантирует, что все пары foreign_id, type_id уникальны.

Смежные вопросы