拥有并属于许多 API 个更新
Has and belongs to many API updates
我的 Rails 项目中有一个 has_and_belongs_to_many
。架构如下所示
create_table :dogs do |t|
t.string :name
t.string :breed
t.string :dog_type
end
create_table :users_dogs, id: false do |t|
t.belongs_to :user
t.belongs_to :dog
t.index ["user_id", "dog_id"], name: "by_user_and_dog", unique: true
t.index ["user_id"], name: "index_users_dogs_on_user_id"
t.index ["dog_id"], name: "index_users_dogs_on_dog_id"
end
create_table :users do |t|
t.string :name
t.string :email
end
还有我的模特
class User < ApplicationRecord
has_and_belongs_to_many :dogs
validate :only_one_good_dog_per_breed
validate :only_one_bad_dog_per_breed
validate :at_least_one_good_dog
end
class Dogs < ApplicationRecord
DOG_TYPES = %w[good bad].freeze
BREEDS = %w[poodle bulldog]
has_and_belongs_to_many :users
validates :name, :breed, :dog_type, presence: true
validates :breed,
inclusion: { in: BREEDS, allowed_options: BREEDS.join(", ") }
validates :dog_type,
inclusion: { in: DOG_TYPES, allowed_options: DOG_TYPES.join(", ") }
validates :name, uniqueness: { scope: [:breed, :dog_type] }
end
如您所见,用户可以养的狗有一些限制。他们每个品种只能有 1 dog_type。这个名字真的可以是任何东西。而且他们必须始终至少拥有一只好狗。
好的,现在回答我的问题。我的 API 客户有一个更新用户 API 路由。目前他们可以发送他们的 Dog id 作为用户参数的一部分来更新他们的狗。
def update
if @user.update(user_params)
render json: @user, status: :ok
else
render json: { errors: @user.errors }, status: :unprocessable_entity
end
end
private
def user_params
params.require(:user).permit(
:name,
dog_ids: []
)
end
现在我意识到,如果我的 API 客户想要执行以下任何操作,他们将必须始终发送所有用户狗 ID,更新其中一只狗的名字,添加新创建的 Dog 对象添加到用户拥有的狗的列表中,或者从属于用户的狗列表中删除狗。
截至目前,我的 API 只允许创建 Dog 对象。由于这些狗可以拥有并属于许多不同的用户,我不想直接更新或删除狗,因为这可能会影响我的其他共享狗的用户,而他们的狗根本没有改变。
我想知道我是否应该继续要求我的 API 客户端始终发送将与我的用户关联的所有 dog_ids。或者,如果我应该在我的用户 API 控制器中创建三个动作。一个是将一只狗添加到用户的狗列表中。一个是更新用户现有的狗(即,将新的 dog_id 关联到用户并删除共享新狗品种的现有狗 ID,并根据我的验证 dog_type)。以及从用户狗列表中删除狗的一个操作。
对于 has_and_belongs_to_many 类型的关系,这些 API 类型的典型特征是什么?
我不确定 API 这种关系的典型特征是什么。快速 Google 没有找到任何确定的主题。
但是,需要注意的一件事是,这不是经典 CRUD 意义上的资源管理。它正在管理资源之间的关联。
我想狗会使用传统的狗端点进行管理。例如创建一只新狗:
POST/api/v1/dogs
PARAMS:
- name
- breed
- dog_type
然后要创建或删除关联,API 客户端将向这些端点发出请求:
POST /api/v1/users/:user_id/dogs/:id
DELETE /api/v1/users/:user_id/dogs/:id
将对这些请求强制执行与用户相关的验证。
我的 Rails 项目中有一个 has_and_belongs_to_many
。架构如下所示
create_table :dogs do |t|
t.string :name
t.string :breed
t.string :dog_type
end
create_table :users_dogs, id: false do |t|
t.belongs_to :user
t.belongs_to :dog
t.index ["user_id", "dog_id"], name: "by_user_and_dog", unique: true
t.index ["user_id"], name: "index_users_dogs_on_user_id"
t.index ["dog_id"], name: "index_users_dogs_on_dog_id"
end
create_table :users do |t|
t.string :name
t.string :email
end
还有我的模特
class User < ApplicationRecord
has_and_belongs_to_many :dogs
validate :only_one_good_dog_per_breed
validate :only_one_bad_dog_per_breed
validate :at_least_one_good_dog
end
class Dogs < ApplicationRecord
DOG_TYPES = %w[good bad].freeze
BREEDS = %w[poodle bulldog]
has_and_belongs_to_many :users
validates :name, :breed, :dog_type, presence: true
validates :breed,
inclusion: { in: BREEDS, allowed_options: BREEDS.join(", ") }
validates :dog_type,
inclusion: { in: DOG_TYPES, allowed_options: DOG_TYPES.join(", ") }
validates :name, uniqueness: { scope: [:breed, :dog_type] }
end
如您所见,用户可以养的狗有一些限制。他们每个品种只能有 1 dog_type。这个名字真的可以是任何东西。而且他们必须始终至少拥有一只好狗。
好的,现在回答我的问题。我的 API 客户有一个更新用户 API 路由。目前他们可以发送他们的 Dog id 作为用户参数的一部分来更新他们的狗。
def update
if @user.update(user_params)
render json: @user, status: :ok
else
render json: { errors: @user.errors }, status: :unprocessable_entity
end
end
private
def user_params
params.require(:user).permit(
:name,
dog_ids: []
)
end
现在我意识到,如果我的 API 客户想要执行以下任何操作,他们将必须始终发送所有用户狗 ID,更新其中一只狗的名字,添加新创建的 Dog 对象添加到用户拥有的狗的列表中,或者从属于用户的狗列表中删除狗。
截至目前,我的 API 只允许创建 Dog 对象。由于这些狗可以拥有并属于许多不同的用户,我不想直接更新或删除狗,因为这可能会影响我的其他共享狗的用户,而他们的狗根本没有改变。
我想知道我是否应该继续要求我的 API 客户端始终发送将与我的用户关联的所有 dog_ids。或者,如果我应该在我的用户 API 控制器中创建三个动作。一个是将一只狗添加到用户的狗列表中。一个是更新用户现有的狗(即,将新的 dog_id 关联到用户并删除共享新狗品种的现有狗 ID,并根据我的验证 dog_type)。以及从用户狗列表中删除狗的一个操作。
对于 has_and_belongs_to_many 类型的关系,这些 API 类型的典型特征是什么?
我不确定 API 这种关系的典型特征是什么。快速 Google 没有找到任何确定的主题。
但是,需要注意的一件事是,这不是经典 CRUD 意义上的资源管理。它正在管理资源之间的关联。
我想狗会使用传统的狗端点进行管理。例如创建一只新狗:
POST/api/v1/dogs
PARAMS:
- name
- breed
- dog_type
然后要创建或删除关联,API 客户端将向这些端点发出请求:
POST /api/v1/users/:user_id/dogs/:id
DELETE /api/v1/users/:user_id/dogs/:id
将对这些请求强制执行与用户相关的验证。