use nokogiri to get doc titles
This commit is contained in:
parent
264cd85ece
commit
f801932a03
2
Gemfile
2
Gemfile
|
@ -22,6 +22,8 @@ gem "unicorn"
|
||||||
# for asset compilation
|
# for asset compilation
|
||||||
gem "uglifier"
|
gem "uglifier"
|
||||||
|
|
||||||
|
gem "nokogiri"
|
||||||
|
|
||||||
group :test, :development do
|
group :test, :development do
|
||||||
gem "rspec-rails", "~> 2.6"
|
gem "rspec-rails", "~> 2.6"
|
||||||
gem "machinist"
|
gem "machinist"
|
||||||
|
|
|
@ -54,6 +54,7 @@ GEM
|
||||||
mime-types (1.18)
|
mime-types (1.18)
|
||||||
multi_json (1.1.0)
|
multi_json (1.1.0)
|
||||||
mysql2 (0.3.11)
|
mysql2 (0.3.11)
|
||||||
|
nokogiri (1.5.4)
|
||||||
polyglot (0.3.3)
|
polyglot (0.3.3)
|
||||||
rack (1.4.1)
|
rack (1.4.1)
|
||||||
rack-cache (1.2)
|
rack-cache (1.2)
|
||||||
|
@ -123,6 +124,7 @@ DEPENDENCIES
|
||||||
jquery-rails
|
jquery-rails
|
||||||
machinist
|
machinist
|
||||||
mysql2
|
mysql2
|
||||||
|
nokogiri
|
||||||
rails (= 3.2.2)
|
rails (= 3.2.2)
|
||||||
rspec-rails (~> 2.6)
|
rspec-rails (~> 2.6)
|
||||||
sqlite3
|
sqlite3
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
class Story < ActiveRecord::Base
|
class Story < ActiveRecord::Base
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
has_many :taggings
|
has_many :taggings
|
||||||
has_many :comments
|
has_many :comments
|
||||||
has_many :tags, :through => :taggings
|
has_many :tags, :through => :taggings
|
||||||
|
|
||||||
|
@ -12,10 +12,10 @@ class Story < ActiveRecord::Base
|
||||||
|
|
||||||
attr_accessible :url, :title, :description, :story_type, :tags_a
|
attr_accessible :url, :title, :description, :story_type, :tags_a
|
||||||
|
|
||||||
# after this many minutes old, a story cannot be edited
|
# after this many minutes old, a story cannot be edited
|
||||||
MAX_EDIT_MINS = 30
|
MAX_EDIT_MINS = 30
|
||||||
|
|
||||||
attr_accessor :vote, :story_type, :already_posted_story
|
attr_accessor :vote, :story_type, :already_posted_story, :fetched_content
|
||||||
attr_accessor :tags_to_add, :tags_to_delete
|
attr_accessor :tags_to_add, :tags_to_delete
|
||||||
|
|
||||||
after_save :deal_with_tags
|
after_save :deal_with_tags
|
||||||
|
@ -25,7 +25,7 @@ class Story < ActiveRecord::Base
|
||||||
if self.url.present?
|
if self.url.present?
|
||||||
# URI.parse is not very lenient, so we can't use it
|
# URI.parse is not very lenient, so we can't use it
|
||||||
|
|
||||||
if self.url.match(/\Ahttps?:\/\/[^\.]+\.[a-z]+\//)
|
if self.url.match(/\Ahttps?:\/\/([^\.]+\.)+[a-z]+(\/|\z)/)
|
||||||
if (s = Story.find_by_url(self.url)) &&
|
if (s = Story.find_by_url(self.url)) &&
|
||||||
(Time.now - s.created_at) < 30.days
|
(Time.now - s.created_at) < 30.days
|
||||||
errors.add(:url, "has already been submitted recently")
|
errors.add(:url, "has already been submitted recently")
|
||||||
|
@ -34,20 +34,22 @@ class Story < ActiveRecord::Base
|
||||||
else
|
else
|
||||||
errors.add(:url, "is not valid")
|
errors.add(:url, "is not valid")
|
||||||
end
|
end
|
||||||
|
elsif self.description.to_s.strip == ""
|
||||||
|
self.errors(:description, "must contain text if no URL posted")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def assign_short_id
|
def assign_short_id
|
||||||
(1...10).each do |tries|
|
(1...10).each do |tries|
|
||||||
if tries == 10
|
if tries == 10
|
||||||
raise "too many hash collisions"
|
raise "too many hash collisions"
|
||||||
end
|
end
|
||||||
|
|
||||||
self.short_id = Utils.random_str(6)
|
self.short_id = Utils.random_str(6)
|
||||||
if !Story.find_by_short_id(self.short_id)
|
if !Story.find_by_short_id(self.short_id)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def deal_with_tags
|
def deal_with_tags
|
||||||
|
@ -72,27 +74,43 @@ class Story < ActiveRecord::Base
|
||||||
self.tags_to_add = []
|
self.tags_to_add = []
|
||||||
end
|
end
|
||||||
|
|
||||||
def comments_url
|
def comments_url
|
||||||
"/p/#{self.short_id}/#{self.title_as_url}"
|
"/p/#{self.short_id}/#{self.title_as_url}"
|
||||||
end
|
end
|
||||||
|
|
||||||
@_comment_count = nil
|
@_comment_count = nil
|
||||||
def comment_count
|
def comment_count
|
||||||
@_comment_count ||=
|
@_comment_count ||=
|
||||||
Keystore.value_for("story:#{self.id}:comment_count").to_i
|
Keystore.value_for("story:#{self.id}:comment_count").to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
def domain
|
def domain
|
||||||
if self.url.blank?
|
if self.url.blank?
|
||||||
nil
|
nil
|
||||||
else
|
else
|
||||||
pu = URI.parse(self.url)
|
pu = URI.parse(self.url)
|
||||||
pu.host.gsub(/^www\d*\./, "")
|
pu.host.gsub(/^www\d*\./, "")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
UP_RANGE = 400
|
def fetched_title(for_remote_ip = nil)
|
||||||
DOWN_RANGE = 100
|
doc = Nokogiri::HTML(fetched_content(for_remote_ip).to_s)
|
||||||
|
return doc.at_css("title").text
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetched_content(for_remote_ip = nil)
|
||||||
|
return @fetched_content if @fetched_content
|
||||||
|
|
||||||
|
begin
|
||||||
|
s = Sponge.new
|
||||||
|
s.timeout = 3
|
||||||
|
@fetched_content = s.fetch(self.url, :get, nil, nil,
|
||||||
|
{ "User-agent" => "lobste.rs! for #{for_remote_ip}" }, 3)
|
||||||
|
rescue
|
||||||
|
end
|
||||||
|
|
||||||
|
@fetched_content
|
||||||
|
end
|
||||||
|
|
||||||
def hotness
|
def hotness
|
||||||
score = upvotes - downvotes
|
score = upvotes - downvotes
|
||||||
|
@ -109,13 +127,14 @@ class Story < ActiveRecord::Base
|
||||||
return -(order + (sign * (seconds.to_f / 45000))).round(7)
|
return -(order + (sign * (seconds.to_f / 45000))).round(7)
|
||||||
end
|
end
|
||||||
|
|
||||||
def linkified_text
|
def linkified_text
|
||||||
Markdowner.markdown(self.description)
|
Markdowner.markdown(self.description)
|
||||||
end
|
end
|
||||||
|
|
||||||
def tags_a
|
def tags_a
|
||||||
tags.map{|t| t.tag }
|
tags.map{|t| t.tag }
|
||||||
end
|
end
|
||||||
|
|
||||||
def tags_a=(new_tags)
|
def tags_a=(new_tags)
|
||||||
self.tags_to_delete = []
|
self.tags_to_delete = []
|
||||||
self.tags_to_add = []
|
self.tags_to_add = []
|
||||||
|
@ -140,41 +159,36 @@ class Story < ActiveRecord::Base
|
||||||
self[:title] = t.strip
|
self[:title] = t.strip
|
||||||
end
|
end
|
||||||
|
|
||||||
def title_as_url
|
def title_as_url
|
||||||
u = self.title.downcase.gsub(/[^a-z0-9_-]/, "_")
|
u = self.title.downcase.gsub(/[^a-z0-9_-]/, "_")
|
||||||
while self.title.match(/__/)
|
while u.match(/__/)
|
||||||
self.title.gsub!("__", "_")
|
u.gsub!("__", "_")
|
||||||
end
|
end
|
||||||
|
u
|
||||||
|
end
|
||||||
|
|
||||||
u
|
def url_or_comments_url
|
||||||
end
|
self.url.blank? ? self.comments_url : self.url
|
||||||
|
end
|
||||||
|
|
||||||
def url_or_comments_url
|
def is_editable_by_user?(user)
|
||||||
self.url.blank? ? self.comments_url : self.url
|
if !user || user.id != self.user_id
|
||||||
end
|
|
||||||
|
|
||||||
def is_editable_by_user?(user)
|
|
||||||
if !user || user.id != self.user_id
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
(Time.now.to_i - self.created_at.to_i < (60 * MAX_EDIT_MINS))
|
(Time.now.to_i - self.created_at.to_i < (60 * MAX_EDIT_MINS))
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_undeletable_by_user?(user)
|
def is_undeletable_by_user?(user)
|
||||||
if !user || user.id != self.user_id
|
if !user || user.id != self.user_id
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_comment_count!
|
def update_comment_count!
|
||||||
Keystore.put("story:#{self.id}:comment_count",
|
Keystore.put("story:#{self.id}:comment_count",
|
||||||
Comment.where(:story_id => self.id).count)
|
Comment.where(:story_id => self.id).count)
|
||||||
end
|
|
||||||
|
|
||||||
def flag!
|
|
||||||
Story.update_counters self.id, :flaggings => 1
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue