brainstem 0.0.2
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/Gemfile +4 -0
- data/Gemfile.lock +51 -0
- data/Guardfile +8 -0
- data/LICENSE +22 -0
- data/README.md +181 -0
- data/Rakefile +6 -0
- data/brainstem.gemspec +28 -0
- data/lib/brainstem.rb +63 -0
- data/lib/brainstem/association_field.rb +35 -0
- data/lib/brainstem/controller_methods.rb +44 -0
- data/lib/brainstem/engine.rb +4 -0
- data/lib/brainstem/presenter.rb +210 -0
- data/lib/brainstem/presenter_collection.rb +279 -0
- data/lib/brainstem/time_classes.rb +14 -0
- data/lib/brainstem/version.rb +3 -0
- data/spec/brainstem/controller_methods_spec.rb +68 -0
- data/spec/brainstem/presenter_collection_spec.rb +486 -0
- data/spec/brainstem/presenter_spec.rb +252 -0
- data/spec/brainstem_spec.rb +25 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/spec_helpers/cleanup.rb +23 -0
- data/spec/spec_helpers/db.rb +79 -0
- data/spec/spec_helpers/presenters.rb +39 -0
- metadata +201 -0
@@ -0,0 +1,252 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Brainstem::Presenter do
|
4
|
+
describe "class methods" do
|
5
|
+
|
6
|
+
describe "presents method" do
|
7
|
+
before do
|
8
|
+
@klass = Class.new(Brainstem::Presenter)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "records itself as the presenter for the named class as a string" do
|
12
|
+
@klass.presents "String"
|
13
|
+
Brainstem.presenter_collection.for(String).should be_a(@klass)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "records itself as the presenter for the given class" do
|
17
|
+
@klass.presents String
|
18
|
+
Brainstem.presenter_collection.for(String).should be_a(@klass)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "records itself as the presenter for the named classes" do
|
22
|
+
@klass.presents String, Array
|
23
|
+
Brainstem.presenter_collection.for(String).should be_a(@klass)
|
24
|
+
Brainstem.presenter_collection.for(Array).should be_a(@klass)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "implicit namespacing" do
|
29
|
+
module V1
|
30
|
+
class SomePresenter < Brainstem::Presenter
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "uses the closest module name as the presenter namespace" do
|
35
|
+
V1::SomePresenter.presents String
|
36
|
+
Brainstem.presenter_collection(:v1).for(String).should be_a(V1::SomePresenter)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "does not map namespaced presenters into the default namespace" do
|
40
|
+
V1::SomePresenter.presents String
|
41
|
+
Brainstem.presenter_collection.for(String).should be_nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "helper method" do
|
46
|
+
before do
|
47
|
+
@klass = Class.new(Brainstem::Presenter) do
|
48
|
+
def call_helper
|
49
|
+
foo
|
50
|
+
end
|
51
|
+
end
|
52
|
+
@helper = Module.new do
|
53
|
+
def foo
|
54
|
+
"I work"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it "includes and extends the given module" do
|
60
|
+
lambda { @klass.new.call_helper }.should raise_error
|
61
|
+
@klass.helper @helper
|
62
|
+
@klass.new.call_helper.should == "I work"
|
63
|
+
@klass.foo.should == "I work"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "filter method" do
|
68
|
+
before do
|
69
|
+
@klass = Class.new(Brainstem::Presenter)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "creates an entry in the filters class ivar" do
|
73
|
+
@klass.filter(:foo, :default => true) { 1 }
|
74
|
+
@klass.filters[:foo][0].should eq({:default => true})
|
75
|
+
@klass.filters[:foo][1].should be_a(Proc)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "accepts names without blocks" do
|
79
|
+
@klass.filter(:foo)
|
80
|
+
@klass.filters[:foo][1].should be_nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "search method" do
|
85
|
+
before do
|
86
|
+
@klass = Class.new(Brainstem::Presenter)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "creates an entry in the search class ivar" do
|
90
|
+
@klass.search do end
|
91
|
+
@klass.search_block.should be_a(Proc)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "post_process hooks" do
|
97
|
+
describe "adding object ids as strings" do
|
98
|
+
before do
|
99
|
+
post_presenter = Class.new(Brainstem::Presenter) do
|
100
|
+
presents Post
|
101
|
+
|
102
|
+
def present(model)
|
103
|
+
{
|
104
|
+
:body => model.body,
|
105
|
+
}
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
@presenter = post_presenter.new
|
110
|
+
@post = Post.first
|
111
|
+
end
|
112
|
+
|
113
|
+
it "outputs the associated object's id and type" do
|
114
|
+
data = @presenter.present_and_post_process(@post)
|
115
|
+
data[:id].should eq(@post.id.to_s)
|
116
|
+
data[:body].should eq(@post.body)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe "converting dates and times" do
|
121
|
+
it "should convert all Time-and-date-like objects to iso8601" do
|
122
|
+
class TimePresenter < Brainstem::Presenter
|
123
|
+
def present(model)
|
124
|
+
{
|
125
|
+
:time => Time.now,
|
126
|
+
:date => Date.new,
|
127
|
+
:recursion => {
|
128
|
+
:time => Time.now,
|
129
|
+
:something => [Time.now, :else],
|
130
|
+
:foo => :bar
|
131
|
+
}
|
132
|
+
}
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
iso8601_time = /\d{4}-\d{2}-\d{2}T\d{2}\:\d{2}\:\d{2}[-+]\d{2}:\d{2}/
|
137
|
+
iso8601_date = /\d{4}-\d{2}-\d{2}/
|
138
|
+
|
139
|
+
struct = TimePresenter.new.present_and_post_process("something")
|
140
|
+
struct[:time].should =~ iso8601_time
|
141
|
+
struct[:date].should =~ iso8601_date
|
142
|
+
struct[:recursion][:time].should =~ iso8601_time
|
143
|
+
struct[:recursion][:something].first.should =~ iso8601_time
|
144
|
+
struct[:recursion][:something].last.should == :else
|
145
|
+
struct[:recursion][:foo].should == :bar
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "outputting polymorphic associations" do
|
150
|
+
before do
|
151
|
+
some_presenter = Class.new(Brainstem::Presenter) do
|
152
|
+
presents Post
|
153
|
+
|
154
|
+
def present(model)
|
155
|
+
{
|
156
|
+
:body => model.body,
|
157
|
+
:subject => association(:subject),
|
158
|
+
:another_subject => association(:subject)
|
159
|
+
}
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
@presenter = some_presenter.new
|
164
|
+
@post = Post.first
|
165
|
+
end
|
166
|
+
|
167
|
+
it "outputs the associated object's id and type" do
|
168
|
+
data = @presenter.present_and_post_process(@post)
|
169
|
+
data[:subject_id].should eq(@post.subject_id.to_s)
|
170
|
+
data[:subject_type].should eq(@post.subject_type)
|
171
|
+
end
|
172
|
+
|
173
|
+
it "outputs custom names for an associated object's id and type" do
|
174
|
+
data = @presenter.present_and_post_process(@post)
|
175
|
+
data[:another_subject_id].should eq(@post.subject_id.to_s)
|
176
|
+
data[:another_subject_type].should eq(@post.subject_type)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
describe "outputting associations" do
|
181
|
+
before do
|
182
|
+
some_presenter = Class.new(Brainstem::Presenter) do
|
183
|
+
presents Workspace
|
184
|
+
|
185
|
+
def present(model)
|
186
|
+
{
|
187
|
+
:updated_at => model.updated_at,
|
188
|
+
:tasks => association(:tasks),
|
189
|
+
:user => association(:user),
|
190
|
+
:something => association(:user),
|
191
|
+
:lead_user => association(:lead_user),
|
192
|
+
:lead_user_with_lambda => association { model.user },
|
193
|
+
:synthetic => association(:synthetic)
|
194
|
+
}
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
@presenter = some_presenter.new
|
199
|
+
@workspace = Workspace.find_by_title "bob workspace 1"
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should not convert or return non-included associations, but should return <association>_id for belongs_to relationships, plus all fields" do
|
203
|
+
json = @presenter.present_and_post_process(@workspace, [])
|
204
|
+
json.keys.should =~ [:id, :updated_at, :something_id, :user_id]
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should convert requested has_many associations (includes) into the <association>_ids format" do
|
208
|
+
@workspace.tasks.length.should > 0
|
209
|
+
@presenter.present_and_post_process(@workspace, [:tasks])[:task_ids].should =~ @workspace.tasks.map(&:id).map(&:to_s)
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should convert requested belongs_to and has_one associations into the <association>_id format when requested" do
|
213
|
+
@presenter.present_and_post_process(@workspace, [:user])[:user_id].should == @workspace.user.id.to_s
|
214
|
+
end
|
215
|
+
|
216
|
+
it "converts non-association models into <model>_id format when they are requested" do
|
217
|
+
@presenter.present_and_post_process(@workspace, [:lead_user])[:lead_user_id].should == @workspace.lead_user.id.to_s
|
218
|
+
end
|
219
|
+
|
220
|
+
it "handles associations provided with lambdas" do
|
221
|
+
@presenter.present_and_post_process(@workspace, [:lead_user_with_lambda])[:lead_user_with_lambda_id].should == @workspace.lead_user.id.to_s
|
222
|
+
end
|
223
|
+
|
224
|
+
it "should return <association>_id fields when the given association ids exist on the model whether it is requested or not" do
|
225
|
+
@presenter.present_and_post_process(@workspace, [:user])[:user_id].should == @workspace.user_id.to_s
|
226
|
+
|
227
|
+
json = @presenter.present_and_post_process(@workspace, [])
|
228
|
+
json.keys.should =~ [:user_id, :something_id, :id, :updated_at]
|
229
|
+
json[:user_id].should == @workspace.user_id.to_s
|
230
|
+
json[:something_id].should == @workspace.user_id.to_s
|
231
|
+
end
|
232
|
+
|
233
|
+
it "should return null, not empty string when ids are missing" do
|
234
|
+
@workspace.user = nil
|
235
|
+
@workspace.tasks = []
|
236
|
+
@presenter.present_and_post_process(@workspace, [:lead_user_with_lambda])[:lead_user_with_lambda_id].should == nil
|
237
|
+
@presenter.present_and_post_process(@workspace, [:user])[:user_id].should == nil
|
238
|
+
@presenter.present_and_post_process(@workspace, [:something])[:something_id].should == nil
|
239
|
+
@presenter.present_and_post_process(@workspace, [:tasks])[:task_ids].should == []
|
240
|
+
end
|
241
|
+
|
242
|
+
context "when the model has an <association>_id method but no column" do
|
243
|
+
it "does not include the <association>_id field" do
|
244
|
+
def @workspace.synthetic_id
|
245
|
+
raise "this explodes because it's not an association"
|
246
|
+
end
|
247
|
+
@presenter.present_and_post_process(@workspace, []).should_not have_key(:synthetic_id)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Brainstem do
|
4
|
+
describe "default_namespace attribute" do
|
5
|
+
it "can be set and read" do
|
6
|
+
Brainstem.default_namespace = "something"
|
7
|
+
Brainstem.default_namespace.should eq("something")
|
8
|
+
end
|
9
|
+
|
10
|
+
it "returns 'none' if unset" do
|
11
|
+
Brainstem.default_namespace.should eq("none")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "presenter collection method" do
|
16
|
+
it "returns an instance of PresenterCollection" do
|
17
|
+
Brainstem.presenter_collection.should be_a(Brainstem::PresenterCollection)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "accepts a namespace" do
|
21
|
+
Brainstem.presenter_collection("v1").should be_a(Brainstem::PresenterCollection)
|
22
|
+
Brainstem.presenter_collection("v1").should_not eq(Brainstem.presenter_collection)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'logger'
|
3
|
+
require 'rr'
|
4
|
+
require 'rspec'
|
5
|
+
require 'sqlite3'
|
6
|
+
|
7
|
+
require 'brainstem'
|
8
|
+
require_relative 'spec_helpers/db'
|
9
|
+
require_relative 'spec_helpers/cleanup'
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.mock_with :rr
|
13
|
+
|
14
|
+
config.before(:each) do
|
15
|
+
Brainstem.logger = Logger.new(StringIO.new)
|
16
|
+
end
|
17
|
+
|
18
|
+
config.after(:each) do
|
19
|
+
Brainstem.clear_collections!
|
20
|
+
Brainstem.default_namespace = nil
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Brainstem
|
2
|
+
|
3
|
+
def self.clear_collections!
|
4
|
+
presenter_collection.presenters.each do |klass, presenter|
|
5
|
+
presenter.clear_options!
|
6
|
+
end
|
7
|
+
@presenter_collection = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
class Presenter
|
11
|
+
def self.clear_options!
|
12
|
+
@default_sort_order = nil
|
13
|
+
@filters = nil
|
14
|
+
@sort_orders = nil
|
15
|
+
@search_block = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def clear_options!
|
19
|
+
self.class.clear_options!
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
|
2
|
+
ActiveRecord::Schema.define do
|
3
|
+
self.verbose = false
|
4
|
+
|
5
|
+
create_table :users, :force => true do |t|
|
6
|
+
t.string :username
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
|
10
|
+
create_table :workspaces, :force => true do |t|
|
11
|
+
t.string :title
|
12
|
+
t.string :description
|
13
|
+
t.belongs_to :user
|
14
|
+
t.timestamps
|
15
|
+
end
|
16
|
+
|
17
|
+
create_table :tasks, :force => true do |t|
|
18
|
+
t.string :name
|
19
|
+
t.integer :parent_id
|
20
|
+
t.belongs_to :workspace
|
21
|
+
t.timestamps
|
22
|
+
end
|
23
|
+
|
24
|
+
create_table :posts, :force => true do |t|
|
25
|
+
t.string :body
|
26
|
+
t.integer :subject_id
|
27
|
+
t.string :subject_type
|
28
|
+
t.timestamps
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class User < ActiveRecord::Base
|
33
|
+
has_many :workspaces
|
34
|
+
end
|
35
|
+
|
36
|
+
class Task < ActiveRecord::Base
|
37
|
+
belongs_to :workspace
|
38
|
+
has_many :sub_tasks, :foreign_key => :parent_id, :class_name => "Task"
|
39
|
+
has_many :posts
|
40
|
+
|
41
|
+
def tags
|
42
|
+
%w[some tags]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Workspace < ActiveRecord::Base
|
47
|
+
belongs_to :user
|
48
|
+
has_many :tasks
|
49
|
+
has_many :posts
|
50
|
+
|
51
|
+
scope :owned_by, -> id { where(:user_id => id) }
|
52
|
+
scope :numeric_description, where(:description => ["1", "2", "3"])
|
53
|
+
|
54
|
+
def lead_user
|
55
|
+
user
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class Post < ActiveRecord::Base
|
60
|
+
belongs_to :subject, :polymorphic => true
|
61
|
+
end
|
62
|
+
|
63
|
+
User.create!(:id => 1, :username => "bob")
|
64
|
+
User.create!(:id => 2, :username => "jane")
|
65
|
+
|
66
|
+
Workspace.create!(:id => 1, :user_id => 1, :title => "bob workspace 1", :description => "a")
|
67
|
+
Workspace.create!(:id => 2, :user_id => 1, :title => "bob workspace 2", :description => "1")
|
68
|
+
Workspace.create!(:id => 3, :user_id => 1, :title => "bob workspace 3", :description => "b")
|
69
|
+
Workspace.create!(:id => 4, :user_id => 1, :title => "bob workspace 4", :description => "2")
|
70
|
+
Workspace.create!(:id => 5, :user_id => 2, :title => "jane workspace 1", :description => "c")
|
71
|
+
Workspace.create!(:id => 6, :user_id => 2, :title => "jane workspace 2", :description => "3")
|
72
|
+
|
73
|
+
Task.create!(:id => 1, :workspace_id => 1, :name => "Buy milk")
|
74
|
+
Task.create!(:id => 2, :workspace_id => 1, :name => "Buy bananas")
|
75
|
+
Task.create!(:id => 3, :workspace_id => 1, :parent_id => 2, :name => "Green preferred")
|
76
|
+
Task.create!(:id => 4, :workspace_id => 1, :parent_id => 2, :name => "One bunch")
|
77
|
+
|
78
|
+
Post.create!(:id => 1, :subject => Workspace.first, :body => "first post!")
|
79
|
+
Post.create!(:id => 2, :subject => Task.first, :body => "this is important. get on it!")
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class WorkspacePresenter < Brainstem::Presenter
|
2
|
+
def present(model)
|
3
|
+
{
|
4
|
+
:title => model.title,
|
5
|
+
:description => model.description,
|
6
|
+
:updated_at => model.updated_at,
|
7
|
+
:tasks => association(:tasks),
|
8
|
+
:lead_user => association(:lead_user, :json_name => "users")
|
9
|
+
}
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class TaskPresenter < Brainstem::Presenter
|
14
|
+
def present(model)
|
15
|
+
{
|
16
|
+
:name => model.name,
|
17
|
+
:sub_tasks => association(:sub_tasks),
|
18
|
+
:other_tasks => association(:sub_tasks, :json_name => "other_tasks"),
|
19
|
+
:workspace => association(:workspace)
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class UserPresenter < Brainstem::Presenter
|
25
|
+
def present(model)
|
26
|
+
{
|
27
|
+
:username => model.username
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class PostPresenter < Brainstem::Presenter
|
33
|
+
def present(model)
|
34
|
+
{
|
35
|
+
:body => model.body,
|
36
|
+
:subject => association(:subject)
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
metadata
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: brainstem
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Sufyan Adam
|
9
|
+
- André Arko
|
10
|
+
- Andrew Cantino
|
11
|
+
- Katlyn Daniluk
|
12
|
+
- Reid Gillette
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
date: 2013-04-29 00:00:00.000000000 Z
|
17
|
+
dependencies:
|
18
|
+
- !ruby/object:Gem::Dependency
|
19
|
+
name: activerecord
|
20
|
+
requirement: !ruby/object:Gem::Requirement
|
21
|
+
none: false
|
22
|
+
requirements:
|
23
|
+
- - ~>
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '3.0'
|
26
|
+
type: :runtime
|
27
|
+
prerelease: false
|
28
|
+
version_requirements: !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rake
|
36
|
+
requirement: !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ! '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
type: :development
|
43
|
+
prerelease: false
|
44
|
+
version_requirements: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: redcarpet
|
52
|
+
requirement: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ! '>='
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
type: :development
|
59
|
+
prerelease: false
|
60
|
+
version_requirements: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
- !ruby/object:Gem::Dependency
|
67
|
+
name: rr
|
68
|
+
requirement: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ! '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
type: :development
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ! '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: rspec
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
none: false
|
94
|
+
requirements:
|
95
|
+
- - ! '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: sqlite3
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ! '>='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
type: :development
|
107
|
+
prerelease: false
|
108
|
+
version_requirements: !ruby/object:Gem::Requirement
|
109
|
+
none: false
|
110
|
+
requirements:
|
111
|
+
- - ! '>='
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
- !ruby/object:Gem::Dependency
|
115
|
+
name: yard
|
116
|
+
requirement: !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
118
|
+
requirements:
|
119
|
+
- - ! '>='
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
type: :development
|
123
|
+
prerelease: false
|
124
|
+
version_requirements: !ruby/object:Gem::Requirement
|
125
|
+
none: false
|
126
|
+
requirements:
|
127
|
+
- - ! '>='
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
description: Brainstem allows you to create rich API presenters that know how to filter,
|
131
|
+
sort, and include associations.
|
132
|
+
email:
|
133
|
+
- dev@mavenlink.com
|
134
|
+
executables: []
|
135
|
+
extensions: []
|
136
|
+
extra_rdoc_files: []
|
137
|
+
files:
|
138
|
+
- brainstem.gemspec
|
139
|
+
- Gemfile
|
140
|
+
- Gemfile.lock
|
141
|
+
- Guardfile
|
142
|
+
- lib/brainstem/association_field.rb
|
143
|
+
- lib/brainstem/controller_methods.rb
|
144
|
+
- lib/brainstem/engine.rb
|
145
|
+
- lib/brainstem/presenter.rb
|
146
|
+
- lib/brainstem/presenter_collection.rb
|
147
|
+
- lib/brainstem/time_classes.rb
|
148
|
+
- lib/brainstem/version.rb
|
149
|
+
- lib/brainstem.rb
|
150
|
+
- LICENSE
|
151
|
+
- Rakefile
|
152
|
+
- README.md
|
153
|
+
- spec/brainstem/controller_methods_spec.rb
|
154
|
+
- spec/brainstem/presenter_collection_spec.rb
|
155
|
+
- spec/brainstem/presenter_spec.rb
|
156
|
+
- spec/brainstem_spec.rb
|
157
|
+
- spec/spec_helper.rb
|
158
|
+
- spec/spec_helpers/cleanup.rb
|
159
|
+
- spec/spec_helpers/db.rb
|
160
|
+
- spec/spec_helpers/presenters.rb
|
161
|
+
homepage: http://developer.mavenlink.com
|
162
|
+
licenses:
|
163
|
+
- MIT
|
164
|
+
post_install_message:
|
165
|
+
rdoc_options: []
|
166
|
+
require_paths:
|
167
|
+
- lib
|
168
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
170
|
+
requirements:
|
171
|
+
- - ! '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
segments:
|
175
|
+
- 0
|
176
|
+
hash: -2131973950543043950
|
177
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
178
|
+
none: false
|
179
|
+
requirements:
|
180
|
+
- - ! '>='
|
181
|
+
- !ruby/object:Gem::Version
|
182
|
+
version: '0'
|
183
|
+
segments:
|
184
|
+
- 0
|
185
|
+
hash: -2131973950543043950
|
186
|
+
requirements: []
|
187
|
+
rubyforge_project:
|
188
|
+
rubygems_version: 1.8.25
|
189
|
+
signing_key:
|
190
|
+
specification_version: 3
|
191
|
+
summary: ActiveRecord presenters with a rich request API
|
192
|
+
test_files:
|
193
|
+
- spec/brainstem/controller_methods_spec.rb
|
194
|
+
- spec/brainstem/presenter_collection_spec.rb
|
195
|
+
- spec/brainstem/presenter_spec.rb
|
196
|
+
- spec/brainstem_spec.rb
|
197
|
+
- spec/spec_helper.rb
|
198
|
+
- spec/spec_helpers/cleanup.rb
|
199
|
+
- spec/spec_helpers/db.rb
|
200
|
+
- spec/spec_helpers/presenters.rb
|
201
|
+
has_rdoc:
|