gnip 0.4.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/README +144 -0
- data/Rakefile +53 -0
- data/TODO +72 -0
- data/bin/gnip +651 -0
- data/doc/api.html +1201 -0
- data/gemspec.rb +47 -0
- data/gnip-0.4.2.gem +0 -0
- data/lib/gnip.rb +71 -0
- data/lib/gnip/activity.rb +663 -0
- data/lib/gnip/api.rb +191 -0
- data/lib/gnip/arguments.rb +21 -0
- data/lib/gnip/blankslate.rb +5 -0
- data/lib/gnip/config.rb +144 -0
- data/lib/gnip/filter.rb +304 -0
- data/lib/gnip/list.rb +126 -0
- data/lib/gnip/options.rb +96 -0
- data/lib/gnip/orderedhash.rb +199 -0
- data/lib/gnip/publisher.rb +309 -0
- data/lib/gnip/resource.rb +301 -0
- data/lib/gnip/template.rb +44 -0
- data/lib/gnip/util.rb +120 -0
- data/sample/data/activity.yml +21 -0
- data/test/auth.rb +60 -0
- data/test/config.yml +2 -0
- data/test/data/activity.xml +14 -0
- data/test/data/activity_only_required.xml +4 -0
- data/test/data/activity_with_payload.xml +22 -0
- data/test/data/activity_with_place.xml +18 -0
- data/test/data/activity_with_place_wo_bounds.xml +36 -0
- data/test/data/activity_with_unbounded_media_urls.xml +44 -0
- data/test/data/activity_without_bounds.xml +24 -0
- data/test/helper.rb +115 -0
- data/test/helper.rb.bak +28 -0
- data/test/integration/auth.rb +12 -0
- data/test/integration/publisher.rb +86 -0
- data/test/lib/shoulda.rb +9 -0
- data/test/lib/shoulda/action_controller.rb +28 -0
- data/test/lib/shoulda/action_controller/helpers.rb +47 -0
- data/test/lib/shoulda/action_controller/macros.rb +277 -0
- data/test/lib/shoulda/action_controller/matchers.rb +37 -0
- data/test/lib/shoulda/action_controller/matchers/assign_to_matcher.rb +109 -0
- data/test/lib/shoulda/action_controller/matchers/filter_param_matcher.rb +57 -0
- data/test/lib/shoulda/action_controller/matchers/render_with_layout_matcher.rb +81 -0
- data/test/lib/shoulda/action_controller/matchers/respond_with_content_type_matcher.rb +70 -0
- data/test/lib/shoulda/action_controller/matchers/respond_with_matcher.rb +77 -0
- data/test/lib/shoulda/action_controller/matchers/route_matcher.rb +93 -0
- data/test/lib/shoulda/action_controller/matchers/set_session_matcher.rb +83 -0
- data/test/lib/shoulda/action_controller/matchers/set_the_flash_matcher.rb +85 -0
- data/test/lib/shoulda/action_mailer.rb +10 -0
- data/test/lib/shoulda/action_mailer/assertions.rb +38 -0
- data/test/lib/shoulda/action_view.rb +10 -0
- data/test/lib/shoulda/action_view/macros.rb +56 -0
- data/test/lib/shoulda/active_record.rb +16 -0
- data/test/lib/shoulda/active_record/assertions.rb +69 -0
- data/test/lib/shoulda/active_record/helpers.rb +40 -0
- data/test/lib/shoulda/active_record/macros.rb +586 -0
- data/test/lib/shoulda/active_record/matchers.rb +42 -0
- data/test/lib/shoulda/active_record/matchers/allow_mass_assignment_of_matcher.rb +83 -0
- data/test/lib/shoulda/active_record/matchers/allow_value_matcher.rb +102 -0
- data/test/lib/shoulda/active_record/matchers/association_matcher.rb +226 -0
- data/test/lib/shoulda/active_record/matchers/ensure_inclusion_of_matcher.rb +87 -0
- data/test/lib/shoulda/active_record/matchers/ensure_length_of_matcher.rb +141 -0
- data/test/lib/shoulda/active_record/matchers/have_db_column_matcher.rb +169 -0
- data/test/lib/shoulda/active_record/matchers/have_index_matcher.rb +105 -0
- data/test/lib/shoulda/active_record/matchers/have_named_scope_matcher.rb +125 -0
- data/test/lib/shoulda/active_record/matchers/have_readonly_attribute_matcher.rb +59 -0
- data/test/lib/shoulda/active_record/matchers/validate_acceptance_of_matcher.rb +41 -0
- data/test/lib/shoulda/active_record/matchers/validate_numericality_of_matcher.rb +39 -0
- data/test/lib/shoulda/active_record/matchers/validate_presence_of_matcher.rb +60 -0
- data/test/lib/shoulda/active_record/matchers/validate_uniqueness_of_matcher.rb +148 -0
- data/test/lib/shoulda/active_record/matchers/validation_matcher.rb +56 -0
- data/test/lib/shoulda/assertions.rb +59 -0
- data/test/lib/shoulda/autoload_macros.rb +46 -0
- data/test/lib/shoulda/context.rb +304 -0
- data/test/lib/shoulda/helpers.rb +8 -0
- data/test/lib/shoulda/macros.rb +73 -0
- data/test/lib/shoulda/private_helpers.rb +20 -0
- data/test/lib/shoulda/proc_extensions.rb +14 -0
- data/test/lib/shoulda/rails.rb +13 -0
- data/test/lib/shoulda/rspec.rb +9 -0
- data/test/lib/shoulda/tasks.rb +3 -0
- data/test/lib/shoulda/tasks/list_tests.rake +29 -0
- data/test/lib/shoulda/tasks/yaml_to_shoulda.rake +28 -0
- data/test/lib/shoulda/test_unit.rb +19 -0
- data/test/lib/xmlsimple.rb +1021 -0
- data/test/loader.rb +25 -0
- data/test/unit/activity.rb +26 -0
- data/test/unit/util.rb +39 -0
- metadata +198 -0
data/lib/gnip/list.rb
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
module Gnip
|
|
2
|
+
# a typed list of objects
|
|
3
|
+
#
|
|
4
|
+
class List
|
|
5
|
+
include Enumerable
|
|
6
|
+
include Comparable
|
|
7
|
+
|
|
8
|
+
def List.for(klass, *args, &block)
|
|
9
|
+
new(klass, *args, &block)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def List.of(klass, *args, &block)
|
|
13
|
+
new(klass, *args, &block)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
attr :list
|
|
17
|
+
attr :klass
|
|
18
|
+
|
|
19
|
+
def initialize(klass, *args, &block)
|
|
20
|
+
@list = []
|
|
21
|
+
@klass = klass
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def new(*args, &block)
|
|
25
|
+
if klass.respond_to?(:for)
|
|
26
|
+
klass.for(*args, &block)
|
|
27
|
+
else
|
|
28
|
+
klass.new(*args, &block)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def cast(value)
|
|
33
|
+
return value if value.is_a?(klass)
|
|
34
|
+
msg =
|
|
35
|
+
if klass.respond_to?(:cast)
|
|
36
|
+
:cast
|
|
37
|
+
elsif klass.respond_to?(:for)
|
|
38
|
+
:for
|
|
39
|
+
else
|
|
40
|
+
:new
|
|
41
|
+
end
|
|
42
|
+
klass.send(msg, value)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def build(*args, &block)
|
|
46
|
+
element = new(*args, &block)
|
|
47
|
+
list << element
|
|
48
|
+
element
|
|
49
|
+
end
|
|
50
|
+
alias_method 'create', 'build'
|
|
51
|
+
|
|
52
|
+
def push(value)
|
|
53
|
+
list << cast(value)
|
|
54
|
+
self
|
|
55
|
+
end
|
|
56
|
+
alias_method '<<', 'push'
|
|
57
|
+
|
|
58
|
+
def each(&block)
|
|
59
|
+
list.each(&block)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def map(&block)
|
|
63
|
+
list.map(&block)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def [](idx)
|
|
67
|
+
list[idx]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def inspect
|
|
71
|
+
"#{ self.class.name }.of(#{ klass.name })#{ list.inspect }"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def clear
|
|
75
|
+
list.clear
|
|
76
|
+
self
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def size
|
|
80
|
+
list.size
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def replace other
|
|
84
|
+
clear
|
|
85
|
+
case other
|
|
86
|
+
when List, Array
|
|
87
|
+
other.flatten.each{|value| push(value)}
|
|
88
|
+
else
|
|
89
|
+
push(other)
|
|
90
|
+
end
|
|
91
|
+
self
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def first
|
|
95
|
+
list.first
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def last
|
|
99
|
+
list.last
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def to_a
|
|
103
|
+
list
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def to_xs
|
|
107
|
+
to_a.map{|element| element.respond_to?(:to_xs) ? element.to_xs : element}
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def method_missing(m, *a, &b)
|
|
111
|
+
if list.respond_to?(m)
|
|
112
|
+
list.send(m, *a, &b)
|
|
113
|
+
else
|
|
114
|
+
super
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def to_yaml(*a, &b)
|
|
119
|
+
list.to_yaml(*a, &b)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def <=> other
|
|
123
|
+
list <=> other
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
data/lib/gnip/options.rb
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
module Gnip
|
|
2
|
+
module Options
|
|
3
|
+
def to_options!
|
|
4
|
+
replace to_options
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def to_options
|
|
8
|
+
keys.inject(Hash.new){|h,k| h.update k.to_s.to_sym => fetch(k)}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def getopt key, default = nil
|
|
12
|
+
[ key ].flatten.each do |key|
|
|
13
|
+
return fetch(key) if has_key?(key)
|
|
14
|
+
key = key.to_s
|
|
15
|
+
return fetch(key) if has_key?(key)
|
|
16
|
+
key = key.to_sym
|
|
17
|
+
return fetch(key) if has_key?(key)
|
|
18
|
+
end
|
|
19
|
+
default
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def getopts *args
|
|
23
|
+
args.flatten.map{|arg| getopt arg}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def hasopt key, default = nil
|
|
27
|
+
[ key ].flatten.each do |key|
|
|
28
|
+
return true if has_key?(key)
|
|
29
|
+
key = key.to_s
|
|
30
|
+
return true if has_key?(key)
|
|
31
|
+
key = key.to_sym
|
|
32
|
+
return true if has_key?(key)
|
|
33
|
+
end
|
|
34
|
+
default
|
|
35
|
+
end
|
|
36
|
+
alias_method 'hasopt?', 'hasopt'
|
|
37
|
+
|
|
38
|
+
def hasopts *args
|
|
39
|
+
args.flatten.map{|arg| hasopt arg}
|
|
40
|
+
end
|
|
41
|
+
alias_method 'hasopts?', 'hasopts'
|
|
42
|
+
|
|
43
|
+
def delopt key, default = nil
|
|
44
|
+
[ key ].flatten.each do |key|
|
|
45
|
+
return delete(key) if has_key?(key)
|
|
46
|
+
key = key.to_s
|
|
47
|
+
return delete(key) if has_key?(key)
|
|
48
|
+
key = key.to_sym
|
|
49
|
+
return delete(key) if has_key?(key)
|
|
50
|
+
end
|
|
51
|
+
default
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def delopts *args
|
|
55
|
+
args.flatten.map{|arg| delopt arg}
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def setopt key, value = nil
|
|
59
|
+
[ key ].flatten.each do |key|
|
|
60
|
+
return self[key]=value if has_key?(key)
|
|
61
|
+
key = key.to_s
|
|
62
|
+
return self[key]=value if has_key?(key)
|
|
63
|
+
key = key.to_sym
|
|
64
|
+
return self[key]=value if has_key?(key)
|
|
65
|
+
end
|
|
66
|
+
return self[key]=value
|
|
67
|
+
end
|
|
68
|
+
alias_method 'setopt!', 'setopt'
|
|
69
|
+
|
|
70
|
+
def setopts opts
|
|
71
|
+
opts.each{|key, value| setopt key, value}
|
|
72
|
+
opts
|
|
73
|
+
end
|
|
74
|
+
alias_method 'setopts!', 'setopts'
|
|
75
|
+
|
|
76
|
+
def select! *a, &b
|
|
77
|
+
replace select(*a, &b).to_hash
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def Options.for(hash)
|
|
82
|
+
hash =
|
|
83
|
+
case hash
|
|
84
|
+
when Hash
|
|
85
|
+
hash
|
|
86
|
+
when Array
|
|
87
|
+
Hash[*hash.flatten]
|
|
88
|
+
when String, Symbol
|
|
89
|
+
{hash => true}
|
|
90
|
+
else
|
|
91
|
+
hash.to_hash
|
|
92
|
+
end
|
|
93
|
+
ensure
|
|
94
|
+
hash.extend(Options) unless hash.is_a?(Options)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
|
|
2
|
+
# AUTHOR
|
|
3
|
+
# jan molic /mig/at/1984/dot/cz/
|
|
4
|
+
#
|
|
5
|
+
# DESCRIPTION
|
|
6
|
+
# Hash with preserved order and some array-like extensions
|
|
7
|
+
# Public domain.
|
|
8
|
+
#
|
|
9
|
+
# THANKS
|
|
10
|
+
# Andrew Johnson for his suggestions and fixes of Hash[],
|
|
11
|
+
# merge, to_a, inspect and shift
|
|
12
|
+
|
|
13
|
+
module Gnip
|
|
14
|
+
class OrderedHash < ::Hash
|
|
15
|
+
attr_accessor :order
|
|
16
|
+
|
|
17
|
+
class << self
|
|
18
|
+
def [] *args
|
|
19
|
+
hsh = OrderedHash.new
|
|
20
|
+
if Hash === args[0]
|
|
21
|
+
hsh.replace args[0]
|
|
22
|
+
elsif (args.size % 2) != 0
|
|
23
|
+
raise ArgumentError, "odd number of elements for Hash"
|
|
24
|
+
else
|
|
25
|
+
0.step(args.size - 1, 2) do |a|
|
|
26
|
+
b = a + 1
|
|
27
|
+
hsh[args[a]] = args[b]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
hsh
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
def initialize(*a, &b)
|
|
34
|
+
super
|
|
35
|
+
@order = []
|
|
36
|
+
end
|
|
37
|
+
def store_only a,b
|
|
38
|
+
store a,b
|
|
39
|
+
end
|
|
40
|
+
alias orig_store store
|
|
41
|
+
def store a,b
|
|
42
|
+
@order.push a unless has_key? a
|
|
43
|
+
super a,b
|
|
44
|
+
end
|
|
45
|
+
alias []= store
|
|
46
|
+
def == hsh2
|
|
47
|
+
return false if @order != hsh2.order
|
|
48
|
+
super hsh2
|
|
49
|
+
end
|
|
50
|
+
def clear
|
|
51
|
+
@order = []
|
|
52
|
+
super
|
|
53
|
+
end
|
|
54
|
+
def delete key
|
|
55
|
+
@order.delete key
|
|
56
|
+
super
|
|
57
|
+
end
|
|
58
|
+
def each_key
|
|
59
|
+
@order.each { |k| yield k }
|
|
60
|
+
self
|
|
61
|
+
end
|
|
62
|
+
def each_value
|
|
63
|
+
@order.each { |k| yield self[k] }
|
|
64
|
+
self
|
|
65
|
+
end
|
|
66
|
+
def each
|
|
67
|
+
@order.each { |k| yield k,self[k] }
|
|
68
|
+
self
|
|
69
|
+
end
|
|
70
|
+
alias each_pair each
|
|
71
|
+
def delete_if
|
|
72
|
+
@order.clone.each { |k|
|
|
73
|
+
delete k if yield(k)
|
|
74
|
+
}
|
|
75
|
+
self
|
|
76
|
+
end
|
|
77
|
+
def values
|
|
78
|
+
ary = []
|
|
79
|
+
@order.each { |k| ary.push self[k] }
|
|
80
|
+
ary
|
|
81
|
+
end
|
|
82
|
+
def keys
|
|
83
|
+
@order
|
|
84
|
+
end
|
|
85
|
+
def first
|
|
86
|
+
{@order.first => self[@order.first]}
|
|
87
|
+
end
|
|
88
|
+
def last
|
|
89
|
+
{@order.last => self[@order.last]}
|
|
90
|
+
end
|
|
91
|
+
def invert
|
|
92
|
+
hsh2 = Hash.new
|
|
93
|
+
@order.each { |k| hsh2[self[k]] = k }
|
|
94
|
+
hsh2
|
|
95
|
+
end
|
|
96
|
+
def reject(&block)
|
|
97
|
+
self.dup.delete_if(&block)
|
|
98
|
+
end
|
|
99
|
+
def reject!(&block)
|
|
100
|
+
hsh2 = reject(&block)
|
|
101
|
+
self == hsh2 ? nil : hsh2
|
|
102
|
+
end
|
|
103
|
+
def replace hsh2
|
|
104
|
+
@order = hsh2.keys
|
|
105
|
+
super hsh2
|
|
106
|
+
end
|
|
107
|
+
def shift
|
|
108
|
+
key = @order.first
|
|
109
|
+
key ? [key,delete(key)] : super
|
|
110
|
+
end
|
|
111
|
+
def unshift k,v
|
|
112
|
+
unless self.include? k
|
|
113
|
+
@order.unshift k
|
|
114
|
+
orig_store(k,v)
|
|
115
|
+
true
|
|
116
|
+
else
|
|
117
|
+
false
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
def push k,v
|
|
121
|
+
unless self.include? k
|
|
122
|
+
@order.push k
|
|
123
|
+
orig_store(k,v)
|
|
124
|
+
true
|
|
125
|
+
else
|
|
126
|
+
false
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
def pop
|
|
130
|
+
key = @order.last
|
|
131
|
+
key ? [key,delete(key)] : nil
|
|
132
|
+
end
|
|
133
|
+
def to_a
|
|
134
|
+
ary = []
|
|
135
|
+
each { |k,v| ary << [k,v] }
|
|
136
|
+
ary
|
|
137
|
+
end
|
|
138
|
+
def to_s
|
|
139
|
+
self.to_a.to_s
|
|
140
|
+
end
|
|
141
|
+
def inspect
|
|
142
|
+
ary = []
|
|
143
|
+
each {|k,v| ary << k.inspect + "=>" + v.inspect}
|
|
144
|
+
'{' + ary.join(", ") + '}'
|
|
145
|
+
end
|
|
146
|
+
def update hsh2
|
|
147
|
+
hsh2.each { |k,v| self[k] = v }
|
|
148
|
+
self
|
|
149
|
+
end
|
|
150
|
+
alias :merge! update
|
|
151
|
+
def merge hsh2
|
|
152
|
+
self.dup update(hsh2)
|
|
153
|
+
end
|
|
154
|
+
def select
|
|
155
|
+
ary = []
|
|
156
|
+
each { |k,v| ary << [k,v] if yield k,v }
|
|
157
|
+
ary
|
|
158
|
+
end
|
|
159
|
+
def class
|
|
160
|
+
Hash
|
|
161
|
+
end
|
|
162
|
+
def __class__
|
|
163
|
+
OrderedHash
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
attr_accessor "to_yaml_style"
|
|
167
|
+
def yaml_inline= bool
|
|
168
|
+
if respond_to?("to_yaml_style")
|
|
169
|
+
self.to_yaml_style = :inline
|
|
170
|
+
else
|
|
171
|
+
unless defined? @__yaml_inline_meth
|
|
172
|
+
@__yaml_inline_meth =
|
|
173
|
+
lambda {|opts|
|
|
174
|
+
YAML::quick_emit(object_id, opts) {|emitter|
|
|
175
|
+
emitter << '{ ' << map{|kv| kv.join ': '}.join(', ') << ' }'
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
class << self
|
|
179
|
+
def to_yaml opts = {}
|
|
180
|
+
begin
|
|
181
|
+
@__yaml_inline ? @__yaml_inline_meth[ opts ] : super
|
|
182
|
+
rescue
|
|
183
|
+
@to_yaml_style = :inline
|
|
184
|
+
super
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
@__yaml_inline = bool
|
|
191
|
+
end
|
|
192
|
+
def yaml_inline!() self.yaml_inline = true end
|
|
193
|
+
|
|
194
|
+
def each_with_index
|
|
195
|
+
@order.each_with_index { |k, index| yield k, self[k], index }
|
|
196
|
+
self
|
|
197
|
+
end
|
|
198
|
+
end # class OrderedHash
|
|
199
|
+
end
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
module Gnip
|
|
2
|
+
class Publisher
|
|
3
|
+
def Publisher.list(options = {})
|
|
4
|
+
options = Gnip.optify!(options)
|
|
5
|
+
scope = options.getopt(:scope, Gnip.scope)
|
|
6
|
+
resource = options.getopt(:resource, Gnip.default.resource)
|
|
7
|
+
endpoint = resource.endpoint "#{ scope }/publishers.xml"
|
|
8
|
+
response = endpoint.get
|
|
9
|
+
xml = response.to_s
|
|
10
|
+
Publisher.list_from_xml(xml, :scope => scope)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def Publisher.list_from_xml(xml, options = {}, &block)
|
|
14
|
+
list = []
|
|
15
|
+
parse_xml(xml, options) do |publisher|
|
|
16
|
+
block ? block.call(publisher) : list.push(publisher)
|
|
17
|
+
end
|
|
18
|
+
block ? nil : list
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def Publisher.from_xml(xml, options = {}, &block)
|
|
22
|
+
parse_xml(xml, options){|publisher| return publisher}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def Publisher.parse_xml(xml, options = {}, &block)
|
|
26
|
+
doc = Nokogiri::XML.parse(xml)
|
|
27
|
+
list = []
|
|
28
|
+
selectors = '*/publishers', 'publisher'
|
|
29
|
+
selectors.each do |selector|
|
|
30
|
+
search = doc.search(selector)
|
|
31
|
+
next unless search.size > 0
|
|
32
|
+
search.each do |node|
|
|
33
|
+
publisher = Publisher.from_node(node, options)
|
|
34
|
+
block ? block.call(publisher) : list.push(publisher)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
block ? nil : list
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def Publisher.from_node(node, options = {})
|
|
41
|
+
name = node['name']
|
|
42
|
+
rules = node.search('supportedRuleTypes/type').map{|type| type.content}
|
|
43
|
+
Publisher.new(name, options.update(:rules => rules))
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def Publisher.for name, options = {}
|
|
47
|
+
options = Gnip.optify!(options)
|
|
48
|
+
scope = options.getopt(:scope, Gnip.scope)
|
|
49
|
+
resource = options.getopt(:resource, Gnip.default.resource)
|
|
50
|
+
endpoint = resource["#{ scope }/publishers/#{ name }.xml"]
|
|
51
|
+
response = endpoint.get
|
|
52
|
+
xml = response.to_s
|
|
53
|
+
publisher = Publisher.from_xml(xml)
|
|
54
|
+
publisher.scope = scope
|
|
55
|
+
publisher
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def Publisher.exists?(*args, &block)
|
|
59
|
+
Publisher.for(*args, &block) rescue false
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def Publisher.resource
|
|
63
|
+
@resource ||= Gnip.default.resource
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def Publisher.create(*args, &block)
|
|
67
|
+
publisher = new(*args, &block)
|
|
68
|
+
resource = Publisher.resource["#{ publisher.scope }/publishers.xml"]
|
|
69
|
+
resource.post(publisher.to_xml(:declaration => true))
|
|
70
|
+
Publisher.for(publisher.name, :scope => publisher.scope)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def Publisher.delete(name, options = {})
|
|
74
|
+
if publisher = Publisher.exists?(name, options)
|
|
75
|
+
publisher.delete
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
Attributes = []
|
|
80
|
+
|
|
81
|
+
Attributes << 'name'
|
|
82
|
+
def name
|
|
83
|
+
@name ||= nil
|
|
84
|
+
end
|
|
85
|
+
def name= value
|
|
86
|
+
@name = String(value)
|
|
87
|
+
ensure
|
|
88
|
+
raise ArgumentError, @name unless @name =~ %r/^[a-zA-Z0-9.+-]+$/
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
Attributes << 'rules'
|
|
92
|
+
def rules
|
|
93
|
+
@rules ||= List.of(String)
|
|
94
|
+
end
|
|
95
|
+
def rules= value
|
|
96
|
+
rules.replace(value)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
attr_accessor :scope
|
|
100
|
+
|
|
101
|
+
def initialize(*args)
|
|
102
|
+
args, options = Gnip.args_for(args)
|
|
103
|
+
self.name = args.shift if args.first
|
|
104
|
+
@scope = options.getopt(:scope, Gnip.scope).to_s
|
|
105
|
+
@resource = options.getopt(:resource, Gnip.default.resource)
|
|
106
|
+
rules = options.getopt(:rules, []).flatten.compact
|
|
107
|
+
@rules = rules.map{|rule| Rule.for(rule)}
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def resource
|
|
111
|
+
@resource["#{ scope }/publishers/#{ name }"]
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class Rule < ::String
|
|
117
|
+
List = []
|
|
118
|
+
|
|
119
|
+
%w[ actor tag to regarding source keyword ].each do |name|
|
|
120
|
+
module_eval <<-code
|
|
121
|
+
def Rule.#{ name }
|
|
122
|
+
@#{ name } ||= Rule.new('#{ name }').freeze
|
|
123
|
+
end
|
|
124
|
+
code
|
|
125
|
+
List << Rule.send(name)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
List.freeze
|
|
129
|
+
|
|
130
|
+
def Rule.list
|
|
131
|
+
List
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def Rule.for(name)
|
|
135
|
+
send(name.to_s.downcase.strip)
|
|
136
|
+
rescue
|
|
137
|
+
raise ArgumentError, "bad rule type #{ name.inspect }"
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def Rule.[] name
|
|
141
|
+
Rule.for(name)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def Publisher.rule
|
|
146
|
+
Rule
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
include Tagz
|
|
150
|
+
def to_xml(*args)
|
|
151
|
+
args, options = Gnip.args_for(args)
|
|
152
|
+
doc = args.first
|
|
153
|
+
|
|
154
|
+
tagz(doc) {
|
|
155
|
+
publisher_(:name => name){
|
|
156
|
+
supportedRuleTypes_{
|
|
157
|
+
rules.each{|rule| type_{ rule }}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
=begin
|
|
164
|
+
def Publisher.template
|
|
165
|
+
@template ||=
|
|
166
|
+
Template.new do
|
|
167
|
+
"
|
|
168
|
+
<publisher name=<%= name.inspect %>>
|
|
169
|
+
<supportedRuleTypes>
|
|
170
|
+
% rules.each do |rule|
|
|
171
|
+
<type><%= rule %></type>
|
|
172
|
+
% end
|
|
173
|
+
</supportedRuleTypes>
|
|
174
|
+
</publisher>
|
|
175
|
+
"
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def to_xml(options = {})
|
|
180
|
+
Publisher.template.expand(self)
|
|
181
|
+
end
|
|
182
|
+
=end
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def delete
|
|
186
|
+
Publisher.resource["#{ scope }/publishers/#{ name }"].delete
|
|
187
|
+
self
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def activity_stream options = {}
|
|
191
|
+
Activity.stream(options.update(:publisher => self, :scope => scope))
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def activity options = {}, &block
|
|
195
|
+
Gnip.optify!(options)
|
|
196
|
+
|
|
197
|
+
style = options.getopt(:style, 'activity').to_s
|
|
198
|
+
raise ArgumentError unless %w( activity notification ).include?(style)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
bucket = options.getopt(:bucket)
|
|
202
|
+
ago = options.getopt(:ago)
|
|
203
|
+
thru = options.getopt(:thru, options.getopt(:through))
|
|
204
|
+
|
|
205
|
+
if Range === ago
|
|
206
|
+
ago, thru = [ago.begin, ago.end].sort.reverse
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
unless bucket
|
|
210
|
+
bucket = ago ? bucket_for_minutes_ago(ago) : 'current'
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
filter = options.getopt(:filter)
|
|
214
|
+
filter = filter.value if(filter and filter.respond_to?(:value))
|
|
215
|
+
|
|
216
|
+
buckets =
|
|
217
|
+
if thru
|
|
218
|
+
thru = 0 if thru =~ /current|now/i
|
|
219
|
+
a, b = [ago, Integer(thru)].sort
|
|
220
|
+
(a..b).to_a.reverse.map{|i| bucket_for_minutes_ago(i)}
|
|
221
|
+
else
|
|
222
|
+
if bucket =~ /all/i
|
|
223
|
+
stream = send("#{ style }_stream")
|
|
224
|
+
stream.buckets.map{|bucket| File.basename(bucket, '.xml')}
|
|
225
|
+
else
|
|
226
|
+
[bucket]
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
activities = []
|
|
231
|
+
|
|
232
|
+
msg = buckets.size > 1 ? 'threadify' : 'each'
|
|
233
|
+
|
|
234
|
+
buckets.send(msg) do |bucket|
|
|
235
|
+
path = "#{ style }/#{ bucket }.xml"
|
|
236
|
+
path = "filters/#{ filter }/#{ path }" if filter
|
|
237
|
+
xml = resource[path].get
|
|
238
|
+
list = Activity.list_from_xml(xml, &block)
|
|
239
|
+
activities.push(*list) unless block
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
activities unless block
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def bucket_for_minutes_ago ago
|
|
246
|
+
bucket = Gnip.time - (Integer(ago) * 60)
|
|
247
|
+
bucket.strftime('%Y%m%d%H%M')
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def notification_stream options = {}
|
|
251
|
+
Activity.stream(options.update(:publisher => self, :scope => scope, :style => 'notification'))
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def notifications options = {}
|
|
255
|
+
Gnip.optify!(options)
|
|
256
|
+
options.setopt!(:style, 'notification') unless options.hasopt?(:style)
|
|
257
|
+
activity(options)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def publish *activities
|
|
261
|
+
activities.flatten!
|
|
262
|
+
activities.compact!
|
|
263
|
+
#xml = "<activiies>#{ activities.map{|activity| activity.to_xml} }</activities>"
|
|
264
|
+
xml = tagz { activities_{ activities.map{|activity| activity.to_xml(tagz.doc)} } }
|
|
265
|
+
resource['activity.xml'].post(xml)
|
|
266
|
+
activities
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def filter
|
|
271
|
+
@filter ||= FilterResource.new(self)
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
class FilterResource
|
|
275
|
+
attr_accessor :publisher
|
|
276
|
+
|
|
277
|
+
def initialize publisher
|
|
278
|
+
@publisher = publisher
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def resource
|
|
282
|
+
publisher.resource
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def list
|
|
286
|
+
xml = resource['filters.xml'].get
|
|
287
|
+
Filter.list_from_xml(xml).each{|filter| filter.publisher = publisher}
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def for name
|
|
291
|
+
xml = resource["filters/#{ name }.xml"].get
|
|
292
|
+
filter = Filter.from_xml(xml)
|
|
293
|
+
ensure
|
|
294
|
+
filter.publisher = publisher if filter
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
alias_method '[]', 'for'
|
|
298
|
+
|
|
299
|
+
def create(name, rules, options)
|
|
300
|
+
Gnip.optify!(options)
|
|
301
|
+
filter = Filter.new(name, rules, options)
|
|
302
|
+
resource['filters.xml'].post(filter.to_xml(:declaration => true))
|
|
303
|
+
filter = self.for(name)
|
|
304
|
+
ensure
|
|
305
|
+
filter.publisher = publisher if filter
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
end
|