Excesso de cookies no aplicativo Rails?

106

ActionDispatch :: Cookies :: CookieOverflow em UsersController # create

Eu tenho este erro quando tento abrir a página. Não sei como depurar esse erro. Você tem alguma sugestão para este problema?

def create
  @user = User.new(params[:user])
  sign_in @user

  if @user.save
    @user.folders.create(:folder_name=>"Default Folder", :user_id=>@user.id)
    flash[:success] = "Welcome to Bunch<it>! "
    redirect_to @user
  else
    @title = "Sign up"
    render 'new'
  end
end


def sign_in(user)
  cookies.permanent.signed[:remember_token] = [user.id, user.salt]
  session[:current_user] = user
  current_user = user
end
erogol
fonte
1
este erro ocorre quando você tem dados / objetos grandes na sessão. Você pode compartilhar o código para criar ação no controlador?
Naren Sisodiya
3
Embora as respostas sobre como alterar seu armazenamento de sessão estejam corretas, eu questiono por que você deseja armazenar o usuário inteiro na sessão. Se você tiver que armazenar algo, armazene o user_id (embora já esteja em seu cookie)
Frederick Cheung
Basta ir ao armazenamento de cache do navegador e limpar os cookies pertencentes ao URL desse site específico. para mim, isso acontece principalmente no localhost.
ben
Eu criei um modelo de usuário com Devisee não reiniciei meu servidor de desenvolvimento depois de executar as migrações. Assim que o fiz, o erro parou.
wuliwong

Respostas:

159

Você tem um limite de 4kb para o que você pode armazenar em um cookie, e quando o Rails converte seu objeto em texto para escrever no cookie, provavelmente é maior que esse limite.

ActionDispatch::Cookies::CookieOverflowErro de Ruby on Rails

Assim CookieOverflowocorre esse erro.

A maneira mais fácil de resolver este é, você precisa alterar seu session_store e não usar o cookie_store. Você pode usar o active_record_storepor exemplo.

Aqui estão os passos

  1. Gere uma migração que cria a tabela de sessão

    rake db:sessions:create
  2. Execute a migração

    rake db:migrate
  3. Modificar config/initializers/session_store.rbde

    (App)::Application.config.session_store :cookie_store, :key => 'xxx'

    para

    (App)::Application.config.session_store :active_record_store

Depois de realizar as três etapas, reinicie seu aplicativo. O Rails agora usará a tabela de sessões para armazenar os dados da sessão, e você não terá o limite de 4kb.

AMIC MING
fonte
1
é possível ver aquele cookie para verificar isso
erogol
só por curiosidade - esse é um limite de 4 kb por sessão ou por aplicativo?
colllin de
1
@colllin, é por sessão.
Alex D
eu preciso da active_record_storejoia?
Saad Masood
ou é parte dos trilhos4
Saad Masood
78

Para fazer a :active_record_storefuncionalidade funcionar no Rails 4/5, você deve adicionar a gem activerecord-session_store ao seu Gemfile:

gem 'activerecord-session_store'

em seguida, execute o gerador de migração:

rails generate active_record:session_migration
rake db:migrate

E, finalmente, defina seu armazenamento de sessão em config/initializers/session_store.rb:

Rails.application.config.session_store :active_record_store, :key => '_my_app_session'

ATUALIZAR:

Se alguém está recebendo uma null value in column "session_id" violates not-null constraintmensagem no rails 4, há uma solução alternativa no github (não testado). Você deve criar um inicializador comActiveRecord::SessionStore::Session.attr_accessible :data, :session_id

Alter Lagos
fonte
Você não obteve um erro ao usar esta joia? Eu obtenho o seguinte:ERROR: null value in column "session_id" violates not-null constraint
Peter
@Peter Não aconteceu comigo, mas aqui ainda aparece como um problema em aberto. Meu único conselho é escrever um comentário sobre esse problema para assisti-lo até que alguém conserte. Desculpe: /
Alter Lagos
@Peter Não tenho a certeza se é muito tarde, mas de qualquer forma verifique a minha resposta actualizada
Alter Lagos
2
Após executar "rails generate active_record: session_migration" não se esqueça de executar: "rake db: migrate"!
Patrice Gagnon
2
e se eu não quiser armazenar nada no banco de dados, como posso resgatar o erro? Eu tentei rescue_from ActionDispatch :: Cookies :: CookieOverflow,: with =>: render_404 no ApplicationController mas não funcionou
nisevi
14

Se estiver vendo isso, verifique se não está explodindo alguns dados da sessão. No meu caso, foram milhares da mesma mensagem inseridos na mensagem flash. Apenas dizendo.

Acrescentarei que, se você acha que a solução é aumentar o seu armazenamento de cookies (como a maioria das outras respostas aborda), provavelmente é melhor repensar o que está realmente colocando nos cookies. Se você precisa de mais do que alguns tokens de autenticação, IDs de sessão e talvez alguns cookies de layout / rastreamento, você está vivendo nos anos 90.

David Hempy
fonte
1
Eu estava fundindo profundamente alguns parâmetros para salvar o estado!
Anwar,
2
Essa foi a causa do erro para mim também. Colocando muitos dados na mensagem flash.
knubie 01 de
10

Não é uma boa ideia armazenar um objeto de modelo na sessão.

Confira este railscast neste tópico: http://railscasts.com/episodes/13-dangers-of-model-in-session?autoplay=true

É uma prática melhor armazenar o id (id do usuário, neste caso) dentro da sessão. Então você não terá esse problema.

(Veja também o comentário de Frederick Cheung acima).

Zack Xu
fonte
9

a mensagem de erro indica claramente o problema com o tamanho do armazenamento de cookies que está excedendo.

Suas sessões (por padrão em cookie) precisam ser movidas para o armazenamento de registro ativo ou armazenamento do memcache para corrigir esse problema.

Para sessões baseadas em dados:

config.action_controller.session_store = :active_record_store

Você precisa criar a tabela de sessão conforme abaixo

rake db:sessions:create
rake db:migrate

OU

Para sessões de Memcache:

config.action_controller.session_store = :mem_cache_store

Além disso, você precisa configurar um servidor de cache de memória e configurá-lo conforme a seguir:

config.cache_store = :mem_cache_store, 'localhost', '127.0.0.1:11211',
{:namespace => 'myapp123'}
Meu Deus
fonte
6

Esse erro ocorre porque você está tentando serializar o modelo do usuário. Ao armazenar um objeto em um cookie, o rails usará Marshal.dump, que pode produzir uma grande quantidade de conteúdo, já que está tudo no registro do usuário

Em vez de armazenar o registro real do usuário, session[:current_user] = usertente apenas armazenar o ID do usuário e, em seguida, tenha um método para pesquisar o usuário a partir desse, por exemplo

def sign_in(user)
  ...
  session[:current_user_id] = user.id
end

def current_user
  @current_user ||= User.find(session[:current_user_id])
end
cianmce
fonte
1

Este erro apareceu para mim quando eu estava executando uma especificação. Depois de atualizar o Capivara de 1.x para 2.x. Apenas rake tmp: limpar resolveu.

Artur79
fonte