brainstem 0.2.2 → 0.2.4
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/CHANGELOG.md +13 -0
- data/Gemfile.lock +2 -2
- data/README.md +1 -1
- data/brainstem.gemspec +1 -1
- data/lib/brainstem/association_field.rb +6 -1
- data/lib/brainstem/controller_methods.rb +6 -3
- data/lib/brainstem/presenter_collection.rb +34 -7
- data/lib/brainstem/version.rb +1 -1
- data/pkg/brainstem-0.2.2.gem +0 -0
- data/spec/brainstem/controller_methods_spec.rb +15 -2
- data/spec/brainstem/presenter_collection_spec.rb +177 -22
- data/spec/spec_helpers/db.rb +1 -1
- data/spec/spec_helpers/presenters.rb +2 -1
- metadata +7 -6
data/CHANGELOG.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
+ **0.2.4** - _01/9/2014_
|
4
|
+
|
5
|
+
+ `Brainstem::ControllerMethods#present_object` now simulates an only request (by providing the `only` parameter to Brainstem) when attempting to present a single model.
|
6
|
+
|
7
|
+
+ **0.2.3** - _11/21/2013_
|
8
|
+
|
9
|
+
+ `Brainstem::ControllerMethods#present_object` now runs the default filters that are defined in the presenter.
|
10
|
+
|
11
|
+
+ `Brainstem.presenter_collection` now takes two optional options:
|
12
|
+
+ `raise_on_empty` - Boolean that defaults to false and when set to true will raise an exception (default: `ActiveRecord::RecordNotFound`) when the result set is empty.
|
13
|
+
+ `empty_error_class` - Exception class to raise when `raise_on_empty` is true.
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -6,7 +6,7 @@ Brainstem is designed to power rich APIs in Rails. The Brainstem gem provides a
|
|
6
6
|
|
7
7
|
## Why Brainstem?
|
8
8
|
|
9
|
-
*
|
9
|
+
* Separate business and presentation logic with Presenters.
|
10
10
|
* Version your Presenters for consistency as your API evolves.
|
11
11
|
* Expose end-user selectable filters and sorts.
|
12
12
|
* Whitelist your existing scopes to act as API filters for your users.
|
data/brainstem.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.require_paths = ["lib"]
|
18
18
|
gem.version = Brainstem::VERSION
|
19
19
|
|
20
|
-
gem.add_dependency "activerecord", "
|
20
|
+
gem.add_dependency "activerecord", ">= 3.0"
|
21
21
|
|
22
22
|
gem.add_development_dependency "rake"
|
23
23
|
gem.add_development_dependency "redcarpet" # for markdown in yard
|
@@ -6,10 +6,14 @@ module Brainstem
|
|
6
6
|
# @return [String] The name of the method that is being proxied.
|
7
7
|
attr_reader :method_name
|
8
8
|
|
9
|
-
# @!attribute [
|
9
|
+
# @!attribute [rw] json_name
|
10
10
|
# @return [String] The name of the top-level JSON key for objects provided by this association.
|
11
11
|
attr_accessor :json_name
|
12
12
|
|
13
|
+
# @!attribute [rw] restrict_to_only
|
14
|
+
# @return [Boolean] Option for this association to be restricted to only queries.
|
15
|
+
attr_accessor :restrict_to_only
|
16
|
+
|
13
17
|
# @!attribute [r] block
|
14
18
|
# @return [Proc] The block to be called when fetching models instead of calling a method on the model
|
15
19
|
attr_reader :block
|
@@ -21,6 +25,7 @@ module Brainstem
|
|
21
25
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
22
26
|
method_name = args.first.to_sym if args.first.is_a?(String) || args.first.is_a?(Symbol)
|
23
27
|
@json_name = options[:json_name]
|
28
|
+
@restrict_to_only = options[:restrict_to_only] || false
|
24
29
|
if block_given?
|
25
30
|
raise ArgumentError, "options[:json_name] is required when using a block" unless options[:json_name]
|
26
31
|
raise ArgumentError, "Method name is invalid with a block" if method_name
|
@@ -27,7 +27,8 @@ module Brainstem
|
|
27
27
|
# only required if the name cannot be inferred.
|
28
28
|
# @return (see PresenterCollection#presenting)
|
29
29
|
def present_object(objects, options = {})
|
30
|
-
options.
|
30
|
+
options.merge!(:params => params)
|
31
|
+
|
31
32
|
if objects.is_a?(ActiveRecord::Relation) || objects.is_a?(Array)
|
32
33
|
raise ActiveRecord::RecordNotFound if objects.empty?
|
33
34
|
klass = objects.first.class
|
@@ -35,9 +36,11 @@ module Brainstem
|
|
35
36
|
else
|
36
37
|
klass = objects.class
|
37
38
|
ids = objects.id
|
39
|
+
options[:params][:only] = ids.to_s
|
38
40
|
end
|
39
|
-
|
40
|
-
|
41
|
+
|
42
|
+
options[:as] = (options[:key_map] || {})[klass.to_s] || klass.table_name
|
43
|
+
present(klass, options) { klass.where(:id => ids) }
|
41
44
|
end
|
42
45
|
alias_method :present_objects, :present_object
|
43
46
|
end
|
@@ -47,7 +47,7 @@ module Brainstem
|
|
47
47
|
# key these models will use in the struct that is output
|
48
48
|
options[:as] = (options[:as] || name.to_s.tableize).to_sym
|
49
49
|
|
50
|
-
allowed_includes = calculate_allowed_includes options[:presenter], presented_class
|
50
|
+
allowed_includes = calculate_allowed_includes options[:presenter], presented_class, options[:params][:only].present?
|
51
51
|
includes_hash = filter_includes options[:params][:include], allowed_includes
|
52
52
|
|
53
53
|
if searching? options
|
@@ -74,6 +74,12 @@ module Brainstem
|
|
74
74
|
|
75
75
|
# Load Includes
|
76
76
|
records = scope.to_a
|
77
|
+
|
78
|
+
# Determine if an exception should be raised on an empty result set.
|
79
|
+
if options[:raise_on_empty] && records.empty?
|
80
|
+
raise options[:empty_error_class] || ActiveRecord::RecordNotFound
|
81
|
+
end
|
82
|
+
|
77
83
|
records = order_for_search(records, ordered_search_ids) if searching? options
|
78
84
|
model = records.first
|
79
85
|
|
@@ -132,10 +138,15 @@ module Brainstem
|
|
132
138
|
private
|
133
139
|
|
134
140
|
def paginate(scope, options)
|
135
|
-
|
136
|
-
|
141
|
+
if options[:params][:limit].present? && options[:params][:offset].present?
|
142
|
+
limit = calculate_limit(options)
|
143
|
+
offset = calculate_offset(options)
|
144
|
+
else
|
145
|
+
limit = calculate_per_page(options)
|
146
|
+
offset = limit * (calculate_page(options) - 1)
|
147
|
+
end
|
137
148
|
|
138
|
-
[scope.limit(
|
149
|
+
[scope.limit(limit).offset(offset).uniq, scope.select("distinct #{scope.connection.quote_table_name options[:table_name]}.id").count] # as of Rails 3.2.5, uniq.count generates the wrong SQL.
|
139
150
|
end
|
140
151
|
|
141
152
|
def calculate_per_page(options)
|
@@ -148,13 +159,23 @@ module Brainstem
|
|
148
159
|
[(options[:params][:page] || 1).to_i, 1].max
|
149
160
|
end
|
150
161
|
|
162
|
+
def calculate_limit(options)
|
163
|
+
[[options[:params][:limit].to_i, 1].max, default_max_per_page].min
|
164
|
+
end
|
165
|
+
|
166
|
+
def calculate_offset(options)
|
167
|
+
[options[:params][:offset].to_i, 0].max
|
168
|
+
end
|
169
|
+
|
151
170
|
# Gather allowed includes by inspecting the presented hash. For now, this requires that a new instance of the
|
152
171
|
# presented class always be presentable.
|
153
|
-
def calculate_allowed_includes(presenter, presented_class)
|
172
|
+
def calculate_allowed_includes(presenter, presented_class, is_only_query)
|
154
173
|
allowed_includes = {}
|
155
174
|
model = presented_class.new
|
156
175
|
presenter.present(model).each do |k, v|
|
157
176
|
next unless v.is_a?(AssociationField)
|
177
|
+
next if v.restrict_to_only && !is_only_query
|
178
|
+
|
158
179
|
if v.json_name
|
159
180
|
v.json_name = v.json_name.tableize.to_sym
|
160
181
|
else
|
@@ -229,10 +250,16 @@ module Brainstem
|
|
229
250
|
search_options = HashWithIndifferentAccess.new(
|
230
251
|
:include => includes,
|
231
252
|
:order => { :sort_order => sort_name, :direction => direction },
|
232
|
-
:per_page => calculate_per_page(options),
|
233
|
-
:page => calculate_page(options)
|
234
253
|
)
|
235
254
|
|
255
|
+
if options[:params][:limit].present? && options[:params][:offset].present?
|
256
|
+
search_options[:limit] = calculate_limit(options)
|
257
|
+
search_options[:offset] = calculate_offset(options)
|
258
|
+
else
|
259
|
+
search_options[:per_page] = calculate_per_page(options)
|
260
|
+
search_options[:page] = calculate_page(options)
|
261
|
+
end
|
262
|
+
|
236
263
|
search_options.reverse_merge!(extract_filters(options))
|
237
264
|
|
238
265
|
result_ids, count = options[:presenter].search_block.call(options[:params][:search], search_options)
|
data/lib/brainstem/version.rb
CHANGED
data/pkg/brainstem-0.2.2.gem
CHANGED
Binary file
|
@@ -59,9 +59,22 @@ describe Brainstem::ControllerMethods do
|
|
59
59
|
@controller.call_results[:block_result].pluck(:id).should == [1]
|
60
60
|
end
|
61
61
|
|
62
|
-
it "passes
|
62
|
+
it "passes through the controller params" do
|
63
|
+
@controller.present_object(Workspace.find(1), :key_map => { "Workspace" => "your_workspaces" })
|
64
|
+
@controller.call_results[:options][:params].should == @controller.params.merge(:only => '1')
|
65
|
+
end
|
66
|
+
|
67
|
+
it "passes through supplied options" do
|
68
|
+
@controller.present_object(Workspace.find(1), :foo => :bar)
|
69
|
+
@controller.call_results[:options][:foo].should == :bar
|
70
|
+
end
|
71
|
+
|
72
|
+
it "adds an only param if there is only one object to present" do
|
63
73
|
@controller.present_object(Workspace.find(1))
|
64
|
-
@controller.call_results[:options][:
|
74
|
+
@controller.call_results[:options][:params][:only].should == "1"
|
75
|
+
|
76
|
+
@controller.present_object(Workspace.all)
|
77
|
+
@controller.call_results[:options][:params][:only].should be_nil
|
65
78
|
end
|
66
79
|
end
|
67
80
|
end
|
@@ -44,20 +44,98 @@ describe Brainstem::PresenterCollection do
|
|
44
44
|
end
|
45
45
|
|
46
46
|
describe "limits and offsets" do
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
47
|
+
context "when only per_page and page are present" do
|
48
|
+
it "honors the user's requested page size and page and returns counts" do
|
49
|
+
result = @presenter_collection.presenting("workspaces", :params => { :per_page => 1, :page => 2 }) { Workspace.order('id desc') }[:results]
|
50
|
+
result.length.should == 1
|
51
|
+
result.first[:id].should == Workspace.order('id desc')[1].id.to_s
|
52
|
+
|
53
|
+
result = @presenter_collection.presenting("workspaces", :params => { :per_page => 2, :page => 2 }) { Workspace.order('id desc') }[:results]
|
54
|
+
result.length.should == 2
|
55
|
+
result.map { |m| m[:id] }.should == Workspace.order('id desc')[2..3].map(&:id).map(&:to_s)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "defaults to 1 if the page number is less than 1" do
|
59
|
+
result = @presenter_collection.presenting("workspaces", :params => { :per_page => 1, :page => 0 }) { Workspace.order('id desc') }[:results]
|
60
|
+
result.length.should == 1
|
61
|
+
result.first[:id].should == Workspace.order('id desc')[0].id.to_s
|
62
|
+
end
|
55
63
|
end
|
56
64
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
65
|
+
context "when only limit and offset are present" do
|
66
|
+
it "honors the user's requested limit and offset and returns counts" do
|
67
|
+
result = @presenter_collection.presenting("workspaces", :params => { :limit => 1, :offset => 2 }) { Workspace.order('id desc') }[:results]
|
68
|
+
result.length.should == 1
|
69
|
+
result.first[:id].should == Workspace.order('id desc')[2].id.to_s
|
70
|
+
|
71
|
+
result = @presenter_collection.presenting("workspaces", :params => { :limit => 2, :offset => 2 }) { Workspace.order('id desc') }[:results]
|
72
|
+
result.length.should == 2
|
73
|
+
result.map { |m| m[:id] }.should == Workspace.order('id desc')[2..3].map(&:id).map(&:to_s)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "defaults to offset 0 if the passed offset is less than 0 and limit to 1 if the passed limit is less than 1" do
|
77
|
+
stub.proxy(@presenter_collection).calculate_offset(anything).times(1)
|
78
|
+
stub.proxy(@presenter_collection).calculate_limit(anything).times(1)
|
79
|
+
result = @presenter_collection.presenting("workspaces", :params => { :limit => -1, :offset => -1 }) { Workspace.order('id desc') }[:results]
|
80
|
+
result.length.should == 1
|
81
|
+
result.first[:id].should == Workspace.order('id desc')[0].id.to_s
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "when both sets of params are present" do
|
86
|
+
it "prefers limit and offset over per_page and page" do
|
87
|
+
result = @presenter_collection.presenting("workspaces", :params => { :limit => 1, :offset => 0, :per_page => 2, :page => 2 }) { Workspace.order('id desc') }[:results]
|
88
|
+
result.length.should == 1
|
89
|
+
result.first[:id].should == Workspace.order('id desc')[0].id.to_s
|
90
|
+
end
|
91
|
+
|
92
|
+
it "uses per_page and page if limit and offset are not complete" do
|
93
|
+
result = @presenter_collection.presenting("workspaces", :params => { :limit => 5, :per_page => 1, :page => 0 }) { Workspace.order('id desc') }[:results]
|
94
|
+
result.length.should == 1
|
95
|
+
result.first[:id].should == Workspace.order('id desc')[0].id.to_s
|
96
|
+
|
97
|
+
result = @presenter_collection.presenting("workspaces", :params => { :offset => 5, :per_page => 1, :page => 0 }) { Workspace.order('id desc') }[:results]
|
98
|
+
result.length.should == 1
|
99
|
+
result.first[:id].should == Workspace.order('id desc')[0].id.to_s
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "raise_on_empty option" do
|
105
|
+
context "raise_on_empty is true" do
|
106
|
+
context "results are empty" do
|
107
|
+
it "should raise the provided error class when the empty_error_class option is provided" do
|
108
|
+
class MyException < Exception; end
|
109
|
+
|
110
|
+
lambda {
|
111
|
+
@presenter_collection.presenting("workspaces", :raise_on_empty => true, :empty_error_class => MyException) { Workspace.where(:id => nil) }
|
112
|
+
}.should raise_error(MyException)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should raise ActiveRecord::RecordNotFound when the empty_error_class option is not provided" do
|
116
|
+
lambda {
|
117
|
+
@presenter_collection.presenting("workspaces", :raise_on_empty => true) { Workspace.where(:id => nil) }
|
118
|
+
}.should raise_error(ActiveRecord::RecordNotFound)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "results are not empty" do
|
123
|
+
it "should not raise an exception" do
|
124
|
+
Workspace.count.should > 0
|
125
|
+
|
126
|
+
lambda {
|
127
|
+
@presenter_collection.presenting("workspaces", :raise_on_empty => true) { Workspace.order('id desc') }
|
128
|
+
}.should_not raise_error
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "raise_on_empty is false" do
|
134
|
+
it "should not raise an exception when the results are empty" do
|
135
|
+
lambda {
|
136
|
+
@presenter_collection.presenting("workspaces") { Workspace.where(:id => nil) }
|
137
|
+
}.should_not raise_error
|
138
|
+
end
|
61
139
|
end
|
62
140
|
end
|
63
141
|
|
@@ -198,6 +276,23 @@ describe Brainstem::PresenterCollection do
|
|
198
276
|
result[:users][Workspace.first.lead_user.id.to_s].should be_present
|
199
277
|
end
|
200
278
|
|
279
|
+
describe "restricted associations" do
|
280
|
+
it "does apply includes that are restricted to only queries in an only query" do
|
281
|
+
t = Task.first
|
282
|
+
result = @presenter_collection.presenting("tasks", :params => { :include => "restricted", :only => t.id.to_s }, :max_per_page => 2) { Task.where(:id => t.id) }
|
283
|
+
result[:tasks][t.id.to_s].keys.should include(:restricted_id)
|
284
|
+
result.keys.should include(:restricted_associations)
|
285
|
+
end
|
286
|
+
|
287
|
+
it "does not apply includes that are restricted to only queries in a non-only query" do
|
288
|
+
t = Task.first
|
289
|
+
result = @presenter_collection.presenting("tasks", :params => { :include => "restricted" }, :max_per_page => 2) { Task.where(:id => t.id) }
|
290
|
+
|
291
|
+
result[:tasks][t.id.to_s].keys.should_not include(:restricted_id)
|
292
|
+
result.keys.should_not include(:restricted_associations)
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
201
296
|
describe "polymorphic associations" do
|
202
297
|
it "works with polymorphic associations" do
|
203
298
|
result = @presenter_collection.presenting("posts", :params => { :include => "subject" }) { Post.order('id desc') }
|
@@ -269,21 +364,21 @@ describe Brainstem::PresenterCollection do
|
|
269
364
|
|
270
365
|
it "converts boolean parameters from strings to booleans" do
|
271
366
|
WorkspacePresenter.filter(:owned_by_bob) { |scope, boolean| boolean ? scope.where(:user_id => bob.id) : scope.where(:user_id => jane.id) }
|
272
|
-
result = @presenter_collection.presenting("workspaces", :params => { :owned_by_bob => "false" }) { Workspace.
|
367
|
+
result = @presenter_collection.presenting("workspaces", :params => { :owned_by_bob => "false" }) { Workspace.where(nil) }
|
273
368
|
result[:workspaces].values.find { |workspace| workspace[:title].include?("jane") }.should be
|
274
369
|
result[:workspaces].values.find { |workspace| workspace[:title].include?("bob") }.should_not be
|
275
370
|
end
|
276
371
|
|
277
372
|
it "ensures arguments are strings" do
|
278
373
|
WorkspacePresenter.filter(:owned_by_bob) { |scope, string| string.should be_a(String); scope }
|
279
|
-
result = @presenter_collection.presenting("workspaces", :params => { :owned_by_bob => [1, 2] }) { Workspace.
|
374
|
+
result = @presenter_collection.presenting("workspaces", :params => { :owned_by_bob => [1, 2] }) { Workspace.where(nil) }
|
280
375
|
end
|
281
376
|
|
282
377
|
it "allows filters to be called with false as an argument" do
|
283
378
|
WorkspacePresenter.filter(:nothing) { |scope, bool| bool ? scope.where(:id => nil) : scope }
|
284
|
-
result = @presenter_collection.presenting("workspaces", :params => { :nothing => "true" }) { Workspace.
|
379
|
+
result = @presenter_collection.presenting("workspaces", :params => { :nothing => "true" }) { Workspace.where(nil) }
|
285
380
|
result[:workspaces].length.should eq(0)
|
286
|
-
result = @presenter_collection.presenting("workspaces", :params => { :nothing => "false" }) { Workspace.
|
381
|
+
result = @presenter_collection.presenting("workspaces", :params => { :nothing => "false" }) { Workspace.where(nil) }
|
287
382
|
result[:workspaces].length.should_not eq(0)
|
288
383
|
end
|
289
384
|
|
@@ -295,7 +390,7 @@ describe Brainstem::PresenterCollection do
|
|
295
390
|
scope
|
296
391
|
}
|
297
392
|
|
298
|
-
@presenter_collection.presenting("workspaces", :params => { :between => "1:10" }) { Workspace.
|
393
|
+
@presenter_collection.presenting("workspaces", :params => { :between => "1:10" }) { Workspace.where(nil) }
|
299
394
|
end
|
300
395
|
|
301
396
|
context "with defaults" do
|
@@ -346,27 +441,27 @@ describe Brainstem::PresenterCollection do
|
|
346
441
|
end
|
347
442
|
|
348
443
|
it "calls the named scope with default arguments" do
|
349
|
-
result = @presenter_collection.presenting("workspaces") { Workspace.
|
444
|
+
result = @presenter_collection.presenting("workspaces") { Workspace.where(nil) }
|
350
445
|
result[:workspaces].keys.should eq(bob.workspaces.pluck(:id).map(&:to_s))
|
351
446
|
end
|
352
447
|
|
353
448
|
it "calls the named scope with given arguments" do
|
354
|
-
result = @presenter_collection.presenting("workspaces", :params => { :owned_by => jane.id.to_s }) { Workspace.
|
449
|
+
result = @presenter_collection.presenting("workspaces", :params => { :owned_by => jane.id.to_s }) { Workspace.where(nil) }
|
355
450
|
result[:workspaces].keys.should eq(jane.workspaces.pluck(:id).map(&:to_s))
|
356
451
|
end
|
357
452
|
|
358
453
|
it "can use filters without lambdas in the presenter or model, but behaves strangely when false is given" do
|
359
454
|
WorkspacePresenter.filter(:numeric_description)
|
360
455
|
|
361
|
-
result = @presenter_collection.presenting("workspaces") { Workspace.
|
456
|
+
result = @presenter_collection.presenting("workspaces") { Workspace.where(nil) }
|
362
457
|
result[:workspaces].keys.should eq(%w[1 2 3 4])
|
363
458
|
|
364
|
-
result = @presenter_collection.presenting("workspaces", :params => { :numeric_description => "true" }) { Workspace.
|
459
|
+
result = @presenter_collection.presenting("workspaces", :params => { :numeric_description => "true" }) { Workspace.where(nil) }
|
365
460
|
result[:workspaces].keys.should eq(%w[2 4])
|
366
461
|
|
367
462
|
# This is probably not the behavior that the developer or user intends. You should always use a one-argument lambda in your
|
368
463
|
# model scope declaration!
|
369
|
-
result = @presenter_collection.presenting("workspaces", :params => { :numeric_description => "false" }) { Workspace.
|
464
|
+
result = @presenter_collection.presenting("workspaces", :params => { :numeric_description => "false" }) { Workspace.where(nil) }
|
370
465
|
result[:workspaces].keys.should eq(%w[2 4])
|
371
466
|
end
|
372
467
|
end
|
@@ -503,6 +598,66 @@ describe Brainstem::PresenterCollection do
|
|
503
598
|
@presenter_collection.presenting("workspaces", :params => { :search => "blah", :order => "created_at:asc"}) { Workspace.order("id asc") }
|
504
599
|
end
|
505
600
|
end
|
601
|
+
|
602
|
+
describe "pagination" do
|
603
|
+
it "passes through limit and offset if they are requested" do
|
604
|
+
WorkspacePresenter.search do |string, options|
|
605
|
+
options[:limit].should == 1
|
606
|
+
options[:offset].should == 2
|
607
|
+
[[1], 1]
|
608
|
+
end
|
609
|
+
|
610
|
+
@presenter_collection.presenting("workspaces", :params => { :search => "blah", :limit => 1, :offset => 2}) { Workspace.order("id asc") }
|
611
|
+
end
|
612
|
+
|
613
|
+
it "passes through only limit and offset if all pagination options are requested" do
|
614
|
+
WorkspacePresenter.search do |string, options|
|
615
|
+
options[:limit].should == 1
|
616
|
+
options[:offset].should == 2
|
617
|
+
options[:per_page].should == nil
|
618
|
+
options[:page].should == nil
|
619
|
+
[[1], 1]
|
620
|
+
end
|
621
|
+
|
622
|
+
@presenter_collection.presenting("workspaces", :params => { :search => "blah", :limit => 1, :offset => 2, :per_page => 3, :page => 4}) { Workspace.order("id asc") }
|
623
|
+
end
|
624
|
+
|
625
|
+
it "passes through page and per_page when limit not present" do
|
626
|
+
WorkspacePresenter.search do |string, options|
|
627
|
+
options[:limit].should == nil
|
628
|
+
options[:offset].should == nil
|
629
|
+
options[:per_page].should == 3
|
630
|
+
options[:page].should == 4
|
631
|
+
[[1], 1]
|
632
|
+
end
|
633
|
+
|
634
|
+
@presenter_collection.presenting("workspaces", :params => { :search => "blah", :offset => 2, :per_page => 3, :page => 4}) { Workspace.order("id asc") }
|
635
|
+
end
|
636
|
+
|
637
|
+
it "passes through page and per_page when offset not present" do
|
638
|
+
WorkspacePresenter.search do |string, options|
|
639
|
+
options[:limit].should == nil
|
640
|
+
options[:offset].should == nil
|
641
|
+
options[:per_page].should == 3
|
642
|
+
options[:page].should == 4
|
643
|
+
[[1], 1]
|
644
|
+
end
|
645
|
+
|
646
|
+
@presenter_collection.presenting("workspaces", :params => { :search => "blah", :limit => 1, :per_page => 3, :page => 4}) { Workspace.order("id asc") }
|
647
|
+
end
|
648
|
+
|
649
|
+
it "passes through page and per_page by default" do
|
650
|
+
WorkspacePresenter.search do |string, options|
|
651
|
+
options[:limit].should == nil
|
652
|
+
options[:offset].should == nil
|
653
|
+
options[:per_page].should == 20
|
654
|
+
options[:page].should == 1
|
655
|
+
[[1], 1]
|
656
|
+
end
|
657
|
+
|
658
|
+
@presenter_collection.presenting("workspaces", :params => { :search => "blah"}) { Workspace.order("id asc") }
|
659
|
+
end
|
660
|
+
end
|
506
661
|
end
|
507
662
|
end
|
508
663
|
|
data/spec/spec_helpers/db.rb
CHANGED
@@ -49,7 +49,7 @@ class Workspace < ActiveRecord::Base
|
|
49
49
|
has_many :posts
|
50
50
|
|
51
51
|
scope :owned_by, -> id { where(:user_id => id) }
|
52
|
-
scope :numeric_description, where(:description => ["1", "2", "3"])
|
52
|
+
scope :numeric_description, -> description { where(:description => ["1", "2", "3"]) }
|
53
53
|
|
54
54
|
def lead_user
|
55
55
|
user
|
@@ -16,7 +16,8 @@ class TaskPresenter < Brainstem::Presenter
|
|
16
16
|
:name => model.name,
|
17
17
|
:sub_tasks => association(:sub_tasks),
|
18
18
|
:other_tasks => association(:sub_tasks, :json_name => "other_tasks"),
|
19
|
-
:workspace => association(:workspace)
|
19
|
+
:workspace => association(:workspace),
|
20
|
+
:restricted => association(:json_name => "restricted_association", :restrict_to_only => true) { |model| model }
|
20
21
|
}
|
21
22
|
end
|
22
23
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: brainstem
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,14 +9,14 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2014-03-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: '3.0'
|
22
22
|
type: :runtime
|
@@ -24,7 +24,7 @@ dependencies:
|
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
26
26
|
requirements:
|
27
|
-
- -
|
27
|
+
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '3.0'
|
30
30
|
- !ruby/object:Gem::Dependency
|
@@ -132,6 +132,7 @@ extensions: []
|
|
132
132
|
extra_rdoc_files: []
|
133
133
|
files:
|
134
134
|
- brainstem.gemspec
|
135
|
+
- CHANGELOG.md
|
135
136
|
- Gemfile
|
136
137
|
- Gemfile.lock
|
137
138
|
- Guardfile
|
@@ -174,7 +175,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
174
175
|
version: '0'
|
175
176
|
segments:
|
176
177
|
- 0
|
177
|
-
hash:
|
178
|
+
hash: 1278718761883180932
|
178
179
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
179
180
|
none: false
|
180
181
|
requirements:
|
@@ -183,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
183
184
|
version: '0'
|
184
185
|
segments:
|
185
186
|
- 0
|
186
|
-
hash:
|
187
|
+
hash: 1278718761883180932
|
187
188
|
requirements: []
|
188
189
|
rubyforge_project:
|
189
190
|
rubygems_version: 1.8.25
|