diff options
-rw-r--r-- | app/models/refinery/blog/post.rb | 7 | ||||
-rw-r--r-- | app/views/refinery/blog/admin/posts/_form.html.erb | 16 | ||||
-rw-r--r-- | app/views/refinery/blog/posts/_post.html.erb | 8 | ||||
-rw-r--r-- | config/initializers/url_validator.rb | 85 | ||||
-rw-r--r-- | config/locales/en.yml | 7 | ||||
-rw-r--r-- | db/migrate/20120103055909_add_source_url_to_blog_posts.rb | 7 | ||||
-rw-r--r-- | lib/refinery/blog.rb | 1 | ||||
-rw-r--r-- | lib/refinery/blog/configuration.rb | 9 | ||||
-rw-r--r-- | spec/models/refinery/blog/post_spec.rb | 35 |
9 files changed, 171 insertions, 4 deletions
diff --git a/app/models/refinery/blog/post.rb b/app/models/refinery/blog/post.rb index cbb99bd..c119e44 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, :author 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 |