2

我有一个 Register 模型,它 has_many :telephones Register 模型接受_nested_attributes_for :telephones, :reject_if 号码和代码空白?,并且有 attr_accessible :telephones_attributes (以及所有其他字段)

电话belongs_to :register 并且所有字段都具有attr_accessible

当表单发送参数时,它似乎格式正确,但是当表单字段发送到 @register.attributes = params[:register] 时,它将更新所有字段,但不会更新现有电话(应该更新到它的字段也是如此),它们只是保持以前的样子(我在调试时检查过)

现在这是它变得奇怪的地方,在我测试它的控制台中,我认为它与参数有关,因为我可以让它在那里工作,现在我发现它的行为就像我想要的 has_many 关联只有在第一次之后我尝试分配它,我在控制器中尝试了这个(质量分配参数两次)并且它有效。

当然,它必须与我使用 model.attributes = params 分配的事实有关,我这样做是为了我还可以保存对系统更改的监视(而且我没有这样做在 before_filters 中,因为我必须访问一些我认为特定于控制器的数据,例如 current_user 和 on)可能是糟糕的设计......但这不是很奇怪吗?我必须批量分配两次才能工作?这是某种错误吗?有谁知道是否有办法解决它?

  • 我在 Rails 2.3.8,红宝石 1.8.6

编辑:这是示例代码,这里的很多代码都是葡萄牙语,虽然:/

电话 = 电话,地籍 = 登记

正如你所看到的,我有一个 all_changes 方法来聚合对某些关联所做的更改,还有一个用于注释的自定义设置器(commentario_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

您还应该注意到,您不需要在接受嵌套属性_for 中使用 reject_if 条件,因为您已经在验证基类中是否存在 :dd​​d 和 :numero 。

于 2010-12-17T23:39:49.170 回答