#ruby-on-rails #rails-api #api-versioning
#ruby-on-rails #rails-api #api-управление версиями
Вопрос:
Я искал информацию о создании API-интерфейсов Rails и о том, как правильно применять некоторые версии для проверки моделей.
Предположим, что есть модель и маршрут, подобные этим:
class Person < ApplicationRecord
validates :name, presence: true
end
namespace :v1
resources :people
end
Итак, моя модель проверяет name
, присутствует ли она.
Но, если я хочу выпустить новую версию своего API с новой проверкой Person
, чтобы сделать, например, job
поле обязательным, как это:
class Person < ApplicationRecord
validates :name, presence: true
validates :job, presence: true
end
Если я сделаю это таким образом, я бы сломал свою конечную точку V1. Итак, есть ли хорошая практика, чтобы сделать это, не нарушая мою предыдущую конечную точку V1? Или я должен удалить эти проверки из модели и сделать это на уровне параметров запроса?
Я видел несколько драгоценных камней, которые делают это на уровне модели, но я хотел бы знать, есть ли для этого какой-то шаблон без использования какого-либо дополнительного драгоценного камня.
Ответ №1:
Самый простой способ добиться этого — использовать :on
option для ваших проверок и выполнять контекстные проверки, например
class Person < ApplicationRecord
validates :name, presence: true
validates :job, presence: true, on: :v2
end
Затем вы можете использовать person.valid?
в своей конечной точке v1 и person.valid?(:v2)
в конечной точке v2.
Но это решение достаточно хорошо только для простых сценариев, оно не масштабируется в долгосрочных или более сложных приложениях.
Лучшим решением было бы извлечь логику проверки для формирования объектов, созданных из ваших параметров, и иметь отдельные объекты формы для каждой версии ваших конечных точек, которые содержат некоторые критические изменения, например:
class PersonV1Form
include ActiveModel::Validations
attr_accessor :name, :job
validates :name, presence: true
def initialize(params = {})
@name = params[:name]
@job = params[:job]
end
end
class PersonV2Form
include ActiveModel::Validations
attr_accessor :name, :job
validates :name, :job, presence: true
def initialize(params = {})
@name = params[:name]
@job = params[:job]
end
end
Затем в ваших контроллерах вы можете просто проверять объекты формы, прежде чем использовать их для подачи вашей модели:
module V1
class PeopleController < ApplicationController
def create
person = PersonV1Form.new(params[:person])
if person.valid?
# ...
end
end
end
end
module V2
class PeopleController < ApplicationController
def create
person = PersonV2Form.new(params[:person])
if person.valid?
# ...
end
end
end
end