Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

407
Visualizações
¿Manera limpia de implementar la validación en rutas no crudas en Rails?

¿Cómo implementa la validación en rutas NO CRUD? Por ejemplo, hay una ruta para buscar recipes . Acepta parámetros de term (para búsqueda), sort , page , etc.

¿Cuál es la mejor manera de hacer esto en Rails?

La solución más sencilla sería validar todas estas cosas usando el montón de expresiones if-else en el controlador, pero estoy buscando algo más limpio y más fácil para la extensión y el mantenimiento.

terminé con lo siguiente

 class RequestValidation attr_reader :validators attr_reader :errors def initialize @validators = [] @errors = [] end def add_validator(validator) @validators << validator end def validate @validators.each do |validator| validator.validate @errors += validator.errors end end def valid? validate errors.empty? end end

Ejemplo de clase de validador

 class SortValidator < Validator VALID_SORT_FIELD = [:created_at, :rate, :total_time] VALID_SORT_DIRECTIONS = [:asc, :desc] def validate return unless param valid = true begin sort = param.to_unsafe_h if sort.size == 1 k = sort.keys[0].to_sym v = sort.values[0].to_sym valid = VALID_SORT_FIELD.include?(k) && VALID_SORT_DIRECTIONS.include?(v) else valid = false end rescue => ex valid = false end @errors << "Sort parameter invalid" unless valid end def is_valid? !errors.empty? end end

Entonces, RequestValidation es como una clase de constructor/contenedor para todos los validadores. Y luego, en el controlador:

 validation = RequestValidation.new validation.add_validator(RecipesValidators::SortValidator.new(params[:sort])) validation.validate if validation.errors.empty?

De esta manera, cuando se requiere una nueva validación, solo necesitamos crear una nueva clase de Validador y agregarla para solicitar la validación.

Dado que me tomé una pausa de Rails durante varios años, existen dudas sobre si este código es limpio y ordenado y de acuerdo con los principios de Ruby.

¿O hay un mejor camino?

Gracias por adelantado

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

Hoy en día iría poniendo algún contrato y una estructura fuertemente tipada entre el controlador y la base de datos.

Algo como:

 # obtain an instance of RecipeSearchParamsContract def contract @contract ||= SomeValidationContract.new end # obtain an instance of a coercing struct def input MyStruct.new(params) end def query MyQuery.new end def your_action if contract.call(params).success? render query.call(input) end end

Entonces estás separando completamente todas las preocupaciones. Buenas librerías para basar tu código son dry-validator y dry-struct , con las cuales puedes generar un contrato de la siguiente manera:

 class SearchParamsContract < Dry::Validation::Contract params do optional(:sort).hash(max_size?: 1) do optional(:rate).value(included_in?: %w[asc desc]) optional(:created_at).value(included_in?: %w[asc desc]) optional(:total_time).value(included_in?: %w[asc desc]) end optional(:page).value(:integer) optional(:term).filled(:string) end end

Usando esto, la estructura forzada y validada está disponible en el resultado mismo, por lo que puede encadenar todo y usar la coincidencia de patrones estructurales para obtener un código increíble y muy rubí (sin rieles extra)

 def search case contract.call(params) in Success(input) @recipes = query.call(input) else render :error end end
over 4 years ago · Santiago Trujillo Relatório

0

La solución aquí nunca fue realmente un validador personalizado; en su lugar, debe crear una clase como un modelo o un objeto de formulario para encapsular las validaciones y los datos. El hecho de que su acción no persista no significa que no pueda usar un modelo para representar datos y lógica empresarial.

 class RecipeSearch include ActiveModel::Model include ActiveModel::Attributes attribute :query, :string attribute :sort_by, :string # ... validates :query, length: { minimum: 5 } validates :sort_by, in: ['newest', 'quickest', 'cheapest'] # ... # @todo apply filters to Recipe and return collection def perform # ... end end

Esto le permite agregar validaciones y lógica. Y pasarlo a formularios:

 <%= form_with(model: local_assigns(:recipe_seach) || RecipeSearch.new) do |f| %> # ... <% end %>

También es un error pensar que la búsqueda no puede ser parte de CRUD. Después de todo, es solo lectura con filtros aplicados. Si realmente necesita una vista separada de su índice normal, entonces cree una acción de búsqueda separada, pero no es realmente una necesidad.

 class RecipesController def index @recipe_search = RecipeSearch.new(search_params) @recipes = @recipe_search.perform end private def search_params params.fetch(:recipe_search, {}) .permit(:query, :sort_by) end end
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda