2

私は has_many :telephones Register model accept_nested_attributes_for :telephones, :reject_if number and code blank? を持ち、attr_accessible :telephones_attributes (および他のすべてのフィールド) を持つ Register モデルを持っています。

電話は belongs_to :register で、すべてのフィールドに attr_accessible があります

フォームがパラメーターを送信するとき、それは適切に形成されているように見えますが、フォームフィールドが @register.attributes = params[:register] に送信されると、すべてのフィールドが更新されますが、既存の電話は更新されません (更新を取得する必要があります)。そのフィールドも)、以前の状態のままです(デバッグ時に確認しました)

これは奇妙なところです。コンソールでテストすると、params に関するものだと思っていました。そこで動作させることができたので、初めて has_many 関連付けに対して必要なように動作することを発見しました。私はそれを割り当てようとしましたが、コントローラーでこれを試しました(大量割り当てパラメーターを2回)が機能します。

もちろん、私が model.attributes = params を割り当てに使用しているという事実と関係があるに違いありません。私はこの方法でそれを行っているので、システムへの変更の監視を保存することもできます(そして、私はこれを行っていません)。私は current_user のようなコントローラーに固有であると感じるいくつかのデータにアクセスする必要があるため、 before_filters で)おそらく設計が不十分です...しかし、それは奇妙ではありませんか?これが機能するには、2回一括割り当てする必要がありますか? これは何かのバグですか?それを修正する方法があるかどうか誰かが知っていますか?

  • 私はレール2.3.8、ルビー1.8.6を使用しています

編集: これがサンプル コードです。このコードの多くはポルトガル語です。

telefone = 電話、cadastro = レジスター

ご覧のとおり、いくつかの関連付けに対して行われた変更を集約する all_changes メソッドを持っています。一度に 1 つのコメントを追加する手段として、comments(comentario_interno/externo) のカスタム セッターがあります...

    #models

class Telefone < ActiveRecord::Base
  #relações
  belongs_to :cadastro
  #validações
  validates_presence_of :ddd
  validates_presence_of :numero
  validates_numericality_of :ddd
  validates_numericality_of :numero

  attr_accessible :ddd, :numero, :cadastro_id, :id

end

