blogpostify 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +97 -0
- data/Rakefile +2 -0
- data/blogpostify.gemspec +23 -0
- data/db/migrate/20150209104023_create_posts.rb +14 -0
- data/lib/blogpostify/blog.rb +38 -0
- data/lib/blogpostify/engine.rb +15 -0
- data/lib/blogpostify/post.rb +35 -0
- data/lib/blogpostify/version.rb +3 -0
- data/lib/blogpostify/view_helpers.rb +26 -0
- data/lib/blogpostify.rb +62 -0
- data/lib/tasks/blogpostify.rake +19 -0
- metadata +99 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9af182d4d709ae1c185aa8d4ecba533667317764
|
4
|
+
data.tar.gz: 45b18953a7bee41d38042c513382d02f47e3fd95
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2070132e49cf7ed728825b513dabb6ad8daa3ef003cb88383b39abe1cb00cf774d3578449c7712115e98ad60e28820a3721fbe90d43bfc30f227476f63f5cec5
|
7
|
+
data.tar.gz: 96feee3872d01231abfcc8a3e872ffa9db499b2b040359ab3764ade9ec8021c63697bf19bf83d75ca082335fffe68a62d1f5fd179f3e18b0ae7018c28c78336b
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Dan Wentworth
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
# Blogpostify
|
2
|
+
|
3
|
+
Simple little gem to fetch the latest blog posts from multiple RSS or Atom feeds and cache them in an ActiveRecord model to be displayed in your Rails application.
|
4
|
+
|
5
|
+
Blogpostify comes with rake tasks and view helpers to assit with integration into your existing application.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'blogpostify'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Once bundled with your application, run the migration included with the gem:
|
20
|
+
|
21
|
+
```sh
|
22
|
+
bundle exec rake db:migrate
|
23
|
+
```
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
### Configuration
|
28
|
+
Add your blog details in an initializer `config/initializers/blogpostify.rb`:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
Blogpostify.configure do |config|
|
32
|
+
config.add_blog("Riding Rails", "http://weblog.rubyonrails.org/feed/atom.xml")
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
The title of your blog will be parameterized to form an blog identifier for your cached posts. If you want to set this to something else, set the third parameter. You can also add a path to an icon that represents this blog if you like.
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
Blogpostify.configure do |config|
|
40
|
+
config.add_blog("Riding Rails", "http://weblog.rubyonrails.org/feed/atom.xml")
|
41
|
+
config.add_blog("Signal v. Noise", "https://signalvnoise.com/posts.rss", "svn", "https://basecamp.com/assets/general/basecamp.png")
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
Okay, great! You're all ready to start fetching blog posts.
|
46
|
+
|
47
|
+
### Updating
|
48
|
+
|
49
|
+
For your convenience we've included a couple of rake tasks to assist with updating blog posts. Feel free to use these in conjunction with `cron` to update your posts, if you're using something like `clockwork` to schedule tasks, we'll look at that in a second.
|
50
|
+
|
51
|
+
`blogpostify:update_all` will go through each configured blog and attempt to fetch new posts for them:
|
52
|
+
|
53
|
+
```sh
|
54
|
+
bundle exec rake blogpostify:update_all
|
55
|
+
=> 2 new posts added
|
56
|
+
```
|
57
|
+
|
58
|
+
`blogpostify:update` can be used to just update a single blog, pass BLOG as an environment variable to specifty the blog:
|
59
|
+
|
60
|
+
```sh
|
61
|
+
bundle exec rake blogpostify:update BLOG=svn
|
62
|
+
=> 4 new posts added
|
63
|
+
```
|
64
|
+
|
65
|
+
So what if you're using something like `clockwork` or another ruby based worker to run your scheduled task? No problem. To update all blogs simply run:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
Blogpostify.update_blogs
|
69
|
+
=> [#<Blogpostify::Post...]
|
70
|
+
```
|
71
|
+
|
72
|
+
Just want to update one blog? No problem:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
Blogpostify.update_blog('svn')
|
76
|
+
=> [#<Blogpostify::Post...]
|
77
|
+
```
|
78
|
+
|
79
|
+
If we can't find the blog specified in the configuration you'll recieve a Blogpostify::BlogNotFound error.
|
80
|
+
|
81
|
+
### Displaying Entries
|
82
|
+
|
83
|
+
There are a couple of helpers included to assist you in displaying your post entries in your app. `blog_populated?` allows you to check if any blog posts have been fetched for a blog yet. `blog_posts_for` fetches the most recent posts for a particular blog, sorted by published date. Lets have a look at these in practice in `app/views/dashboard/index.html.haml`:
|
84
|
+
|
85
|
+
```haml
|
86
|
+
- if blog_populated?('svn')
|
87
|
+
%h4 Latest News
|
88
|
+
%ul.blog-posts
|
89
|
+
= blog_posts_for('svn', :count => 1) do |post|
|
90
|
+
%li.post
|
91
|
+
%span.title= post.title
|
92
|
+
%span.description= truncate post.description, :length => 90
|
93
|
+
%span.published= post.published_at.strftime("%-d %b %H:%M")
|
94
|
+
%span.link= link_to "Read More...", post.link
|
95
|
+
```
|
96
|
+
|
97
|
+
Note that you can optionally pass `count` to `blog_posts_for` to only get the n-latest posts. By default this is 3.
|
data/Rakefile
ADDED
data/blogpostify.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'blogpostify/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "blogpostify"
|
8
|
+
spec.version = Blogpostify::VERSION
|
9
|
+
spec.authors = ["Dan Wentworth"]
|
10
|
+
spec.email = ["dan@atechmedia.com"]
|
11
|
+
spec.summary = %q{Fetch, cache and display blog posts in your Rails app.}
|
12
|
+
spec.homepage = "http://darkphnx.com"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
21
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
22
|
+
spec.add_dependency "rails", "~> 4"
|
23
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreatePosts < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :blogpostify_posts do |t|
|
4
|
+
t.string :blog
|
5
|
+
t.string :title
|
6
|
+
t.text :description
|
7
|
+
t.string :guid
|
8
|
+
t.string :link
|
9
|
+
t.timestamp :published_at
|
10
|
+
|
11
|
+
t.timestamps
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Blogpostify
|
2
|
+
class Blog
|
3
|
+
|
4
|
+
attr_accessor :title, :url, :short_name, :icon
|
5
|
+
|
6
|
+
def initialize(title, url, short_name, icon)
|
7
|
+
self.title = title
|
8
|
+
self.url = url
|
9
|
+
self.short_name = short_name
|
10
|
+
self.icon = icon
|
11
|
+
end
|
12
|
+
|
13
|
+
def update_posts
|
14
|
+
created = []
|
15
|
+
|
16
|
+
open(self.url) do |body|
|
17
|
+
rss = RSS::Parser.parse(body)
|
18
|
+
rss.items.each do |post|
|
19
|
+
post = Post.create_from_item(self.short_name, post)
|
20
|
+
|
21
|
+
# Post not saved if guid is already registered for this blog
|
22
|
+
created << post if post.persisted?
|
23
|
+
end
|
24
|
+
|
25
|
+
created
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def posts
|
30
|
+
Post.where(:blog => self.short_name).asc
|
31
|
+
end
|
32
|
+
|
33
|
+
def short_name
|
34
|
+
@short_name ||= title.parameterize
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Blogpostify
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
|
4
|
+
initializer 'blogpostify.initialize' do |app|
|
5
|
+
config.paths["db/migrate"].expanded.each do |expanded_path|
|
6
|
+
app.config.paths["db/migrate"] << expanded_path
|
7
|
+
end
|
8
|
+
|
9
|
+
ActiveSupport.on_load :action_controller do
|
10
|
+
helper Blogpostify::ViewHelpers
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Blogpostify
|
2
|
+
class Post < ActiveRecord::Base
|
3
|
+
|
4
|
+
self.table_name = 'blogpostify_posts'
|
5
|
+
|
6
|
+
scope :asc, -> { order(:published_at).reverse_order }
|
7
|
+
|
8
|
+
validates :guid, :uniqueness => { :scope => :blog }
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
include ActionView::Helpers::SanitizeHelper
|
13
|
+
|
14
|
+
def create_from_item(blog_name, post_item)
|
15
|
+
post = self.new
|
16
|
+
post.blog = blog_name
|
17
|
+
post.title = post_item.title
|
18
|
+
post.description = sanitize_description(post_item.description)
|
19
|
+
post.guid = post_item.guid.content
|
20
|
+
post.published_at = post_item.pubDate
|
21
|
+
post.link = post_item.link
|
22
|
+
post.save
|
23
|
+
post
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# Truncate the description to the configured length to the nearest whole word
|
29
|
+
def sanitize_description(description)
|
30
|
+
ActionController::Base.helpers.strip_tags(description)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Blogpostify
|
2
|
+
module ViewHelpers
|
3
|
+
|
4
|
+
def blog_populated?(blog_name)
|
5
|
+
blog = Blogpostify.find_blog!(blog_name)
|
6
|
+
blog.posts.exists?
|
7
|
+
end
|
8
|
+
|
9
|
+
def blog_posts_for(blog_name, options={}, &block)
|
10
|
+
options.reverse_merge!({
|
11
|
+
:count => 3
|
12
|
+
})
|
13
|
+
|
14
|
+
blog = Blogpostify.find_blog!(blog_name)
|
15
|
+
posts_scope = blog.posts.asc.limit(options[:count])
|
16
|
+
|
17
|
+
if block_given?
|
18
|
+
posts_scope.each {|post| yield post }
|
19
|
+
return nil # Block should do all of the rendering
|
20
|
+
else
|
21
|
+
posts_scope.to_a
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
data/lib/blogpostify.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'rss'
|
3
|
+
|
4
|
+
require "blogpostify/version"
|
5
|
+
require "blogpostify/blog"
|
6
|
+
require "blogpostify/post"
|
7
|
+
require "blogpostify/view_helpers"
|
8
|
+
require 'blogpostify/engine'
|
9
|
+
|
10
|
+
module Blogpostify
|
11
|
+
|
12
|
+
class BlogNotFoundError < StandardError; end
|
13
|
+
|
14
|
+
class Configuration
|
15
|
+
def blogs
|
16
|
+
@blogs ||= []
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_blog(title, url, icon=nil, short_name=nil)
|
20
|
+
self.blogs << Blog.new(title, url, short_name, icon)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class << self
|
25
|
+
attr_accessor :configuration
|
26
|
+
|
27
|
+
def configure
|
28
|
+
self.configuration ||= Configuration.new
|
29
|
+
yield configuration
|
30
|
+
end
|
31
|
+
|
32
|
+
def find_blog!(blog_short_name)
|
33
|
+
blog_short_name = blog_short_name.to_s
|
34
|
+
|
35
|
+
found_blog = blogs.find do |blog|
|
36
|
+
blog.short_name == blog_short_name
|
37
|
+
end
|
38
|
+
|
39
|
+
if found_blog.nil?
|
40
|
+
raise BlogNotFoundError, "Blog #{blog_short_name} is not configured. Check Blogpostify#blogs."
|
41
|
+
else
|
42
|
+
found_blog
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def blogs
|
47
|
+
configuration.blogs
|
48
|
+
end
|
49
|
+
|
50
|
+
def update_blogs
|
51
|
+
blogs.flat_map do |blog|
|
52
|
+
blog.update_posts
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def update_blog(blog_name)
|
57
|
+
find_blog!(blog_name).update_posts
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
namespace :blogpostify do
|
2
|
+
|
3
|
+
desc 'Poll all configured blogs and update the posts'
|
4
|
+
task :update_all => :environment do
|
5
|
+
new_posts = Blogpostify.update_blogs
|
6
|
+
puts "#{new_posts.count} new posts added"
|
7
|
+
end
|
8
|
+
|
9
|
+
desc 'Update the posts for a single blog, pass blog identifier in BLOG'
|
10
|
+
task :update => :environment do
|
11
|
+
begin
|
12
|
+
new_posts = Blogpostify.update_blog(ENV['BLOG'])
|
13
|
+
puts "#{new_posts.count} new posts added"
|
14
|
+
rescue Blogpostify::BlogNotFoundError
|
15
|
+
puts "Blog #{ENV['BLOG']} is not configured"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: blogpostify
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dan Wentworth
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rails
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '4'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '4'
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
- dan@atechmedia.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- Gemfile
|
63
|
+
- LICENSE.txt
|
64
|
+
- README.md
|
65
|
+
- Rakefile
|
66
|
+
- blogpostify.gemspec
|
67
|
+
- db/migrate/20150209104023_create_posts.rb
|
68
|
+
- lib/blogpostify.rb
|
69
|
+
- lib/blogpostify/blog.rb
|
70
|
+
- lib/blogpostify/engine.rb
|
71
|
+
- lib/blogpostify/post.rb
|
72
|
+
- lib/blogpostify/version.rb
|
73
|
+
- lib/blogpostify/view_helpers.rb
|
74
|
+
- lib/tasks/blogpostify.rake
|
75
|
+
homepage: http://darkphnx.com
|
76
|
+
licenses:
|
77
|
+
- MIT
|
78
|
+
metadata: {}
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
requirements: []
|
94
|
+
rubyforge_project:
|
95
|
+
rubygems_version: 2.2.2
|
96
|
+
signing_key:
|
97
|
+
specification_version: 4
|
98
|
+
summary: Fetch, cache and display blog posts in your Rails app.
|
99
|
+
test_files: []
|