Изменение записей в моей миграции выдает ошибку authlogic - PullRequest
2 голосов
/ 27 апреля 2010

Я добавляю несколько столбцов в одну из моих таблиц базы данных, а затем заполняю эти столбцы:

def self.up
  add_column :contacts, :business_id, :integer
  add_column :contacts, :business_type, :string

  Contact.reset_column_information
  Contact.all.each do |contact|
    contact.update_attributes(:business_id => contact.client_id, :business_type => 'Client')
  end

  remove_column :contacts, :client_id
end

Строка contact.update_attributes вызывает следующую ошибку Authlogic:

You must activate the Authlogic::Session::Base.controller with a controller object before creating objects

Понятия не имею, что здесь происходит - я не использую метод контроллера для изменения каждой строки в таблице. Я также не создаю новые объекты.

Ошибка не возникает, если таблица контактов пуста.

У меня был гугл, и похоже, что эта ошибка может возникать при запуске тестов вашего контроллера, и исправляется добавлением к ним before_filter :activate_authlogic, но в моем случае это не актуально.

Есть идеи? Я в тупике.

Вот моя модель контакта по запросу:

class Contact < ActiveRecord::Base
  belongs_to :contactable, :polymorphic => true
  has_many :phone_numbers, :as => :callable
  has_many :email_addresses, :as => :emailable

  accepts_nested_attributes_for :phone_numbers
  accepts_nested_attributes_for :email_addresses

  validates_presence_of :first_name, :last_name
  validates_format_of :first_name, :last_name, :with => /^[-a-zA-Z ]+$/

  default_scope :order => 'first_name ASC, last_name ASC'

  def full_name
    "#{self.first_name} #{self.last_name}"
  end

  def to_s
    full_name
  end
end

Информация о версии: Rails 2.3.5, Authlogic 2.1.3

rake db: migrate - вывод трассировки можно найти на сайте pastie здесь: http://pastie.org/944446

Информация наблюдателя:

У меня есть ActivityObserver, который наблюдает за моей Contact моделью и создает Activity с помощью обратного вызова after_update.

В моей Activity модели я хакерски ассоциирую @current user с деятельностью, создаваемой с помощью обратного вызова before_save.

Вот соответствующие фрагменты кода:

class ActivityObserver < ActiveRecord::Observer
  observe :contact

  def after_update(subject)
    Activity.create(:action => 'Updated', :subject => subject)
  end
end

class Activity < ActiveRecord::Base
  belongs_to :subject, :polymorphic => true
  belongs_to :user

  def before_save
    # FIXME: This is a messy hack way to get the user's id
    self.user = UserSession.find.record
  end
end

Это определенно , где Authlogic принимает участие. KandadaBoggu - победитель - большое спасибо за понимание !!!

Что касается исправлений, я думаю, что в принципе их нет. Если я хочу создать действие, когда мой контакт обновляется посредством миграции, по определению нет @current_user для связи. Я подумаю, как обойти это, но Кандада Боггу определенно ответила на мой вопрос.

Ответы [ 6 ]

3 голосов
/ 03 мая 2010

Похоже, как создается объект сеанса Authlogic при обновлении модели контакта. Есть ли у вас наблюдатели ИЛИ до / после фильтров для Contact модели?

Из авторской документации для Authlogic::Session::Base.activated?

# Returns true if a controller has been set and can be used properly. 
# This MUST be set before anything can be done. Similar to how ActiveRecord 
# won't allow you to do anything without establishing a DB connection. In your 
# framework environment this is done for you, but if you are using Authlogic 
# outside of your framework, you need to assign a controller object to Authlogic 
# via Authlogic::Session::Base.controller = obj. See the controller= method for 
# more information.

Один из способов обойти эту проблему, установив controller перед изменением экземпляра модели Contact, т. Е .:

def self.up
  add_column :contacts, :business_id, :integer
  add_column :contacts, :business_type, :string

  Authlogic::Session::Base.controller = 
                       Authlogic::ControllerAdapters::RailsAdapter.new(self)

  Contact.reset_column_information
  Contact.all.each do |contact|
    contact.update_attributes(:business_id => contact.client_id, 
              :business_type => 'Client')
  end

  remove_column :contacts, :client_id
end

Примечание: Я не проверял этот код.

1 голос
/ 01 мая 2010

Я не уверен, что это сработает, но стоит попробовать:

заменить эту строку:

contact.update_attributes(:business_id => contact.client_id, :business_type => 'Client')

с:

contact.update_attribute(:business_id, contact.client_id)
contact.update_attribute(:business_type, 'Client')

Я не могу воспроизвести вашу проблему, поэтому я только догадываюсь:

По какой-то причине update_attributes вызвал это исключение. Я предполагаю, что это на этапе проверки. Поэтому мы пропускаем проверку, используя update_attribute.

Если это все еще не работает, то исключение срабатывает дальше вниз по стеку. В худшем случае вы можете написать SQL для обновления ваших моделей.

0 голосов
/ 03 мая 2010

примечание: я предполагаю, что в вашем приложении есть модель с именем User. Если нет, то, что я использую act_as_authentic, я имею в виду.

Короткая версия: Добавьте следующее к вашей миграции:

User.controller = true

или

UserSession.controller = true

Если это исправит это, то проблема в том, что ваша миграция пытается загрузить вашу пользовательскую модель, для которой требуется настроенный контроллер.

Просмотр http://github.com/binarylogic/authlogic/blob/v2.1.3/lib/authlogic/session/activation.rb источник - это, вероятно, то место, с которого вы хотите начать, если то, что я описал, не работает.

EDIT:

Добавить в начало вашей миграции:

module Authlogic::ActsAsAuthentic::Base::Config
  def acts_as_authentic(unsupported_options = nil, &block)
  end
end

Это должно отключить метод act_as_authentic, чтобы ваша модель не использовала все дополнительные элементы.

0 голосов
/ 03 мая 2010

Как то, что я знаю

 update_attributes(attributes) 

Принимает только один параметр. Вы, наверное, имеете в виду

 update_attribute(name,value)
0 голосов
/ 03 мая 2010

Это довольно странно. Я вообще не понимаю, как Authlogic вызывается при миграции.

Вы пробовали rake db:migrate --trace?

Одна мысль - вы можете попробовать:

contact.business_id = contact.client_id
contact.business_type = 'Client'
contact.save_without_session_maintenance
0 голосов
/ 27 апреля 2010

Это должно быть следующим, НЕ ПРОВЕРИТЬ.

belongs_to :contactable, :polymorphic => true, :foreign_key=>'client_id'
...