class Cadastro < ActiveRecord::Base
  #relações
  #cliente
  belongs_to :estado
  belongs_to :indicacao
  has_many :telefones
  has_one :outra_indicacao
  #venda
  belongs_to :user
  belongs_to :banco
  belongs_to :plano
  belongs_to :pacote
  belongs_to :situacao
  belongs_to :situacao_diversa
  has_many :comentario_internos
  has_many :comentario_externos

  #system
  #has_many :sys_logs
  has_many :sys_logs, :as => :monitorable
  has_many :email_history, :through => :sys_logs, :conditions => {:type => 'SysEmail'} , :source => :sys_actions
  has_many :lock_history, :through => :sys_logs, :conditions => {:type => 'SysLock'}, :source => :sys_actions
  has_many :alteracao_history, :through => :sys_logs, :conditions => {:type => 'SysAlteracao'}, :source => :sys_actions

  #filtros

  #validações
  #cliente
  validates_presence_of :tipo, :nome, :cpfcnpj, :rg, :data_nascimento, :profissao, :filiacao, :email, :logradouro,
                        :tp_logradouro, :numero, :bairro, :cep, :cidade
  validates_uniqueness_of :cpfcnpj
  validates_presence_of :estado
  #validate :must_have_at_least_one_telephone
  #venda
  validates_presence_of :user
  validates_presence_of :situacao
  validates_numericality_of :agencia, :allow_blank => true
  validates_numericality_of :digito_agencia, :allow_blank => true
  validates_numericality_of :cc, :allow_blank => true
  validates_numericality_of :digito_cc, :allow_blank => true
  validates_numericality_of :cpf_titular, :allow_blank => true
  #cpf must be unique




  accepts_nested_attributes_for :telefones, :reject_if => lambda {|attr| attr['ddd'].blank? && attr['numero'].blank?}
  accepts_nested_attributes_for :outra_indicacao
  accepts_nested_attributes_for :comentario_internos, :reject_if => lambda {|attr| attr['comentario'].blank?}
  accepts_nested_attributes_for :comentario_externos, :reject_if => lambda {|attr| attr['comentario'].blank?}

  #attr_accessible :new_comentario_interno, :new_comentario_externo, :telefones_attributes

  attr_accessible :telefones_attributes, :new_comentario_interno, :new_comentario_externo, :outra_indicacao_attributes,
                  :user_id, :cc, :digito_cc, :data_instalacao, :cpfcnpj, :profissao, :tp_logradouro, :agencia, :cpf_titular,
                  :situacao_id, :estado_id, :plano_id, :banco_id, :nome, :data_nascimento, :cep, :observacao, :data_agendamento,
                  :dia_vencimento, :digito_agencia, :pacote_id, :nome_titular, :logradouro,
                  :indicacao_id, :telefones_attributes, :contrato, :confirmacao_condicoes, :estado_civil, :cidade,
                  :horario_retorno, :tipo, :sexo, :filiacao, :complemento, :bairro, :rg, :expeditor, :email, :numero,
                  :situacao_diversa_id

  def new_comentario_interno=(attributes = {})
    self.comentario_internos << ComentarioInterno.new(:user_id => attributes[:user_id], :comentario => attributes[:comentario]) unless attributes[:comentario].blank?
  end

  def new_comentario_externo=(attributes = {})
    self.comentario_externos << ComentarioExterno.new(:user_id => attributes[:user_id], :comentario => attributes[:comentario]) unless attributes[:comentario].blank?
  end

  def self.buscar_cadastros(options = {})
    conditions = []
    conditions << sanitize_sql(["cadastros.situacao_id = ?", options[:situacao_id]]) unless options[:situacao_id].blank?
    conditions << sanitize_sql(["cadastros.user_id = ?", options[:user_id]]) unless options[:user_id].blank?
    conditions << sanitize_sql(["cadastros.created_at >= ? AND cadastros.created_at < ?",
                                Date.civil(options[:ano].to_i, options[:mes].to_i, 1),
                                Date.civil(options[:ano].to_i, options[:mes].to_i, -1)]) unless options[:ano].blank? || options[:mes].blank?

    self.find(:all, :conditions => conditions.join(" AND "))
  end

  def self.vendas_count_on(situacao_id, options = {})
    select = sanitize_sql(["SELECT count(*) FROM cadastros LEFT JOIN situacaos ON cadastros.situacao_id = situacaos.id
    WHERE situacaos.id = ?", situacao_id])
    select << sanitize_sql([" AND cadastros.user_id = ?", options[:user_id]]) unless options[:user_id].blank?
    select << sanitize_sql([" AND cadastros.created_at >= ? AND cadastros.created_at < ?",
                            Date.civil(options[:ano].to_i, options[:mes].to_i, 1),
                            Date.civil(options[:ano].to_i, options[:mes].to_i, -1)]) unless options[:ano].blank? || options[:mes].blank?

    count_by_sql(select)
  end

  def all_changes
    #agregar telefones, outra indicacao, comentarios internos, comentarios externos
    changes = self.changes
    h = Hash.new
    h["outra_indicacao"] = self.outra_indicacao.descricao_change if self.outra_indicacao && self.outra_indicacao.changed?

    if self.id
      old_telefones = connection.execute("select ddd || '-' || numero as numformat from telefones where cadastro_id = #{self.id}").collect {|t| t["numformat"]}
    else
      old_telefones = []
    end
    new_telefones = self.telefones.collect {|t| "#{t.ddd}-#{t.numero}"}
    h["telefones"] = [old_telefones.join(', '), new_telefones.join(', ')] unless (old_telefones - new_telefones).empty?
    changes.delete("syslogid")
    changes.merge(h)
  end

  def locked?
    #pegar o ultimo lock e retornar o valor
    last_lock = self.lock_history.last
    if last_lock
      return last_lock.locked?
    else
      return false
    end
  end

end

#here's what Ive got to do in controller for this to work, remember its only when updating existing phones, creating is working normally

@cadastro.attributes = params[:cadastro]
    @cadastro.attributes = {:telefones_attributes => params[:cadastro][:telefones_attributes]}
4

1 に答える 1

0

あなたの例では、 all_changes がどのように使用されているか、または呼び出されているかどうかは明確ではありません。コードを単純化して、問題が実際に Rails にあるのか、実装にあるのかを確認してください。たとえば、次のように動作するはずです。

class Telefone < ActiveRecord::Base
  belongs_to :cadastro
  validates_presence_of :ddd
  validates_presence_of :numero
  validates_numericality_of :ddd
  validates_numericality_of :numero
end

class Cadastro < ActiveRecord::Base
  has_many :telefones

  accepts_nested_attributes_for :telefones
end

@cadastro.attributes = {:telefones_attributes => [{:ddd => 111, :numero => 1234567}]}
@cadastro.save

また、基本クラスで :ddd と :numero の存在を既に検証しているため、accepts_nested_attributes_for で reject_if 条件が必要ないことにも注意してください。

于 2010-12-17T23:39:49.170 に答える