Ошибка? Я должен массово назначить параметры два раза, чтобы обновить ассоциацию has_many
У меня есть модель Register, в которой has_many:telephones Модель регистра accepts_nested_attributes_for:telephones,:reject_if number and code blank?, и имеет attr_accessible:telephones_attributes (и все другие поля)
Телефоны принадлежат: регистрируются и имеют атрибут attr_accessible для всех полей
Когда форма отправляет параметры, она кажется правильно сформированной, но когда поля формы отправляются на @register.attributes = params[:register], она обновит все поля, но не существующие телефоны (которые должны были получить обновление для поля тоже), они просто остаются прежними (я проверял при отладке)
Вот когда это становится странным, в консоли, когда я тестировал его, я думал, что это что-то с параметрами params, потому что я мог заставить его работать там, теперь я обнаружил, что он ведет себя так, как я хочу для ассоциации has_many, только после первого раза Я пытаюсь назначить это, я попробовал это в контроллере (массовое назначение параметров два раза), и это работает.
Конечно, это должно быть как-то связано с тем фактом, что я использую model.attributes = params для назначения, я делаю это таким образом, чтобы я также мог сохранить мониторинг изменений в системе (и я этого не делаю в before_filters, потому что я должен получить доступ к некоторым данным, которые, как мне кажется, специфичны для контроллера, например current_user и on), может быть, плохой дизайн... но разве это не странно? Мне нужно назначить два раза, чтобы это работало? Это какая-то ошибка? Кто-нибудь знает, есть ли способ это исправить?
- Я на рельсах 2.3.8, рубин 1.8.6
Изменить: Вот пример кода, большая часть этого кода здесь на португальском языке, tho:/
телефон = телефоны, кадастр = регистрация
Как вы можете видеть, у меня есть метод 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 ответ
В вашем примере неясно, как используется 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 в базовом классе.