activegist 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/.travis.yml +9 -0
- data/CHANGELOG +2 -0
- data/Gemfile +7 -0
- data/LICENSE +20 -0
- data/README.rdoc +96 -0
- data/Rakefile +15 -0
- data/activegist.gemspec +29 -0
- data/lib/active_gist.rb +134 -0
- data/lib/active_gist/api.rb +33 -0
- data/lib/active_gist/attributes.rb +107 -0
- data/lib/active_gist/class_methods.rb +42 -0
- data/lib/active_gist/errors/invalid.rb +5 -0
- data/lib/active_gist/files.rb +40 -0
- data/lib/active_gist/version.rb +8 -0
- data/lib/activegist.rb +1 -0
- data/spec/fixtures/all_gists.json +87 -0
- data/spec/fixtures/gist_1.json +78 -0
- data/spec/fixtures/gist_1_star.json +4 -0
- data/spec/fixtures/gist_1_updated.json +71 -0
- data/spec/fixtures/gist_2.json +65 -0
- data/spec/fixtures/gist_2_star.json +4 -0
- data/spec/fixtures/gist_delete_star.json +4 -0
- data/spec/fixtures/gist_destroy.json +4 -0
- data/spec/fixtures/gist_forked.json +33 -0
- data/spec/fixtures/gist_put_star.json +4 -0
- data/spec/fixtures/new_gist.json +63 -0
- data/spec/fixtures/public_gists.json +61 -0
- data/spec/fixtures/starred_gists.json +35 -0
- data/spec/lib/active_gist/files_spec.rb +16 -0
- data/spec/lib/active_gist_spec.rb +308 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/support/fakeweb.rb +20 -0
- metadata +173 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
HTTP/1.1 201 Created
|
2
|
+
Location: https://api.github.com/gists/1
|
3
|
+
X-RateLimit-Limit: 5000
|
4
|
+
X-RateLimit-Remaining: 4999
|
5
|
+
|
6
|
+
{
|
7
|
+
"url": "https://api.github.com/gists/1",
|
8
|
+
"id": "1",
|
9
|
+
"description": "description of gist",
|
10
|
+
"public": true,
|
11
|
+
"user": {
|
12
|
+
"login": "octocat",
|
13
|
+
"id": 1,
|
14
|
+
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
15
|
+
"gravatar_id": "somehexcode",
|
16
|
+
"url": "https://api.github.com/users/octocat"
|
17
|
+
},
|
18
|
+
"files": {
|
19
|
+
"ring.erl": {
|
20
|
+
"size": 932,
|
21
|
+
"filename": "ring.erl",
|
22
|
+
"raw_url": "https://gist.github.com/raw/365370/8c4d2d43d178df44f4c03a7f2ac0ff512853564e/ring.erl",
|
23
|
+
"content": "contents of gist"
|
24
|
+
}
|
25
|
+
},
|
26
|
+
"comments": 0,
|
27
|
+
"html_url": "https://gist.github.com/1",
|
28
|
+
"git_pull_url": "git://gist.github.com/1.git",
|
29
|
+
"git_push_url": "git@gist.github.com:1.git",
|
30
|
+
"created_at": "2010-04-14T02:15:15Z",
|
31
|
+
"forks": [
|
32
|
+
{
|
33
|
+
"user": {
|
34
|
+
"login": "octocat",
|
35
|
+
"id": 1,
|
36
|
+
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
37
|
+
"gravatar_id": "somehexcode",
|
38
|
+
"url": "https://api.github.com/users/octocat"
|
39
|
+
},
|
40
|
+
"url": "https://api.github.com/gists/5",
|
41
|
+
"created_at": "2011-04-14T16:00:49Z"
|
42
|
+
}
|
43
|
+
],
|
44
|
+
"history": [
|
45
|
+
{
|
46
|
+
"url": "https://api.github.com/gists/1/57a7f021a713b1c5a6a199b54cc514735d2d462f",
|
47
|
+
"version": "57a7f021a713b1c5a6a199b54cc514735d2d462f",
|
48
|
+
"user": {
|
49
|
+
"login": "octocat",
|
50
|
+
"id": 1,
|
51
|
+
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
52
|
+
"gravatar_id": "somehexcode",
|
53
|
+
"url": "https://api.github.com/users/octocat"
|
54
|
+
},
|
55
|
+
"change_status": {
|
56
|
+
"deletions": 0,
|
57
|
+
"additions": 180,
|
58
|
+
"total": 180
|
59
|
+
},
|
60
|
+
"committed_at": "2010-04-14T02:15:15Z"
|
61
|
+
}
|
62
|
+
]
|
63
|
+
}
|
@@ -0,0 +1,61 @@
|
|
1
|
+
HTTP/1.1 200 OK
|
2
|
+
Link: <https://api.github.com/resource?page=2>; rel="next",
|
3
|
+
<https://api.github.com/resource?page=5>; rel="last"
|
4
|
+
X-RateLimit-Limit: 5000
|
5
|
+
X-RateLimit-Remaining: 4999
|
6
|
+
Content-type: application/json; charset=utf-8
|
7
|
+
|
8
|
+
[
|
9
|
+
{
|
10
|
+
"url": "https://api.github.com/gists/1",
|
11
|
+
"id": "1",
|
12
|
+
"description": "description of gist",
|
13
|
+
"public": true,
|
14
|
+
"user": {
|
15
|
+
"login": "octocat",
|
16
|
+
"id": 1,
|
17
|
+
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
18
|
+
"gravatar_id": "somehexcode",
|
19
|
+
"url": "https://api.github.com/users/octocat"
|
20
|
+
},
|
21
|
+
"files": {
|
22
|
+
"ring.erl": {
|
23
|
+
"size": 932,
|
24
|
+
"filename": "ring.erl",
|
25
|
+
"raw_url": "https://gist.github.com/raw/365370/8c4d2d43d178df44f4c03a7f2ac0ff512853564e/ring.erl",
|
26
|
+
"content": "contents of gist"
|
27
|
+
}
|
28
|
+
},
|
29
|
+
"comments": 0,
|
30
|
+
"html_url": "https://gist.github.com/1",
|
31
|
+
"git_pull_url": "git://gist.github.com/1.git",
|
32
|
+
"git_push_url": "git@gist.github.com:1.git",
|
33
|
+
"created_at": "2010-04-14T02:15:15Z"
|
34
|
+
},
|
35
|
+
{
|
36
|
+
"url": "https://api.github.com/gists/2",
|
37
|
+
"id": "2",
|
38
|
+
"description": "description of gist",
|
39
|
+
"public": true,
|
40
|
+
"user": {
|
41
|
+
"login": "octocat",
|
42
|
+
"id": 1,
|
43
|
+
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
44
|
+
"gravatar_id": "somehexcode",
|
45
|
+
"url": "https://api.github.com/users/octocat"
|
46
|
+
},
|
47
|
+
"files": {
|
48
|
+
"ring.erl": {
|
49
|
+
"size": 932,
|
50
|
+
"filename": "ring.erl",
|
51
|
+
"raw_url": "https://gist.github.com/raw/365370/8c4d2d43d178df44f4c03a7f2ac0ff512853564e/ring.erl",
|
52
|
+
"content": "contents of gist"
|
53
|
+
}
|
54
|
+
},
|
55
|
+
"comments": 0,
|
56
|
+
"html_url": "https://gist.github.com/2",
|
57
|
+
"git_pull_url": "git://gist.github.com/2.git",
|
58
|
+
"git_push_url": "git@gist.github.com:2.git",
|
59
|
+
"created_at": "2010-04-14T02:15:15Z"
|
60
|
+
}
|
61
|
+
]
|
@@ -0,0 +1,35 @@
|
|
1
|
+
HTTP/1.1 200 OK
|
2
|
+
Link: <https://api.github.com/resource?page=2>; rel="next",
|
3
|
+
<https://api.github.com/resource?page=5>; rel="last"
|
4
|
+
X-RateLimit-Limit: 5000
|
5
|
+
X-RateLimit-Remaining: 4999
|
6
|
+
Content-type: application/json; charset=utf-8
|
7
|
+
|
8
|
+
[
|
9
|
+
{
|
10
|
+
"url": "https://api.github.com/gists/3",
|
11
|
+
"id": "3",
|
12
|
+
"description": "description of gist",
|
13
|
+
"public": false,
|
14
|
+
"user": {
|
15
|
+
"login": "octocat",
|
16
|
+
"id": 1,
|
17
|
+
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
18
|
+
"gravatar_id": "somehexcode",
|
19
|
+
"url": "https://api.github.com/users/octocat"
|
20
|
+
},
|
21
|
+
"files": {
|
22
|
+
"ring.erl": {
|
23
|
+
"size": 932,
|
24
|
+
"filename": "ring.erl",
|
25
|
+
"raw_url": "https://gist.github.com/raw/365370/8c4d2d43d178df44f4c03a7f2ac0ff512853564e/ring.erl",
|
26
|
+
"content": "contents of gist"
|
27
|
+
}
|
28
|
+
},
|
29
|
+
"comments": 0,
|
30
|
+
"html_url": "https://gist.github.com/3",
|
31
|
+
"git_pull_url": "git://gist.github.com/3.git",
|
32
|
+
"git_push_url": "git@gist.github.com:3.git",
|
33
|
+
"created_at": "2010-04-14T02:15:15Z"
|
34
|
+
}
|
35
|
+
]
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveGist::Files do
|
4
|
+
describe "with no files" do
|
5
|
+
it "should produce empty json" do
|
6
|
+
subject.as_json.should == {}.as_json
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "with 1 file" do
|
11
|
+
before { subject['file1.txt'] = { :content => 'data' } }
|
12
|
+
it "should produce json with a file" do
|
13
|
+
subject.as_json.should == { 'file1.txt' => { :content => 'data' } }.as_json
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,308 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
describe ActiveGist do
|
5
|
+
let(:valid_attributes) do { :files => { "file1.txt" => { :content => 'String file contents' } } } end
|
6
|
+
|
7
|
+
def expect_request(method, path, data = nil, headers = { :accept => 'application/json' }, return_val = {:id=>1})
|
8
|
+
RestClient::Request.should_receive(:execute) do |options|
|
9
|
+
expectation = [method, File.join("https://api.github.com", path)]
|
10
|
+
actual = [options[:method], options[:url]]
|
11
|
+
case data
|
12
|
+
when NilClass then expectation << nil; actual << options[:payload]
|
13
|
+
when String then expectation << data; actual << options[:payload]
|
14
|
+
when Hash then expectation << JSON.parse(data.to_json); actual << JSON.parse(options[:payload])
|
15
|
+
else raise "Don't know how to handle data format: #{data.inspect}"
|
16
|
+
end
|
17
|
+
options[:headers].each { |k,v| headers[k] = v unless headers.key?(k) }
|
18
|
+
expectation << headers
|
19
|
+
actual << options[:headers]
|
20
|
+
|
21
|
+
actual.should == expectation
|
22
|
+
return_val.to_json
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should not be 'equal' to another object with same id" do
|
27
|
+
obj = Object.new
|
28
|
+
def obj.id; '1'; end
|
29
|
+
ActiveGist.new(:id => '1').should_not == obj
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "a new gist" do
|
33
|
+
it "assign a file and validate" do
|
34
|
+
a = ActiveGist.new
|
35
|
+
a.files['file1.txt'] = { :content => "this is test content" }
|
36
|
+
a.should be_valid
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "an existing gist" do
|
41
|
+
describe "that is starred" do
|
42
|
+
subject { ActiveGist.find(1) }
|
43
|
+
|
44
|
+
it "check if it is starred" do
|
45
|
+
subject.should be_starred
|
46
|
+
end
|
47
|
+
|
48
|
+
it "check valid request" do
|
49
|
+
subject
|
50
|
+
expect_request(:get, "/gists/1/star")
|
51
|
+
subject.starred?
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "unstarring it" do
|
55
|
+
it { subject.unstar!; should_not be_starred }
|
56
|
+
it "check valid request" do
|
57
|
+
subject
|
58
|
+
expect_request :delete, "gists/1/star"
|
59
|
+
subject.unstar!
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "that is not starred" do
|
65
|
+
subject { ActiveGist.find(2) }
|
66
|
+
|
67
|
+
it "check if it is not starred" do
|
68
|
+
subject.should_not be_starred
|
69
|
+
end
|
70
|
+
|
71
|
+
it "check valid request" do
|
72
|
+
subject
|
73
|
+
expect_request :get, "/gists/2/star"
|
74
|
+
subject.starred?
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "starring it" do
|
78
|
+
it { subject.star!; should be_starred }
|
79
|
+
it "check valid request" do
|
80
|
+
subject
|
81
|
+
expect_request :put, "/gists/2/star", ""
|
82
|
+
subject.star!
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "destroying it" do
|
88
|
+
subject { ActiveGist.find 1 }
|
89
|
+
|
90
|
+
it "should destroy properly" do
|
91
|
+
subject.destroy
|
92
|
+
subject.should_not be_persisted
|
93
|
+
subject.should_not be_new_record
|
94
|
+
subject.should be_destroyed
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should send correct request" do
|
98
|
+
subject
|
99
|
+
expect_request :delete, "gists/1"
|
100
|
+
subject.destroy
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "forking it" do
|
105
|
+
subject { ActiveGist.find 1 }
|
106
|
+
|
107
|
+
it "should return the forked gist" do
|
108
|
+
subject.fork.should_not == subject
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should send the correct request" do
|
112
|
+
subject
|
113
|
+
expect_request :post, "/gists/1/fork", ""
|
114
|
+
subject.fork
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "validation" do
|
120
|
+
before { subject.valid? }
|
121
|
+
|
122
|
+
it "should not validate presence of description" do
|
123
|
+
subject.errors[:description].should_not include("can't be blank")
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should not validate presence of public" do
|
127
|
+
# github requires this but we're just going to default it to false
|
128
|
+
subject.errors[:public].should_not include("can't be blank")
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should validate presence of files" do
|
132
|
+
subject.errors[:files].should include("can't be blank")
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
describe "creating a valid gist with arrays and hashes" do
|
137
|
+
subject { ActiveGist.create!(valid_attributes) }
|
138
|
+
|
139
|
+
it "should return the new gist" do
|
140
|
+
subject.id.should == '1'
|
141
|
+
subject.url.should == 'https://api.github.com/gists/1'
|
142
|
+
subject.should be_public # this would default to false but our fake response returns true
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should be persisted" do
|
146
|
+
subject.should be_persisted
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should send proper request" do
|
150
|
+
expect_request :post, "/gists", valid_attributes.merge(:description => nil, :public => false)
|
151
|
+
subject
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe 'changing just files' do
|
156
|
+
subject { ActiveGist.find(1) }
|
157
|
+
before { subject.files['file1.txt'][:content] = 'updated' }
|
158
|
+
it { should_not be_persisted }
|
159
|
+
end
|
160
|
+
|
161
|
+
describe "changing an existing gist" do
|
162
|
+
subject { ActiveGist.find(1) }
|
163
|
+
before do
|
164
|
+
subject.description = "updated description"
|
165
|
+
subject.files['old_name.txt'][:filename] = 'new_name.txt'
|
166
|
+
subject.files['deleted.txt'] = nil
|
167
|
+
subject.files['file1.txt'][:content] = "updated file contents"
|
168
|
+
end
|
169
|
+
|
170
|
+
it { should_not be_persisted }
|
171
|
+
|
172
|
+
it "should send proper request to save" do
|
173
|
+
expect_request :patch, "/gists/1", {
|
174
|
+
:description => "updated description",
|
175
|
+
:files => subject.files
|
176
|
+
}
|
177
|
+
subject.save!
|
178
|
+
end
|
179
|
+
|
180
|
+
describe "saving" do
|
181
|
+
before { subject.save! }
|
182
|
+
|
183
|
+
it "should store the new description" do
|
184
|
+
subject.description.should == 'returned updated description'
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should remove the renamed file's old filename" do
|
188
|
+
subject.files.should_not have_key('old_name.txt')
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should add the renamed file's new filename" do
|
192
|
+
subject.files.should have_key('new_name.txt')
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should remove the deleted file" do
|
196
|
+
subject.files.should_not have_key('deleted.txt')
|
197
|
+
end
|
198
|
+
|
199
|
+
it "should update the modified file contents" do
|
200
|
+
subject.files['file1.txt'][:content].should == 'returned updated file contents'
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe "saving a valid gist" do
|
206
|
+
subject { ActiveGist.new(valid_attributes) }
|
207
|
+
before { subject.save }
|
208
|
+
|
209
|
+
it '#save should return true' do
|
210
|
+
subject.save.should be_true
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should be persisted" do
|
214
|
+
subject.should be_persisted
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
describe "creating an invalid gist" do
|
219
|
+
it "::create! should raise an error" do
|
220
|
+
proc { ActiveGist.create! }.should raise_error
|
221
|
+
end
|
222
|
+
|
223
|
+
it "::create should return a record that is not persisted" do
|
224
|
+
ActiveGist.create.should_not be_persisted
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
describe "saving an invalid gist" do
|
229
|
+
it '#save! should raise an error' do
|
230
|
+
proc { ActiveGist.new.save! }.should raise_error
|
231
|
+
end
|
232
|
+
|
233
|
+
it '#save should return false' do
|
234
|
+
ActiveGist.new.save.should be_false
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
it "should have a count of all gists" do
|
239
|
+
ActiveGist.count.should == 3
|
240
|
+
end
|
241
|
+
|
242
|
+
it "should have a count of public gists" do
|
243
|
+
ActiveGist.count(:public).should == 2
|
244
|
+
end
|
245
|
+
|
246
|
+
it "should have a count of starred gists" do
|
247
|
+
ActiveGist.count(:starred).should == 1
|
248
|
+
end
|
249
|
+
|
250
|
+
it "should return the last gist" do
|
251
|
+
ActiveGist.last.id.should == '3'
|
252
|
+
end
|
253
|
+
|
254
|
+
it "should return the first gist" do
|
255
|
+
ActiveGist.first.id.should == '1'
|
256
|
+
end
|
257
|
+
|
258
|
+
it "should find a gist by id" do
|
259
|
+
ActiveGist.find(2).should == ActiveGist.all[1]
|
260
|
+
|
261
|
+
# check request
|
262
|
+
expect_request(:get, "/gists/2")
|
263
|
+
ActiveGist.find(2)
|
264
|
+
end
|
265
|
+
|
266
|
+
describe "a gist returned by github" do
|
267
|
+
subject { ActiveGist.first }
|
268
|
+
it { should respond_to(:url) }
|
269
|
+
it { should respond_to(:id) }
|
270
|
+
it { should respond_to(:description) }
|
271
|
+
it { should respond_to(:public?) }
|
272
|
+
it { should respond_to(:user) }
|
273
|
+
it { should respond_to(:files) }
|
274
|
+
it { should respond_to(:comments) }
|
275
|
+
it { should respond_to(:html_url) }
|
276
|
+
it { should respond_to(:git_pull_url) }
|
277
|
+
it { should respond_to(:git_push_url) }
|
278
|
+
it { should respond_to(:created_at) }
|
279
|
+
it { should be_persisted }
|
280
|
+
end
|
281
|
+
|
282
|
+
describe "fetching all gists" do
|
283
|
+
subject { ActiveGist.all }
|
284
|
+
|
285
|
+
it { should have(3).gists }
|
286
|
+
|
287
|
+
it "should request the gist properly" do
|
288
|
+
expect_request(:get, "/gists", nil, {:accept => 'application/json'}, [])
|
289
|
+
subject
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
describe "active model lint tests" do
|
294
|
+
include Test::Unit::Assertions
|
295
|
+
include ActiveModel::Lint::Tests
|
296
|
+
|
297
|
+
def model
|
298
|
+
subject
|
299
|
+
end
|
300
|
+
|
301
|
+
# to_s is to support ruby-1.9
|
302
|
+
ActiveModel::Lint::Tests.public_instance_methods.map{|m| m.to_s}.grep(/^test/).each do |m|
|
303
|
+
example m.gsub('_',' ') do
|
304
|
+
send m
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|