2 votes

Assurer l'unicité d'une valeur imbriquée dans JSONB dans Rails ActiveRecord sans self.class.exists ?

Normalement, nous pourrions utiliser self.class.exists?(api_key: api_key) pour vérifier si une autre ligne du tableau a une valeur avant de l'enregistrer :

def set_api_key
  self.api_key ||= loop do
    api_key = SecureRandom.hex(24)
    break api_key unless self.class.exists?(api_key: api_key)
  end
end

Mais dans cet exemple, api_key est en fait une valeur sur une colonne JSONB appelée config :

class User < ApplicationRecord
  before_validation :set_api_key, on: [:create]
  validates :api_key, presence: true, uniqueness: true

  store_accessor :config, :status, :plan, :api_key

  def set_api_key
    self.api_key ||= loop do
      api_key = SecureRandom.hex(24)
      break api_key unless self.class.exists?(api_key: api_key)
    end
  end
end

Supposons que :status , :plan , :api_key sont tous des attributs de premier niveau d'une colonne JSONB appelée config .

Cela se traduit par : ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column users.api_key does not exist

Existe-t-il un moyen simple de réaliser cela dans Rails, de la même façon que self.class.exists?(key: value) fonctionne ? Existe-t-il une requête SQL peu coûteuse à utiliser à la place ?

1voto

DanBrooker Points 146

Il existe des opérateurs spéciaux à utiliser avec json(b) ( Docs Postgres )

En ->> permet d'accéder à un élément jsonb sous la forme d'une chaîne de caractères, par exemple. config->>api_key au lieu de config.api_key

Vous devriez être en mesure de le faire self.class.exists?('config->>api_key = ?', api_key)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X