Проблема в том, что вы не можете позвонить на Category.all.map(&:id)
внутри вызываемого на validates_inclusion_of
.
Первое указание на то, что это так, станет очевидным при попытке запустить
rake db:migrate:down VERSION=<n>
rake db:migrate:up VERSOIN=<n>
где <n>
- номер версии миграции, которая создает модель категории.
Вы получите что-то вроде:
in /Users/sseefried/tmp/so)
== CreateCategories: reverting ===============================================
-- drop_table(:categories)
-> 0.0032s
== CreateCategories: reverted (0.0034s) ======================================
(in /Users/sseefried/tmp/so)
rake aborted!
SQLite3::SQLException: no such table: categories: SELECT * FROM "categories"
(See full trace by running task with --trace)
Это потому, что rake
пытается загрузить app/models/category.rb
перед запуском миграции. Поскольку модель Category
не существует, она терпит неудачу.
Другой способ увидеть проблему - это сделать tail -f log/development.log
, а затем попытаться открыть консоль с помощью script/console
. Вы увидите SQL-запрос в форме:
SELECT * FROM "categories"
на выходе. Это соответствует звонку на Category.all.map(:&id)
. Однако, как только вы начнете набирать команды, такие как:
c1 = Category.new, :name => "Category 1"
вы увидите, что запрос SELECT * from "categories"
не появляется в журнале. Мораль этой истории такова: только константы могут появляться в вызовах validations_inclusion_of
, потому что код там будет оцениваться только один раз. .
Единственная причина, по которой ваш консольный код работал, заключается в том, что в предыдущем сеансе консоли вы создали объект Category
с id=1
Вы можете написать пользовательскую проверку, которая делает то, что вы хотите:
validate :parent_exists
protected
def parent_exists
ids = Category.all.map(&:id)
if !parent_id.blank? && !ids.member?(parent_id)
errors.add(:parent_id, "does not point to a valid parent record")
end
end
Ваши тесты rspec пройдут, как только вы добавите этот код.