heavenstudio / pag_seguro

A Ruby Client to deal with PagSeguro's API
http://heavenstudio.com.br
71 stars 38 forks source link

Erro ao tentar gerar o XML #10

Closed josuetex closed 11 years ago

josuetex commented 11 years ago

Exception: can't modify frozen object

Nessa linha: Haml::Engine.new(xml_content).render(nil, items: @items, payment: self, sender: @sender, shipping: @shipping, pre_approval: @pre_approval)

Do metodo: checkout_xml

Da Class: Payment

Alguém poderia me ajudar?

teonimesic commented 11 years ago

Por favor coloque o stack trace inteiro, e de preferência o código que está usando que gerou este problema, bem como a versão do ruby e da gem que está usando

josuetex commented 11 years ago

Versões:

Ruby 1.9.2-290 gem 'pag_seguro' (atual)

Código Ruby:

c = MikCobranca.find(params[:id])

  payment = PagSeguro::Payment.new(email, token, :id => c.id)

  payment.items = [PagSeguro::Item.new(:id => 1, :description => c.referente, 
                        :amount => c.valor.to_s,  
                        :quantity => "1")]

  payment.shipping = PagSeguro::Shipping.new(
    :state => c.empresa.uf,
    :city => c.empresa.cidade, :postal_code => c.empresa.cep,
    :district => c.empresa.bairro,
    :street => c.empresa.logradouro,
    :number => "1",
    :complement => c.empresa.complemento)

  if payment.valid?       
    redirect_to  payment.checkout_payment_url
  end

Full Trace:

