web-dev-qa-db-fra.com

Rails has_many avec des conditions dynamiques

Ce que je veux, c'est créer un modèle qui se connecte à un autre en utilisant une association has_many de manière dynamique, sans la clé étrangère comme ceci:

has_many :faixas_aliquotas, :class_name => 'Fiscal::FaixaAliquota',
            :conditions => ["regra_fiscal = ?", ( lambda { return self.regra_fiscal } ) ]

Mais je reçois l'erreur:

: SELECT * FROM "fis_faixa_aliquota" WHERE ("fis_faixa_aliquota".situacao_fiscal_id = 1
AND (regra_fiscal = E'--- !Ruby/object:Proc {}'))

Est-ce possible?

56
Fabiano Soriani

Rails 4+ way (Merci à Thomas qui a répondu ci-dessous):

has_many :faixas_aliquotas, -> (object) { 
           where("regra_fiscal = ?", object.regra_fiscal)
         },
         :class_name => 'Fiscal::FaixaAliquota'

Rails 3.1+:

has_many :faixas_aliquotas, :class_name => 'Fiscal::FaixaAliquota',
         :conditions => proc { "regra_fiscal = #{self.regra_fiscal}" }

Rails 3 et inférieurs:

has_many :faixas_aliquotas, :class_name => 'Fiscal::FaixaAliquota',
         :conditions => ['regra_fiscal = #{self.regra_fiscal}']

Non, ce n'est pas une erreur. Les conditions sont spécifiées entre guillemets simples et contiennent toujours le code #{self.regra_fiscal}. Lorsque la clause conditions est évaluée, la méthode regra_fiscal sera appelée sur l'objet de self (quelle que soit la classe). Mettre des guillemets doubles ne fonctionnera pas.

J'espère que c'est ce que vous recherchez.

95
Chirantan

Rails 4 + façon:

has_many :faixas_aliquotas, -> (object){ where("regra_fiscal = ?", object.regra_fiscal)},  :class_name => 'Fiscal::FaixaAliquota'
55
Thomas

Il existe un autre type de solution. Cependant, ce ne sera pas la portée par défaut.

has_many :faixas_aliquotas, :class_name => 'Fiscal::FaixaAliquota' do 
  def filter(situacao_fiscal)
    find(:all, :conditions => {:regra_fiscal => situacao_fiscal.regra_fiscal})
  end
end

De cette façon, vous seriez en mesure de faire

situacao_fiscal.faixas_aliquotas.filter(situacao_fiscal)

Je ne sais pas si c'est élégant et quelque chose qui résoudrait votre problème. Il peut y avoir de meilleures façons de procéder.

8
Chirantan

Rails 4 + d'une autre manière:

has_many :faixas_aliquotas, -> (object){ where(regra_fiscal: object.regra_fiscal) }, :class_name => 'Fiscal::FaixaAliquota'
4
GeoffreyHervet

Dans Rails 3.1 besoin d'utiliser proc, Proc.new {"field = # {self.send (: other_field)}"}

3
Amala

Dans Rails 3.1 vous pouvez utiliser Proc.new pour vos conditions. Comme indiqué par @Amala, mais générez à la place un hachage comme ceci:

has_many :faixas_aliquotas, :class_name => 'Fiscal::FaixaAliquota',
   :conditions => {:regra_fiscal => Proc.new { {:regra_fiscal => self.regra_fiscal} }

L'avantage de cette approche est que si vous faites object.faixas_aliquotas.build, l'objet nouvellement créé aura automatiquement le même regra_fiscal attribut comme parent.

1
bayfieldcoder