aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/models/refinery/blog/post.rb7
-rw-r--r--app/views/refinery/blog/admin/posts/_form.html.erb16
-rw-r--r--app/views/refinery/blog/posts/_post.html.erb8
-rw-r--r--config/initializers/url_validator.rb85
-rw-r--r--config/locales/en.yml7
-rw-r--r--db/migrate/20120103055909_add_source_url_to_blog_posts.rb7
-rw-r--r--lib/refinery/blog.rb1
-rw-r--r--lib/refinery/blog/configuration.rb9
-rw-r--r--spec/models/refinery/blog/post_spec.rb35
9 files changed, 171 insertions, 4 deletions
diff --git a/app/models/refinery/blog/post.rb b/app/models/refinery/blog/post.rb
index 883f4fc..1eae99a 100644
--- a/app/models/refinery/blog/post.rb
+++ b/app/models/refinery/blog/post.rb
@@ -22,6 +22,12 @@ module Refinery
validates :title, :presence => true, :uniqueness => true
validates :body, :presence => true
+
+ validates :source_url, :url => { :if => 'Refinery::Blog.config.validate_source_url',
+ :update => true,
+ :allow_nil => true,
+ :allow_blank => true,
+ :verify => [:resolve_redirects]}
has_friendly_id :friendly_id_source, :use_slug => true,
:default_locale => (::Refinery::I18n.default_frontend_locale rescue :en),
@@ -48,6 +54,7 @@ module Refinery
attr_accessible :title, :body, :custom_teaser, :tag_list, :draft, :published_at, :custom_url
attr_accessible :browser_title, :meta_keywords, :meta_description, :user_id, :category_ids
+ attr_accessible :source_url, :source_url_title
self.per_page = Refinery::Setting.find_or_set(:blog_posts_per_page, 10)
diff --git a/app/views/refinery/blog/admin/posts/_form.html.erb b/app/views/refinery/blog/admin/posts/_form.html.erb
index a33baeb..68b1d31 100644
--- a/app/views/refinery/blog/admin/posts/_form.html.erb
+++ b/app/views/refinery/blog/admin/posts/_form.html.erb
@@ -83,6 +83,22 @@
<div class='field'>
<span class='label_with_help'>
+ <%= f.label :source_url_title, t('.source_url_title') %>
+ <%= refinery_help_tag t('.source_url_title_help') %>
+ </span>
+ <%= f.text_field :source_url_title, :class => "widest" %>
+ </div>
+
+ <div class='field'>
+ <span class='label_with_help'>
+ <%= f.label :source_url, t('.source_url') %>
+ <%= refinery_help_tag t('.source_url_help') %>
+ </span>
+ <%= f.text_field :source_url, :class => "widest" %>
+ </div>
+
+ <div class='field'>
+ <span class='label_with_help'>
<%= f.label :user_id, t('.author') %>
<%= refinery_help_tag t('.author_help') %>
<br/>
diff --git a/app/views/refinery/blog/posts/_post.html.erb b/app/views/refinery/blog/posts/_post.html.erb
index 020ba41..77e43ff 100644
--- a/app/views/refinery/blog/posts/_post.html.erb
+++ b/app/views/refinery/blog/posts/_post.html.erb
@@ -10,7 +10,13 @@
<time datetime="<%=l @post.published_at.to_date, :format => :default %>" class='posted_at'>
<%= t('created_at', :scope => 'refinery.blog.shared.posts', :when => l(@post.published_at.to_date, :format => :short)) %>
</time>
- <%= "#{t('by', :scope => 'refinery.blog.posts.show')} #{@post.author.username}" if @post.author.present? %>.
+ <%= content_tag(:div, "#{t('by', :scope => 'refinery.blog.posts.show')} #{@post.author.username}", :class => "blog_author") if @post.author.present? %>
+ <% if @post.source_url.present? %>
+ <div class='blog_source'>
+ <%= "#{t('source', :scope => 'refinery.blog.posts.show')}: " %>
+ <%= link_to (@post.source_url_title.blank? ? @post.source_url : @post.source_url_title), @post.source_url %>
+ </div>
+ <% end %>
<% if (categories = @post.categories).any? %>
<aside class='filed_in'>
<%= t('filed_in', :scope => 'refinery.blog.posts.show') %>
diff --git a/config/initializers/url_validator.rb b/config/initializers/url_validator.rb
new file mode 100644
index 0000000..15635e0
--- /dev/null
+++ b/config/initializers/url_validator.rb
@@ -0,0 +1,85 @@
+require 'net/http'
+
+class UrlValidator < ActiveModel::EachValidator
+
+ def validate_each(record, attribute, value)
+ url = value
+
+ # Regex code by 'Arsenic' from http://snippets.dzone.com/posts/show/3654
+ if url =~ /^
+( (https?):\/\/ )?
+( [a-z\d]+([\-\.][a-z\d]+)*\.[a-z]{2,6} )
+(
+(:
+( \d{1,5} )
+)?
+( \/.* )?
+)?
+$/ix
+ url = "http#{'s' if $7 == '81'}://#{url}" unless $1
+ else
+ record.errors[attribute] << 'Not a valid URL'
+ end
+
+ if options[:verify]
+ begin
+ url_response = RedirectFollower.new(url).resolve
+ url = url_response.url if options[:verify] == [:resolve_redirects]
+ rescue RedirectFollower::TooManyRedirects
+ record.errors[attribute] << 'URL is redirecting too many times'
+ rescue
+ record.errors[attribute] << 'could not be resolved'
+ end
+ end
+
+ if options[:update]
+ value.replace url
+ end
+ end
+end
+
+# Code below written by John Nunemaker
+# See blog post at http://railstips.org/blog/archives/2009/03/04/following-redirects-with-nethttp/
+class RedirectFollower
+ class TooManyRedirects < StandardError; end
+
+ attr_accessor :url, :body, :redirect_limit, :response
+
+ def initialize(url, limit=5)
+ @url, @redirect_limit = url, limit
+ logger.level = Logger::INFO
+ end
+
+ def logger
+ @logger ||= Logger.new(STDOUT)
+ end
+
+ def resolve
+ raise TooManyRedirects if redirect_limit < 0
+
+ self.response = Net::HTTP.get_response(URI.parse(url))
+
+ logger.info "redirect limit: #{redirect_limit}"
+ logger.info "response code: #{response.code}"
+ logger.debug "response body: #{response.body}"
+
+ if response.kind_of?(Net::HTTPRedirection)
+ self.url = redirect_url
+ self.redirect_limit -= 1
+
+ logger.info "redirect found, headed to #{url}"
+ resolve
+ end
+
+ self.body = response.body
+ self
+ end
+
+ def redirect_url
+ if response['location'].nil?
+ response.body.match(/<a href=\"([^>]+)\">/i)[1]
+ else
+ response['location']
+ end
+ end
+end \ No newline at end of file
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 64d4064..a3268c1 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -41,6 +41,10 @@ en:
published_at: Publish Date
custom_url: Custom Url
custom_url_help: Generate the url for the blog post from this text instead of the title.
+ source_url: Source Url
+ source_url_help: Stores the url for the source of the post material.
+ source_url_title: Source Url Title
+ source_url_title_help: Title for the source url for the post.
author: Author
author_help: Set which user this post will show as the author.
copy_body: Copy Post Body to Teaser
@@ -136,7 +140,8 @@ en:
name: Name
email: Email
message: Message
- by: by
+ by: By
+ source: Source
tagged:
no_blog_articles_yet: There are no blog articles posted yet. Stay tuned.
posts_tagged: Posts tagged
diff --git a/db/migrate/20120103055909_add_source_url_to_blog_posts.rb b/db/migrate/20120103055909_add_source_url_to_blog_posts.rb
new file mode 100644
index 0000000..cd6fd27
--- /dev/null
+++ b/db/migrate/20120103055909_add_source_url_to_blog_posts.rb
@@ -0,0 +1,7 @@
+class AddSourceUrlToBlogPosts < ActiveRecord::Migration
+ def change
+ add_column Refinery::Blog::Post.table_name, :source_url, :string
+ add_column Refinery::Blog::Post.table_name, :source_url_title, :string
+
+ end
+end
diff --git a/lib/refinery/blog.rb b/lib/refinery/blog.rb
index 38f5813..e5b717f 100644
--- a/lib/refinery/blog.rb
+++ b/lib/refinery/blog.rb
@@ -7,6 +7,7 @@ module Refinery
module Blog
require 'refinery/blog/engine'
+ require 'refinery/blog/configuration'
autoload :Version, 'refinery/blog/version'
autoload :Tab, 'refinery/blog/tabs'
diff --git a/lib/refinery/blog/configuration.rb b/lib/refinery/blog/configuration.rb
new file mode 100644
index 0000000..aa1264a
--- /dev/null
+++ b/lib/refinery/blog/configuration.rb
@@ -0,0 +1,9 @@
+module Refinery
+ module Blog
+ include ActiveSupport::Configurable
+
+ config_accessor :validate_source_url
+
+ self.validate_source_url = false
+ end
+end \ No newline at end of file
diff --git a/spec/models/refinery/blog/post_spec.rb b/spec/models/refinery/blog/post_spec.rb
index 60a04ec..fb7e3b1 100644
--- a/spec/models/refinery/blog/post_spec.rb
+++ b/spec/models/refinery/blog/post_spec.rb
@@ -212,9 +212,40 @@ module Refinery
subject.class.teasers_enabled?.should be_false
end
end
-
end
-
+
+ describe "source url" do
+ it "should allow a source url and title" do
+ p = FactoryGirl.create(:blog_post, :source_url => 'google.com', :source_url_title => 'author')
+ p.should be_valid
+ p.source_url.should include('google')
+ p.source_url_title.should include('author')
+ end
+ end
+
+ describe ".validate_source_url?" do
+ context "with Refinery::Setting validate_source_url set to true" do
+ before do
+ Refinery::Setting.set(:validate_source_url, { :scoping => 'blog', :value => true })
+ Refinery::Blog.validate_source_url = true
+ end
+ it "should have canonical url" do
+ p = FactoryGirl.create(:blog_post, :source_url => 'google.com', :source_url_title => 'google')
+ p.source_url.should include('www')
+ end
+ end
+ context "with Refinery::Setting validate_source_url set to false" do
+ before do
+ Refinery::Setting.set(:validate_source_url, { :scoping => 'blog', :value => false })
+ Refinery::Blog.validate_source_url = false
+ end
+ it "should have original url" do
+ p = FactoryGirl.create(:blog_post, :source_url => 'google.com', :source_url_title => 'google')
+ p.source_url.should_not include('www')
+ end
+ end
+ end
+
end
end
end \ No newline at end of file