atnd4r 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +4 -0
- data/.gitignore +5 -0
- data/ChangeLog +9 -0
- data/README.rdoc +57 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/atnd4r.gemspec +46 -0
- data/lib/atnd4r.rb +257 -0
- data/spec/atnd4r_spec.rb +331 -0
- data/spec/spec_helper.rb +22 -0
- metadata +69 -0
data/.document
ADDED
data/ChangeLog
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
= atnd4r
|
2
|
+
|
3
|
+
ATND WebAPI wrapper for Ruby.
|
4
|
+
* Project Website - http://github.com/sugamasao/atnd4r/tree/master
|
5
|
+
|
6
|
+
== Developers
|
7
|
+
* {sugamasao}[http://sugamasao.dip.jp/] <sugamasao@gmail.com>
|
8
|
+
|
9
|
+
== Features/Problems
|
10
|
+
|
11
|
+
* Ruby 1.8.7 での動作確認を行っています
|
12
|
+
|
13
|
+
== Synopsis
|
14
|
+
|
15
|
+
使用例
|
16
|
+
|
17
|
+
require 'rubygems'
|
18
|
+
require 'atnd4r'
|
19
|
+
|
20
|
+
=== 入力データについて
|
21
|
+
|
22
|
+
検索用メソッドとして、下記の二つを用意しています。
|
23
|
+
|
24
|
+
* Atnd4r.get_event_list
|
25
|
+
* Atnd4r.get_user_list
|
26
|
+
|
27
|
+
引数は、検索条件を Hash で渡せば良いです。
|
28
|
+
例えば、 event_id が 1 の情報を調べる為には、
|
29
|
+
|
30
|
+
irb(main):002:0> Atnd4r.get_event_list({:event_id => 1})
|
31
|
+
|
32
|
+
のような形式になります。
|
33
|
+
一つの KEY に対して、複数の値を渡す場合は配列に入れて渡してください。
|
34
|
+
|
35
|
+
irb(main):003:0> Atnd4r.get_event_list({:event_id => [1,2]})
|
36
|
+
|
37
|
+
詳細な検索の仕様は{ATND API の公式ページ}[http://api.atnd.org] をご覧ください。
|
38
|
+
なお、ATND API における、format パラメータのみ、XML固定となっていますので、format パラメータを Atnd4R へ渡しても無視されます。
|
39
|
+
|
40
|
+
=== 出力データについて
|
41
|
+
|
42
|
+
受け取ったデータは以下の形式のAtnd4r::AtndAPIというオブジェクトでラッピングされて返却されます。
|
43
|
+
|
44
|
+
基本的には XML データを Ruby 用のオブジェクトに変換したものですので、XMLのプロパティなどはほぼそのままです(ただし、ハイフンの名前のものはアンダースコアにしています)。
|
45
|
+
|
46
|
+
また、各プロパティは XML の属性にしたがったオブジェクトに変換されています。例えば、Integer とあれば Fixnum 型のように。
|
47
|
+
|
48
|
+
==== Atnd4Rの戻り値のオブジェクトについて
|
49
|
+
|
50
|
+
XMLに記載されている属性に従い、 String や Fixnum のようなRubyの型になっています。
|
51
|
+
詳細は{Atnd4R解説エントリ}[http://d.hatena.ne.jp/seiunsky/20090730/1248972545] をご覧ください。
|
52
|
+
|
53
|
+
== Copyright
|
54
|
+
|
55
|
+
Author:: sugamasao <sugamasao@gmail.com>
|
56
|
+
License:: Ruby's
|
57
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "atnd4r"
|
8
|
+
gem.summary = %Q{ATND の API を Ruby から使用するたのラッパークラスです}
|
9
|
+
gem.email = "sugamasao@gmail.com"
|
10
|
+
gem.homepage = "http://github.com/sugamasao/atnd4r"
|
11
|
+
gem.authors = ["sugamasao"]
|
12
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
13
|
+
end
|
14
|
+
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'spec/rake/spectask'
|
20
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
21
|
+
spec.libs << 'lib' << 'spec'
|
22
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
23
|
+
end
|
24
|
+
|
25
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
26
|
+
spec.libs << 'lib' << 'spec'
|
27
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
28
|
+
spec.rcov = true
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
task :default => :spec
|
33
|
+
|
34
|
+
require 'rake/rdoctask'
|
35
|
+
Rake::RDocTask.new do |rdoc|
|
36
|
+
if File.exist?('VERSION.yml')
|
37
|
+
config = YAML.load(File.read('VERSION.yml'))
|
38
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
39
|
+
else
|
40
|
+
version = ""
|
41
|
+
end
|
42
|
+
|
43
|
+
rdoc.rdoc_dir = 'rdoc'
|
44
|
+
rdoc.title = "atnd4r #{version}"
|
45
|
+
rdoc.rdoc_files.include('README*')
|
46
|
+
rdoc.rdoc_files.include('Changelog')
|
47
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
48
|
+
rdoc.options = ["--charset", "utf-8", "--line-numbers"]
|
49
|
+
end
|
50
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.6
|
data/atnd4r.gemspec
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{atnd4r}
|
5
|
+
s.version = "0.0.6"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["sugamasao"]
|
9
|
+
s.date = %q{2009-07-28}
|
10
|
+
s.email = %q{sugamasao@gmail.com}
|
11
|
+
s.extra_rdoc_files = [
|
12
|
+
"ChangeLog",
|
13
|
+
"README.rdoc"
|
14
|
+
]
|
15
|
+
s.files = [
|
16
|
+
".document",
|
17
|
+
".gitignore",
|
18
|
+
"ChangeLog",
|
19
|
+
"README.rdoc",
|
20
|
+
"Rakefile",
|
21
|
+
"VERSION",
|
22
|
+
"atnd4r.gemspec",
|
23
|
+
"lib/atnd4r.rb",
|
24
|
+
"spec/atnd4r_spec.rb",
|
25
|
+
"spec/spec_helper.rb"
|
26
|
+
]
|
27
|
+
s.homepage = %q{http://github.com/sugamasao/atnd4r}
|
28
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
29
|
+
s.require_paths = ["lib"]
|
30
|
+
s.rubygems_version = %q{1.3.4}
|
31
|
+
s.summary = %q{ATND の API を Ruby から使用するたのラッパークラスです}
|
32
|
+
s.test_files = [
|
33
|
+
"spec/atnd4r_spec.rb",
|
34
|
+
"spec/spec_helper.rb"
|
35
|
+
]
|
36
|
+
|
37
|
+
if s.respond_to? :specification_version then
|
38
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
39
|
+
s.specification_version = 3
|
40
|
+
|
41
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
42
|
+
else
|
43
|
+
end
|
44
|
+
else
|
45
|
+
end
|
46
|
+
end
|
data/lib/atnd4r.rb
ADDED
@@ -0,0 +1,257 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'rexml/document'
|
3
|
+
|
4
|
+
module Atnd4r
|
5
|
+
@atnd_api_url = 'api.atnd.org'
|
6
|
+
@atnd_api_port = 80
|
7
|
+
@atnd_api_events = '/events/'
|
8
|
+
@atnd_api_users = '/events/users/'
|
9
|
+
|
10
|
+
# ATND へのリクエストで 400 番台や 500 番台の応答コードが返された時に出力されます
|
11
|
+
class ATNDHTTPError < StandardError; end
|
12
|
+
|
13
|
+
# ATND へのリクエスト時のパラメータが不正(もしくは何も無かった場合)
|
14
|
+
class ATNDParameterError < StandardError; end;
|
15
|
+
|
16
|
+
########################
|
17
|
+
# アクセッサメソッド
|
18
|
+
########################
|
19
|
+
|
20
|
+
#ATND の HOST名(http:// は不要)を設定します。
|
21
|
+
#万が一 URL に変更がある場合は独自に設定してください
|
22
|
+
def self.atnd_api_url=(val = "")
|
23
|
+
@atnd_api_url = val
|
24
|
+
end
|
25
|
+
|
26
|
+
#ATND の ポート番号を設定します。
|
27
|
+
#万が一 URL に変更がある場合は独自に設定してください
|
28
|
+
def self.atnd_api_port=(val = 0)
|
29
|
+
@atnd_api_port = val.to_i
|
30
|
+
end
|
31
|
+
|
32
|
+
#ATND の イベント情報 API のパスを設定します。(末尾は '/' である必要があります)
|
33
|
+
#万が一 URL に変更がある場合は独自に設定してください
|
34
|
+
def self.atnd_api_events=(val = 0)
|
35
|
+
@atnd_api_events = val.to_i
|
36
|
+
end
|
37
|
+
|
38
|
+
#ATND の 出席情報 API のパスを設定します。(末尾は '/' である必要があります)
|
39
|
+
#万が一 URL に変更がある場合は独自に設定してください
|
40
|
+
def self.atnd_api_users=(val = "")
|
41
|
+
@atnd_api_users = val
|
42
|
+
end
|
43
|
+
|
44
|
+
###################
|
45
|
+
# public method
|
46
|
+
##################
|
47
|
+
|
48
|
+
#== イベントサーチAPI
|
49
|
+
#イベントサーチAPI を実行します
|
50
|
+
#=== 引数
|
51
|
+
#_param_:: Hashのオブジェクト。一つの検索パラメータに対して、複数の値を渡す場合は、value部分を配列にしてください。
|
52
|
+
#例えば、event_id で検索する場合は、下記のようなパラメータを渡してください
|
53
|
+
# {:event_id => 1}
|
54
|
+
#event_id を複数渡したい場合は配列にします。
|
55
|
+
# {:event_id => [1,2]}
|
56
|
+
#=== 戻り値
|
57
|
+
#Atnd4r::AtndAPI:: Atnd4r::AtndAPIオブジェクト
|
58
|
+
#=== 例外
|
59
|
+
#Atnd4r::ATNDHTTPError:: API ヘアクセスした際に、400系や500系の応答コードがかえってきた場合に発生します
|
60
|
+
#Atnd4r::ATNDParameterError:: API 実行結果に Error メッセージが入っていた場合に発生します
|
61
|
+
def self.get_event_list(param = {})
|
62
|
+
xml = get_xml(@atnd_api_events, make_query(param))
|
63
|
+
event = parse_common_xml(xml)
|
64
|
+
event.events = parse_events_xml(xml)
|
65
|
+
|
66
|
+
return event
|
67
|
+
end
|
68
|
+
|
69
|
+
#== 出欠確認API
|
70
|
+
#出欠確認API を実行します
|
71
|
+
#=== 引数
|
72
|
+
#_param_:: Hashのオブジェクト。一つの検索パラメータに対して、複数の値を渡す場合は、value部分を配列にしてください。
|
73
|
+
#例えば、user_id で検索する場合は、下記のようなパラメータを渡してください
|
74
|
+
# {:user_id => 1}
|
75
|
+
#user_id を複数渡したい場合は配列にします。
|
76
|
+
# {:user_id => [1,2]}
|
77
|
+
#=== 戻り値
|
78
|
+
#Atnd4r::AtndAPI:: Atnd4r::AtndAPIオブジェクト
|
79
|
+
#=== 例外
|
80
|
+
#Atnd4r::ATNDHTTPError:: API ヘアクセスした際に、400系や500系の応答コードがかえってきた場合に発生します
|
81
|
+
#Atnd4r::ATNDParameterError:: API 実行結果に Error メッセージが入っていた場合に発生します
|
82
|
+
def self.get_user_list(param = {})
|
83
|
+
xml = get_xml(@atnd_api_users, make_query(param))
|
84
|
+
event = parse_common_xml(xml)
|
85
|
+
event.events = parse_users_xml(xml)
|
86
|
+
|
87
|
+
return event
|
88
|
+
end
|
89
|
+
|
90
|
+
###################
|
91
|
+
# private method
|
92
|
+
##################
|
93
|
+
|
94
|
+
# パラメータから QueryString を作成する。一つの Key に複数の値がある場合、カンマ区切りにする
|
95
|
+
def self.make_query(param = {})
|
96
|
+
query = []
|
97
|
+
param.each do |key, val|
|
98
|
+
if val.nil?
|
99
|
+
val = ""
|
100
|
+
end
|
101
|
+
|
102
|
+
# format のオプションは無視する(XML固定のため)
|
103
|
+
if key.to_s == 'format'
|
104
|
+
next
|
105
|
+
end
|
106
|
+
# key がシンボルの場合に備えて to_s しておく
|
107
|
+
query << key.to_s.strip + "=" + Array(val).map {|value| value.to_s.strip}.join(",")
|
108
|
+
end
|
109
|
+
|
110
|
+
# format を XML にする
|
111
|
+
query << 'format=xml'
|
112
|
+
|
113
|
+
return query.join("&")
|
114
|
+
end
|
115
|
+
|
116
|
+
# 共通の XMLデータのパース
|
117
|
+
def self.parse_common_xml(xml)
|
118
|
+
common = AtndAPI.new(xml.elements['hash'])
|
119
|
+
end
|
120
|
+
|
121
|
+
# AtndEvent の配列を返却する
|
122
|
+
def self.parse_events_xml(xml)
|
123
|
+
events_list = [] # AtndEvent の配列
|
124
|
+
|
125
|
+
# /hash/error/message があったら Error とする
|
126
|
+
raise ATNDParameterError.new("ATND Request Parameter Error : " + xml.elements['/hash/error/message'].text) if xml.elements['/hash/error/message']
|
127
|
+
|
128
|
+
xml.elements.each('/hash/events/event') do |event|
|
129
|
+
events_list << AtndEvent.new(event)
|
130
|
+
end
|
131
|
+
|
132
|
+
return events_list
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
# AtndEvent の配列を返却する
|
137
|
+
def self.parse_users_xml(xml)
|
138
|
+
users_list = [] # AtndEvent の配列
|
139
|
+
|
140
|
+
# /hash/error/message があったら Error とする
|
141
|
+
raise ATNDParameterError.new("ATND Request Parameter Error : " + xml.elements['/hash/error/message'].text) if xml.elements['/hash/error/message']
|
142
|
+
|
143
|
+
xml.elements.each('/hash/events/event') do |event|
|
144
|
+
users_list << AtndEvent.new(event)
|
145
|
+
end
|
146
|
+
|
147
|
+
return users_list
|
148
|
+
end
|
149
|
+
|
150
|
+
# ATND API を実行して、XML を取得する
|
151
|
+
def self.get_xml(api_url, query)
|
152
|
+
doc = nil
|
153
|
+
Net::HTTP.version_1_2
|
154
|
+
Net::HTTP.start(@atnd_api_url, @atnd_api_port) do |http|
|
155
|
+
response = http.get(api_url + '?' + query)
|
156
|
+
if response.code =~ /[45]\d\d/
|
157
|
+
raise ATNDHTTPError.new("ATND API Server Error : #{response['status']}")
|
158
|
+
end
|
159
|
+
doc = REXML::Document.new response.body
|
160
|
+
end
|
161
|
+
return doc
|
162
|
+
end
|
163
|
+
|
164
|
+
################
|
165
|
+
# private setting
|
166
|
+
###############
|
167
|
+
private_class_method :get_xml, :parse_common_xml, :parse_events_xml, :parse_users_xml, :make_query
|
168
|
+
|
169
|
+
class AtndAPI
|
170
|
+
def initialize(xml)
|
171
|
+
@results_returned = AtndAPIUtil::to_ruby_type xml.elements['results-returned']
|
172
|
+
@results_available = AtndAPIUtil::to_ruby_type xml.elements['results-available']
|
173
|
+
@results_start = AtndAPIUtil::to_ruby_type xml.elements['results-start']
|
174
|
+
@events = nil
|
175
|
+
end
|
176
|
+
|
177
|
+
attr_reader :results_returned, :results_available, :results_start
|
178
|
+
attr_accessor :events
|
179
|
+
end
|
180
|
+
|
181
|
+
class AtndEvent
|
182
|
+
# XML オブジェクト
|
183
|
+
def initialize(event)
|
184
|
+
# 共通データ
|
185
|
+
@accepted = AtndAPIUtil::to_ruby_type event.elements['accepted']
|
186
|
+
@event_id = AtndAPIUtil::to_ruby_type event.elements['event-id']
|
187
|
+
@updated_at = AtndAPIUtil::to_ruby_type event.elements['updated-at']
|
188
|
+
@title = AtndAPIUtil::to_ruby_type event.elements['title']
|
189
|
+
@waiting = AtndAPIUtil::to_ruby_type event.elements['waiting']
|
190
|
+
@event_url = AtndAPIUtil::to_ruby_type event.elements['event-url']
|
191
|
+
@limit = AtndAPIUtil::to_ruby_type event.elements['limit']
|
192
|
+
|
193
|
+
# 出席情報の場合
|
194
|
+
@users = []
|
195
|
+
event.elements.each('users/user') do |user|
|
196
|
+
@users << AtndUser.new(user)
|
197
|
+
end
|
198
|
+
|
199
|
+
# イベント情報の場合
|
200
|
+
@place = AtndAPIUtil::to_ruby_type event.elements['place']
|
201
|
+
@lon = AtndAPIUtil::to_ruby_type event.elements['lon']
|
202
|
+
@ended_at = AtndAPIUtil::to_ruby_type event.elements['ended-at']
|
203
|
+
@url = AtndAPIUtil::to_ruby_type event.elements['url']
|
204
|
+
@owner_nickname = AtndAPIUtil::to_ruby_type event.elements['owner-nickname']
|
205
|
+
@catch = AtndAPIUtil::to_ruby_type event.elements['catch']
|
206
|
+
@description = AtndAPIUtil::to_ruby_type event.elements['description']
|
207
|
+
@owner_id = AtndAPIUtil::to_ruby_type event.elements['owner-id']
|
208
|
+
@lat = AtndAPIUtil::to_ruby_type event.elements['lat']
|
209
|
+
@address = AtndAPIUtil::to_ruby_type event.elements['address']
|
210
|
+
@started_at = AtndAPIUtil::to_ruby_type event.elements['started-at']
|
211
|
+
end
|
212
|
+
|
213
|
+
attr_reader :accepted, :event_id, :updated_at, :title, :waiting, :event_url, :limit
|
214
|
+
attr_reader :users
|
215
|
+
attr_reader :place, :lon, :ended_at, :url, :owner_nickname, :catch, :description, :owner_id, :lat, :address, :started_at
|
216
|
+
end
|
217
|
+
|
218
|
+
class AtndUser
|
219
|
+
def initialize(user)
|
220
|
+
@status = AtndAPIUtil::to_ruby_type user.elements['status']
|
221
|
+
@nickname = AtndAPIUtil::to_ruby_type user.elements['nickname']
|
222
|
+
@user_id = AtndAPIUtil::to_ruby_type user.elements['user-id']
|
223
|
+
end
|
224
|
+
attr_reader :status, :nickname, :user_id
|
225
|
+
end
|
226
|
+
|
227
|
+
|
228
|
+
require 'time'
|
229
|
+
module AtndAPIUtil
|
230
|
+
# REXML::Element
|
231
|
+
def self.to_ruby_type(element)
|
232
|
+
|
233
|
+
# 子要素が取得できない場合は nil を返す
|
234
|
+
return nil if element.nil?
|
235
|
+
|
236
|
+
# 要素が無い場合、属性に nil が付くので、値が true であれば nil を返す
|
237
|
+
if element.attributes['nil']
|
238
|
+
return nil if element.attributes['nil'] == 'true'
|
239
|
+
end
|
240
|
+
|
241
|
+
val = nil
|
242
|
+
element_type = element.attributes['type']
|
243
|
+
element_type = element_type.downcase if element_type
|
244
|
+
case element_type
|
245
|
+
when 'integer'
|
246
|
+
val = element.text.to_i
|
247
|
+
when 'decimal'
|
248
|
+
val = element.text.to_f
|
249
|
+
when 'datetime'
|
250
|
+
val = Time.parse(element.text)
|
251
|
+
else
|
252
|
+
val = element.text
|
253
|
+
end
|
254
|
+
return val
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
data/spec/atnd4r_spec.rb
ADDED
@@ -0,0 +1,331 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
require 'rexml/document'
|
3
|
+
require 'net/http'
|
4
|
+
require 'time'
|
5
|
+
require 'pp'
|
6
|
+
|
7
|
+
|
8
|
+
module Atnd4r
|
9
|
+
# private methods to public
|
10
|
+
public_class_method :get_xml, :parse_users_xml, :parse_events_xml, :parse_common_xml, :make_query
|
11
|
+
end
|
12
|
+
|
13
|
+
describe Atnd4r, "get_event_list で値を取得した場合" do
|
14
|
+
xml_string =<<-EOF
|
15
|
+
<hash>
|
16
|
+
<results-returned type="integer">9999</results-returned>
|
17
|
+
<results-available type="integer">1</results-available>
|
18
|
+
<events type="array">
|
19
|
+
<event>
|
20
|
+
<accepted type="integer">1</accepted>
|
21
|
+
<event-id type="integer">1</event-id>
|
22
|
+
<updated-at type="datetime">2009-01-01T00:00:00+09:00</updated-at>
|
23
|
+
<title>hoge event</title>
|
24
|
+
<waiting type="integer">0</waiting>
|
25
|
+
<event-url>hoge.com</event-url>
|
26
|
+
<users type="array">
|
27
|
+
<user>
|
28
|
+
<status type="integer">1</status>
|
29
|
+
<nickname>name</nickname>
|
30
|
+
<user-id type="integer">1</user-id>
|
31
|
+
</user>
|
32
|
+
</users>
|
33
|
+
<limit type="integer">1</limit>
|
34
|
+
</event>
|
35
|
+
</events>
|
36
|
+
<results-start type="integer">1</results-start>
|
37
|
+
</hash>
|
38
|
+
EOF
|
39
|
+
before(:each) do
|
40
|
+
@http_mock = create_http_mock(xml_string, "200", "200 Ok")
|
41
|
+
Net::HTTP.stub!(:start).and_yield(@http_mock)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "AtndAPI オブジェクトが取得されること" do
|
45
|
+
event = Atnd4r::get_event_list({:event_id => 1})
|
46
|
+
event.class.should == Atnd4r::AtndAPI
|
47
|
+
event.results_returned.should == 9999
|
48
|
+
event.events[0].title.should == "hoge event"
|
49
|
+
event.events[0].users[0].nickname.should == "name"
|
50
|
+
end
|
51
|
+
|
52
|
+
after do
|
53
|
+
@http_mock = nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe Atnd4r, "get_user_list で値を取得した場合" do
|
58
|
+
xml_string =<<-EOF
|
59
|
+
<hash>
|
60
|
+
<results-returned type="integer">9999</results-returned>
|
61
|
+
<results-available type="integer">1</results-available>
|
62
|
+
<events type="array">
|
63
|
+
<event>
|
64
|
+
<accepted type="integer">1</accepted>
|
65
|
+
<event-id type="integer">1</event-id>
|
66
|
+
<updated-at type="datetime">2009-01-01T00:00:00+09:00</updated-at>
|
67
|
+
<title>hoge event</title>
|
68
|
+
<waiting type="integer">0</waiting>
|
69
|
+
<event-url>hoge.com</event-url>
|
70
|
+
<users type="array">
|
71
|
+
<user>
|
72
|
+
<status type="integer">1</status>
|
73
|
+
<nickname>name</nickname>
|
74
|
+
<user-id type="integer">1</user-id>
|
75
|
+
</user>
|
76
|
+
</users>
|
77
|
+
<limit type="integer">1</limit>
|
78
|
+
</event>
|
79
|
+
</events>
|
80
|
+
<results-start type="integer">1</results-start>
|
81
|
+
</hash>
|
82
|
+
EOF
|
83
|
+
before(:each) do
|
84
|
+
@http_mock = create_http_mock(xml_string, "200", "200 Ok")
|
85
|
+
Net::HTTP.stub!(:start).and_yield(@http_mock)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "AtndAPI オブジェクトが取得されること" do
|
89
|
+
event = Atnd4r::get_user_list({:user_id => 1})
|
90
|
+
event.class.should == Atnd4r::AtndAPI
|
91
|
+
event.results_returned.should == 9999
|
92
|
+
event.events[0].title.should == "hoge event"
|
93
|
+
event.events[0].users[0].nickname.should == "name"
|
94
|
+
end
|
95
|
+
|
96
|
+
after do
|
97
|
+
@http_mock = nil
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "Atnd4r::get_xml で、サーバーエラー(4xx)が返された)場合" do
|
102
|
+
before(:each) do
|
103
|
+
@http_mock = create_http_mock("body", "400", "400_error")
|
104
|
+
Net::HTTP.stub!(:start).and_yield(@http_mock)
|
105
|
+
end
|
106
|
+
|
107
|
+
it "は、400 ならATNDHTTPError を返す事" do
|
108
|
+
lambda {
|
109
|
+
Atnd4r.get_xml("api", "query")
|
110
|
+
}.should raise_error(Atnd4r::ATNDHTTPError, /400_error/)
|
111
|
+
end
|
112
|
+
|
113
|
+
after do
|
114
|
+
@http_mock = nil
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "Atnd4r::get_xml で、サーバーエラー(4xx)が返された)場合" do
|
119
|
+
before(:each) do
|
120
|
+
@http_mock = create_http_mock("body", "500", "500_error")
|
121
|
+
Net::HTTP.stub!(:start).and_yield(@http_mock)
|
122
|
+
end
|
123
|
+
|
124
|
+
it "は、500 ならATNDHTTPError を返す事" do
|
125
|
+
lambda {
|
126
|
+
Atnd4r.get_xml("api", "query")
|
127
|
+
}.should raise_error(Atnd4r::ATNDHTTPError, /500_error/)
|
128
|
+
end
|
129
|
+
|
130
|
+
after do
|
131
|
+
@http_mock = nil
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "Atnd4r::get_xml でXML が正しく取得できたとき" do
|
136
|
+
before(:each) do
|
137
|
+
xml_string = "<tag>hoge</tag>"
|
138
|
+
@http_mock = create_http_mock(xml_string, "200", "200 Ok")
|
139
|
+
Net::HTTP.stub!(:start).and_yield(@http_mock)
|
140
|
+
end
|
141
|
+
|
142
|
+
it "は、XMLオブジェクトの値として、 hoge を返す事" do
|
143
|
+
doc = Atnd4r.get_xml("api", "query")
|
144
|
+
doc.elements["tag"].text.should == "hoge"
|
145
|
+
end
|
146
|
+
|
147
|
+
after do
|
148
|
+
@http_mock = nil
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
describe "Atnd4r::make_query が、引数なしのパラメータを解析するとき" do
|
154
|
+
it "は、文字列を返す事" do
|
155
|
+
query = Atnd4r::make_query()
|
156
|
+
query.class.should == String
|
157
|
+
end
|
158
|
+
|
159
|
+
it "は、内容はformatパラメータ文字列になっていること" do
|
160
|
+
query = Atnd4r::make_query()
|
161
|
+
query.should == "format=xml"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe "Atnd4r::make_query がひとつのkey&valueのパラメータを解析するとき" do
|
166
|
+
it "は、Keyがシンボルでも文字列を返す事" do
|
167
|
+
query = Atnd4r::make_query({:key => "value"})
|
168
|
+
query.should == "key=value&format=xml"
|
169
|
+
end
|
170
|
+
|
171
|
+
it "は、Keyが文字列でも文字列を返す事" do
|
172
|
+
query = Atnd4r::make_query({"key" => "value"})
|
173
|
+
query.should == "key=value&format=xml"
|
174
|
+
end
|
175
|
+
|
176
|
+
it "は、Keyやvalueにスペースが混じっている場合除去された文字列を返す事" do
|
177
|
+
query = Atnd4r::make_query({" key " => " value "})
|
178
|
+
query.should == "key=value&format=xml"
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe "Atnd4r::make_query がひとつのkey 対して複数valueのパラメータを解析するとき" do
|
183
|
+
it "は、値が複数の場合は、カンマ区切りになるよ" do
|
184
|
+
query = Atnd4r::make_query({"key" => ["value1", "value2"]})
|
185
|
+
query.should == "key=value1,value2&format=xml"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe "Atnd4r::make_query がひとつのkey 対してvalueが nil のとき" do
|
190
|
+
it "は、値が空文字になるよ" do
|
191
|
+
query = Atnd4r::make_query({"key" => nil})
|
192
|
+
query.should == "key=&format=xml"
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe "Atnd4r::parse_users_xml XML がエラーメッセージだったとき" do
|
197
|
+
xml_string = "<hash><error><message>error!</message></error></hash>"
|
198
|
+
doc = REXML::Document.new xml_string
|
199
|
+
|
200
|
+
it "は、例外 ATNDParameterError が発生する" do
|
201
|
+
lambda {
|
202
|
+
Atnd4r.parse_users_xml(doc)
|
203
|
+
}.should raise_error(Atnd4r::ATNDParameterError, /error!/)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
describe "Atnd4r::parse_common_xml が正常に処理したとき" do
|
208
|
+
xml_string =<<-EOF
|
209
|
+
<hash>
|
210
|
+
<results-returned type="integer">1</results-returned>
|
211
|
+
<results-available type="integer">2</results-available>
|
212
|
+
<results-start type="integer">3</results-start>
|
213
|
+
</hash>
|
214
|
+
EOF
|
215
|
+
doc = REXML::Document.new xml_string
|
216
|
+
|
217
|
+
events = Atnd4r::parse_common_xml(doc)
|
218
|
+
it "は、AtndAPIオブジェクトの内容として、result_xxx の値を持っている事" do
|
219
|
+
events.results_returned.should == 1
|
220
|
+
events.results_available.should == 2
|
221
|
+
events.results_start.should == 3
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
|
226
|
+
describe "Atnd4r::parse_users_xml が正常に処理したとき" do
|
227
|
+
xml_string =<<-EOF
|
228
|
+
<hash>
|
229
|
+
<results-returned type="integer">1</results-returned>
|
230
|
+
<results-available type="integer">1</results-available>
|
231
|
+
<events type="array">
|
232
|
+
<event>
|
233
|
+
<accepted type="integer">1</accepted>
|
234
|
+
<event-id type="integer">1</event-id>
|
235
|
+
<updated-at type="datetime">2009-01-01T00:00:00+09:00</updated-at>
|
236
|
+
<title>hoge event</title>
|
237
|
+
<waiting type="integer">0</waiting>
|
238
|
+
<event-url>hoge.com</event-url>
|
239
|
+
<users type="array">
|
240
|
+
<user>
|
241
|
+
<status type="integer">1</status>
|
242
|
+
<nickname>name</nickname>
|
243
|
+
<user-id type="integer">1</user-id>
|
244
|
+
</user>
|
245
|
+
</users>
|
246
|
+
<limit type="integer">1</limit>
|
247
|
+
</event>
|
248
|
+
</events>
|
249
|
+
<results-start type="integer">1</results-start>
|
250
|
+
</hash>
|
251
|
+
EOF
|
252
|
+
doc = REXML::Document.new xml_string
|
253
|
+
|
254
|
+
it "は、入力されたイベントの値がそのまま取得できる" do
|
255
|
+
events = Atnd4r.parse_users_xml(doc)
|
256
|
+
events.length.should == 1
|
257
|
+
events[0].accepted.should == 1
|
258
|
+
events[0].event_id.should == 1
|
259
|
+
events[0].updated_at.should == Time.parse("2009-01-01T00:00:00+09:00")
|
260
|
+
events[0].title.should == "hoge event"
|
261
|
+
events[0].waiting.should == 0
|
262
|
+
events[0].event_url.should == "hoge.com"
|
263
|
+
events[0].limit.should == 1
|
264
|
+
end
|
265
|
+
|
266
|
+
it "は、入力されたユーザの値がそのまま取得できる" do
|
267
|
+
events = Atnd4r.parse_users_xml(doc)
|
268
|
+
events[0].users.length.should == 1
|
269
|
+
events[0].users[0].status.should == 1
|
270
|
+
events[0].users[0].nickname.should == "name"
|
271
|
+
events[0].users[0].user_id.should == 1
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
|
276
|
+
describe "Atnd4r::parse_events_xml が正常に処理したとき" do
|
277
|
+
xml_string =<<-EOF
|
278
|
+
<hash>
|
279
|
+
<results-returned type="integer">1</results-returned>
|
280
|
+
<results-available type="integer">1</results-available>
|
281
|
+
<events type="array">
|
282
|
+
<event>
|
283
|
+
<place/>
|
284
|
+
<lon type="decimal">0.0</lon>
|
285
|
+
<accepted type="integer">1</accepted>
|
286
|
+
<event-id type="integer">1</event-id>
|
287
|
+
<updated-at type="datetime">2009-01-01T11:11:11+09:00</updated-at>
|
288
|
+
<title>hoge event</title>
|
289
|
+
<ended-at nil="true"/>
|
290
|
+
<waiting type="integer">0</waiting>
|
291
|
+
<event-url>hoge.com</event-url>
|
292
|
+
<url nil="true"/>
|
293
|
+
<owner-nickname>name</owner-nickname>
|
294
|
+
<catch>catch</catch>
|
295
|
+
<description>description</description>
|
296
|
+
<owner-id type="integer">1</owner-id>
|
297
|
+
<limit type="integer">1</limit>
|
298
|
+
<lat nil="true"/>
|
299
|
+
<address/>
|
300
|
+
<started-at type="datetime">2009-01-01T00:00:00+09:00</started-at>
|
301
|
+
</event>
|
302
|
+
</events>
|
303
|
+
<results-start type="integer">1</results-start>
|
304
|
+
</hash>
|
305
|
+
EOF
|
306
|
+
doc = REXML::Document.new xml_string
|
307
|
+
|
308
|
+
it "は、入力されたイベントの値がそのまま取得できる" do
|
309
|
+
events = Atnd4r.parse_events_xml(doc)
|
310
|
+
events.length.should == 1
|
311
|
+
events[0].lon.should == 0.0
|
312
|
+
events[0].accepted.should == 1
|
313
|
+
events[0].event_id.should == 1
|
314
|
+
events[0].updated_at.should == Time.parse("2009-01-01T11:11:11+09:00")
|
315
|
+
events[0].started_at.should == Time.parse("2009-01-01T00:00:00+09:00")
|
316
|
+
events[0].title.should == "hoge event"
|
317
|
+
events[0].waiting.should == 0
|
318
|
+
events[0].event_url.should == "hoge.com"
|
319
|
+
events[0].url.should == nil
|
320
|
+
events[0].owner_nickname.should == "name"
|
321
|
+
events[0].owner_id.should == 1
|
322
|
+
events[0].description.should == "description"
|
323
|
+
events[0].catch.should == "catch"
|
324
|
+
events[0].lat.should == nil
|
325
|
+
events[0].address.should == nil
|
326
|
+
events[0].limit.should == 1
|
327
|
+
end
|
328
|
+
|
329
|
+
end
|
330
|
+
|
331
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec'
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
4
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
5
|
+
require 'atnd4r'
|
6
|
+
|
7
|
+
Spec::Runner.configure do |config|
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
# HTTP MOCK
|
12
|
+
def create_http_mock(body = "", code = "", status = "")
|
13
|
+
@response_mock = mock(Net::HTTPResponse)
|
14
|
+
@response_mock.stub!(:body).and_return(body)
|
15
|
+
@response_mock.stub!(:code).and_return(code)
|
16
|
+
@response_mock.stub!(:[]).and_return(status)
|
17
|
+
@http_mock = mock('http')
|
18
|
+
@http_mock.stub!(:get).and_return(@response_mock)
|
19
|
+
|
20
|
+
return @http_mock
|
21
|
+
end
|
22
|
+
|
metadata
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: atnd4r
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.6
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- sugamasao
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-07-28 00:00:00 +09:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: sugamasao@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- ChangeLog
|
24
|
+
- README.rdoc
|
25
|
+
files:
|
26
|
+
- .document
|
27
|
+
- .gitignore
|
28
|
+
- ChangeLog
|
29
|
+
- README.rdoc
|
30
|
+
- Rakefile
|
31
|
+
- VERSION
|
32
|
+
- atnd4r.gemspec
|
33
|
+
- lib/atnd4r.rb
|
34
|
+
- spec/atnd4r_spec.rb
|
35
|
+
- spec/spec_helper.rb
|
36
|
+
has_rdoc: true
|
37
|
+
homepage: http://github.com/sugamasao/atnd4r
|
38
|
+
licenses: []
|
39
|
+
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options:
|
42
|
+
- --charset=UTF-8
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: "0"
|
50
|
+
version:
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
version:
|
57
|
+
requirements: []
|
58
|
+
|
59
|
+
rubyforge_project:
|
60
|
+
rubygems_version: 1.3.5
|
61
|
+
signing_key:
|
62
|
+
specification_version: 3
|
63
|
+
summary: !binary |
|
64
|
+
QVRORCDjga4gQVBJIOOCkiBSdWJ5IOOBi+OCieS9v+eUqOOBmeOCi+OBn+OB
|
65
|
+
ruODqeODg+ODkeODvOOCr+ODqeOCueOBp+OBmQ==
|
66
|
+
|
67
|
+
test_files:
|
68
|
+
- spec/atnd4r_spec.rb
|
69
|
+
- spec/spec_helper.rb
|