Ошибка? Я должен массово назначить параметры два раза, чтобы обновить ассоциацию has_many - PullRequest
2 голосов
/ 16 декабря 2010

У меня есть модель Register, которая has_many: телефоны Зарегистрируйте модель accepts_nested_attributes_for: телефоны,: reject_if, номер и код незаполнен?

Телефоны принадлежат_ для регистрации и имеют атрибут attr_accessible для всех полей

Когда форма отправляет параметры, она кажется правильно сформированной, но когда поля формы отправляются на @ register.attributes = params [: register], она обновит все поля, но не существующие телефоны (которые должны были быть получены обновление для его полей), они просто остаются прежними (я проверял при отладке)

Теперь это то, где это становится странным, в консоли, когда я тестировал его, я думал, что это что-то с параметрами, потому что я мог заставить его работать там, теперь я обнаружил, что он ведет себя так, как я хочу для ассоциации has_many, только после в первый раз, когда я пытаюсь назначить его, я попробовал это в контроллере (массовое назначение параметров два раза), и это работает.

Конечно, это должно быть как-то связано с тем фактом, что я использую model.attributes = params для назначения, я делаю это таким образом, чтобы я также мог сохранить мониторинг изменений в системе (и я не делать это в before_filters, потому что мне нужно получить доступ к некоторым данным, которые, как мне кажется, специфичны для контроллера, например current_user и on), может быть, это плохой дизайн ... но не странно ли? ? Это какая-то ошибка? Кто-нибудь знает, есть ли способ это исправить?

  • Я на рельсах 2.3.8, рубин 1.8.6

Edit: Вот пример кода, большая часть этого кода здесь на португальском языке, tho: /

telefone = телефоны, кадастр = регистрация

Как вы можете видеть, у меня есть метод all_changes, который объединяет изменения, внесенные в некоторые ассоциации, есть пользовательский установщик для комментариев (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]}

1 Ответ

0 голосов
/ 18 декабря 2010

В вашем примере неясно, как используется 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

Вы также должны заметить, что вам не нужно условие reject_if в вашем accepts_nested_attributes_for, потому что вы уже проверяете наличие: ddd и: Numberro в базовом классе.

...