mirror of https://github.com/rails/rails
Foxy fixtures. Adapter#disable_referential_integrity. Closes #9981.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@8036 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
parent
742694e0eb
commit
49eafd8c36
|
@ -1,5 +1,14 @@
|
|||
*SVN*
|
||||
|
||||
* Foxy fixtures, from rathole (http://svn.geeksomnia.com/rathole/trunk/README)
|
||||
- stable, autogenerated IDs
|
||||
- specify associations (belongs_to, has_one, has_many) by label, not ID
|
||||
- specify HABTM associations as inline lists
|
||||
- autofill timestamp columns
|
||||
- support YAML defaults
|
||||
- fixture label interpolation
|
||||
Enabled for fixtures that correspond to a model class and don't specify a primary key value. #9981 [jbarnette]
|
||||
|
||||
* Add docs explaining how to protect all attributes using attr_accessible with no arguments. Closes #9631 [boone, rmm5t]
|
||||
|
||||
* Update add_index documentation to use new options api. Closes #9787 [kamal]
|
||||
|
|
|
@ -70,6 +70,13 @@ module ActiveRecord
|
|||
name
|
||||
end
|
||||
|
||||
# REFERENTIAL INTEGRITY ====================================
|
||||
|
||||
# Override to turn off referential integrity while executing +&block+
|
||||
def disable_referential_integrity(&block)
|
||||
yield
|
||||
end
|
||||
|
||||
# CONNECTION MANAGEMENT ====================================
|
||||
|
||||
# Is this connection active and ready to perform queries?
|
||||
|
|
|
@ -224,6 +224,18 @@ module ActiveRecord
|
|||
"0"
|
||||
end
|
||||
|
||||
# REFERENTIAL INTEGRITY ====================================
|
||||
|
||||
def disable_referential_integrity(&block) #:nodoc:
|
||||
old = select_value("SELECT @@FOREIGN_KEY_CHECKS")
|
||||
|
||||
begin
|
||||
update("SET FOREIGN_KEY_CHECKS = 0")
|
||||
yield
|
||||
ensure
|
||||
update("SET FOREIGN_KEY_CHECKS = #{old}")
|
||||
end
|
||||
end
|
||||
|
||||
# CONNECTION MANAGEMENT ====================================
|
||||
|
||||
|
|
|
@ -364,6 +364,14 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
# REFERENTIAL INTEGRITY ====================================
|
||||
|
||||
def disable_referential_integrity(&block) #:nodoc:
|
||||
execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER ALL" }.join(";"))
|
||||
yield
|
||||
ensure
|
||||
execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} ENABLE TRIGGER ALL" }.join(";"))
|
||||
end
|
||||
|
||||
# DATABASE STATEMENTS ======================================
|
||||
|
||||
|
|
|
@ -215,6 +215,199 @@ end
|
|||
# the results of your transaction until Active Record supports nested transactions or savepoints (in progress.)
|
||||
# 2. Your database does not support transactions. Every Active Record database supports transactions except MySQL MyISAM.
|
||||
# Use InnoDB, MaxDB, or NDB instead.
|
||||
#
|
||||
# = Advanced YAML Fixtures
|
||||
#
|
||||
# YAML fixtures that don't specify an ID get some extra features:
|
||||
#
|
||||
# * Stable, autogenerated ID's
|
||||
# * Label references for associations (belongs_to, has_one, has_many)
|
||||
# * HABTM associations as inline lists
|
||||
# * Autofilled timestamp columns
|
||||
# * Fixture label interpolation
|
||||
# * Support for YAML defaults
|
||||
#
|
||||
# == Stable, autogenerated ID's
|
||||
#
|
||||
# Here, have a monkey fixture:
|
||||
#
|
||||
# george:
|
||||
# id: 1
|
||||
# name: George the Monkey
|
||||
#
|
||||
# reginald:
|
||||
# id: 2
|
||||
# name: Reginald the Pirate
|
||||
#
|
||||
# Each of these fixtures has two unique identifiers: one for the database
|
||||
# and one for the humans. Why don't we generate the primary key instead?
|
||||
# Hashing each fixture's label yields a consistent ID:
|
||||
#
|
||||
# george: # generated id: 503576764
|
||||
# name: George the Monkey
|
||||
#
|
||||
# reginald: # generated id: 324201669
|
||||
# name: Reginald the Pirate
|
||||
#
|
||||
# ActiveRecord looks at the fixture's model class, discovers the correct
|
||||
# primary key, and generates it right before inserting the fixture
|
||||
# into the database.
|
||||
#
|
||||
# The generated ID for a given label is constant, so we can discover
|
||||
# any fixture's ID without loading anything, as long as we know the label.
|
||||
#
|
||||
# == Label references for associations (belongs_to, has_one, has_many)
|
||||
#
|
||||
# Specifying foreign keys in fixtures can be very fragile, not to
|
||||
# mention difficult to read. Since ActiveRecord can figure out the ID of
|
||||
# and fixture from its label, you can specify FK's by label instead of ID.
|
||||
#
|
||||
# === belongs_to
|
||||
#
|
||||
# Let's break out some more monkeys and pirates.
|
||||
#
|
||||
# ### in pirates.yml
|
||||
#
|
||||
# reginald:
|
||||
# id: 1
|
||||
# name: Reginald the Pirate
|
||||
# monkey_id: 1
|
||||
#
|
||||
# ### in monkeys.yml
|
||||
#
|
||||
# george:
|
||||
# id: 1
|
||||
# name: George the Monkey
|
||||
# pirate_id: 1
|
||||
#
|
||||
# Add a few more monkeys and pirates and break this into multiple files,
|
||||
# and it gets pretty hard to keep track of what's going on. Let's
|
||||
# use labels instead of ID's:
|
||||
#
|
||||
# ### in pirates.yml
|
||||
#
|
||||
# reginald:
|
||||
# name: Reginald the Pirate
|
||||
# monkey: george
|
||||
#
|
||||
# ### in monkeys.yml
|
||||
#
|
||||
# george:
|
||||
# name: George the Monkey
|
||||
# pirate: reginald
|
||||
#
|
||||
# Pow! All is made clear. ActiveRecord reflects on the fixture's model class,
|
||||
# finds all the +belongs_to+ associations, and allows you to specify
|
||||
# a target *label* for the *association* (monkey: george) rather than
|
||||
# a target *id* for the *FK* (monkey_id: 1).
|
||||
#
|
||||
# === has_and_belongs_to_many
|
||||
#
|
||||
# Time to give our monkey some fruit.
|
||||
#
|
||||
# ### in monkeys.yml
|
||||
#
|
||||
# george:
|
||||
# id: 1
|
||||
# name: George the Monkey
|
||||
# pirate_id: 1
|
||||
#
|
||||
# ### in fruits.yml
|
||||
#
|
||||
# apple:
|
||||
# id: 1
|
||||
# name: apple
|
||||
#
|
||||
# orange:
|
||||
# id: 2
|
||||
# name: orange
|
||||
#
|
||||
# grape:
|
||||
# id: 3
|
||||
# name: grape
|
||||
#
|
||||
# ### in fruits_monkeys.yml
|
||||
#
|
||||
# apple_george:
|
||||
# fruit_id: 1
|
||||
# monkey_id: 1
|
||||
#
|
||||
# orange_george:
|
||||
# fruit_id: 2
|
||||
# monkey_id: 1
|
||||
#
|
||||
# grape_george:
|
||||
# fruit_id: 3
|
||||
# monkey_id: 1
|
||||
#
|
||||
# Let's make the HABTM fixture go away.
|
||||
#
|
||||
# ### in monkeys.yml
|
||||
#
|
||||
# george:
|
||||
# name: George the Monkey
|
||||
# pirate: reginald
|
||||
# fruits: apple, orange, grape
|
||||
#
|
||||
# ### in fruits.yml
|
||||
#
|
||||
# apple:
|
||||
# name: apple
|
||||
#
|
||||
# orange:
|
||||
# name: orange
|
||||
#
|
||||
# grape:
|
||||
# name: grape
|
||||
#
|
||||
# Zap! No more fruits_monkeys.yml file. We've specified the list of fruits
|
||||
# on George's fixture, but we could've just as easily specified a list
|
||||
# of monkeys on each fruit. As with +belongs_to+, ActiveRecord reflects on
|
||||
# the fixture's model class and discovers the +has_and_belongs_to_many+
|
||||
# associations.
|
||||
#
|
||||
# == Autofilled timestamp columns
|
||||
#
|
||||
# If your table/model specifies any of ActiveRecord's
|
||||
# standard timestamp columns (created_at, created_on, updated_at, updated_on),
|
||||
# they will automatically be set to Time.now.
|
||||
#
|
||||
# If you've set specific values, they'll be left alone.
|
||||
#
|
||||
# == Fixture label interpolation
|
||||
#
|
||||
# The label of the current fixture is always available as a column value:
|
||||
#
|
||||
# geeksomnia:
|
||||
# name: Geeksomnia's Account
|
||||
# subdomain: $LABEL
|
||||
#
|
||||
# Also, sometimes (like when porting older join table fixtures) you'll need
|
||||
# to be able to get ahold of the identifier for a given label. ERB
|
||||
# to the rescue:
|
||||
#
|
||||
# george_reginald:
|
||||
# monkey_id: <%= Fixtures.identify(:reginald) %>
|
||||
# pirate_id: <%= Fixtures.identify(:george) %>
|
||||
#
|
||||
# == Support for YAML defaults
|
||||
#
|
||||
# You probably already know how to use YAML to set and reuse defaults in
|
||||
# your +database.yml+ file,. You can use the same technique in your fixtures:
|
||||
#
|
||||
# DEFAULTS: &DEFAULTS
|
||||
# created_on: <%= 3.weeks.ago.to_s(:db) %>
|
||||
#
|
||||
# first:
|
||||
# name: Smurf
|
||||
# <<: *DEFAULTS
|
||||
#
|
||||
# second:
|
||||
# name: Fraggle
|
||||
# <<: *DEFAULTS
|
||||
#
|
||||
# Any fixture labeled "DEFAULTS" is safely ignored.
|
||||
|
||||
class Fixtures < YAML::Omap
|
||||
DEFAULT_FILTER_RE = /\.ya?ml$/
|
||||
|
||||
|
@ -279,32 +472,41 @@ class Fixtures < YAML::Omap
|
|||
|
||||
unless table_names_to_fetch.empty?
|
||||
ActiveRecord::Base.silence do
|
||||
fixtures_map = {}
|
||||
connection.disable_referential_integrity do
|
||||
fixtures_map = {}
|
||||
|
||||
fixtures = table_names_to_fetch.map do |table_name|
|
||||
fixtures_map[table_name] = Fixtures.new(connection, File.split(table_name.to_s).last, class_names[table_name.to_sym], File.join(fixtures_directory, table_name.to_s))
|
||||
end
|
||||
fixtures = table_names_to_fetch.map do |table_name|
|
||||
fixtures_map[table_name] = Fixtures.new(connection, File.split(table_name.to_s).last, class_names[table_name.to_sym], File.join(fixtures_directory, table_name.to_s))
|
||||
end
|
||||
|
||||
all_loaded_fixtures.update(fixtures_map)
|
||||
all_loaded_fixtures.update(fixtures_map)
|
||||
|
||||
connection.transaction(Thread.current['open_transactions'].to_i == 0) do
|
||||
fixtures.reverse.each { |fixture| fixture.delete_existing_fixtures }
|
||||
fixtures.each { |fixture| fixture.insert_fixtures }
|
||||
connection.transaction(Thread.current['open_transactions'].to_i == 0) do
|
||||
fixtures.reverse.each { |fixture| fixture.delete_existing_fixtures }
|
||||
fixtures.each { |fixture| fixture.insert_fixtures }
|
||||
|
||||
# Cap primary key sequences to max(pk).
|
||||
if connection.respond_to?(:reset_pk_sequence!)
|
||||
table_names.each do |table_name|
|
||||
connection.reset_pk_sequence!(table_name)
|
||||
# Cap primary key sequences to max(pk).
|
||||
if connection.respond_to?(:reset_pk_sequence!)
|
||||
table_names.each do |table_name|
|
||||
connection.reset_pk_sequence!(table_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cache_fixtures(connection, fixtures)
|
||||
cache_fixtures(connection, fixtures)
|
||||
end
|
||||
end
|
||||
end
|
||||
cached_fixtures(connection, table_names)
|
||||
end
|
||||
|
||||
# Returns a consistent identifier for +label+. This will always
|
||||
# be a positive integer, and will always be the same for a given
|
||||
# label, assuming the same OS, platform, and version of Ruby.
|
||||
def self.identify(label)
|
||||
label.to_s.hash.abs
|
||||
end
|
||||
|
||||
attr_reader :table_name
|
||||
|
||||
def initialize(connection, table_name, class_name, fixture_path, file_filter = DEFAULT_FILTER_RE)
|
||||
|
@ -322,12 +524,90 @@ class Fixtures < YAML::Omap
|
|||
end
|
||||
|
||||
def insert_fixtures
|
||||
values.each do |fixture|
|
||||
now = ActiveRecord::Base.default_timezone == :utc ? Time.now.utc : Time.now
|
||||
now = now.to_s(:db)
|
||||
|
||||
# allow a standard key to be used for doing defaults in YAML
|
||||
delete(assoc("DEFAULTS"))
|
||||
|
||||
# track any join tables we need to insert later
|
||||
habtm_fixtures = Hash.new do |h, habtm|
|
||||
h[habtm] = HabtmFixtures.new(@connection, habtm.options[:join_table], nil, nil)
|
||||
end
|
||||
|
||||
each do |label, fixture|
|
||||
row = fixture.to_hash
|
||||
|
||||
if model_class && model_class < ActiveRecord::Base && !row[primary_key_name]
|
||||
# fill in timestamp columns if they aren't specified
|
||||
timestamp_column_names.each do |name|
|
||||
row[name] = now unless row.key?(name)
|
||||
end
|
||||
|
||||
# interpolate the fixture label
|
||||
row.each do |key, value|
|
||||
row[key] = label if value == "$LABEL"
|
||||
end
|
||||
|
||||
# generate a primary key
|
||||
row[primary_key_name] = Fixtures.identify(label)
|
||||
|
||||
model_class.reflect_on_all_associations.each do |association|
|
||||
case association.macro
|
||||
when :belongs_to
|
||||
if value = row.delete(association.name.to_s)
|
||||
fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s
|
||||
row[fk_name] = Fixtures.identify(value)
|
||||
end
|
||||
when :has_and_belongs_to_many
|
||||
if (targets = row.delete(association.name.to_s))
|
||||
targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/)
|
||||
join_fixtures = habtm_fixtures[association]
|
||||
|
||||
targets.each do |target|
|
||||
join_fixtures["#{label}_#{target}"] = Fixture.new(
|
||||
{ association.primary_key_name => Fixtures.identify(label),
|
||||
association.association_foreign_key => Fixtures.identify(target) }, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@connection.insert_fixture(fixture, @table_name)
|
||||
end
|
||||
|
||||
# insert any HABTM join tables we discovered
|
||||
habtm_fixtures.values.each do |fixture|
|
||||
fixture.delete_existing_fixtures
|
||||
fixture.insert_fixtures
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
class HabtmFixtures < ::Fixtures #:nodoc:
|
||||
def read_fixture_files; end
|
||||
end
|
||||
|
||||
def model_class
|
||||
@model_class ||= @class_name.is_a?(Class) ?
|
||||
@class_name : @class_name.constantize rescue nil
|
||||
end
|
||||
|
||||
def primary_key_name
|
||||
@primary_key_name ||= model_class && model_class.primary_key
|
||||
end
|
||||
|
||||
def timestamp_column_names
|
||||
@timestamp_column_names ||= %w(created_at created_on updated_at updated_on).select do |name|
|
||||
column_names.include?(name)
|
||||
end
|
||||
end
|
||||
|
||||
def column_names
|
||||
@column_names ||= @connection.columns(@table_name).collect(&:name)
|
||||
end
|
||||
|
||||
def read_fixture_files
|
||||
if File.file?(yaml_file_path)
|
||||
read_yaml_fixture_files
|
||||
|
|
|
@ -252,9 +252,9 @@ class EagerAssociationTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_eager_with_scoped_order_using_association_limiting_without_explicit_scope
|
||||
posts_with_explicit_order = Post.find(:all, :conditions => 'comments.id', :include => :comments, :order => 'posts.id DESC', :limit => 2)
|
||||
posts_with_explicit_order = Post.find(:all, :conditions => 'comments.id is not null', :include => :comments, :order => 'posts.id DESC', :limit => 2)
|
||||
posts_with_scoped_order = Post.with_scope(:find => {:order => 'posts.id DESC'}) do
|
||||
Post.find(:all, :conditions => 'comments.id', :include => :comments, :limit => 2)
|
||||
Post.find(:all, :conditions => 'comments.id is not null', :include => :comments, :limit => 2)
|
||||
end
|
||||
assert_equal posts_with_explicit_order, posts_with_scoped_order
|
||||
end
|
||||
|
|
|
@ -548,7 +548,7 @@ class HasManyAssociationsTest < Test::Unit::TestCase
|
|||
client_ary = firm.clients_using_finder_sql.find("2", "3")
|
||||
assert_kind_of Array, client_ary
|
||||
assert_equal 2, client_ary.size
|
||||
assert_equal client, client_ary.first
|
||||
assert client_ary.include?(client)
|
||||
end
|
||||
|
||||
def test_find_all
|
||||
|
|
|
@ -295,4 +295,33 @@ ActiveRecord::Schema.define do
|
|||
t.column :city, :string, :null => false
|
||||
t.column :type, :string
|
||||
end
|
||||
|
||||
create_table :parrots, :force => true do |t|
|
||||
t.column :name, :string
|
||||
t.column :created_at, :datetime
|
||||
t.column :created_on, :datetime
|
||||
t.column :updated_at, :datetime
|
||||
t.column :updated_on, :datetime
|
||||
end
|
||||
|
||||
create_table :pirates, :force => true do |t|
|
||||
t.column :catchphrase, :string
|
||||
t.column :parrot_id, :integer
|
||||
t.column :created_on, :datetime
|
||||
t.column :updated_on, :datetime
|
||||
end
|
||||
|
||||
create_table :parrots_pirates, :id => false, :force => true do |t|
|
||||
t.column :parrot_id, :integer
|
||||
t.column :pirate_id, :integer
|
||||
end
|
||||
|
||||
create_table :treasures, :force => true do |t|
|
||||
t.column :name, :string
|
||||
end
|
||||
|
||||
create_table :parrots_treasures, :id => false, :force => true do |t|
|
||||
t.column :parrot_id, :integer
|
||||
t.column :treasure_id, :integer
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
class Parrot < ActiveRecord::Base
|
||||
has_and_belongs_to_many :pirates
|
||||
has_and_belongs_to_many :treasures
|
||||
end
|
|
@ -0,0 +1,16 @@
|
|||
george:
|
||||
name: "Curious George"
|
||||
treasures: diamond, sapphire
|
||||
|
||||
louis:
|
||||
name: "King Louis"
|
||||
treasures: [diamond, sapphire]
|
||||
|
||||
frederick:
|
||||
name: $LABEL
|
||||
|
||||
DEFAULTS: &DEFAULTS
|
||||
treasures: sapphire, ruby
|
||||
|
||||
davey:
|
||||
<<: *DEFAULTS
|
|
@ -0,0 +1,7 @@
|
|||
george_blackbeard:
|
||||
parrot_id: <%= Fixtures.identify(:george) %>
|
||||
pirate_id: <%= Fixtures.identify(:blackbeard) %>
|
||||
|
||||
louis_blackbeard:
|
||||
parrot_id: <%= Fixtures.identify(:louis) %>
|
||||
pirate_id: <%= Fixtures.identify(:blackbeard) %>
|
|
@ -0,0 +1,4 @@
|
|||
class Pirate < ActiveRecord::Base
|
||||
belongs_to :parrot
|
||||
has_and_belongs_to_many :parrots
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
blackbeard:
|
||||
catchphrase: "Yar."
|
||||
parrot: george
|
||||
|
||||
redbeard:
|
||||
catchphrase: "Avast!"
|
||||
parrot: louis
|
||||
created_on: <%= 2.weeks.ago.to_s(:db) %>
|
||||
updated_on: <%= 2.weeks.ago.to_s(:db) %>
|
|
@ -0,0 +1,3 @@
|
|||
class Treasure < ActiveRecord::Base
|
||||
has_and_belongs_to_many :parrots
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
diamond:
|
||||
name: $LABEL
|
||||
|
||||
sapphire:
|
||||
name: $LABEL
|
||||
|
||||
ruby:
|
||||
name: $LABEL
|
|
@ -7,6 +7,9 @@ require 'fixtures/reply'
|
|||
require 'fixtures/joke'
|
||||
require 'fixtures/course'
|
||||
require 'fixtures/category'
|
||||
require 'fixtures/parrot'
|
||||
require 'fixtures/pirate'
|
||||
require 'fixtures/treasure'
|
||||
|
||||
class FixturesTest < Test::Unit::TestCase
|
||||
self.use_instantiated_fixtures = true
|
||||
|
@ -446,3 +449,83 @@ class FasterFixturesTest < Test::Unit::TestCase
|
|||
assert_equal 'Welcome to the weblog', posts(:welcome).title
|
||||
end
|
||||
end
|
||||
|
||||
class FoxyFixturesTest < Test::Unit::TestCase
|
||||
fixtures :parrots, :parrots_pirates, :pirates, :treasures
|
||||
|
||||
def test_identifies_strings
|
||||
assert_equal(Fixtures.identify("foo"), Fixtures.identify("foo"))
|
||||
assert_not_equal(Fixtures.identify("foo"), Fixtures.identify("FOO"))
|
||||
end
|
||||
|
||||
def test_identifies_symbols
|
||||
assert_equal(Fixtures.identify(:foo), Fixtures.identify(:foo))
|
||||
end
|
||||
|
||||
TIMESTAMP_COLUMNS = %w(created_at created_on updated_at updated_on)
|
||||
|
||||
def test_populates_timestamp_columns
|
||||
TIMESTAMP_COLUMNS.each do |property|
|
||||
assert_not_nil(parrots(:george).send(property), "should set #{property}")
|
||||
end
|
||||
end
|
||||
|
||||
def test_populates_all_columns_with_the_same_time
|
||||
last = nil
|
||||
|
||||
TIMESTAMP_COLUMNS.each do |property|
|
||||
current = parrots(:george).send(property)
|
||||
last ||= current
|
||||
|
||||
assert_equal(last, current)
|
||||
last = current
|
||||
end
|
||||
end
|
||||
|
||||
def test_only_populates_columns_that_exist
|
||||
assert_not_nil(pirates(:blackbeard).created_on)
|
||||
assert_not_nil(pirates(:blackbeard).updated_on)
|
||||
end
|
||||
|
||||
def test_preserves_existing_fixture_data
|
||||
assert_equal(2.weeks.ago.to_date, pirates(:redbeard).created_on.to_date)
|
||||
assert_equal(2.weeks.ago.to_date, pirates(:redbeard).updated_on.to_date)
|
||||
end
|
||||
|
||||
def test_generates_unique_ids
|
||||
assert_not_nil(parrots(:george).id)
|
||||
assert_not_equal(parrots(:george).id, parrots(:louis).id)
|
||||
end
|
||||
|
||||
def test_resolves_belongs_to_symbols
|
||||
assert_equal(parrots(:george), pirates(:blackbeard).parrot)
|
||||
end
|
||||
|
||||
def test_supports_join_tables
|
||||
assert(pirates(:blackbeard).parrots.include?(parrots(:george)))
|
||||
assert(pirates(:blackbeard).parrots.include?(parrots(:louis)))
|
||||
assert(parrots(:george).pirates.include?(pirates(:blackbeard)))
|
||||
end
|
||||
|
||||
def test_supports_inline_habtm
|
||||
assert(parrots(:george).treasures.include?(treasures(:diamond)))
|
||||
assert(parrots(:george).treasures.include?(treasures(:sapphire)))
|
||||
assert(!parrots(:george).treasures.include?(treasures(:ruby)))
|
||||
end
|
||||
|
||||
def test_supports_yaml_arrays
|
||||
assert(parrots(:louis).treasures.include?(treasures(:diamond)))
|
||||
assert(parrots(:louis).treasures.include?(treasures(:sapphire)))
|
||||
end
|
||||
|
||||
def test_strips_DEFAULTS_key
|
||||
assert_raise(StandardError) { parrots(:DEFAULTS) }
|
||||
|
||||
# this lets us do YAML defaults and not have an extra fixture entry
|
||||
%w(sapphire ruby).each { |t| assert(parrots(:davey).treasures.include?(treasures(t))) }
|
||||
end
|
||||
|
||||
def test_supports_label_interpolation
|
||||
assert_equal("frederick", parrots(:frederick).name)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue