2009-09-10 2 views
4

У меня возникла проблема с созданием новой строки модели в базе данных с помощью ActiveRecord в приложении Sinatra, которое я разрабатываю. Объект, о котором идет речь, создается без ошибок (с помощью save !, никаких исключений не возникает), но большая часть данных, которые я указываю для сохранения, отсутствует.Проблема при создании модели ActiveRecord: данные отсутствуют из сохранения

class ProjectMeta < ActiveRecord::Base 
    attr_accessor :completion_ratio, :num_stories, :num_completed_stories, :original_target_date, :current_target_date 

    ... 

    def self.create_from_project(project) 
     meta = ProjectMeta.new 
     meta.project_id = project.id 
     meta.num_stories = project.num_stories 
     meta.num_completed_stories = project.num_completed_stories 
     meta.completion_ratio = ProjectMeta.calculate_ratio(project.num_completed_stories, project.num_stories) 
     meta.current_target_date = project.current_target_date 
     meta.save! 
     meta 
    end 

    ... 

end 

Все проверки на данных из объекта проекта я представляемого, а также новый мета-объект я создаю, показывают, что данные присутствуют. Но когда я делаю meta.inspect до и после сохранения, он показывает, что все данные (кроме project_id) находятся в состоянии по умолчанию (нули). Я также проверил meta.errors.nil? и, конечно же, после сохранения не было никаких ошибок.

Что является самым озадачивающим, так это то, что если я развернусь и получу новый мета-экземпляр с этим project_id и включу данные, это не сэкономит никакой проблеме для db.

Это меня разочаровывает, потому что я создал несколько сайтов в Rails и Sinatra с помощью ActiveRecord. Этот вопрос полностью озадачивает меня. Может ли кто-нибудь сказать мне, что я делаю неправильно?

+0

Забыл упомянуть, что я пробовал каждое заклинание творения, о котором я могу думать: ProjectMeta.create (: project_id => project.id ...), ProjectMeta.create do ... end и т. Д. – localshred

ответ

6

Вот как оно работает

  1. При первом доступе к модели столбцы из соответствующей таблицы базы данных являются retri проверены и сохранены внутри данных модели. Эта информация может быть получена с помощью метода класса columns.

  2. Когда вы получаете доступ к атрибуту какой-либо модели, Ruby не находит соответствующий метод в классе и запускает метод #method_missing. Этот метод проверяет модель :: columns, чтобы проверить, существует ли соответствующий столбец. Если это так, он создает Accessors для этого столбца, так что в следующий раз, когда вы получите доступ к атрибуту этой модели, метод accessor будет вызван напрямую, без необходимости вызова #method_missing (позже медленнее).

Аксессоры выглядеть следующим образом:

def my_attribute 
    read_attribute(:my_attribute) 
end 

def my_attribute=(value) 
    write_attribute(:my_attribute, value) 
end 

Для #read_attribute и #write_attribute методов есть ярлык: # [] и # []=. Если по какой-то причине вам необходимо напрямую обращаться к базовым данным (например,сделать некоторые преобразования данных), вы можете написать их коротко:

def my_attribute 
    self[:my_attribute] 
end 

def my_attribute=(value) 
    self[:my_attribute] = value 
end 

Модели имеет специальный аксессор - # attributes - которая возвращает «имя_столбец => значение» Hash.

ПРИМЕЧАНИЕ: данные для каждого столбца хранятся в специальном экземпляре Hash внутри экземпляра модели, а не в переменных экземпляра «@column_name». Когда вы определяете accessors с #attr_accessor, вы блокируете обычный способ определения атрибутов доступа через #method_missing. Ваши данные хранятся в переменных экземпляра вместо хэша «attributes», поэтому он не сохраняется в базе данных.

Если вы хотите добавить новый атрибут в свою модель, вам действительно нужно добавить столбец в таблицу базы данных, соответствующую этой модели, а затем перезагрузить все приложение.

+0

Это ТОЧНО, что мне не хватало. Я обнаружил, что исправление заключалось в удалении строки attr_accessor, но было смущено в отношении _why_. Благодаря! – localshred

+0

Это старый ответ, но ... СПАСИБО! Просто потратил 2 часа, пытаясь понять, почему модель не спасет. Я разрабатывал его без AR и там был attr_accessor. –

0

Attr_accessors никогда не будут сохранены в БД. Это внутренние переменные внутри экземпляра. Если вы хотите сохранить значения, вам нужно создать реальные столбцы.

Сделайте переход, чтобы объявить столбцы, затем повторите попытку.

1

Существует важное различие между полями базы данных и временными объявленными свойствами attr_accessor. Если вы объявили свои столбцы, объявления attr_accessor не нужны.

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

Например, чтобы посмотреть, что запланировано, чтобы спастись:

class MyModel < ActiveRecord::Base 
    attr_accessor :not_saved 
end 

model = MyModel.new(:not_saved => 'foo') 

puts model.attributes.inspect 

Есть способы, чтобы получить информацию о том, что столбцы доступны в модели, такие как:

MyModel.columns_names 
Смежные вопросы