haml (4.0.2) lib/haml/engine.rb:136:in block in render' haml (4.0.2) lib/haml/engine.rb:135:ininstance_eval' haml (4.0.2) lib/haml/engine.rb:135:in ensure in render' haml (4.0.2) lib/haml/engine.rb:135:inrender' /vagrant/pag_seguro/lib/pag_seguro/payment.rb:40:in checkout_xml' /vagrant/pag_seguro/lib/pag_seguro/payment.rb:85:insend_checkout' /vagrant/pag_seguro/lib/pag_seguro/payment.rb:89:in parse_checkout_response' /vagrant/pag_seguro/lib/pag_seguro/payment.rb:54:incode' /vagrant/pag_seguro/lib/pag_seguro/payment.rb:50:in checkout_payment_url' app/controllers/admin/minhas_cobrancas_controller.rb:89:inpagar' actionpack (3.0.9) lib/action_controller/metal/implicit_render.rb:4:in send_action' actionpack (3.0.9) lib/abstract_controller/base.rb:150:inprocess_action' actionpack (3.0.9) lib/action_controller/metal/rendering.rb:11:in process_action' actionpack (3.0.9) lib/abstract_controller/callbacks.rb:18:inblock in process_action' activesupport (3.0.9) lib/active_support/callbacks.rb:451:in _run__667204591__process_action__787652345__callbacks' activesupport (3.0.9) lib/active_support/callbacks.rb:410:in_run_process_action_callbacks' activesupport (3.0.9) lib/active_support/callbacks.rb:94:in run_callbacks' actionpack (3.0.9) lib/abstract_controller/callbacks.rb:17:inprocess_action' actionpack (3.0.9) lib/action_controller/metal/instrumentation.rb:30:in block in process_action' activesupport (3.0.9) lib/active_support/notifications.rb:52:inblock in instrument' activesupport (3.0.9) lib/active_support/notifications/instrumenter.rb:21:in instrument' activesupport (3.0.9) lib/active_support/notifications.rb:52:ininstrument' actionpack (3.0.9) lib/action_controller/metal/instrumentation.rb:29:in process_action' actionpack (3.0.9) lib/action_controller/metal/rescue.rb:17:inprocess_action' newrelic_rpm (3.6.0.78) lib/new_relic/agent/instrumentation/rails3/action_controller.rb:38:in block in process_action' newrelic_rpm (3.6.0.78) lib/new_relic/agent/instrumentation/controller_instrumentation.rb:272:inblock in perform_action_with_newrelic_trace' newrelic_rpm (3.6.0.78) lib/new_relic/agent/method_tracer.rb:235:in trace_execution_scoped' newrelic_rpm (3.6.0.78) lib/new_relic/agent/instrumentation/controller_instrumentation.rb:267:inperform_action_with_newrelic_trace' newrelic_rpm (3.6.0.78) lib/new_relic/agent/instrumentation/rails3/action_controller.rb:37:in process_action' actionpack (3.0.9) lib/abstract_controller/base.rb:119:inprocess' actionpack (3.0.9) lib/abstract_controller/rendering.rb:41:in process' actionpack (3.0.9) lib/action_controller/metal.rb:138:indispatch' actionpack (3.0.9) lib/action_controller/metal/rack_delegation.rb:14:in dispatch' actionpack (3.0.9) lib/action_controller/metal.rb:178:inblock in action' actionpack (3.0.9) lib/action_dispatch/routing/route_set.rb:62:in call' actionpack (3.0.9) lib/action_dispatch/routing/route_set.rb:62:indispatch' actionpack (3.0.9) lib/action_dispatch/routing/route_set.rb:27:in call' rack-mount (0.6.14) lib/rack/mount/route_set.rb:148:inblock in call' rack-mount (0.6.14) lib/rack/mount/code_generation.rb:93:in block in recognize' rack-mount (0.6.14) lib/rack/mount/code_generation.rb:96:inoptimized_each' rack-mount (0.6.14) lib/rack/mount/code_generation.rb:92:in recognize' rack-mount (0.6.14) lib/rack/mount/route_set.rb:139:incall' actionpack (3.0.9) lib/action_dispatch/routing/route_set.rb:493:in call' newrelic_rpm (3.6.0.78) lib/new_relic/rack/error_collector.rb:12:incall' newrelic_rpm (3.6.0.78) lib/new_relic/rack/agent_hooks.rb:18:in call' newrelic_rpm (3.6.0.78) lib/new_relic/rack/browser_monitoring.rb:16:incall' newrelic_rpm (3.6.0.78) lib/new_relic/rack/developer_mode.rb:28:in call' exception_notification (3.0.1) lib/exception_notifier.rb:41:incall' warden (1.0.5) lib/warden/manager.rb:35:in block in call' warden (1.0.5) lib/warden/manager.rb:34:incatch' warden (1.0.5) lib/warden/manager.rb:34:in call' client_side_validations (3.1.0) lib/client_side_validations/middleware.rb:18:incall' actionpack (3.0.9) lib/action_dispatch/middleware/best_standards_support.rb:17:in call' actionpack (3.0.9) lib/action_dispatch/middleware/head.rb:14:incall' rack (1.2.3) lib/rack/methodoverride.rb:24:in call' actionpack (3.0.9) lib/action_dispatch/middleware/params_parser.rb:21:incall' actionpack (3.0.9) lib/action_dispatch/middleware/flash.rb:182:in call' actionpack (3.0.9) lib/action_dispatch/middleware/session/abstract_store.rb:149:incall' actionpack (3.0.9) lib/action_dispatch/middleware/cookies.rb:302:in call' activerecord (3.0.9) lib/active_record/query_cache.rb:32:inblock in call' activerecord (3.0.9) lib/active_record/connection_adapters/abstract/query_cache.rb:28:in cache' activerecord (3.0.9) lib/active_record/query_cache.rb:12:incache' activerecord (3.0.9) lib/active_record/query_cache.rb:31:in call' activerecord (3.0.9) lib/active_record/connection_adapters/abstract/connection_pool.rb:354:incall' actionpack (3.0.9) lib/action_dispatch/middleware/callbacks.rb:46:in block in call' activesupport (3.0.9) lib/active_support/callbacks.rb:416:in_run_call_callbacks' actionpack (3.0.9) lib/action_dispatch/middleware/callbacks.rb:44:in call' rack (1.2.3) lib/rack/sendfile.rb:107:incall' actionpack (3.0.9) lib/action_dispatch/middleware/remote_ip.rb:48:in call' actionpack (3.0.9) lib/action_dispatch/middleware/show_exceptions.rb:47:incall' railties (3.0.9) lib/rails/rack/logger.rb:13:in call' rack (1.2.3) lib/rack/runtime.rb:17:incall' activesupport (3.0.9) lib/active_support/cache/strategy/local_cache.rb:72:in call' rack (1.2.3) lib/rack/lock.rb:11:inblock in call' internal:prelude:10:in synchronize' rack (1.2.3) lib/rack/lock.rb:11:incall' actionpack (3.0.9) lib/action_dispatch/middleware/static.rb:30:in call' railties (3.0.9) lib/rails/application.rb:168:incall' railties (3.0.9) lib/rails/application.rb:77:in method_missing' railties (3.0.9) lib/rails/rack/log_tailer.rb:14:incall' rack (1.2.3) lib/rack/content_length.rb:13:in call' rack (1.2.3) lib/rack/handler/webrick.rb:52:inservice' /home/vagrant/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/webrick/httpserver.rb:111:in service' /home/vagrant/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/webrick/httpserver.rb:70:inrun' /home/vagrant/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/webrick/server.rb:183:in `block in start_thread'

kurko commented 11 years ago

@josuetex se você fizer downgrade para 0.4.1, o problema persiste?

teonimesic commented 11 years ago

Você pode olhar o Gemfile.lock para dizer a versão exata da gem? Seria a 0.5.2?

E qual a versão do rails que está usando? Vou criar um projeto rails nestas versões para testar o problema.

josuetex commented 11 years ago

@kurko Ainda não fiz o downgrade.

@teonimesic As versões são:

pag_seguro 0.5.2 Rails 3.0.9

teonimesic commented 11 years ago

@josuetex se puder me passar também o schema da tabela mik_cobrancas ( só copiar o código do db/schema.rb desta tabela ), e se possível me dá um um "seed" de um MikCobranca que não funciona para agilizar o teste aqui.

josuetex commented 11 years ago

Quanto ao seed, nenhum funciona. Creio que isso está relacionado ao ambiente Rails, pois funcionou fora do ambiente Rails.

create_table "mik_cobrancas", :force => true do |t| t.integer "empresa_id" t.date "vencimento" t.float "valor" t.date "data_pagamento" t.float "valor_pago" t.integer "situacao_id" t.integer "num_pagamento" t.string "referente" t.string "tipo_cobranca" t.text "obs" t.string "mes_referente" t.float "desconto" t.float "acrescimo" t.string "ps_code_transacao" t.datetime "created_at" t.datetime "updated_at" t.string "cadastrado_por" t.string "modificado_por" end

teonimesic commented 11 years ago

Agora que vi que a empresa está em uma tabela separada, passa o schema da empresa também? Em relação ao seed, eu só queria um valor para estes elementos que não funcionam para fazer um teste. Algo como MikCobranca.first.attributes e Empresa.first.attributes. Não necessariamente precisa ser o primeiro, pode ser qualquer um que puder copiar para o qual o problema ocorre.

josuetex commented 11 years ago

Empresa (retirei o cpf):

{"ativa"=>true, "bairro"=>"Gleba C", "bloqueio_automatico"=>false, "celular"=>"", "cep"=>"42800000", "cidade"=>"Bahia", "complemento"=>"", "cpf_cnpj"=>"00000000000", "created_at"=>Ter, 08 Nov 2011 14:17:00 BRST -02:00, "dia_vencimento"=>"1", "dias_para_bloqueio"=>10, "email_empresa"=>"pvchip1@gmail.com", "email_provedor"=>"pvchip1@gmail.com", "email_recebimento_relatorio"=>"pvchip1@gmail.com", "id"=>1, "logo_content_type"=>nil, "logo_file_name"=>nil, "logo_file_size"=>nil, "logo_updated_at"=>nil, "logradouro"=>"Rua I Quadra 2", "mensagem_pendencia_automatica"=>true, "mensalidade_automatica"=>true, "mik_plano_id"=>1, "nome"=>"Paulo Vinicius", "nome_fantasia"=>"WIFI-ZONE", "numero"=>nil, "situacao_empresa"=>nil, "status_acesso"=>"L", "status_financeiro"=>"L", "subdominio"=>"wifizone", "telefone"=>"(71) 8752-1246", "telefone_provedor"=>"(71) 8752-1246", "tipo"=>"Física", "uf"=>"BA", "updated_at"=>Sex, 29 Mar 2013 11:19:00 BRT -03:00, "valor_unitario"=>1.0}

{"acrescimo"=>nil, "cadastrado_por"=>nil, "created_at"=>Sab, 27 Abr 2013 21:08:51 BRT -03:00, "data_pagamento"=>nil, "desconto"=>nil, "empresa_id"=>1, "id"=>883, "mes_referente"=>nil, "modificado_por"=>nil, "num_pagamento"=>1, "obs"=>nil, "ps_code_transacao"=>nil, "referente"=>"Mensalidade MikWeb", "situacao_id"=>1, "tipo_cobranca"=>"M", "updated_at"=>Sab, 27 Abr 2013 21:08:51 BRT -03:00, "valor"=>30.0, "valor_pago"=>nil, "vencimento"=>Dom, 28 Abr 2013}

teonimesic commented 11 years ago

Ótimo, se puder só copiar também no schema.rb a parte da tabela da empresa que já devo conseguir fazer um teste bem próximo do que tem aí!

josuetex commented 11 years ago

create_table "empresas", :force => true do |t| t.string "nome" t.string "tipo" t.string "cpf_cnpj" t.string "telefone" t.string "celular" t.datetime "created_at" t.datetime "updated_at" t.boolean "mensalidade_automatica", :default => true t.boolean "ativa", :default => true t.string "situacao_empresa" t.text "email_recebimento_relatorio" t.string "email_empresa" t.string "subdominio" t.string "nome_fantasia" t.string "email_provedor" t.string "telefone_provedor" t.string "cep" t.string "logradouro" t.string "numero" t.string "complemento" t.string "bairro" t.string "cidade" t.string "uf" t.string "logo_file_name" t.string "logo_content_type" t.string "logo_file_size" t.datetime "logo_updated_at" t.float "valor_unitario" t.string "dia_vencimento" t.string "status_financeiro" t.string "status_acesso" t.integer "mik_plano_id" t.boolean "bloqueio_automatico", :default => true t.boolean "mensagem_pendencia_automatica", :default => true t.integer "dias_para_bloqueio", :default => 10 end

teonimesic commented 11 years ago

@josuetex eu criei um projeto novo em rails, contendo o minímo necessário para reproduzir seu código, mas ele funcionou corretamente. Segue o link do projeto: https://github.com/teonimesic/test_pag_seguro_frozen_error

Neste projeto eu só crio um MikCobranca, uma Empresa, e gero um pagamento com o mesmo código que colocou acima.

Baixe e rode ele e veja se o problema persiste em sua máquina. Acredito que o problema esteja em alguma outra Gem que esteja alterado algum dos parametros que esteja tentando enviar. Aconselho que utilize este projeto que criei como base, e vá lentamente adicionando novas gems e o código dos models (empresa e MikCobranca) até que encontre o culpado por alterar a classe String ou dar freeze nas Strings. Em especial, acredito que o problema talvez seja a gem que use para trabalhar com o campo de CPF/CNPJ.

Não vejo muito mais como posso ajudar, pois não consegui reproduzir o problema em minha máquina nas versões especificadas.

teonimesic commented 11 years ago

Apenas para esclarecer melhor, o problema parece ser que alguma outra Gem que esteja usando faça um freeze em algum dos objetos que está passando como parâmetro. Você pode checar se um objeto está "frozen" ou não utilizando o método frozen?, e.g.: c.empresa.cidade.frozen?.

O problema é que um objeto congelado não permite que nada nela seja alterado. Seria até possível alterar toda a gem para "duplicar" os argumentos de entrada ao invés de usá-los diretamente, mas isso me parece um pouco inapropriado e geraria muito código desnecessário.

teonimesic commented 11 years ago

Outra possibilidade que pensei, talvez mais rápida que a anterior, é você usar o método dup em suas string:

payment = PagSeguro::Payment.new(email.dup, token.dup, :id => c.id.dup)

payment.items = [PagSeguro::Item.new(:id => 1, :description => c.referente.dup, 
  :amount => c.valor.to_s.dup,  
  :quantity => "1")]

payment.shipping = PagSeguro::Shipping.new(
  :state => c.empresa.uf.dup,
  :city => c.empresa.cidade.dup, :postal_code => c.empresa.cep.dup,
  :district => c.empresa.bairro.dup,
  :street => c.empresa.logradouro.dup,
  :number => "1",
  :complement => c.empresa.complemento.dup)

Este método simplesmente cria uma cópia do Objeto, mas sem manter seu status original ( no caso criar uma cópia não "frozen" do objeto ).

teonimesic commented 11 years ago

Caso o código acima funcione, peço que vá removendo os dups até que encontre o responsável pelo problema. Com isto em mãos, vou reavaliar o código da gem para ver se ela está fazendo algo esquisito com este parâmetro de entrada.

kurko commented 11 years ago

Acho que o ideal seria @josuetex pushar uma app Rails dummy com o problema acontecendo para que a gente pudesse olhar. Afinal, ele está conseguindo reproduzir o problema.

josuetex commented 11 years ago

Não funcionou o dup ... Algo está errado no Haml no meu ambiente. Teste fora dele e deu certo. Irei tentar rodar alguma coisa do Haml fora desse contexto do pag_seguro.

josuetex commented 11 years ago

O problema realmente estava no método que passei:

Haml::Engine.new(xml_content).render(nil, items: @items, payment: self, sender: @sender, shipping: @shipping, pre_approval: @pre_approval)

Em vez do primeiro parametro ser nil eu coloquei Object.new conforme abaixo:

Haml::Engine.new(xml_content).render(Object.new, items: @items, payment: self, sender: @sender, shipping: @shipping, pre_approval: @pre_approval)

Na documentação o valor padrão é Object.new.

O por que? Eu ainda não sei, mas vou descobrir.

Valeu!!!

josuetex commented 11 years ago

E aí, faço um fork e corrijo pra mim ou vão modificar alguma coisa ?

teonimesic commented 11 years ago

Qual a versão do haml que aparece no gemfile.lock?

josuetex commented 11 years ago

4.0.2

teonimesic commented 11 years ago

Arghh! Que erro esquisito hahaha! Coloquei essa versão do Haml mas mesmo assim não deu problema. Está usando haml-rails? Qual versão? Esse é o último teste que tento para reproduzir o problema, se não der certo eu altero o código para usar Object.new e dane-se!

josuetex commented 11 years ago

Não estou usando haml-rails.

josuetex commented 11 years ago

@teonimesic Posso referenciar a gem 'pag_seguro' ou gem 'pag_seguro', :git => 'git://github.com/heavenstudio/pag_seguro.git' ?

teonimesic commented 11 years ago

@josuetex eu alterei a versão da gem também para 0.5.3 com a correção. Use gem 'pag_seguro', '>=0.5.3'

josuetex commented 11 years ago

Valeu!

teonimesic commented 11 years ago

Vou dar o problema (seja lá como acontece) por encerrado. Qualquer coisa reabra o problema