You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

comment.rb 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. ################################################################################
  2. #
  3. # Copyright (C) 2008 pmade inc. (Peter Jones pjones@pmade.com)
  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.
  23. #
  24. ################################################################################
  25. class Comment < ActiveRecord::Base
  26. ################################################################################
  27. EMAIL_RE = /^[^@\s]+@(?:[-a-z0-9]+\.)+[a-z]{2,}$/i
  28. ################################################################################
  29. attr_accessible(:reply_id, :author_name, :author_email, :author_url,
  30. :cached_parent_url, :wants_replies, :content)
  31. ################################################################################
  32. validates_presence_of(:author_name, :content)
  33. validates_format_of(:author_email, :with => EMAIL_RE, :allow_blank => true)
  34. ################################################################################
  35. belongs_to(:banter, :polymorphic => true)
  36. belongs_to(:head, :class_name => 'Comment', :foreign_key => 'reply_id')
  37. has_many(:replies, :class_name => 'Comment', :foreign_key => 'reply_id')
  38. ################################################################################
  39. # Returns all the top-level comments for the given parent object.
  40. def self.for (parent)
  41. parent.comments.find(:all, {
  42. :include => :replies,
  43. :conditions => ["#{table_name}.reply_id IS NULL AND #{table_name}.approved = ?", true],
  44. :order => "#{table_name}.created_at ASC",
  45. })
  46. end
  47. ################################################################################
  48. # Approve the comment with the given ID, or approval code. Returns
  49. # the approved comment if found.
  50. def self.approve! (id)
  51. conditions = ['']
  52. conditions.first << (id.to_s.match(/^\d+$/) ? 'id=?' : 'approval_code=?')
  53. conditions << id
  54. if comment = find(:first, :conditions => conditions)
  55. comment.approved = true
  56. comment.save!
  57. comment
  58. end
  59. end
  60. ################################################################################
  61. # Expire comments that haven't been approved.
  62. def self.expire! (seconds=14.days)
  63. water_level = Time.now - seconds
  64. delete_all(["approved = ? AND updated_at < ?", false, water_level])
  65. end
  66. ################################################################################
  67. # Returns a list of email addresses of people that are monitoring
  68. # the comment with the given ID.
  69. def self.watchers (id)
  70. comments = find(:all, :conditions => ['(id=? OR reply_id=?) AND wants_replies=?', id, id, true])
  71. comments.map(&:author_email).reject {|e| e.blank?}
  72. end
  73. ################################################################################
  74. # Returns the author's URL, cleaned up if necessary.
  75. def author_url
  76. url = self[:author_url]
  77. url.blank? ? nil : "http://#{url}" unless url.match(/^http:\/\//i)
  78. end
  79. ################################################################################
  80. # Return a textual description of the comment's parent object.
  81. def parent_description
  82. desc = banter.class.to_s.underscore.humanize + ': '
  83. if banter.respond_to?(:title)
  84. desc << banter.title
  85. elsif banter.respond_to?(:name)
  86. desc << banter.name
  87. elsif banter.respond_to?(:description)
  88. desc << banter.description.to_s[0, 32]
  89. else
  90. desc << banter.id
  91. end
  92. desc
  93. end
  94. ################################################################################
  95. private
  96. ################################################################################
  97. def create_approval_code
  98. return unless approval_code.blank?
  99. self.approval_code = Digest::MD5.hexdigest("#{object_id}#{id}#{Time.now.to_i}")
  100. end
  101. ################################################################################
  102. before_create do |comment|
  103. # Automatically approve if a logged in user created the comment
  104. comment.approved = true unless comment.user_id.nil?
  105. end
  106. ################################################################################
  107. after_create do |comment|
  108. unless comment.approved?
  109. comment.send(:create_approval_code)
  110. Comment.update_all(["approval_code=?", comment.approval_code], ["id=?", comment.id])
  111. BanterMailer.deliver_moderation_message(comment)
  112. end
  113. end
  114. ################################################################################
  115. before_save do |comment|
  116. # Cache the contents as HTML
  117. comment.content_cache = RedCloth.new(comment.content).to_html
  118. # Send out reply notices
  119. if comment.approved? and !comment.mail_sent? and !comment.reply_id.blank?
  120. watchers = Comment.watchers(comment.reply_id)
  121. comment.mail_sent = true
  122. BanterMailer.deliver_reply_message(comment, watchers) unless watchers.empty?
  123. end
  124. end
  125. end