2012-08-29 9 views
6

Desde hace días he estado tratando de llegar al fondo de lo que la costura que ser algo que debe ser muy fácil de hacer ... sin embargo todavía estoy muy nuevo en el mundo de los carriles y Ruby y simplemente no puedo trabajar con esto ...: pprueba Rspec de counter_cache columna de regresar 0

De todos modos el problema que tengo es que tengo varias columnas: counter_cache en las de mi modelo, que funcionan muy bien cuando las pruebo manualmente. Sin embargo, estoy queriendo hacer lo de TDD y no puedo probarlos en rspec por alguna razón desconocida.

De todos modos aquí es un ejemplo de mi modelo (del usuario, comentarios & Medios):

class User < ActiveRecord::Base 
    has_many :comments 
    has_many :media, dependent: :destroy 
end 

class Comment < ActiveRecord::Base 
    attr_accessible :content, :user_id 
    belongs_to :commentable, polymorphic: true, :counter_cache => true 
    belongs_to :user, :counter_cache => true 

    validates :user_id, :presence => true 
    validates :content, :presence => true, :length => { :maximum => 255 } 
end 

class Medium < ActiveRecord::Base 
attr_accessible :caption, :user_id 

belongs_to :user, :counter_cache => true 

has_many :comments, as: :commentable 

validates :user_id, presence: true 
validates :caption, length: { maximum: 140 }, allow_nil: true, allow_blank: true 

default_scope order: 'media.created_at DESC' 
end 

A continuación se muestra de de configuración del esquema de la tabla:

create_table "users", :force => true do |t| 
    t.integer "comments_count",   :default => 0, :null => false 
    t.integer "media_count",   :default => 0, :null => false 
end 

create_table "comments", :force => true do |t| 
    t.text  "content" 
    t.integer "commentable_id" 
    t.string "commentable_type" 
    t.datetime "created_at",  :null => false 
    t.datetime "updated_at",  :null => false 
    t.integer "user_id" 
end 

create_table "media", :force => true do |t| 
    t.integer "user_id" 
    t.string "caption" 
    t.datetime "created_at",     :null => false 
    t.datetime "updated_at",     :null => false 
    t.integer "comments_count", :default => 0, :null => false 
end 

Y ahora aquí es una muestra de un ejemplo rspec que he intentado:

require 'spec_helper' 

describe "Experimental" do 

    describe "counter_cache" do 
    let!(:user) { FactoryGirl.create(:user)} 

    subject { user } 

    before do 
     @media = user.media.create(caption: "Test media") 
    end 

    its "media array should include the media object" do 
     m = user.media 
     m.each do |e| 
     puts e.caption # Outputting "Test media" as expected 
     end 

     user.media.should include(@media) #This works 
    end 

    it "media_count should == 1 " do # This isnt working? 
     puts user.media_count #Outputting 0 
     user.media_count.should == 1 
    end 
    end 
end 

Y finalmente el mensaje de error e rspec que me está dando:

Failures: 

    1) Experimental counter_cache media_count should == 1 
    Failure/Error: user.media_count.should == 1 
     expected: 1 
      got: 0 (using ==) 
    # ./spec/models/experimental_spec.rb:24:in `block (3 levels) in <top (required)>' 

Finished in 0.20934 seconds 
2 examples, 1 failure 

También tenga en cuenta que esto está sucediendo por toda mi columna counter_cache en toda mi modelo de. También probé varias formas diferentes de probar esto, pero todos devuelven el mensaje de error anterior.

realmente esperando que alguien me puede ayudar con esto. :)

Gracias montones de antemano! Luke

Respuesta

26

El counter_cache se está actualizando directamente en la base de datos. Esto no afectará a la copia del modelo que haya cargado en la memoria lo que necesita para volver a cargarlo:

it "media_count should == 1 " do 
    user.reload 
    user.media_count.should == 1 
end 

Pero, no creo que así es como me gustaría probar esto. A medida que lo tienes, tu prueba está muy unida a un código de configuración que parece que no necesita estar ahí. ¿Qué tal algo así para una especificación independiente:

it "has a counter cache" do 
    user = FactoryGirl.create(:user) 
    expect { 
     user.media.create(caption: "Test media") 
    }.to change { User.last.media_count }.by(1) 
end 
+1

Thanks heaps! No sabía que el modelo se había cargado en la memoria y que, por lo tanto, se requería una recarga. –

+0

bien, entonces ahora cuando se hace esto con el método user.reload, funciona. Pero luego quise limpiar las especificaciones y usar el ejemplo más limpio que me proporcionó, ¿y esto no funciona? –

+0

El error que recibo es el siguiente: –

Cuestiones relacionadas