lucid_works 0.5.3 → 0.6.0
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.
- data/README.rdoc +5 -20
- data/lib/lucid_works/associations/has_many.rb +70 -0
- data/lib/lucid_works/associations/has_one.rb +38 -0
- data/lib/lucid_works/associations/proxy.rb +51 -0
- data/lib/lucid_works/associations.rb +71 -52
- data/lib/lucid_works/base.rb +53 -7
- data/lib/lucid_works/collection.rb +1 -1
- data/lib/lucid_works/datasource.rb +6 -5
- data/lib/lucid_works/patch_restclient.rb +2 -2
- data/lib/lucid_works/patch_time.rb +1 -1
- data/lib/lucid_works/version.rb +1 -1
- data/lib/lucid_works.rb +3 -0
- data/spec/lib/lucid_works/associations/has_many_spec.rb +167 -0
- data/spec/lib/lucid_works/associations/has_one_spec.rb +177 -0
- data/spec/lib/lucid_works/associations_spec.rb +68 -88
- data/spec/lib/lucid_works/base_spec.rb +32 -13
- data/spec/lib/lucid_works/collection_spec.rb +1 -1
- data/spec/lib/lucid_works/datasource_spec.rb +4 -4
- data/spec/lib/lucid_works/server_spec.rb +6 -3
- metadata +9 -2
data/README.rdoc
CHANGED
@@ -227,23 +227,6 @@ Then
|
|
227
227
|
|
228
228
|
thing.build_whatnot -> an unsaved Whatnot
|
229
229
|
|
230
|
-
==== Has_singleton associations
|
231
|
-
|
232
|
-
The has_singleton association is used to associate a resource with another intransient singleton resource, i.e. one that always exists and calling destroy does not remove it.
|
233
|
-
|
234
|
-
class Thing < LucidWorks::Base
|
235
|
-
has_one :whatnot
|
236
|
-
end
|
237
|
-
|
238
|
-
class Whatnot < LucidWorks::Base
|
239
|
-
self.singleton = true
|
240
|
-
belongs_to :thing
|
241
|
-
end
|
242
|
-
|
243
|
-
Then
|
244
|
-
|
245
|
-
thing.whatnot -> an unsaved Whatnot
|
246
|
-
|
247
230
|
=== Belongs_to associations
|
248
231
|
|
249
232
|
Te belongs to association augments the model with methods to access its parent. Given:
|
@@ -257,6 +240,8 @@ Then:
|
|
257
240
|
|
258
241
|
whatnot.thing -> A Thing
|
259
242
|
|
243
|
+
For more information on association see LucidWorks::Associations::ClassMethods
|
244
|
+
|
260
245
|
=== Schema
|
261
246
|
|
262
247
|
A class may have a schema defined as follows:
|
@@ -267,11 +252,11 @@ A class may have a schema defined as follows:
|
|
267
252
|
attribute :bool1, :boolean
|
268
253
|
attribute :integer1, :integer
|
269
254
|
attributes :string2, :string3, :string4
|
270
|
-
attributes :bool2,
|
271
|
-
attributes :int2,
|
255
|
+
attributes :bool2, :bool3, :type => :boolean
|
256
|
+
attributes :int2, :int3, :type => :integer
|
272
257
|
attribute :string_with_values, :values => ['one', 'two']
|
273
258
|
attribute :dontsendme, :omit_during_update => true
|
274
|
-
attribute :sendnull,
|
259
|
+
attribute :sendnull, :string, :nil_when_blank => true
|
275
260
|
end
|
276
261
|
end
|
277
262
|
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module LucidWorks
|
2
|
+
module Associations
|
3
|
+
class HasMany < Proxy #:nodoc:
|
4
|
+
|
5
|
+
def build(attributes={})
|
6
|
+
@target_class.new(attributes.merge({:parent => @owner}))
|
7
|
+
# Don't cache it - it's only a single target
|
8
|
+
end
|
9
|
+
|
10
|
+
def create(attributes={})
|
11
|
+
target = build(attributes)
|
12
|
+
target.save
|
13
|
+
target
|
14
|
+
end
|
15
|
+
|
16
|
+
def create!(attributes={})
|
17
|
+
target = build(attributes)
|
18
|
+
if target.save
|
19
|
+
target
|
20
|
+
else
|
21
|
+
raise target.errors.full_messages
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def remember_find_options(options)
|
26
|
+
@find_options = options
|
27
|
+
end
|
28
|
+
|
29
|
+
# Explicit find call does not use the remembered options, or cache the result
|
30
|
+
def find(id_or_find_type, options={})
|
31
|
+
@target_class.send(:find, id_or_find_type, options.merge(:parent => @owner))
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# Caching rules
|
37
|
+
# It's easy to cache a has_one resource as we never search for different things.
|
38
|
+
# With a has_many the user can either use .others and get the entire collection
|
39
|
+
# or .others.find(id) and get just one. What do we cache?
|
40
|
+
#
|
41
|
+
# Interestingly for us the cost difference is marginal between the two forms of
|
42
|
+
# the call. Should we just grab all of them and return the one they want?
|
43
|
+
# Probably not. Not every elegant and there is some cost to creating models
|
44
|
+
# on our end.
|
45
|
+
#
|
46
|
+
# Okay for now we will just not cache .find()
|
47
|
+
#
|
48
|
+
# The largest challenge is this sequence:
|
49
|
+
#
|
50
|
+
# a = others.find(1) #
|
51
|
+
# others.find(1).name
|
52
|
+
# b = others.first # requires retrieving all
|
53
|
+
|
54
|
+
|
55
|
+
def load_target(options={})
|
56
|
+
if @target.nil? || options[:force]
|
57
|
+
if @options[:has_content] === false
|
58
|
+
return true # make method_missing happy so it will operate on NilClass
|
59
|
+
else
|
60
|
+
opts = (@find_options || {}).merge(:parent => @owner)
|
61
|
+
@target = @target_class.send(:find, :all, opts)
|
62
|
+
@find_options = {}
|
63
|
+
end
|
64
|
+
else
|
65
|
+
end
|
66
|
+
@target
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module LucidWorks
|
2
|
+
module Associations
|
3
|
+
class HasOne < Proxy #:nodoc:
|
4
|
+
|
5
|
+
def build(attributes={})
|
6
|
+
@target = @target_class.new(attributes.merge({:parent => @owner}))
|
7
|
+
end
|
8
|
+
|
9
|
+
def create(attributes={})
|
10
|
+
build(attributes)
|
11
|
+
@target.save
|
12
|
+
@target
|
13
|
+
end
|
14
|
+
|
15
|
+
def create!(attributes={})
|
16
|
+
build(attributes)
|
17
|
+
if @target.save
|
18
|
+
@target
|
19
|
+
else
|
20
|
+
raise @target.errors.full_messages
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def load_target(options={})
|
27
|
+
if @target.nil? || options[:force]
|
28
|
+
if @options[:has_content] === false
|
29
|
+
return true # make method_missing happy so it will operate on NilClass
|
30
|
+
else
|
31
|
+
@target = @target_class.send(:find, :singleton, :parent => @owner)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
@target
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module LucidWorks
|
2
|
+
module Associations
|
3
|
+
|
4
|
+
# This is the root class of our association proxies:
|
5
|
+
#
|
6
|
+
# Associations
|
7
|
+
# Proxy
|
8
|
+
# HasOne
|
9
|
+
# HasMany
|
10
|
+
|
11
|
+
class Proxy #:nodoc:
|
12
|
+
instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_|caller|^object_id$)/ }
|
13
|
+
|
14
|
+
def initialize(owner, target_class, options={})
|
15
|
+
@owner, @target_class, @options = owner, target_class, options
|
16
|
+
@target = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
# Sets the target of this proxy to <tt>\target</tt>.
|
20
|
+
def target=(target)
|
21
|
+
@target = target
|
22
|
+
end
|
23
|
+
|
24
|
+
def loaded?
|
25
|
+
!!@target
|
26
|
+
end
|
27
|
+
|
28
|
+
# Can targets be retrieved for all owners if this type, in one step using owner/all/target
|
29
|
+
def supports_all?
|
30
|
+
@options[:supports_all]
|
31
|
+
end
|
32
|
+
|
33
|
+
def reload!
|
34
|
+
load_target(:force => true)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
# Forwards any missing method call to the \target.
|
40
|
+
def method_missing(method, *args, &block)
|
41
|
+
if load_target
|
42
|
+
if @target.respond_to?(method)
|
43
|
+
@target.send(method, *args, &block)
|
44
|
+
else
|
45
|
+
super
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -1,37 +1,58 @@
|
|
1
1
|
module LucidWorks
|
2
2
|
|
3
|
+
#
|
4
|
+
# See LucidWorks::Associations::ClassMethods
|
5
|
+
#
|
3
6
|
module Associations
|
4
7
|
extend ActiveSupport::Concern
|
5
8
|
|
6
9
|
module ClassMethods
|
7
10
|
|
11
|
+
def associations #:nodoc:
|
12
|
+
@associations ||= {}
|
13
|
+
end
|
14
|
+
|
8
15
|
# Specifies a singleton child resource.
|
9
16
|
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
+
# has_one :resource, <options>
|
18
|
+
#
|
19
|
+
# In the parent resource, creates methods:
|
20
|
+
#
|
21
|
+
# .resource
|
22
|
+
# .resource!
|
23
|
+
# .resource.build(attributes={})
|
24
|
+
# .resource.create(attributes={})
|
25
|
+
# .resource.create!(attributes={})
|
26
|
+
# .build_resource(attributes={})
|
27
|
+
# .create_resource(attributes={})
|
28
|
+
#
|
29
|
+
# _.resource_ will not actually load the resource until used i.e. resource._anything_ is called.
|
30
|
+
# After being loaded, the child is cached. Use _.resource!_ or _resource.reload!_ to relaod it.
|
31
|
+
#
|
32
|
+
# _.resource!_ will load the resource immediately, or reload it if it was already loaded.
|
33
|
+
#
|
34
|
+
# _.build_ creates a new model but does not save it. Parent is preset to the calling class.
|
35
|
+
#
|
36
|
+
# _.create_ builds the model, saves it, then returns it.
|
37
|
+
# You need to check persisted? and errors to see if the save succeeded.
|
38
|
+
#
|
39
|
+
# _.build_resource_ and _.create_resource_ are aliases for _.resource.build_ and _.resource.create_ respectively.
|
40
|
+
#
|
17
41
|
# === Options
|
18
42
|
#
|
19
43
|
# The declaration can also include an options hash to specialize the behavior of the association.
|
20
44
|
#
|
21
45
|
# Options are:
|
22
|
-
# [:class_name]
|
23
|
-
# Specify the class name of the association. Use it
|
46
|
+
# [:class_name => "name"]
|
47
|
+
# Specify the class name of the association. Use it if you want to us a child class name different
|
24
48
|
# from the association name, e.g.
|
25
|
-
# has_one :
|
26
|
-
# has_one :foo, :class_name => :'
|
27
|
-
# [:has_content]
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
|
32
|
-
# will instead build and return new, unsaved, model. This is useful for pseudo-resources that only
|
33
|
-
# provide actions, not data.
|
34
|
-
#
|
49
|
+
# has_one :foo # Use class Foo
|
50
|
+
# has_one :foo, :class_name => :'things/foo_bar' # use class Things::FooBar
|
51
|
+
# [:has_content => false]
|
52
|
+
# If set to false, indicated that this resource may not be retrieved using a GET,
|
53
|
+
# and will cause the _.resource_ method to return nil until the resource is built or created.
|
54
|
+
# This is useful for pseudo-resources that only provide actions, not data.
|
55
|
+
|
35
56
|
def has_one(*arguments)
|
36
57
|
options = arguments.last.is_a?(Hash) ? arguments.pop : {}
|
37
58
|
arguments.each do |resource|
|
@@ -39,7 +60,7 @@ module LucidWorks
|
|
39
60
|
end
|
40
61
|
end
|
41
62
|
|
42
|
-
# Specifies a child resource.
|
63
|
+
# Specifies a collection child resource.
|
43
64
|
#
|
44
65
|
# e.g. for Blog has_many posts
|
45
66
|
#
|
@@ -86,57 +107,55 @@ module LucidWorks
|
|
86
107
|
|
87
108
|
private
|
88
109
|
|
89
|
-
def define_has_one(resource, options={})
|
90
|
-
resource_class_name = (options
|
110
|
+
def define_has_one(resource, options={}) #:nodoc:
|
111
|
+
resource_class_name = (options.delete(:class_name) || resource).to_s.camelize
|
112
|
+
associations[resource.to_sym] = {:type => :has_one, :class_name => "#{resource_class_name}"}.merge(options)
|
91
113
|
|
92
114
|
class_eval <<-EOF, __FILE__, __LINE__ + 1
|
93
|
-
def #{resource}
|
94
|
-
@#{resource}
|
95
|
-
end
|
96
|
-
EOF
|
115
|
+
def #{resource}
|
116
|
+
@#{resource}_association ||= HasOne.new(self, #{resource_class_name}, #{options.to_s})
|
117
|
+
end
|
97
118
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
def build_#{resource}(options = {})
|
111
|
-
#{resource_class_name}.new(options.merge :parent => self)
|
112
|
-
end
|
113
|
-
EOF
|
114
|
-
end
|
119
|
+
def #{resource}!
|
120
|
+
#{resource}.reload!
|
121
|
+
end
|
122
|
+
|
123
|
+
def build_#{resource}(options = {})
|
124
|
+
#{resource}.build(options)
|
125
|
+
end
|
126
|
+
|
127
|
+
def create_#{resource}(options = {})
|
128
|
+
#{resource}.create(options)
|
129
|
+
end
|
130
|
+
EOF
|
115
131
|
end
|
116
132
|
|
117
|
-
def define_has_many(resources, options
|
133
|
+
def define_has_many(resources, options={}) #:nodoc:
|
118
134
|
resource = resources.to_s.singularize
|
119
|
-
resource_class_name = (options
|
135
|
+
resource_class_name = (options.delete(:class_name) || resource).to_s.classify
|
136
|
+
associations[resource.to_sym] = {:type => :has_many, :class_name => "#{resource_class_name}"}.merge(options)
|
120
137
|
|
121
138
|
class_eval <<-EOF, __FILE__, __LINE__ + 1
|
122
139
|
def #{resources}(options={})
|
123
|
-
@#{resources}
|
140
|
+
@#{resources}_association ||= HasMany.new(self, #{resource_class_name}, #{options.to_s})
|
141
|
+
@#{resources}_association.remember_find_options(options) unless options.empty?
|
142
|
+
@#{resources}_association
|
124
143
|
end
|
125
144
|
|
126
145
|
def #{resources}!(options={})
|
127
|
-
|
146
|
+
#{resources}(options).reload!
|
128
147
|
end
|
129
148
|
|
130
|
-
def #{resource}(
|
131
|
-
#{
|
149
|
+
def build_#{resource}(options = {})
|
150
|
+
#{resources}.build(options)
|
132
151
|
end
|
133
152
|
|
134
153
|
def create_#{resource}(options = {})
|
135
|
-
#{
|
154
|
+
#{resources}.create(options)
|
136
155
|
end
|
137
156
|
|
138
|
-
def
|
139
|
-
#{
|
157
|
+
def #{resource}(id, options={})
|
158
|
+
#{resources}.find(id, options)
|
140
159
|
end
|
141
160
|
EOF
|
142
161
|
end
|
data/lib/lucid_works/base.rb
CHANGED
@@ -141,8 +141,8 @@ module LucidWorks
|
|
141
141
|
|
142
142
|
results =
|
143
143
|
if kind_of_find == :all
|
144
|
-
data.collect do |
|
145
|
-
new(
|
144
|
+
data.collect do |model_attributes|
|
145
|
+
new(model_attributes.merge(:parent => parent, :persisted => true))
|
146
146
|
end
|
147
147
|
else
|
148
148
|
attributes = data.is_a?(Hash) ? data : {}
|
@@ -154,11 +154,56 @@ module LucidWorks
|
|
154
154
|
end
|
155
155
|
|
156
156
|
# Process :include options
|
157
|
-
#
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
157
|
+
#
|
158
|
+
# In the section, to reduce confusion we will use the terms owner/target instead of
|
159
|
+
# parent/child to describe the association.
|
160
|
+
#
|
161
|
+
# If we are doing a find(:all) and this owner resource supports retrieval of all targets
|
162
|
+
# in one request with owners/all/targets, get them and attach them to the original models'
|
163
|
+
# association proxys.
|
164
|
+
#
|
165
|
+
results_array = [results].flatten # allow us to process a single result or array with the same code
|
166
|
+
if includes && !results_array.empty?
|
167
|
+
includes = [includes].flatten
|
168
|
+
includes.each do |association_name|
|
169
|
+
association_info = associations[association_name.to_s.singularize.to_sym]
|
170
|
+
target_class = class_eval(association_info[:class_name]) # get scoping right
|
171
|
+
target_name = association_info[:class_name].underscore
|
172
|
+
|
173
|
+
if kind_of_find == :all && association_info[:supports_all]
|
174
|
+
all_targets_path = "#{collection_url(parent)}/all/#{target_name}"
|
175
|
+
raw_response = ActiveSupport::Notifications.instrument("lucid_works.request") do |payload|
|
176
|
+
payload[:method] = :get
|
177
|
+
payload[:uri] = all_targets_path
|
178
|
+
payload[:response] = RestClient.get(all_targets_path)
|
179
|
+
end
|
180
|
+
if association_info[:type] == :has_one
|
181
|
+
all_targets_attributes = JSON.parse raw_response
|
182
|
+
all_targets_attributes.each do |target_attributes|
|
183
|
+
owner_id = target_attributes['id']
|
184
|
+
owner = results_array.detect { |result| result.id == owner_id }
|
185
|
+
if owner
|
186
|
+
target = target_class.new(target_attributes.merge(:parent => owner, :persisted => true))
|
187
|
+
association_proxy = owner.send(association_name)
|
188
|
+
association_proxy.target = target
|
189
|
+
end
|
190
|
+
end
|
191
|
+
elsif association_info[:type] == :has_many
|
192
|
+
# [{"history":[...history_models...],"id":372},{"history":[...history_models...],"id":371}]
|
193
|
+
JSON.parse(raw_response).each do |group_of_targets|
|
194
|
+
owner_id = group_of_targets['id']
|
195
|
+
owner = results_array.detect { |result| result.id == owner_id }
|
196
|
+
targets = group_of_targets[target_name].collect do |target_attrs|
|
197
|
+
target_class.new(target_attrs.merge(:parent => owner, :persisted => true))
|
198
|
+
end
|
199
|
+
association_proxy = owner.send(association_name)
|
200
|
+
association_proxy.target = targets
|
201
|
+
end
|
202
|
+
end
|
203
|
+
else # kind_of_find != :all || !supports_all
|
204
|
+
results_array.each do |result|
|
205
|
+
result.send("#{association_name}!")
|
206
|
+
end
|
162
207
|
end
|
163
208
|
end
|
164
209
|
end
|
@@ -249,6 +294,7 @@ module LucidWorks
|
|
249
294
|
def initialize(options)
|
250
295
|
raise ArgumentError.new("new requires a Hash") unless options.is_a?(Hash)
|
251
296
|
@parent = self.class.extract_parent_from_options(options)
|
297
|
+
@associations = {}
|
252
298
|
@persisted = options.delete(:persisted) || singleton? || false
|
253
299
|
@attributes = {}.with_indifferent_access
|
254
300
|
load_attributes(options)
|
@@ -2,8 +2,9 @@ module LucidWorks
|
|
2
2
|
|
3
3
|
class Datasource < Base
|
4
4
|
belongs_to :collection
|
5
|
-
has_many :histories, :class_name => :history
|
6
|
-
has_one :status, :
|
5
|
+
has_many :histories, :class_name => :history, :supports_all => true
|
6
|
+
has_one :status, :supports_all => true
|
7
|
+
has_one :schedule, :crawldata
|
7
8
|
has_one :index, :job, :has_content => false
|
8
9
|
|
9
10
|
schema do
|
@@ -62,7 +63,7 @@ module LucidWorks
|
|
62
63
|
|
63
64
|
|
64
65
|
def empty!
|
65
|
-
|
66
|
+
build_index.destroy
|
66
67
|
end
|
67
68
|
|
68
69
|
def editable?
|
@@ -81,11 +82,11 @@ module LucidWorks
|
|
81
82
|
end
|
82
83
|
|
83
84
|
def start_crawl!
|
84
|
-
|
85
|
+
build_job.save
|
85
86
|
end
|
86
87
|
|
87
88
|
def stop_crawl!
|
88
|
-
|
89
|
+
build_job.destroy
|
89
90
|
end
|
90
91
|
|
91
92
|
def t_type
|
data/lib/lucid_works/version.rb
CHANGED
data/lib/lucid_works.rb
CHANGED
@@ -23,6 +23,9 @@ require 'lucid_works/patch_time'
|
|
23
23
|
|
24
24
|
require 'lucid_works/exceptions'
|
25
25
|
require 'lucid_works/associations'
|
26
|
+
require 'lucid_works/associations/proxy'
|
27
|
+
require 'lucid_works/associations/has_one'
|
28
|
+
require 'lucid_works/associations/has_many'
|
26
29
|
require 'lucid_works/server'
|
27
30
|
require 'lucid_works/base'
|
28
31
|
require 'lucid_works/schema'
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LucidWorks::Associations::HasMany do
|
4
|
+
before :all do
|
5
|
+
@fake_server_uri = "http://12.0.0.1:99999"
|
6
|
+
@server = LucidWorks::Server.new(@fake_server_uri)
|
7
|
+
|
8
|
+
class ::Target < LucidWorks::Base
|
9
|
+
attr_accessor :foo
|
10
|
+
end
|
11
|
+
class ::Owner < LucidWorks::Base
|
12
|
+
has_many :targets
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
before :each do
|
17
|
+
@owner = Owner.new(:parent => @server)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should not load the targets if just referenced" do
|
21
|
+
Target.should_not_receive(:find)
|
22
|
+
@owner.targets
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should load the target with find(:parent => Owner) when target is accessed" do
|
26
|
+
Target.should_receive(:find).with(:all, :parent => @owner)
|
27
|
+
@owner.targets.first
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should load the target with find(:parent => Owner) and remembered options when target is accessed" do
|
31
|
+
Target.should_receive(:find).with(:all, :parent => @owner, :include => :foo)
|
32
|
+
@owner.targets(:include => :foo)
|
33
|
+
@owner.targets.first
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should cache the targets and not reload them on every access" do
|
37
|
+
mock_targets = [double('target1'), double('target2')]
|
38
|
+
Target.should_receive(:find).with(:all, :parent => @owner).once.and_return(mock_targets)
|
39
|
+
@owner.targets.first
|
40
|
+
@owner.targets.first
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should delegate methods to the target" do
|
44
|
+
mock_targets = [double('target1'), double('target2')]
|
45
|
+
Target.stub(:find) { mock_targets }
|
46
|
+
mock_targets.should_receive(:first)
|
47
|
+
@owner.targets.first
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#loaded?" do
|
51
|
+
it "should return true if the target has been loaded, false otherwise" do
|
52
|
+
mock_targets = [double('target1'), double('target2')]
|
53
|
+
Target.stub(:find) { mock_targets }
|
54
|
+
|
55
|
+
@owner.targets.loaded?.should be_false
|
56
|
+
@owner.targets.first
|
57
|
+
@owner.targets.loaded?.should be_true
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#reload!" do
|
62
|
+
it "should force a reload of the target" do
|
63
|
+
mock_targets = [double('target1'), double('target2')]
|
64
|
+
Target.should_receive(:find).with(:all, :parent => @owner).twice.and_return(mock_targets)
|
65
|
+
@owner.targets.first
|
66
|
+
@owner.targets.reload!
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#find" do
|
71
|
+
it "should call Target.find with the provided options (not remembered options)" do
|
72
|
+
@owner.targets(:include => :foo)
|
73
|
+
Target.should_receive(:find).with(123, :parent => @owner)
|
74
|
+
@owner.targets.find(123)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should pass the find options to Target.find() when actually accessed" do
|
78
|
+
mock_target = double('target')
|
79
|
+
Target.should_receive(:find).with(123, :parent => @owner).and_return(mock_target)
|
80
|
+
@owner.targets.find(123).class
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "#build" do
|
85
|
+
it "should new up a target and initialize it with the supplied attributes" do
|
86
|
+
target = @owner.targets.build(:foo => 'bar')
|
87
|
+
target.should_not be_persisted
|
88
|
+
target.foo.should == 'bar'
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should initialize the new target's parent" do
|
92
|
+
target = @owner.targets.build
|
93
|
+
target.parent.should == @owner
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "#create" do
|
98
|
+
it "should new up a target and initialize it with the supplied attributes, then attempt to save it" do
|
99
|
+
mock_target = double('target')
|
100
|
+
Target.should_receive(:new).with(:foo => :bar, :parent => @owner).and_return(mock_target)
|
101
|
+
mock_target.should_receive(:save).and_return(:save_result)
|
102
|
+
target = @owner.targets.create(:foo => :bar)
|
103
|
+
target.should == mock_target
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should initialize the new target's parent" do
|
107
|
+
target = @owner.targets.build
|
108
|
+
target.parent.should == @owner
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "#create!" do
|
113
|
+
before do
|
114
|
+
@mock_target = double('target')
|
115
|
+
Target.should_receive(:new).with(:foo => :bar, :parent => @owner).and_return(@mock_target)
|
116
|
+
end
|
117
|
+
|
118
|
+
context "when save succeeds" do
|
119
|
+
before do
|
120
|
+
@mock_target.should_receive(:save).and_return(true)
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should return the target" do
|
124
|
+
target = @owner.targets.create!(:foo => :bar)
|
125
|
+
target.should == @mock_target
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context "when save fails" do
|
130
|
+
before do
|
131
|
+
@mock_target.should_receive(:save).and_return(false)
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should raise an error" do
|
135
|
+
lambda {
|
136
|
+
@owner.targets.create!(:foo => :bar)
|
137
|
+
}.should raise_error
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context "with options :supports_all => true" do
|
143
|
+
before :all do
|
144
|
+
class ::AllableTarget < LucidWorks::Base
|
145
|
+
end
|
146
|
+
class ::Owner
|
147
|
+
has_many :allable_targets, :supports_all => true
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe "Owner.find(:all, :include => :targets)" do
|
152
|
+
it "should use owwner/all/targets to retrieve the targets" do
|
153
|
+
owners_json = '[{"id":1},{"id":2}]'
|
154
|
+
target_json = '[{"id":1,"allable_target":[{"id":1,"fruit":"apple"},{"id":1,"fruit":"pear"}]},' +
|
155
|
+
'{"id":2,"allable_target":[{"id":2,"fruit":"orange"}]}]'
|
156
|
+
RestClient.should_receive(:get).with("#{@fake_server_uri}/api/owners").
|
157
|
+
once.ordered.and_return(owners_json)
|
158
|
+
RestClient.should_receive(:get).with("#{@fake_server_uri}/api/owners/all/allable_target").
|
159
|
+
once.ordered.and_return(target_json)
|
160
|
+
owners = Owner.find(:all, :parent => @server, :include => :allable_targets)
|
161
|
+
owners.first.allable_targets.first.fruit.should == 'apple'
|
162
|
+
owners.first.allable_targets.last.fruit.should == 'pear'
|
163
|
+
owners.last.allable_targets.first.fruit.should == 'orange'
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LucidWorks::Associations::HasOne do
|
4
|
+
before :all do
|
5
|
+
@fake_server_uri = "http://12.0.0.1:99999"
|
6
|
+
@server = LucidWorks::Server.new(@fake_server_uri)
|
7
|
+
|
8
|
+
class ::Target < LucidWorks::Base
|
9
|
+
attr_accessor :foo
|
10
|
+
end
|
11
|
+
class ::Owner < LucidWorks::Base
|
12
|
+
has_one :target
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
before :each do
|
17
|
+
@owner = Owner.new(:parent => @server)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should not load the target if just referenced" do
|
21
|
+
Target.should_not_receive(:find)
|
22
|
+
@owner.target
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should load the target with find(:parent => Owner) when target is accessed" do
|
26
|
+
Target.should_receive(:find).with(:singleton, :parent => @owner)
|
27
|
+
@owner.target.class
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should cache the target and not reload it on every access" do
|
31
|
+
mock_target = double('target')
|
32
|
+
Target.should_receive(:find).with(:singleton, :parent => @owner).once.and_return(mock_target)
|
33
|
+
@owner.target.class
|
34
|
+
@owner.target.class
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should delegate methods to the target" do
|
38
|
+
mock_target = double('target')
|
39
|
+
Target.stub(:find) { mock_target }
|
40
|
+
mock_target.should_receive(:foo)
|
41
|
+
@owner.target.foo
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#loaded?" do
|
45
|
+
it "should return true if the target has been loaded, false otherwise" do
|
46
|
+
mock_target = double('target')
|
47
|
+
Target.stub(:find) { mock_target }
|
48
|
+
|
49
|
+
@owner.target.loaded?.should be_false
|
50
|
+
@owner.target.class
|
51
|
+
@owner.target.loaded?.should be_true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#reload!" do
|
56
|
+
it "should force a reload of the target" do
|
57
|
+
mock_target = double('target')
|
58
|
+
Target.should_receive(:find).with(:singleton, :parent => @owner).twice.and_return(mock_target)
|
59
|
+
@owner.target.class
|
60
|
+
@owner.target.reload!
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#build" do
|
65
|
+
it "should new up a target and initialize it with the supplied attributes" do
|
66
|
+
target = @owner.target.build(:foo => 'bar')
|
67
|
+
target.should_not be_persisted
|
68
|
+
target.foo.should == 'bar'
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should initialize the new target's parent" do
|
72
|
+
target = @owner.target.build
|
73
|
+
target.parent.should == @owner
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#create" do
|
78
|
+
it "should new up a target and initialize it with the supplied attributes, then attempt to save it" do
|
79
|
+
mock_target = double('target')
|
80
|
+
Target.should_receive(:new).with(:foo => :bar, :parent => @owner).and_return(mock_target)
|
81
|
+
mock_target.should_receive(:save).and_return(:save_result)
|
82
|
+
target = @owner.target.create(:foo => :bar)
|
83
|
+
target.should == mock_target
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should initialize the new target's parent" do
|
87
|
+
target = @owner.target.build
|
88
|
+
target.parent.should == @owner
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "#create!" do
|
93
|
+
before do
|
94
|
+
@mock_target = double('target')
|
95
|
+
Target.should_receive(:new).with(:foo => :bar, :parent => @owner).and_return(@mock_target)
|
96
|
+
end
|
97
|
+
|
98
|
+
context "when save succeeds" do
|
99
|
+
before do
|
100
|
+
@mock_target.should_receive(:save).and_return(true)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should return the target" do
|
104
|
+
target = @owner.target.create!(:foo => :bar)
|
105
|
+
target.should == @mock_target
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context "when save fails" do
|
110
|
+
before do
|
111
|
+
@mock_target.should_receive(:save).and_return(false)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should raise an error" do
|
115
|
+
lambda {
|
116
|
+
@owner.target.create!(:foo => :bar)
|
117
|
+
}.should raise_error
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "with option has_content => false" do
|
123
|
+
before :all do
|
124
|
+
class ::TargetWithoutContent < LucidWorks::Base
|
125
|
+
attr_accessor :foo
|
126
|
+
end
|
127
|
+
class ::Owner
|
128
|
+
has_one :target_without_content, :has_content => false
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
before :each do
|
133
|
+
@owner = Owner.new(:parent => @server)
|
134
|
+
end
|
135
|
+
|
136
|
+
context "before any build or create" do
|
137
|
+
describe "attribute accesses" do
|
138
|
+
it "should not attempt to retrieve the target, and let the caller interact with NilClass" do
|
139
|
+
TargetWithoutContent.should_not_receive(:find)
|
140
|
+
@owner.target_without_content.should be_a(NilClass)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context "after build" do
|
146
|
+
it "should return the target" do
|
147
|
+
target = @owner.target_without_content.build(:foo => 'bar')
|
148
|
+
target.should be_a(TargetWithoutContent)
|
149
|
+
target.foo.should == 'bar'
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context "with options :supports_all => true" do
|
155
|
+
before :all do
|
156
|
+
class ::TargetWithAll < LucidWorks::Base
|
157
|
+
end
|
158
|
+
class ::Owner
|
159
|
+
has_one :target_with_all, :supports_all => true
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "Owner.find(:all, :include => :target)" do
|
164
|
+
it "should use owwner/all/target to retrieve the targets" do
|
165
|
+
owners_json = '[{"id":1},{"id":2}]'
|
166
|
+
target_json = '[{"id":1,"fruit":"apple"},{"id":2,"fruit":"orange"}]'
|
167
|
+
RestClient.should_receive(:get).with("#{@fake_server_uri}/api/owners").
|
168
|
+
once.ordered.and_return(owners_json)
|
169
|
+
RestClient.should_receive(:get).with("#{@fake_server_uri}/api/owners/all/target_with_all").
|
170
|
+
once.ordered.and_return(target_json)
|
171
|
+
owners = Owner.find(:all, :parent => @server, :include => :target_with_all)
|
172
|
+
owners.first.target_with_all.fruit.should == 'apple'
|
173
|
+
owners.last.target_with_all.fruit.should == 'orange'
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
@@ -4,128 +4,108 @@ describe LucidWorks::Associations do
|
|
4
4
|
before :all do
|
5
5
|
@fake_server_uri = "http://fakehost.com:8888"
|
6
6
|
@server = LucidWorks::Server.new(@fake_server_uri)
|
7
|
-
|
8
|
-
class ::Blog < LucidWorks::Base
|
9
|
-
has_many :posts
|
10
|
-
has_one :homepage
|
11
|
-
has_one :launch_party, :has_content => false
|
12
|
-
end
|
13
|
-
@blog = ::Blog.new(:parent => @server)
|
14
|
-
|
15
|
-
class ::Post < LucidWorks::Base
|
16
|
-
belongs_to :blog
|
17
|
-
end
|
18
|
-
|
19
|
-
class ::Homepage < LucidWorks::Base
|
20
|
-
self.singleton = true
|
21
|
-
belongs_to :blog
|
22
|
-
end
|
23
|
-
|
24
|
-
class ::LaunchParty < LucidWorks::Base
|
25
|
-
self.singleton = true
|
26
|
-
belongs_to :blog
|
27
|
-
end
|
28
7
|
end
|
29
8
|
|
30
9
|
describe ".has_one" do
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
@blog.launch_party.should == mock_launch_party
|
38
|
-
@blog.launch_party.should == mock_launch_party
|
39
|
-
end
|
10
|
+
before :all do
|
11
|
+
class ::Blog < LucidWorks::Base
|
12
|
+
has_one :homepage
|
13
|
+
has_one :calendar, :bogus_option => :bogus_value
|
14
|
+
has_one :sitemap, :class_name => 'blog_site_map', :bogus_option => :bogus_value
|
40
15
|
end
|
16
|
+
class ::Homepage < LucidWorks::Base ; end
|
17
|
+
class ::Calendar < LucidWorks::Base ; end
|
18
|
+
class ::BlogSiteMap < LucidWorks::Base ; end
|
41
19
|
|
42
|
-
|
43
|
-
|
44
|
-
LaunchParty.should_not_receive(:find)
|
45
|
-
|
46
|
-
launch_party = @blog.launch_party!
|
20
|
+
@blog = ::Blog.new(:parent => @server)
|
21
|
+
end
|
47
22
|
|
48
|
-
|
49
|
-
|
50
|
-
|
23
|
+
describe "#resource" do
|
24
|
+
it "should create a HasOne association proxy for the specified class" do
|
25
|
+
LucidWorks::Associations::HasOne.should_receive(:new).
|
26
|
+
with(@blog, Homepage, {})
|
27
|
+
@blog.homepage
|
51
28
|
end
|
52
29
|
end
|
53
30
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
31
|
+
describe "#build_resource" do
|
32
|
+
it "should call .resource.build" do
|
33
|
+
mock_association = double("has_one association")
|
34
|
+
@blog.should_receive(:homepage).and_return(mock_association)
|
35
|
+
mock_association.should_receive(:build).with(:foo => :bar)
|
36
|
+
@blog.build_homepage(:foo => :bar)
|
60
37
|
end
|
38
|
+
end
|
61
39
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
end
|
40
|
+
describe "#create_resource" do
|
41
|
+
it "should call .resource.create" do
|
42
|
+
mock_association = double("has_one association")
|
43
|
+
@blog.should_receive(:homepage).and_return(mock_association)
|
44
|
+
mock_association.should_receive(:create).with(:foo => :bar)
|
45
|
+
@blog.create_homepage(:foo => :bar)
|
69
46
|
end
|
47
|
+
end
|
70
48
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
homepage.should be_persisted
|
76
|
-
end
|
77
|
-
end
|
49
|
+
it "should pass thru options to the proxy" do
|
50
|
+
LucidWorks::Associations::HasOne.should_receive(:new).
|
51
|
+
with(@blog, Calendar, :bogus_option => :bogus_value)
|
52
|
+
@blog.calendar
|
78
53
|
end
|
79
|
-
end
|
80
54
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
55
|
+
it "should respect the :class_name option" do
|
56
|
+
LucidWorks::Associations::HasOne.should_receive(:new).
|
57
|
+
with(@blog, BlogSiteMap, :bogus_option => :bogus_value)
|
58
|
+
@blog.sitemap
|
85
59
|
end
|
86
60
|
end
|
87
61
|
|
88
62
|
describe ".has_many" do
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
@blog.posts!
|
63
|
+
before :all do
|
64
|
+
class ::Blog < LucidWorks::Base
|
65
|
+
has_many :posts
|
93
66
|
end
|
94
|
-
end
|
95
67
|
|
96
|
-
|
97
|
-
|
98
|
-
mock_posts = double('some posts')
|
99
|
-
Post.should_receive(:find).once.and_return(mock_posts)
|
100
|
-
@blog.posts.should == mock_posts
|
101
|
-
@blog.posts.should == mock_posts
|
68
|
+
class ::Post < LucidWorks::Base
|
69
|
+
belongs_to :blog
|
102
70
|
end
|
103
71
|
end
|
104
72
|
|
105
|
-
|
106
|
-
|
107
|
-
Post.should_receive(:find).with('child_id', :parent => @blog)
|
108
|
-
@blog.post('child_id')
|
109
|
-
end
|
73
|
+
before :each do
|
74
|
+
@blog = ::Blog.new(:parent => @server)
|
110
75
|
end
|
111
76
|
|
112
|
-
describe "
|
113
|
-
it "should
|
114
|
-
|
115
|
-
|
77
|
+
describe "#resources" do
|
78
|
+
it "should create a HasMany association proxy for the specified class" do
|
79
|
+
mock_proxy = double('hasmany proxy', :find => nil)
|
80
|
+
LucidWorks::Associations::HasMany.should_receive(:new).
|
81
|
+
with(@blog, Post, {}).
|
82
|
+
and_return(mock_proxy)
|
83
|
+
@blog.posts
|
116
84
|
end
|
117
85
|
end
|
118
86
|
|
119
|
-
describe "#
|
120
|
-
it "should
|
121
|
-
|
122
|
-
|
123
|
-
post.
|
87
|
+
describe "#resource" do
|
88
|
+
it "should call Resource.find" do
|
89
|
+
mock_proxy = double('hasmany proxy', :first => nil)
|
90
|
+
Post.should_receive(:find).with('child_id', :parent => @blog).and_return(mock_proxy)
|
91
|
+
@blog.post('child_id').first
|
124
92
|
end
|
125
93
|
end
|
126
94
|
end
|
127
95
|
|
128
96
|
describe ".belongs_to" do
|
97
|
+
before :all do
|
98
|
+
class ::Blog < LucidWorks::Base
|
99
|
+
has_many :posts # Same as above - keep
|
100
|
+
end
|
101
|
+
class ::Post < LucidWorks::Base
|
102
|
+
belongs_to :blog
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
before :each do
|
107
|
+
@blog = ::Blog.new(:parent => @server)
|
108
|
+
end
|
129
109
|
|
130
110
|
describe ".belongs_to_association_name (private)" do
|
131
111
|
it "should return the name of the association" do
|
@@ -16,6 +16,7 @@ describe LucidWorks::Base do
|
|
16
16
|
|
17
17
|
class Widget < LucidWorks::Base
|
18
18
|
has_one :singleton_widget
|
19
|
+
has_one :singleton_widget_that_supports_all, :supports_all => true
|
19
20
|
end
|
20
21
|
|
21
22
|
class SingletonWidget < LucidWorks::Base
|
@@ -226,18 +227,36 @@ describe LucidWorks::Base do
|
|
226
227
|
|
227
228
|
describe ":include option" do
|
228
229
|
context "with a single argument" do
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
230
|
+
context "for a subresource that does not support /all" do
|
231
|
+
it "should retrieve the :included submodel by retrieving them individually" do
|
232
|
+
RestClient.should_receive(:get).with("#{@fake_server_uri}/widgets").and_return(WIDGETS_JSON)
|
233
|
+
mock_singleton1 = double('singleton widget1')
|
234
|
+
mock_singleton2 = double('singleton widget2')
|
235
|
+
mock_singleton3 = double('singleton widget3')
|
236
|
+
SingletonWidget.should_receive(:find).and_return(mock_singleton1, mock_singleton2, mock_singleton3)
|
237
|
+
|
238
|
+
widgets = Widget.find(:all, :include => :singleton_widget, :parent => @server)
|
239
|
+
|
240
|
+
widgets[0].singleton_widget.should == mock_singleton1
|
241
|
+
widgets[1].singleton_widget.should == mock_singleton2
|
242
|
+
widgets[2].singleton_widget.should == mock_singleton3
|
243
|
+
end
|
244
|
+
end
|
235
245
|
|
236
|
-
|
246
|
+
context "for a subresource that supports /all" do
|
247
|
+
it "should retrieve the :included submodel by using /submodel/all" do
|
248
|
+
RestClient.should_receive(:get).with("#{@fake_server_uri}/widgets").and_return(WIDGETS_JSON)
|
249
|
+
mock_singleton1 = double('singleton widget1')
|
250
|
+
mock_singleton2 = double('singleton widget2')
|
251
|
+
mock_singleton3 = double('singleton widget3')
|
252
|
+
SingletonWidget.should_receive(:find).and_return(mock_singleton1, mock_singleton2, mock_singleton3)
|
237
253
|
|
238
|
-
|
239
|
-
|
240
|
-
|
254
|
+
widgets = Widget.find(:all, :include => :singleton_widget, :parent => @server)
|
255
|
+
|
256
|
+
widgets[0].singleton_widget.should == mock_singleton1
|
257
|
+
widgets[1].singleton_widget.should == mock_singleton2
|
258
|
+
widgets[2].singleton_widget.should == mock_singleton3
|
259
|
+
end
|
241
260
|
end
|
242
261
|
end
|
243
262
|
|
@@ -253,9 +272,9 @@ describe LucidWorks::Base do
|
|
253
272
|
mock_singleton1 = double('singleton widget1')
|
254
273
|
mock_singleton2 = double('singleton widget2')
|
255
274
|
mock_singleton3 = double('singleton widget3')
|
256
|
-
mock_other_widgets_1 = double('other widgets 1')
|
257
|
-
mock_other_widgets_2 = double('other widgets 2')
|
258
|
-
mock_other_widgets_3 = double('other widgets 3')
|
275
|
+
mock_other_widgets_1 = double('other widgets 1', :supports_all? => false)
|
276
|
+
mock_other_widgets_2 = double('other widgets 2', :supports_all? => false)
|
277
|
+
mock_other_widgets_3 = double('other widgets 3', :supports_all? => false)
|
259
278
|
SingletonWidget.should_receive(:find).and_return(mock_singleton1, mock_singleton2, mock_singleton3)
|
260
279
|
OtherWidget.should_receive(:find).and_return(mock_other_widgets_1, mock_other_widgets_2, mock_other_widgets_3)
|
261
280
|
|
@@ -222,7 +222,7 @@ describe LucidWorks::Datasource do
|
|
222
222
|
end
|
223
223
|
end
|
224
224
|
|
225
|
-
describe "#
|
225
|
+
describe "#build_index" do
|
226
226
|
it "should return a new LucidWorks::Datasource::Index for this datasource" do
|
227
227
|
@datasource = LucidWorks::Datasource.create(
|
228
228
|
:collection => @collection,
|
@@ -234,7 +234,7 @@ describe LucidWorks::Datasource do
|
|
234
234
|
)
|
235
235
|
@datasource.should be_valid
|
236
236
|
|
237
|
-
index = @datasource.
|
237
|
+
index = @datasource.build_index
|
238
238
|
index.should be_a(LucidWorks::Datasource::Index)
|
239
239
|
index.should be_persisted # special case - singletons are always considered persisted
|
240
240
|
end
|
@@ -253,9 +253,9 @@ describe LucidWorks::Datasource do
|
|
253
253
|
@datasource.should be_valid
|
254
254
|
end
|
255
255
|
|
256
|
-
describe "#
|
256
|
+
describe "#build_job" do
|
257
257
|
it "should return a new LucidWorks::Datasource::Job for this datasource" do
|
258
|
-
job = @datasource.
|
258
|
+
job = @datasource.build_job
|
259
259
|
job.should be_a(LucidWorks::Datasource::Job)
|
260
260
|
job.should be_persisted # special case - singletons are always considered persisted
|
261
261
|
end
|
@@ -29,9 +29,12 @@ describe LucidWorks::Server do
|
|
29
29
|
end
|
30
30
|
|
31
31
|
describe "#collections" do
|
32
|
-
|
33
|
-
|
34
|
-
LucidWorks::
|
32
|
+
it "should create a HasMany association proxy for the specified class" do
|
33
|
+
mock_proxy = double('has_many proxy', :find => nil)
|
34
|
+
LucidWorks::Associations::HasMany.should_receive(:new).
|
35
|
+
with(@server, LucidWorks::Collection, {}).
|
36
|
+
and_return(mock_proxy)
|
37
|
+
|
35
38
|
@server.collections
|
36
39
|
end
|
37
40
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: lucid_works
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.6.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Sam Pierson
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-04-
|
13
|
+
date: 2011-04-25 00:00:00 -07:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -101,6 +101,9 @@ files:
|
|
101
101
|
- config/locales/en.yml
|
102
102
|
- lib/lucid_works.rb
|
103
103
|
- lib/lucid_works/associations.rb
|
104
|
+
- lib/lucid_works/associations/has_many.rb
|
105
|
+
- lib/lucid_works/associations/has_one.rb
|
106
|
+
- lib/lucid_works/associations/proxy.rb
|
104
107
|
- lib/lucid_works/base.rb
|
105
108
|
- lib/lucid_works/collection.rb
|
106
109
|
- lib/lucid_works/collection/activity.rb
|
@@ -131,6 +134,8 @@ files:
|
|
131
134
|
- lib/lucid_works/utils.rb
|
132
135
|
- lib/lucid_works/version.rb
|
133
136
|
- lucid_works.gemspec
|
137
|
+
- spec/lib/lucid_works/associations/has_many_spec.rb
|
138
|
+
- spec/lib/lucid_works/associations/has_one_spec.rb
|
134
139
|
- spec/lib/lucid_works/associations_spec.rb
|
135
140
|
- spec/lib/lucid_works/base_spec.rb
|
136
141
|
- spec/lib/lucid_works/collection/activity/history_spec.rb
|
@@ -176,6 +181,8 @@ signing_key:
|
|
176
181
|
specification_version: 3
|
177
182
|
summary: Ruby wrapper for the LucidWorks REST API
|
178
183
|
test_files:
|
184
|
+
- spec/lib/lucid_works/associations/has_many_spec.rb
|
185
|
+
- spec/lib/lucid_works/associations/has_one_spec.rb
|
179
186
|
- spec/lib/lucid_works/associations_spec.rb
|
180
187
|
- spec/lib/lucid_works/base_spec.rb
|
181
188
|
- spec/lib/lucid_works/collection/activity/history_spec.rb
|