active-fedora 13.1.2 → 13.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github_changelog_generator +2 -0
- data/CHANGELOG.md +3362 -0
- data/CONTRIBUTING.md +23 -1
- data/README.md +4 -0
- data/active-fedora.gemspec +14 -13
- data/lib/active_fedora/version.rb +1 -1
- metadata +104 -206
- data/spec/config_helper.rb +0 -17
- data/spec/fixtures/dino.jpg +0 -0
- data/spec/fixtures/dino_jpg_no_file_ext +0 -0
- data/spec/fixtures/minivan.jpg +0 -0
- data/spec/fixtures/rails_root/config/fake_fedora.yml +0 -7
- data/spec/fixtures/rails_root/config/fedora.yml +0 -12
- data/spec/fixtures/rails_root/config/solr.yml +0 -15
- data/spec/fixtures/rails_root/config/solr_mappings.yml +0 -16
- data/spec/fixtures/rails_root/config/solr_mappings_af_0.1.yml +0 -9
- data/spec/fixtures/rails_root/config/solr_mappings_bl_2.4.yml +0 -17
- data/spec/integration/associations/rdf_spec.rb +0 -61
- data/spec/integration/associations_spec.rb +0 -680
- data/spec/integration/attached_files_spec.rb +0 -146
- data/spec/integration/attributes_spec.rb +0 -73
- data/spec/integration/autosave_association_spec.rb +0 -24
- data/spec/integration/base_spec.rb +0 -184
- data/spec/integration/basic_contains_association_spec.rb +0 -121
- data/spec/integration/belongs_to_association_spec.rb +0 -260
- data/spec/integration/caching_spec.rb +0 -59
- data/spec/integration/clean_connection_spec.rb +0 -21
- data/spec/integration/collection_association_spec.rb +0 -166
- data/spec/integration/date_time_properties_spec.rb +0 -41
- data/spec/integration/delete_all_spec.rb +0 -64
- data/spec/integration/direct_container_spec.rb +0 -250
- data/spec/integration/directly_contains_one_association_spec.rb +0 -96
- data/spec/integration/eradicate_spec.rb +0 -52
- data/spec/integration/fedora_solr_sync_spec.rb +0 -30
- data/spec/integration/file_fixity_spec.rb +0 -36
- data/spec/integration/file_spec.rb +0 -221
- data/spec/integration/generators/fedora_generator_spec.rb +0 -26
- data/spec/integration/generators/solr_generator_spec.rb +0 -23
- data/spec/integration/gone_spec.rb +0 -41
- data/spec/integration/has_and_belongs_to_many_associations_spec.rb +0 -414
- data/spec/integration/has_many_associations_spec.rb +0 -436
- data/spec/integration/has_subresource_spec.rb +0 -34
- data/spec/integration/indexing/descendant_fetcher_spec.rb +0 -64
- data/spec/integration/indexing_spec.rb +0 -110
- data/spec/integration/indirect_container_spec.rb +0 -290
- data/spec/integration/json_serialization_spec.rb +0 -32
- data/spec/integration/marshal_spec.rb +0 -39
- data/spec/integration/nested_attribute_spec.rb +0 -177
- data/spec/integration/nested_hash_resources_spec.rb +0 -43
- data/spec/integration/persistence_spec.rb +0 -37
- data/spec/integration/query_result_builder_spec.rb +0 -37
- data/spec/integration/rdf_nested_attributes_spec.rb +0 -85
- data/spec/integration/relation_delegation_spec.rb +0 -52
- data/spec/integration/relation_spec.rb +0 -117
- data/spec/integration/scoped_query_spec.rb +0 -134
- data/spec/integration/scoping_spec.rb +0 -48
- data/spec/integration/solr_hit_spec.rb +0 -32
- data/spec/integration/versionable_spec.rb +0 -256
- data/spec/integration/with_metadata_spec.rb +0 -111
- data/spec/lib/active_fedora/null_logger_spec.rb +0 -10
- data/spec/rcov.opts +0 -2
- data/spec/spec.opts +0 -5
- data/spec/spec_helper.rb +0 -106
- data/spec/support/an_active_model.rb +0 -29
- data/spec/unit/active_fedora/indexing/inserter_spec.rb +0 -35
- data/spec/unit/active_fedora_spec.rb +0 -118
- data/spec/unit/aggregation/list_source_spec.rb +0 -134
- data/spec/unit/aggregation/ordered_reader_spec.rb +0 -43
- data/spec/unit/association_hash_spec.rb +0 -64
- data/spec/unit/attached_files_spec.rb +0 -218
- data/spec/unit/attributes_spec.rb +0 -146
- data/spec/unit/base_active_model_spec.rb +0 -28
- data/spec/unit/base_cma_spec.rb +0 -15
- data/spec/unit/base_extra_spec.rb +0 -33
- data/spec/unit/base_spec.rb +0 -328
- data/spec/unit/builder/has_and_belongs_to_many_spec.rb +0 -8
- data/spec/unit/callback_spec.rb +0 -65
- data/spec/unit/change_set_spec.rb +0 -60
- data/spec/unit/checksum_spec.rb +0 -25
- data/spec/unit/code_configurator_spec.rb +0 -41
- data/spec/unit/collection_proxy_spec.rb +0 -25
- data/spec/unit/config_spec.rb +0 -18
- data/spec/unit/core/fedora_id_translator_spec.rb +0 -29
- data/spec/unit/core/fedora_uri_translator_spec.rb +0 -19
- data/spec/unit/core/logger_spec.rb +0 -18
- data/spec/unit/core_spec.rb +0 -242
- data/spec/unit/default_model_mapper_spec.rb +0 -39
- data/spec/unit/fedora_spec.rb +0 -31
- data/spec/unit/file/streaming_spec.rb +0 -33
- data/spec/unit/file_configurator_spec.rb +0 -295
- data/spec/unit/file_io_spec.rb +0 -137
- data/spec/unit/file_path_builder_spec.rb +0 -18
- data/spec/unit/file_spec.rb +0 -489
- data/spec/unit/files_hash_spec.rb +0 -52
- data/spec/unit/filter_spec.rb +0 -133
- data/spec/unit/finder_methods_spec.rb +0 -154
- data/spec/unit/fixity_service_spec.rb +0 -128
- data/spec/unit/forbidden_attributes_protection_spec.rb +0 -50
- data/spec/unit/has_and_belongs_to_many_association_spec.rb +0 -125
- data/spec/unit/has_many_association_spec.rb +0 -131
- data/spec/unit/indexers/global_indexer_spec.rb +0 -41
- data/spec/unit/indexing/map/index_object_spec.rb +0 -25
- data/spec/unit/indexing/map_spec.rb +0 -27
- data/spec/unit/indexing_service_spec.rb +0 -28
- data/spec/unit/indexing_spec.rb +0 -86
- data/spec/unit/inheritance_spec.rb +0 -60
- data/spec/unit/ldp_resource_spec.rb +0 -15
- data/spec/unit/loadable_from_json_spec.rb +0 -40
- data/spec/unit/logger_spec.rb +0 -19
- data/spec/unit/model_classifier_spec.rb +0 -49
- data/spec/unit/ordered_spec.rb +0 -367
- data/spec/unit/orders/list_node_spec.rb +0 -151
- data/spec/unit/orders/ordered_list_spec.rb +0 -335
- data/spec/unit/orders/reflection_spec.rb +0 -22
- data/spec/unit/pathing_spec.rb +0 -35
- data/spec/unit/persistence_spec.rb +0 -115
- data/spec/unit/property_predicate_spec.rb +0 -35
- data/spec/unit/property_spec.rb +0 -25
- data/spec/unit/query_result_builder_spec.rb +0 -31
- data/spec/unit/query_spec.rb +0 -307
- data/spec/unit/querying_spec.rb +0 -24
- data/spec/unit/rdf/indexing_service_spec.rb +0 -114
- data/spec/unit/rdf_vocab_spec.rb +0 -30
- data/spec/unit/readonly_spec.rb +0 -24
- data/spec/unit/reflection_spec.rb +0 -42
- data/spec/unit/rspec_matchers/belong_to_associated_active_fedora_object_matcher_spec.rb +0 -37
- data/spec/unit/rspec_matchers/have_many_associated_active_fedora_objects_matcher_spec.rb +0 -38
- data/spec/unit/rspec_matchers/have_predicate_matcher_spec.rb +0 -38
- data/spec/unit/schema_indexing_strategy_spec.rb +0 -68
- data/spec/unit/scoping_spec.rb +0 -67
- data/spec/unit/serializers_spec.rb +0 -19
- data/spec/unit/solr_config_options_spec.rb +0 -57
- data/spec/unit/solr_hit_spec.rb +0 -57
- data/spec/unit/solr_query_builder_spec.rb +0 -18
- data/spec/unit/solr_service_spec.rb +0 -165
- data/spec/unit/sparql_insert_spec.rb +0 -31
- data/spec/unit/validations_spec.rb +0 -92
- data/spec/unit/with_metadata/default_metadata_class_factory_spec.rb +0 -29
- data/spec/unit/with_metadata/metadata_node_spec.rb +0 -69
data/spec/config_helper.rb
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
def mock_yaml(hash, path)
|
|
2
|
-
mock_file = instance_double(File, path.split("/")[-1])
|
|
3
|
-
allow(File).to receive(:exist?).with(path).and_return(true)
|
|
4
|
-
allow(File).to receive(:open).with(path).and_return(mock_file)
|
|
5
|
-
allow(Psych).to receive(:load).and_return(hash)
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
def stub_rails(opts = {})
|
|
9
|
-
Object.const_set("Rails", Class)
|
|
10
|
-
Rails.send(:undef_method, :env) if Rails.respond_to?(:env)
|
|
11
|
-
Rails.send(:undef_method, :root) if Rails.respond_to?(:root)
|
|
12
|
-
opts.each { |k, v| Rails.send(:define_method, k) { return v } }
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def unstub_rails
|
|
16
|
-
Object.send(:remove_const, :Rails) if defined?(Rails)
|
|
17
|
-
end
|
data/spec/fixtures/dino.jpg
DELETED
|
Binary file
|
|
Binary file
|
data/spec/fixtures/minivan.jpg
DELETED
|
Binary file
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
development:
|
|
2
|
-
default:
|
|
3
|
-
url: http://localhost:8983/solr/development
|
|
4
|
-
full_text:
|
|
5
|
-
url: http://localhost:8983/solr/development
|
|
6
|
-
test:
|
|
7
|
-
default:
|
|
8
|
-
url: http://localhost:8983/solr/test
|
|
9
|
-
full_text:
|
|
10
|
-
url: http://localhost:8983/solr/test
|
|
11
|
-
production:
|
|
12
|
-
default:
|
|
13
|
-
url: http://localhost:8080/solr/production
|
|
14
|
-
full_text:
|
|
15
|
-
url: http://localhost:8080/solr/production
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
id: id
|
|
2
|
-
default: searchable
|
|
3
|
-
searchable:
|
|
4
|
-
date: _dt
|
|
5
|
-
string: _t
|
|
6
|
-
text: _t
|
|
7
|
-
symbol: _s
|
|
8
|
-
integer: _i
|
|
9
|
-
long: _l
|
|
10
|
-
boolean: _b
|
|
11
|
-
float: _f
|
|
12
|
-
double: _d
|
|
13
|
-
displayable: _display
|
|
14
|
-
facetable: _facet
|
|
15
|
-
sortable: _sort
|
|
16
|
-
unstemmed_searchable: _unstem_search
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
id: id
|
|
2
|
-
default: searchable
|
|
3
|
-
searchable:
|
|
4
|
-
id: id
|
|
5
|
-
date: _dt
|
|
6
|
-
string: _t
|
|
7
|
-
text: _t
|
|
8
|
-
symbol: _s
|
|
9
|
-
integer: _i
|
|
10
|
-
long: _l
|
|
11
|
-
boolean: _b
|
|
12
|
-
float: _f
|
|
13
|
-
double: _d
|
|
14
|
-
displayable: _display
|
|
15
|
-
facetable: _facet
|
|
16
|
-
sortable: _sort
|
|
17
|
-
unstemmed_searchable: _unstem_search
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe "rdf associations" do
|
|
4
|
-
context "when there is one relationship for the predicate" do
|
|
5
|
-
before do
|
|
6
|
-
class Foo < ActiveFedora::Base
|
|
7
|
-
end
|
|
8
|
-
class Library < ActiveFedora::Base
|
|
9
|
-
has_and_belongs_to_many :foos, predicate: ::RDF::URI('http://example.com')
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
after do
|
|
13
|
-
Object.send(:remove_const, :Foo)
|
|
14
|
-
Object.send(:remove_const, :Library)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
let(:library) { Library.new }
|
|
18
|
-
|
|
19
|
-
it "doesn't not bother to filter by class type" do
|
|
20
|
-
expect(library.association(:foo_ids)).not_to receive(:filter_by_class)
|
|
21
|
-
library.foos.to_a
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
describe "the id setter" do
|
|
25
|
-
it "can handle nil" do
|
|
26
|
-
library.foo_ids = nil
|
|
27
|
-
expect(library.foo_ids).to eq []
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
it "can handle array with nils" do
|
|
31
|
-
library.foo_ids = [nil, nil]
|
|
32
|
-
expect(library.foo_ids).to eq []
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
context "when two relationships have the same predicate" do
|
|
38
|
-
before do
|
|
39
|
-
class Foo < ActiveFedora::Base
|
|
40
|
-
end
|
|
41
|
-
class Bar < ActiveFedora::Base
|
|
42
|
-
end
|
|
43
|
-
class Library < ActiveFedora::Base
|
|
44
|
-
has_and_belongs_to_many :foos, predicate: ::RDF::URI('http://example.com')
|
|
45
|
-
has_and_belongs_to_many :bars, predicate: ::RDF::URI('http://example.com')
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
after do
|
|
49
|
-
Object.send(:remove_const, :Foo)
|
|
50
|
-
Object.send(:remove_const, :Bar)
|
|
51
|
-
Object.send(:remove_const, :Library)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
let(:library) { Library.new }
|
|
55
|
-
|
|
56
|
-
it "filters by class type" do
|
|
57
|
-
expect(library.association(:foo_ids)).to receive(:filter_by_class).and_call_original
|
|
58
|
-
library.foos.to_a
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
@@ -1,680 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe ActiveFedora::Base do
|
|
4
|
-
describe "use a URI as the property" do
|
|
5
|
-
before do
|
|
6
|
-
class Book < ActiveFedora::Base
|
|
7
|
-
belongs_to :author, predicate: ::RDF::Vocab::DC.creator, class_name: 'Person'
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
class Person < ActiveFedora::Base
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
after do
|
|
15
|
-
Object.send(:remove_const, :Book)
|
|
16
|
-
Object.send(:remove_const, :Person)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
subject(:book) { Book.new(author: person) }
|
|
20
|
-
let(:person) { Person.create }
|
|
21
|
-
|
|
22
|
-
it "goes" do
|
|
23
|
-
book.save
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
describe "explicit foreign key" do
|
|
28
|
-
before do
|
|
29
|
-
class FooThing < ActiveFedora::Base
|
|
30
|
-
has_many :bars, class_name: 'BarThing', predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, as: :foothing
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
class BarThing < ActiveFedora::Base
|
|
34
|
-
belongs_to :foothing, class_name: 'FooThing', predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
after do
|
|
39
|
-
Object.send(:remove_const, :FooThing)
|
|
40
|
-
Object.send(:remove_const, :BarThing)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
let(:foo) { FooThing.create }
|
|
44
|
-
let(:bar) { BarThing.create }
|
|
45
|
-
|
|
46
|
-
it "associates from bar to foo" do
|
|
47
|
-
bar.foothing = foo
|
|
48
|
-
bar.save
|
|
49
|
-
expect(foo.bars).to eq [bar]
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
it "associates from foo to bar" do
|
|
53
|
-
foo.bars << bar
|
|
54
|
-
expect(bar.foothing).to eq foo
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
describe "type validator" do
|
|
59
|
-
before do
|
|
60
|
-
class EnsureBanana
|
|
61
|
-
def self.validate!(_reflection, object)
|
|
62
|
-
unless object.try(:banana?)
|
|
63
|
-
raise ActiveFedora::AssociationTypeMismatch, "#{object} must be a banana"
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
class FooThing < ActiveFedora::Base
|
|
68
|
-
attr_accessor :banana
|
|
69
|
-
has_many :bars, class_name: 'BarThing', predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, as: :foothing, type_validator: EnsureBanana
|
|
70
|
-
def banana?
|
|
71
|
-
!banana.nil?
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
class BarThing < ActiveFedora::Base
|
|
76
|
-
attr_accessor :banana
|
|
77
|
-
belongs_to :foothing, class_name: 'FooThing', predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, type_validator: EnsureBanana
|
|
78
|
-
def banana?
|
|
79
|
-
!banana.nil?
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
after do
|
|
85
|
-
Object.send(:remove_const, :FooThing)
|
|
86
|
-
Object.send(:remove_const, :BarThing)
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
let(:foo) { FooThing.create }
|
|
90
|
-
let(:bar) { BarThing.create }
|
|
91
|
-
|
|
92
|
-
it "validates on singular associations" do
|
|
93
|
-
expect { bar.foothing = foo }.to raise_error ActiveFedora::AssociationTypeMismatch, "#{foo} must be a banana"
|
|
94
|
-
foo.banana = true
|
|
95
|
-
expect { bar.foothing = foo }.not_to raise_error
|
|
96
|
-
end
|
|
97
|
-
it "validates on collection associations" do
|
|
98
|
-
expect { foo.bars << bar }.to raise_error ActiveFedora::AssociationTypeMismatch, "#{bar} must be a banana"
|
|
99
|
-
bar.banana = true
|
|
100
|
-
expect { foo.bars << bar }.not_to raise_error
|
|
101
|
-
end
|
|
102
|
-
it "does NOT validate on destroy" do
|
|
103
|
-
bar.banana = true
|
|
104
|
-
foo.bars << bar
|
|
105
|
-
bar.banana = false
|
|
106
|
-
expect { foo.bars.destroy(bar) }.not_to raise_error
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
describe "complex example" do
|
|
111
|
-
before do
|
|
112
|
-
class Library < ActiveFedora::Base
|
|
113
|
-
has_many :books, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.hasConstituent
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
class Book < ActiveFedora::Base
|
|
117
|
-
belongs_to :library, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.hasConstituent
|
|
118
|
-
belongs_to :author, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.hasMember, class_name: 'Person'
|
|
119
|
-
belongs_to :publisher, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.hasMember
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
class Person < ActiveFedora::Base
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
class Publisher < ActiveFedora::Base
|
|
126
|
-
end
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
after do
|
|
130
|
-
Object.send(:remove_const, :Library)
|
|
131
|
-
Object.send(:remove_const, :Book)
|
|
132
|
-
Object.send(:remove_const, :Person)
|
|
133
|
-
Object.send(:remove_const, :Publisher)
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
describe "an unsaved instance" do
|
|
137
|
-
describe "of has_many" do
|
|
138
|
-
before do
|
|
139
|
-
@library = Library.new
|
|
140
|
-
@book = Book.new
|
|
141
|
-
@book.save
|
|
142
|
-
@book2 = Book.new
|
|
143
|
-
@book2.save
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
it "builds child" do
|
|
147
|
-
new_book = @library.books.build({})
|
|
148
|
-
expect(new_book).to be_new_record
|
|
149
|
-
expect(new_book).to be_kind_of Book
|
|
150
|
-
expect(new_book.library).to be_kind_of Library
|
|
151
|
-
expect(@library.books).to eq [new_book]
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
it "makes a new child" do
|
|
155
|
-
new_book = @library.books.new
|
|
156
|
-
expect(new_book).to be_new_record
|
|
157
|
-
expect(new_book).to be_kind_of Book
|
|
158
|
-
expect(new_book.library).to be_kind_of Library
|
|
159
|
-
expect(@library.books).to eq [new_book]
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
it "does not create children if the parent isn't saved" do
|
|
163
|
-
expect { @library.books.create({}) }.to raise_error ActiveFedora::RecordNotSaved, "You cannot call create unless the parent is saved"
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
it "creates children" do
|
|
167
|
-
@library.save!
|
|
168
|
-
new_book = @library.books.create({})
|
|
169
|
-
expect(new_book).to_not be_new_record
|
|
170
|
-
expect(new_book).to be_kind_of Book
|
|
171
|
-
expect(new_book.library).to eq @library
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
it "builds parent" do
|
|
175
|
-
new_library = @book.build_library({})
|
|
176
|
-
expect(new_library).to be_new_record
|
|
177
|
-
expect(new_library).to be_kind_of Library
|
|
178
|
-
expect(@book.library).to eq new_library
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
it "creates parent" do
|
|
182
|
-
new_library = @book.create_library({})
|
|
183
|
-
expect(new_library).to_not be_new_record
|
|
184
|
-
expect(new_library).to be_kind_of Library
|
|
185
|
-
expect(@book.library).to eq new_library
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
it "lets you shift onto the association" do
|
|
189
|
-
expect(@library).to be_new_record
|
|
190
|
-
expect(@library.books.size).to eq 0
|
|
191
|
-
expect(@library.books).to eq []
|
|
192
|
-
expect(@library.book_ids).to eq []
|
|
193
|
-
@library.books << @book
|
|
194
|
-
expect(@library.books).to eq [@book]
|
|
195
|
-
expect(@library.book_ids).to eq [@book.id]
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
it "lets you set an array of objects" do
|
|
199
|
-
@library.books = [@book, @book2]
|
|
200
|
-
expect(@library.books).to contain_exactly @book, @book2
|
|
201
|
-
@library.save
|
|
202
|
-
|
|
203
|
-
@library.books = [@book]
|
|
204
|
-
expect(@library.books).to eq [@book]
|
|
205
|
-
end
|
|
206
|
-
it "lets you set an array of object ids" do
|
|
207
|
-
@library.book_ids = [@book.id, @book2.id]
|
|
208
|
-
expect(@library.books).to contain_exactly @book, @book2
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
it "setter should wipe out previously saved relations" do
|
|
212
|
-
@library.book_ids = [@book.id, @book2.id]
|
|
213
|
-
@library.book_ids = [@book2.id]
|
|
214
|
-
expect(@library.books).to eq [@book2]
|
|
215
|
-
end
|
|
216
|
-
|
|
217
|
-
it "saving the parent should save the relationships on the children" do
|
|
218
|
-
@library.save
|
|
219
|
-
@library.books = [@book, @book2]
|
|
220
|
-
@library.save
|
|
221
|
-
@library = Library.find(@library.id)
|
|
222
|
-
expect(@library.books).to contain_exactly @book, @book2
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
it "lets you lookup an array of objects with solr" do
|
|
226
|
-
@library.save
|
|
227
|
-
@book.library = @library
|
|
228
|
-
@book2.library = @library
|
|
229
|
-
@book.save
|
|
230
|
-
@book2.save
|
|
231
|
-
|
|
232
|
-
@library = Library.find(@library.id)
|
|
233
|
-
expect(@library.books).to contain_exactly @book, @book2
|
|
234
|
-
|
|
235
|
-
solr_resp = @library.books(response_format: :solr)
|
|
236
|
-
expect(solr_resp.size).to eq 2
|
|
237
|
-
expect(solr_resp[0].id).to eq @book.id
|
|
238
|
-
expect(solr_resp[1].id).to eq @book2.id
|
|
239
|
-
end
|
|
240
|
-
end
|
|
241
|
-
|
|
242
|
-
describe "of belongs to" do
|
|
243
|
-
before do
|
|
244
|
-
@library = Library.new
|
|
245
|
-
@library.save
|
|
246
|
-
@book = Book.new
|
|
247
|
-
@book.save
|
|
248
|
-
end
|
|
249
|
-
it "does not do anything if you set a nil id" do
|
|
250
|
-
@book.library_id = nil
|
|
251
|
-
end
|
|
252
|
-
it "is settable from the book side" do
|
|
253
|
-
@book.library_id = @library.id
|
|
254
|
-
expect(@book.library).to eq @library
|
|
255
|
-
expect(@book.library.id).to eq @library.id
|
|
256
|
-
@book.attributes = { library_id: nil }
|
|
257
|
-
expect(@book.library_id).to be_nil
|
|
258
|
-
end
|
|
259
|
-
end
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
describe "a saved instance" do
|
|
263
|
-
describe "of belongs_to" do
|
|
264
|
-
before do
|
|
265
|
-
@library = Library.new
|
|
266
|
-
@library.save
|
|
267
|
-
@book = Book.new
|
|
268
|
-
@book.save
|
|
269
|
-
@person = Person.new
|
|
270
|
-
@person.save
|
|
271
|
-
@publisher = Publisher.new
|
|
272
|
-
@publisher.save
|
|
273
|
-
end
|
|
274
|
-
it "has many books once it has been saved" do
|
|
275
|
-
@library.books << @book
|
|
276
|
-
|
|
277
|
-
expect(@book.library.id).to eq @library.id
|
|
278
|
-
@library.books.reload
|
|
279
|
-
expect(@library.books).to eq [@book]
|
|
280
|
-
|
|
281
|
-
@library2 = Library.find(@library.id)
|
|
282
|
-
expect(@library2.books).to eq [@book]
|
|
283
|
-
end
|
|
284
|
-
|
|
285
|
-
it "has a count once it has been saved" do
|
|
286
|
-
@book_2 = Book.create
|
|
287
|
-
@library.books << @book << @book_2
|
|
288
|
-
@library.save
|
|
289
|
-
|
|
290
|
-
@library2 = Library.find(@library.id)
|
|
291
|
-
expect(@library2.books.size).to eq 2
|
|
292
|
-
@book_2.reload
|
|
293
|
-
@book_2.delete
|
|
294
|
-
end
|
|
295
|
-
|
|
296
|
-
it "respects the :class_name parameter" do
|
|
297
|
-
@book.author = @person
|
|
298
|
-
@book.save
|
|
299
|
-
new_book = Book.find(@book.id)
|
|
300
|
-
expect(new_book.author_id).to eq @person.id
|
|
301
|
-
expect(new_book.author).to be_kind_of Person
|
|
302
|
-
end
|
|
303
|
-
|
|
304
|
-
it "respects multiple associations that share the same :property and respect associated class" do
|
|
305
|
-
@book.author = @person
|
|
306
|
-
@book.publisher = @publisher
|
|
307
|
-
@book.save
|
|
308
|
-
|
|
309
|
-
new_book = Book.find(@book.id)
|
|
310
|
-
|
|
311
|
-
expect(new_book.publisher_id).to eq @publisher.id
|
|
312
|
-
expect(new_book.publisher).to be_kind_of Publisher
|
|
313
|
-
|
|
314
|
-
expect(new_book.author_id).to eq @person.id
|
|
315
|
-
expect(new_book.author).to be_kind_of Person
|
|
316
|
-
end
|
|
317
|
-
|
|
318
|
-
describe "when changing the belonger" do
|
|
319
|
-
before do
|
|
320
|
-
@book.library = @library
|
|
321
|
-
@book.save
|
|
322
|
-
@library2 = Library.create
|
|
323
|
-
end
|
|
324
|
-
it "replaces an existing instance" do
|
|
325
|
-
expect(@book.library_id).to eq @library.id
|
|
326
|
-
@book.library = @library2
|
|
327
|
-
@book.save
|
|
328
|
-
expect(Book.find(@book.id).library_id).to eq @library2.id
|
|
329
|
-
end
|
|
330
|
-
end
|
|
331
|
-
end
|
|
332
|
-
end
|
|
333
|
-
|
|
334
|
-
describe "when fetching an existing object" do
|
|
335
|
-
before do
|
|
336
|
-
class Dog < ActiveFedora::Base; end
|
|
337
|
-
class BigDog < Dog; end
|
|
338
|
-
class Cat < ActiveFedora::Base; end
|
|
339
|
-
@dog = Dog.create
|
|
340
|
-
@big_dog = BigDog.create
|
|
341
|
-
end
|
|
342
|
-
it "detects class mismatch" do
|
|
343
|
-
expect {
|
|
344
|
-
Cat.find @dog.id
|
|
345
|
-
}.to raise_error(ActiveFedora::ActiveFedoraError)
|
|
346
|
-
end
|
|
347
|
-
|
|
348
|
-
it "does not accept parent class into a subclass" do
|
|
349
|
-
expect {
|
|
350
|
-
BigDog.find @dog.id
|
|
351
|
-
}.to raise_error(ActiveFedora::ActiveFedoraError)
|
|
352
|
-
end
|
|
353
|
-
|
|
354
|
-
it "accepts a subclass into a parent class" do
|
|
355
|
-
# We could prevent this altogether since loading a subclass into
|
|
356
|
-
# a parent class (a BigDog into a Dog) would result in lost of
|
|
357
|
-
# data if the object is saved back and the subclass has more
|
|
358
|
-
# properties than the parent class. However, it does seem reasonable
|
|
359
|
-
# that people might want to use them interchangeably (after all
|
|
360
|
-
# a BigDog is a Dog) and therefore we allow for it.
|
|
361
|
-
expect {
|
|
362
|
-
Dog.find @big_dog.id
|
|
363
|
-
}.not_to raise_error
|
|
364
|
-
end
|
|
365
|
-
end
|
|
366
|
-
|
|
367
|
-
describe "setting belongs_to" do
|
|
368
|
-
before do
|
|
369
|
-
@library = Library.new
|
|
370
|
-
@library.save
|
|
371
|
-
@book = Book.new
|
|
372
|
-
@author = Person.new
|
|
373
|
-
@author.save
|
|
374
|
-
@publisher = Publisher.new
|
|
375
|
-
@publisher.save
|
|
376
|
-
end
|
|
377
|
-
it "sets the association" do
|
|
378
|
-
@book.library = @library
|
|
379
|
-
expect(@book.library.id).to eq @library.id
|
|
380
|
-
@book.save
|
|
381
|
-
|
|
382
|
-
expect(Book.find(@book.id).library.id).to eq @library.id
|
|
383
|
-
end
|
|
384
|
-
it "clears the association" do
|
|
385
|
-
@book.library = @library
|
|
386
|
-
@book.library = nil
|
|
387
|
-
@book.save
|
|
388
|
-
|
|
389
|
-
expect(Book.find(@book.id).library).to be_nil
|
|
390
|
-
end
|
|
391
|
-
|
|
392
|
-
it "replaces the association" do
|
|
393
|
-
@library2 = Library.new
|
|
394
|
-
@library2.save
|
|
395
|
-
@book.library = @library
|
|
396
|
-
@book.save
|
|
397
|
-
@book.library = @library2
|
|
398
|
-
@book.save
|
|
399
|
-
expect(Book.find(@book.id).library.id).to eq @library2.id
|
|
400
|
-
end
|
|
401
|
-
|
|
402
|
-
it "only replaces the matching class association" do
|
|
403
|
-
@publisher2 = Publisher.new
|
|
404
|
-
@publisher2.save
|
|
405
|
-
|
|
406
|
-
@book.publisher = @publisher
|
|
407
|
-
@book.author = @author
|
|
408
|
-
@book.save!
|
|
409
|
-
|
|
410
|
-
@book.publisher = @publisher2
|
|
411
|
-
@book.save!
|
|
412
|
-
|
|
413
|
-
new_book = Book.find(@book.id)
|
|
414
|
-
expect(new_book.publisher.id).to eq @publisher2.id
|
|
415
|
-
expect(new_book.author.id).to eq @author.id
|
|
416
|
-
end
|
|
417
|
-
|
|
418
|
-
it "only clears the matching class association" do
|
|
419
|
-
@book.publisher = @publisher
|
|
420
|
-
@book.author = @author
|
|
421
|
-
@book.save
|
|
422
|
-
|
|
423
|
-
@book.author = nil
|
|
424
|
-
@book.save
|
|
425
|
-
|
|
426
|
-
expect(Book.find(@book.id).author).to be_nil
|
|
427
|
-
expect(Book.find(@book.id).publisher.id).to eq @publisher.id
|
|
428
|
-
end
|
|
429
|
-
|
|
430
|
-
it "is able to be set by id" do
|
|
431
|
-
@book.library_id = @library.id
|
|
432
|
-
expect(@book.library_id).to eq @library.id
|
|
433
|
-
expect(@book.library.id).to eq @library.id
|
|
434
|
-
@book.save
|
|
435
|
-
expect(Book.find(@book.id).library_id).to eq @library.id
|
|
436
|
-
end
|
|
437
|
-
end
|
|
438
|
-
end
|
|
439
|
-
|
|
440
|
-
describe "single direction habtm" do
|
|
441
|
-
before :all do
|
|
442
|
-
class Course < ActiveFedora::Base
|
|
443
|
-
has_and_belongs_to_many :textbooks, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf
|
|
444
|
-
end
|
|
445
|
-
class Textbook < ActiveFedora::Base
|
|
446
|
-
has_many :courses, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf
|
|
447
|
-
end
|
|
448
|
-
end
|
|
449
|
-
after :all do
|
|
450
|
-
Object.send(:remove_const, :Course)
|
|
451
|
-
Object.send(:remove_const, :Textbook)
|
|
452
|
-
end
|
|
453
|
-
|
|
454
|
-
describe "with a parent that has two children" do
|
|
455
|
-
before do
|
|
456
|
-
@course = Course.create
|
|
457
|
-
@t1 = Textbook.create
|
|
458
|
-
@t2 = Textbook.create
|
|
459
|
-
@course.textbooks = [@t1, @t2]
|
|
460
|
-
@course.save
|
|
461
|
-
end
|
|
462
|
-
|
|
463
|
-
it "loads the association stored in the parent" do
|
|
464
|
-
@reloaded_course = Course.find(@course.id)
|
|
465
|
-
expect(@reloaded_course.textbooks).to contain_exactly @t1, @t2
|
|
466
|
-
end
|
|
467
|
-
|
|
468
|
-
it "allows a parent to be deleted from the has_many association" do
|
|
469
|
-
@reloaded_course = Course.find(@course.id)
|
|
470
|
-
@t1.courses.delete(@reloaded_course)
|
|
471
|
-
@reloaded_course.save
|
|
472
|
-
|
|
473
|
-
@reloaded_course = Course.find(@course.id)
|
|
474
|
-
expect(@reloaded_course.textbooks).to eq [@t2]
|
|
475
|
-
end
|
|
476
|
-
|
|
477
|
-
it "allows replacing the children" do
|
|
478
|
-
@t3 = Textbook.create
|
|
479
|
-
@t4 = Textbook.create
|
|
480
|
-
@course.textbooks = [@t3, @t4]
|
|
481
|
-
@course.save
|
|
482
|
-
|
|
483
|
-
expect(@course.reload.textbooks).to contain_exactly @t3, @t4
|
|
484
|
-
end
|
|
485
|
-
|
|
486
|
-
it "allows a child to be deleted from the has_and_belongs_to_many association" do
|
|
487
|
-
@reloaded_course = Course.find(@course.id)
|
|
488
|
-
@reloaded_course.textbooks.delete(@t1)
|
|
489
|
-
@reloaded_course.save
|
|
490
|
-
@t1.save
|
|
491
|
-
|
|
492
|
-
@reloaded_course = Course.find(@course.id)
|
|
493
|
-
expect(@reloaded_course.textbooks).to eq [@t2]
|
|
494
|
-
end
|
|
495
|
-
end
|
|
496
|
-
end
|
|
497
|
-
|
|
498
|
-
describe "association hooks" do
|
|
499
|
-
describe "for habtm" do
|
|
500
|
-
before :all do
|
|
501
|
-
class LibraryBook < ActiveFedora::Base
|
|
502
|
-
has_and_belongs_to_many :pages, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, after_remove: :after_hook, before_remove: :before_hook
|
|
503
|
-
|
|
504
|
-
def before_hook(m)
|
|
505
|
-
say_hi(m)
|
|
506
|
-
before_count(m.reload.library_books.count)
|
|
507
|
-
end
|
|
508
|
-
|
|
509
|
-
def after_hook(m)
|
|
510
|
-
say_hi(m)
|
|
511
|
-
after_count(m.reload.library_books.count)
|
|
512
|
-
end
|
|
513
|
-
|
|
514
|
-
def say_hi(_var); end
|
|
515
|
-
end
|
|
516
|
-
class Page < ActiveFedora::Base
|
|
517
|
-
has_many :library_books, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf
|
|
518
|
-
end
|
|
519
|
-
end
|
|
520
|
-
after :all do
|
|
521
|
-
Object.send(:remove_const, :LibraryBook)
|
|
522
|
-
Object.send(:remove_const, :Page)
|
|
523
|
-
end
|
|
524
|
-
|
|
525
|
-
describe "removing association" do
|
|
526
|
-
subject(:book) do
|
|
527
|
-
book = LibraryBook.create
|
|
528
|
-
book.pages << p1 << p2
|
|
529
|
-
book.save!
|
|
530
|
-
book
|
|
531
|
-
end
|
|
532
|
-
let(:p1) { Page.create }
|
|
533
|
-
let(:p2) { Page.create }
|
|
534
|
-
|
|
535
|
-
it "saves between the before and after hooks" do
|
|
536
|
-
expect(book).to receive(:before_count).with(1)
|
|
537
|
-
expect(book).to receive(:after_count).with(0)
|
|
538
|
-
expect(book).to receive(:say_hi).with(p2).twice
|
|
539
|
-
book.pages.delete(p2)
|
|
540
|
-
end
|
|
541
|
-
end
|
|
542
|
-
end
|
|
543
|
-
describe "for has_many" do
|
|
544
|
-
before :all do
|
|
545
|
-
class LibraryBook < ActiveFedora::Base
|
|
546
|
-
has_many :pages, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, after_remove: :say_hi
|
|
547
|
-
end
|
|
548
|
-
class Page < ActiveFedora::Base
|
|
549
|
-
belongs_to :library_book, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf
|
|
550
|
-
end
|
|
551
|
-
end
|
|
552
|
-
|
|
553
|
-
after :all do
|
|
554
|
-
Object.send(:remove_const, :LibraryBook)
|
|
555
|
-
Object.send(:remove_const, :Page)
|
|
556
|
-
end
|
|
557
|
-
|
|
558
|
-
describe "removing association" do
|
|
559
|
-
let(:p1) { book.pages.build }
|
|
560
|
-
let(:p2) { book.pages.build }
|
|
561
|
-
let(:book) { LibraryBook.new }
|
|
562
|
-
it "runs the hooks" do
|
|
563
|
-
expect(book).to receive(:say_hi).with(p2)
|
|
564
|
-
book.pages.delete(p2)
|
|
565
|
-
end
|
|
566
|
-
end
|
|
567
|
-
end
|
|
568
|
-
end
|
|
569
|
-
|
|
570
|
-
describe "has_many" do
|
|
571
|
-
describe "when an object doesn't have a property, and the class_name is predictable" do
|
|
572
|
-
before(:all) do
|
|
573
|
-
class Bauble < ActiveFedora::Base
|
|
574
|
-
belongs_to :media_object, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf
|
|
575
|
-
end
|
|
576
|
-
class MediaObject < ActiveFedora::Base
|
|
577
|
-
has_many :baubles
|
|
578
|
-
end
|
|
579
|
-
end
|
|
580
|
-
after :all do
|
|
581
|
-
Object.send(:remove_const, :Bauble)
|
|
582
|
-
Object.send(:remove_const, :MediaObject)
|
|
583
|
-
end
|
|
584
|
-
|
|
585
|
-
it "finds the reflection that bears the predicate" do
|
|
586
|
-
expect(MediaObject.new.association(:baubles).send(:find_reflection)).to eq Bauble._reflect_on_association(:media_object)
|
|
587
|
-
end
|
|
588
|
-
end
|
|
589
|
-
|
|
590
|
-
describe "when an object doesn't have a property, but has a class_name" do
|
|
591
|
-
before :all do
|
|
592
|
-
class MasterFile < ActiveFedora::Base
|
|
593
|
-
belongs_to :media_object, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf
|
|
594
|
-
end
|
|
595
|
-
class MediaObject < ActiveFedora::Base
|
|
596
|
-
has_many :parts, class_name: 'MasterFile'
|
|
597
|
-
end
|
|
598
|
-
end
|
|
599
|
-
|
|
600
|
-
after :all do
|
|
601
|
-
Object.send(:remove_const, :MasterFile)
|
|
602
|
-
Object.send(:remove_const, :MediaObject)
|
|
603
|
-
end
|
|
604
|
-
|
|
605
|
-
it "finds the reflection that bears the predicate" do
|
|
606
|
-
expect(MediaObject.new.association(:parts).send(:find_reflection)).to eq MasterFile._reflect_on_association(:media_object)
|
|
607
|
-
end
|
|
608
|
-
end
|
|
609
|
-
|
|
610
|
-
describe "an object has an explicity property" do
|
|
611
|
-
before :all do
|
|
612
|
-
class Bauble < ActiveFedora::Base
|
|
613
|
-
belongs_to :media_object, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf
|
|
614
|
-
end
|
|
615
|
-
class MediaObject < ActiveFedora::Base
|
|
616
|
-
has_many :baubles, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.hasEquivalent
|
|
617
|
-
end
|
|
618
|
-
end
|
|
619
|
-
|
|
620
|
-
after :all do
|
|
621
|
-
Object.send(:remove_const, :Bauble)
|
|
622
|
-
Object.send(:remove_const, :MediaObject)
|
|
623
|
-
end
|
|
624
|
-
|
|
625
|
-
it "finds the reflection that bears the predicate" do
|
|
626
|
-
expect(MediaObject.new.association(:baubles).send(:find_reflection)).to eq MediaObject._reflect_on_association(:baubles)
|
|
627
|
-
end
|
|
628
|
-
end
|
|
629
|
-
end
|
|
630
|
-
|
|
631
|
-
describe "casting when the class name is ActiveFedora::Base" do
|
|
632
|
-
describe "for habtm" do
|
|
633
|
-
before :all do
|
|
634
|
-
class Novel < ActiveFedora::Base
|
|
635
|
-
has_and_belongs_to_many :contents, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, class_name: 'ActiveFedora::Base'
|
|
636
|
-
end
|
|
637
|
-
class TextBook < ActiveFedora::Base
|
|
638
|
-
has_and_belongs_to_many :contents, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, class_name: 'ActiveFedora::Base'
|
|
639
|
-
end
|
|
640
|
-
class Text < ActiveFedora::Base
|
|
641
|
-
has_many :books, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, class_name: 'ActiveFedora::Base'
|
|
642
|
-
end
|
|
643
|
-
class Image < ActiveFedora::Base
|
|
644
|
-
has_many :books, predicate: ActiveFedora::RDF::Fcrepo::RelsExt.isPartOf, class_name: 'ActiveFedora::Base'
|
|
645
|
-
end
|
|
646
|
-
end
|
|
647
|
-
|
|
648
|
-
after :all do
|
|
649
|
-
Object.send(:remove_const, :Novel)
|
|
650
|
-
Object.send(:remove_const, :TextBook)
|
|
651
|
-
Object.send(:remove_const, :Text)
|
|
652
|
-
Object.send(:remove_const, :Image)
|
|
653
|
-
end
|
|
654
|
-
|
|
655
|
-
describe "saving between the before and after hooks" do
|
|
656
|
-
let(:text1) { Text.create }
|
|
657
|
-
let(:image1) { Image.create }
|
|
658
|
-
let(:text2) { Text.create }
|
|
659
|
-
let(:image2) { Image.create }
|
|
660
|
-
let(:book1) { TextBook.create }
|
|
661
|
-
let(:book2) { Novel.create }
|
|
662
|
-
|
|
663
|
-
it "works when added via the has_and_belongs_to_many" do
|
|
664
|
-
book1.contents = [text1, image1]
|
|
665
|
-
book1.save!
|
|
666
|
-
book2.contents = [text2, image2]
|
|
667
|
-
book2.save!
|
|
668
|
-
|
|
669
|
-
expect(book1.reload.contents).to include(text1, image1)
|
|
670
|
-
expect(text1.reload.books).to eq [book1]
|
|
671
|
-
expect(image1.reload.books).to eq [book1]
|
|
672
|
-
|
|
673
|
-
expect(book2.reload.contents).to include(text2, image2)
|
|
674
|
-
expect(text2.reload.books).to eq [book2]
|
|
675
|
-
expect(image2.reload.books).to eq [book2]
|
|
676
|
-
end
|
|
677
|
-
end
|
|
678
|
-
end
|
|
679
|
-
end
|
|
680
|
-
end
|