Domanda

Ho le seguenti classi ActiveRecord:

class User < ActiveRecord::Base
  cattr_accessor :current_user
  has_many :batch_records
end

class BatchRecord < ActiveRecord::Base
  belongs_to :user

  named_scope :current_user, lambda {
    { :conditions => { :user_id => User.current_user && User.current_user.id } }
  }
end

e sto provando a testare il named_scope: current_user utilizzando Dovrei ma quanto segue non funziona.

class BatchRecordTest < ActiveSupport::TestCase
  setup do
    User.current_user = Factory(:user)
  end

  should_have_named_scope :current_user,
                          :conditions => { :assigned_to_id => User.current_user }
end

Il motivo per cui non funziona è perché la chiamata a User.current_user nel metodo should_have_named_scope viene valutata quando la classe viene definita e io cambio il valore di current_user successivamente nel blocco setup durante l'esecuzione del test.

Ecco cosa mi è venuto in mente per testare questo named_scope:

class BatchRecordTest < ActiveSupport::TestCase
  context "with User.current_user set" do
    setup do
      mock_user = flexmock('user', :id => 1)
      flexmock(User).should_receive(:current_user).and_return(mock_user)
    end

    should_have_named_scope :current_user,
                            :conditions => { :assigned_to_id => 1 }
  end
end

Quindi come lo testeresti usando Shoulda ?

È stato utile?

Soluzione

Penso che tu stia procedendo nel modo sbagliato. Innanzitutto, perché è necessario utilizzare un ambito denominato? Non lo fai e basta?

class BatchRecord < ActiveRecord::Base
  belongs_to :user

  def current_user
    self.user.class.current_user
  end
end

Nel qual caso sarebbe banale testarlo. MA! WTF stai definendo current_user come attributo di classe? Ora che Rails 2.2 è "sicuro per i thread" cosa accadrebbe se eseguissi la tua app in due thread separati? Un utente effettuerebbe l'accesso, impostando current_user per TUTTE le istanze User . Ora un altro utente con privilegi di amministratore accede e current_user passa alla loro istanza. Quando il primo utente passa alla pagina successiva, avrà accesso all'account delle altre persone con i loro privilegi di amministratore! Shock! Orrore!

Ciò che raccomando di fare in questo caso è di creare un nuovo metodo controller current_user che restituisca l'istanza dell'utente corrente dell'utente. Puoi anche fare un ulteriore passo avanti e creare un modello wrapper come:

class CurrentUser

  attr_reader :user, :session

  def initialize(user, session)
    @user, @session = user, session
  end

  def authenticated?
    ...
  end

  def method_missing(*args)
    user.send(*args) if authenticated?
  end

end

Oh, a proposito, ora guardo di nuovo la tua domanda, forse uno dei motivi per cui non funziona è che la riga User.current_user & amp; & amp; User.current_user.id restituirà un valore booleano, anziché l'Integer che desideri. EDIT Sono un idiota.

L'ambito denominato è davvero il modo assolutamente sbagliato di farlo. L'ambito denominato ha lo scopo di restituire raccolte, piuttosto che singoli record (che è un altro motivo per cui ciò fallisce). Sta inoltre effettuando una chiamata non necessaria al DB risultante in una query non necessaria.

Altri suggerimenti

Ho appena realizzato che la risposta mi sta fissando. Dovrei lavorare dall'altra parte dell'associazione che sarebbe current_user.batch_records . Quindi ho semplicemente testato il named_scope sul modello User e tutto è a posto.

@ Chris Lloyd - Per quanto riguarda il problema di sicurezza del thread, l'attributo current_user è impostato da un before_filter nel mio ApplicationController , quindi viene modificato per richiesta. Capisco che esiste ancora il potenziale di disastro se ho scelto di correre in un ambiente multi-thread (che attualmente non è il caso). Suppongo che quella soluzione sarebbe interamente un altro argomento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top