tumblrb 1.0.6 → 2.0.1
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/.rvmrc +1 -0
- data/Gemfile +6 -3
- data/Gemfile.lock +46 -0
- data/README.mkd +51 -21
- data/lib/tumblr.rb +27 -26
- data/lib/tumblr/api.rb +49 -0
- data/lib/tumblr/blog.rb +97 -0
- data/lib/tumblr/config.rb +25 -0
- data/lib/tumblr/middleware/params.rb +10 -0
- data/lib/tumblr/middleware/parsing.rb +34 -0
- data/lib/tumblr/object.rb +172 -0
- data/lib/tumblr/objects/answer.rb +5 -0
- data/lib/tumblr/objects/audio.rb +6 -0
- data/lib/tumblr/objects/chat.rb +10 -0
- data/lib/tumblr/objects/link.rb +5 -0
- data/lib/tumblr/objects/photo.rb +22 -0
- data/lib/tumblr/objects/post.rb +89 -0
- data/lib/tumblr/objects/text.rb +5 -0
- data/lib/tumblr/objects/user.rb +7 -0
- data/lib/tumblr/objects/video.rb +11 -0
- data/lib/tumblr/query.rb +48 -0
- data/lib/tumblr/quote.rb +2 -18
- data/lib/tumblr/version.rb +1 -1
- data/tumblrb.gemspec +13 -25
- metadata +54 -25
- data/lib/tumblr/answer.rb +0 -21
- data/lib/tumblr/audio.rb +0 -21
- data/lib/tumblr/conversation.rb +0 -35
- data/lib/tumblr/item.rb +0 -110
- data/lib/tumblr/link.rb +0 -21
- data/lib/tumblr/page.rb +0 -39
- data/lib/tumblr/photo.rb +0 -37
- data/lib/tumblr/regular.rb +0 -21
- data/lib/tumblr/user.rb +0 -11
- data/lib/tumblr/video.rb +0 -23
@@ -0,0 +1,172 @@
|
|
1
|
+
module Tumblr
|
2
|
+
class Object
|
3
|
+
class << self
|
4
|
+
attr_accessor :page_size
|
5
|
+
|
6
|
+
def page_size
|
7
|
+
@page_size ||= 20
|
8
|
+
end
|
9
|
+
|
10
|
+
def unserialize(value)
|
11
|
+
value = JSON.parse(value)
|
12
|
+
systematize(value.first).build(value.last)
|
13
|
+
end
|
14
|
+
|
15
|
+
def systematize(string)
|
16
|
+
string = string.to_s.gsub(/^Tumblr::/, '')
|
17
|
+
"Tumblr::#{string.singularize.classify}".constantize rescue nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def objectify(hash)
|
21
|
+
objectified = {}
|
22
|
+
hash.keys.each do |key|
|
23
|
+
klass = systematize(key)
|
24
|
+
if klass
|
25
|
+
if hash[key].kind_of?(Array)
|
26
|
+
objectified[key] = hash[key].collect { |value| klass.build(value) }
|
27
|
+
else
|
28
|
+
objectified[key] = klass.build(hash[key])
|
29
|
+
end
|
30
|
+
else
|
31
|
+
objectified[key] = hash[key]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
objectified
|
35
|
+
end
|
36
|
+
|
37
|
+
def build(attributes)
|
38
|
+
object = new
|
39
|
+
attributes.each do |attribute, value|
|
40
|
+
if object.respond_to?("#{attribute}=")
|
41
|
+
object.send("#{attribute}=", value)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
object
|
45
|
+
end
|
46
|
+
|
47
|
+
def attributes
|
48
|
+
@attributes ||= Set.new
|
49
|
+
end
|
50
|
+
|
51
|
+
def string_attribute(*args)
|
52
|
+
attr_reader *args
|
53
|
+
args.each do |arg|
|
54
|
+
attributes << arg
|
55
|
+
define_method "#{arg}=" do |value|
|
56
|
+
set_attribute_value(arg, value.to_s)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def array_attribute(*args)
|
62
|
+
options = args.extract_options!
|
63
|
+
attr_reader *args
|
64
|
+
klass = systematize(options[:object]) if options[:object]
|
65
|
+
args.each do |arg|
|
66
|
+
attributes << arg
|
67
|
+
define_method "#{arg}=" do |value|
|
68
|
+
if klass
|
69
|
+
set_attribute_value(arg, value.to_a.collect { |params| klass.build(params) })
|
70
|
+
else
|
71
|
+
set_attribute_value(arg, value.to_a)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def boolean_attribute(*args)
|
78
|
+
attr_reader *args
|
79
|
+
args.each do |arg|
|
80
|
+
attributes << arg
|
81
|
+
define_method "#{arg}=" do |value|
|
82
|
+
set_attribute_value(arg, !!value)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def numeric_attribute(*args)
|
88
|
+
attr_reader *args
|
89
|
+
args.each do |arg|
|
90
|
+
attributes << arg
|
91
|
+
define_method "#{arg}=" do |value|
|
92
|
+
value = (value.to_i == value.to_f) ? value.to_i : value.to_f
|
93
|
+
set_attribute_value(arg, value)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def date_attribute(*args)
|
99
|
+
attr_reader *args
|
100
|
+
args.each do |arg|
|
101
|
+
attributes << arg
|
102
|
+
define_method "#{arg}=" do |value|
|
103
|
+
value = Time.at(value) if value.kind_of?(Fixnum)
|
104
|
+
value = Date.parse(value) rescue nil if value.kind_of?(String)
|
105
|
+
value ||= value
|
106
|
+
set_attribute_value(arg, value)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def object_attribute(*args)
|
112
|
+
attr_reader *args
|
113
|
+
options = args.extract_options!
|
114
|
+
klass = systematize(options[:object]) if options[:object]
|
115
|
+
args.each do |arg|
|
116
|
+
attributes << arg
|
117
|
+
define_method "#{arg}=" do |value|
|
118
|
+
set_attribute_value(arg, klass.build(value))
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def serialize
|
125
|
+
[self.class.to_s, as_json].to_json
|
126
|
+
end
|
127
|
+
|
128
|
+
def storage
|
129
|
+
@_storage ||= Redis::Value.new("#{Blog::STORAGE_KEY}:#{slug}", Tumblr.config.redis)
|
130
|
+
end
|
131
|
+
|
132
|
+
def commit
|
133
|
+
storage.value = serialize
|
134
|
+
end
|
135
|
+
|
136
|
+
def dom_class
|
137
|
+
self.class.to_s.split("::").last.underscore
|
138
|
+
end
|
139
|
+
|
140
|
+
def etag
|
141
|
+
Digest::SHA1.hexdigest(to_json)
|
142
|
+
end
|
143
|
+
|
144
|
+
def as_json
|
145
|
+
json = {}
|
146
|
+
self.class.attributes.each do |key|
|
147
|
+
json[key] = send(key)
|
148
|
+
end
|
149
|
+
json
|
150
|
+
end
|
151
|
+
|
152
|
+
def to_json(force=false)
|
153
|
+
@json = nil if force
|
154
|
+
@json ||= JSON.generate(as_json)
|
155
|
+
end
|
156
|
+
|
157
|
+
private
|
158
|
+
|
159
|
+
def set_attribute_value(key, value)
|
160
|
+
self.instance_variable_set("@#{key}", value)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
require 'tumblr/objects/user'
|
166
|
+
require 'tumblr/objects/post'
|
167
|
+
require 'tumblr/objects/audio'
|
168
|
+
require 'tumblr/objects/chat'
|
169
|
+
require 'tumblr/objects/link'
|
170
|
+
require 'tumblr/objects/photo'
|
171
|
+
require 'tumblr/objects/text'
|
172
|
+
require 'tumblr/objects/video'
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Tumblr
|
2
|
+
class Photo < Post
|
3
|
+
array_attribute :photos
|
4
|
+
array_attribute :sizes
|
5
|
+
string_attribute :caption
|
6
|
+
numeric_attribute :width, :height
|
7
|
+
|
8
|
+
class Size < Object
|
9
|
+
string_attribute :url
|
10
|
+
numeric_attribute :width, :height
|
11
|
+
end
|
12
|
+
|
13
|
+
def photos=(value)
|
14
|
+
photos = value.collect do |value|
|
15
|
+
object = Tumblr::Photo.new
|
16
|
+
object.caption = value["caption"]
|
17
|
+
object.sizes = value["alt_sizes"].collect { |size| Size.build(size) }
|
18
|
+
end
|
19
|
+
set_attribute_value(:photos, photos)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Tumblr
|
2
|
+
class Post < Object
|
3
|
+
extend Query::DelegateMethods
|
4
|
+
numeric_attribute :id
|
5
|
+
date_attribute :date, :timestamp
|
6
|
+
string_attribute :slug, :blog_name, :post_url, :source_url, :source_title, :format
|
7
|
+
array_attribute :tags
|
8
|
+
boolean_attribute :mobile, :bookmarklet
|
9
|
+
|
10
|
+
def self.build(attributes)
|
11
|
+
klass = attributes["type"] ? Object.systematize(attributes["type"]) : self
|
12
|
+
if klass && klass != self
|
13
|
+
klass.build(attributes)
|
14
|
+
else
|
15
|
+
super
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.page(n)
|
20
|
+
query.page([1, n.to_i].max)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.per_page(n)
|
24
|
+
query.per_page(n)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.type(type)
|
28
|
+
query.type(type)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.tagged_with(tag)
|
32
|
+
query.tag(tag)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.find(id)
|
36
|
+
query.id(id).first
|
37
|
+
end
|
38
|
+
|
39
|
+
def commit
|
40
|
+
super
|
41
|
+
tags.each do |tag|
|
42
|
+
Redis::Set.new("#{Blog::STORAGE_KEY}:tags", Tumblr.config.redis) << tag
|
43
|
+
Redis::List.new("#{Blog::STORAGE_KEY}:tags:#{tag.downcase.underscore}", Tumblr.config.redis) << slug
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def html?
|
48
|
+
format == "html"
|
49
|
+
end
|
50
|
+
|
51
|
+
def markdown?
|
52
|
+
format == "markdown"
|
53
|
+
end
|
54
|
+
|
55
|
+
def slug
|
56
|
+
@slug ||= title.parameterize
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_param
|
60
|
+
slug
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def self.query
|
66
|
+
@query ||= Query.new(:page, :per_page, :type, :id, :tag) do |params|
|
67
|
+
page_size = params[:per_page] || self.page_size
|
68
|
+
page = [1, params[:page].to_i].max
|
69
|
+
req_params = {
|
70
|
+
:limit => page_size,
|
71
|
+
:offset => page_size * (page - 1)
|
72
|
+
}
|
73
|
+
[:type, :id, :tag].each do |key|
|
74
|
+
req_params[key] = params[key] if params[key]
|
75
|
+
end
|
76
|
+
|
77
|
+
if params.key?(:per_page) || params.key?(:page)
|
78
|
+
results = Api.get('posts', req_params)
|
79
|
+
WillPaginate::Collection.create(page, page_size, results.body["total_posts"]) do |pager|
|
80
|
+
pager.replace results.body["posts"]
|
81
|
+
end
|
82
|
+
else
|
83
|
+
results = Api.get('posts', :limit => req_params)
|
84
|
+
results.body["posts"]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/lib/tumblr/query.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module Tumblr
|
2
|
+
class Query
|
3
|
+
module DelegateMethods
|
4
|
+
[:first, :last, :all, :length].each do |method|
|
5
|
+
define_method method do
|
6
|
+
query.send(method)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(*parameters, &block)
|
12
|
+
@params = {}
|
13
|
+
@param_keys = parameters.to_a
|
14
|
+
@fetch_block = block
|
15
|
+
end
|
16
|
+
|
17
|
+
[:first, :last, :count, :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?].each do |method|
|
18
|
+
define_method method do |*args, &block|
|
19
|
+
to_a.send(method, *args, &block)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def all
|
24
|
+
to_a
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_a
|
28
|
+
if @array && @array.length > 0
|
29
|
+
@array
|
30
|
+
else
|
31
|
+
@array = @fetch_block.call(@params)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def method_missing(method, *args, &block)
|
36
|
+
if @param_keys.include?(method.to_sym)
|
37
|
+
value = args.length == 1 ? args.first : args
|
38
|
+
@array = nil if value != @params[method.to_sym]
|
39
|
+
@params[method.to_sym] = value
|
40
|
+
self
|
41
|
+
elsif to_a.respond_to?(method)
|
42
|
+
to_a.send(method, *args, &block)
|
43
|
+
else
|
44
|
+
super(method, *args, &block)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/tumblr/quote.rb
CHANGED
@@ -1,21 +1,5 @@
|
|
1
1
|
module Tumblr
|
2
|
-
class Quote <
|
3
|
-
|
4
|
-
|
5
|
-
def as_json
|
6
|
-
super.merge!({
|
7
|
-
:text => text,
|
8
|
-
:source => source
|
9
|
-
})
|
10
|
-
end
|
11
|
-
|
12
|
-
private
|
13
|
-
|
14
|
-
def parse_xml_node(node)
|
15
|
-
super(node)
|
16
|
-
self.text = node.css('quote-text').first.try(:content)
|
17
|
-
self.source = node.css('quote-source').first.try(:content)
|
18
|
-
self
|
19
|
-
end
|
2
|
+
class Quote < Post
|
3
|
+
string_attribute :text, :source
|
20
4
|
end
|
21
5
|
end
|
data/lib/tumblr/version.rb
CHANGED
data/tumblrb.gemspec
CHANGED
@@ -3,37 +3,25 @@ require File.expand_path('../lib/tumblr/version', __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.add_dependency('activesupport', '~> 3.0')
|
6
|
-
s.add_dependency('
|
7
|
-
s.add_dependency('
|
8
|
-
s.add_dependency('addressable')
|
9
|
-
s.
|
10
|
-
s.
|
6
|
+
s.add_dependency('json', '~> 1.6.0')
|
7
|
+
s.add_dependency('faraday', '~> 0.7.5')
|
8
|
+
s.add_dependency('addressable', '~> 2.2.0')
|
9
|
+
s.add_dependency('redis-objects', '~> 0.5.0')
|
10
|
+
s.add_dependency('will_paginate', '~> 3.0.0')
|
11
|
+
s.authors = ["thegorgon"]
|
12
|
+
s.description = %q{A simple blogging platform built on Tumblr and Redis}
|
11
13
|
s.email = ['jessereiss@gmail.com']
|
12
14
|
s.homepage = 'https://github.com/thegorgon/tumblrb'
|
13
15
|
s.name = 'tumblrb'
|
14
16
|
s.platform = Gem::Platform::RUBY
|
15
|
-
s.require_paths << 'lib'
|
16
17
|
s.required_rubygems_version = Gem::Requirement.new('>= 1.3.6') if s.respond_to? :required_rubygems_version=
|
17
18
|
s.rubyforge_project = s.name
|
18
19
|
s.summary = %q{Ruby wrapper for the Tumblr API}
|
19
|
-
|
20
|
-
|
21
|
-
"
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
"lib/tumblr/answer.rb",
|
26
|
-
"lib/tumblr/audio.rb",
|
27
|
-
"lib/tumblr/conversation.rb",
|
28
|
-
"lib/tumblr/item.rb",
|
29
|
-
"lib/tumblr/link.rb",
|
30
|
-
"lib/tumblr/page.rb",
|
31
|
-
"lib/tumblr/photo.rb",
|
32
|
-
"lib/tumblr/quote.rb",
|
33
|
-
"lib/tumblr/regular.rb",
|
34
|
-
"lib/tumblr/user.rb",
|
35
|
-
"lib/tumblr/version.rb",
|
36
|
-
"lib/tumblr/video.rb"
|
37
|
-
]
|
20
|
+
|
21
|
+
s.files = `git ls-files`.split("\n")
|
22
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
23
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
24
|
+
s.require_paths = ["lib"]
|
25
|
+
|
38
26
|
s.version = Tumblr::VERSION.dup
|
39
27
|
end
|