diff --git a/app/models/category.rb b/app/models/category.rb index b5e1a006791..0c4e76a4173 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -1,6 +1,5 @@ class Category < ActiveRecord::Base - - belongs_to :topic + belongs_to :topic, dependent: :destroy belongs_to :user has_many :topics @@ -18,15 +17,13 @@ class Category < ActiveRecord::Base after_save :invalidate_site_cache after_destroy :invalidate_site_cache + scope :popular, lambda { order('topic_count desc') } + def uncategorized_validator return errors.add(:name, I18n.t(:is_reserved)) if name == SiteSetting.uncategorized_name return errors.add(:slug, I18n.t(:is_reserved)) if slug == SiteSetting.uncategorized_name end - def self.popular - order('topic_count desc') - end - # Recalculates `topics_year`, `topics_month`, and `topics_week` # for each Category. def self.update_stats @@ -69,9 +66,4 @@ class Category < ActiveRecord::Base def invalidate_site_cache Site.invalidate_cache end - - before_destroy do - topic.destroy - end - end diff --git a/app/models/category_featured_topic.rb b/app/models/category_featured_topic.rb index 2f5cbad6997..50789997bcd 100644 --- a/app/models/category_featured_topic.rb +++ b/app/models/category_featured_topic.rb @@ -4,19 +4,16 @@ class CategoryFeaturedTopic < ActiveRecord::Base # Populates the category featured topics def self.feature_topics - transaction do Category.all.each do |c| feature_topics_for(c) CategoryFeaturedUser.feature_users_in(c) end end - - nil end def self.feature_topics_for(c) - return unless c.present? + return if c.blank? CategoryFeaturedTopic.transaction do exec_sql "DELETE FROM category_featured_topics WHERE category_id = :category_id", category_id: c.id diff --git a/app/models/category_featured_user.rb b/app/models/category_featured_user.rb index 2443700b6f5..22519b7cf9e 100644 --- a/app/models/category_featured_user.rb +++ b/app/models/category_featured_user.rb @@ -20,7 +20,7 @@ class CategoryFeaturedUser < ActiveRecord::Base ", category_id: category.id, max_featured_users: max_featured_users transaction do - CategoryFeaturedUser.delete_all ['category_id = ?', category.id] + CategoryFeaturedUser.delete_all category_id: category.id user_counts.each do |uc| create(category_id: category.id, user_id: uc['user_id']) end diff --git a/app/models/category_list.rb b/app/models/category_list.rb index 3b5a628d881..255f52d16fc 100644 --- a/app/models/category_list.rb +++ b/app/models/category_list.rb @@ -47,25 +47,22 @@ class CategoryList # Remove categories with no featured topics unless we have the ability to edit one unless Guardian.new(current_user).can_create?(Category) - @categories.delete_if {|c| c.featured_topics.blank? } + @categories.delete_if { |c| c.featured_topics.blank? } end # Get forum topic user records if appropriate if current_user.present? topics = [] - @categories.each {|c| topics << c.featured_topics} + @categories.each { |c| topics << c.featured_topics } topics << @uncategorized topics.flatten! if topics.present? topics.compact! if topics.present? - topic_lookup = TopicUser.lookup_for(current_user, topics) # Attach some data for serialization to each topic - topics.each {|ft| ft.user_data = topic_lookup[ft.id]} + topics.each { |ft| ft.user_data = topic_lookup[ft.id] } end - end - end diff --git a/app/models/draft.rb b/app/models/draft.rb index d49a191e96e..dc31a83e81d 100644 --- a/app/models/draft.rb +++ b/app/models/draft.rb @@ -1,5 +1,4 @@ class Draft < ActiveRecord::Base - NEW_TOPIC = 'new_topic' NEW_PRIVATE_MESSAGE = 'new_private_message' EXISTING_TOPIC = 'topic_' @@ -20,8 +19,6 @@ class Draft < ActiveRecord::Base d = find_draft(user,key) if d && d.sequence == sequence d.data - else - nil end end @@ -29,8 +26,6 @@ class Draft < ActiveRecord::Base d = find_draft(user,key) if d && d.sequence <= sequence d.destroy - else - nil end end @@ -41,5 +36,4 @@ class Draft < ActiveRecord::Base user_id = user.id if User === user Draft.where(user_id: user_id, draft_key: key).first end - end diff --git a/app/models/draft_sequence.rb b/app/models/draft_sequence.rb index c819e824c4e..9283305a24c 100644 --- a/app/models/draft_sequence.rb +++ b/app/models/draft_sequence.rb @@ -2,7 +2,7 @@ class DraftSequence < ActiveRecord::Base def self.next!(user,key) user_id = user user_id = user.id unless user.class == Fixnum - h = {user_id: user_id, draft_key: key} + h = { user_id: user_id, draft_key: key } c = DraftSequence.where(h).first c ||= DraftSequence.new(h) c.sequence ||= 0 @@ -20,10 +20,6 @@ class DraftSequence < ActiveRecord::Base # perf critical path r = exec_sql('select sequence from draft_sequences where user_id = ? and draft_key = ?', user_id, key).values - if r.length == 0 - 0 - else - r[0][0].to_i - end + r.length.zero? ? 0 : r[0][0].to_i end end diff --git a/app/models/email_log.rb b/app/models/email_log.rb index bebbfbcb0ea..e324bedbe38 100644 --- a/app/models/email_log.rb +++ b/app/models/email_log.rb @@ -1,12 +1,10 @@ class EmailLog < ActiveRecord::Base - belongs_to :user validates_presence_of :email_type validates_presence_of :to_address after_create do # Update last_emailed_at if the user_id is present - User.update_all("last_emailed_at = CURRENT_TIMESTAMP", ["id = ?", user_id]) if user_id.present? + User.update_all("last_emailed_at = CURRENT_TIMESTAMP", id: user_id) if user_id.present? end - end diff --git a/app/models/email_token.rb b/app/models/email_token.rb index cfd4455773d..c02794a6562 100644 --- a/app/models/email_token.rb +++ b/app/models/email_token.rb @@ -5,7 +5,7 @@ class EmailToken < ActiveRecord::Base validates_presence_of :user_id validates_presence_of :email - before_validation(:on => :create) do + before_validation(on: :create) do self.token = EmailToken.generate_token end @@ -38,14 +38,13 @@ class EmailToken < ActiveRecord::Base return unless token.present? return unless token.length/2 == EmailToken.token_length - email_token = EmailToken.where("token = ? AND expired = FALSE and created_at >= ?", token, EmailToken.valid_after).includes(:user).first + email_token = EmailToken.where("token = ? and expired = FALSE and created_at >= ?", token, EmailToken.valid_after).includes(:user).first return if email_token.blank? user = email_token.user User.transaction do - row_count = EmailToken.update_all 'confirmed = true', ['id = ? AND confirmed = false', email_token.id] + row_count = EmailToken.update_all 'confirmed = true', id: email_token.id, expired: false if row_count == 1 - # If we are activating the user, send the welcome message user.send_welcome_message = !user.active? @@ -57,7 +56,5 @@ class EmailToken < ActiveRecord::Base user rescue ActiveRecord::RecordInvalid # If the user's email is already taken, just return nil (failure) - nil end - end diff --git a/app/models/error_log.rb b/app/models/error_log.rb index a3739b09c0c..6acb8400fc5 100644 --- a/app/models/error_log.rb +++ b/app/models/error_log.rb @@ -2,7 +2,6 @@ # a mechanism to iterate through errors in reverse # async logging should queue, if dupe stack traces are found in batch error should be merged into prev one - class ErrorLog @lock = Mutex.new @@ -12,7 +11,7 @@ class ErrorLog end def self.clear!(guid) - raise "not implemented" + raise NotImplementedError end def self.clear_all!() @@ -21,22 +20,22 @@ class ErrorLog def self.report_async!(exception, controller, request, user) Thread.new do - self.report!(exception, controller, request, user) + report!(exception, controller, request, user) end end def self.report!(exception, controller, request, user) add_row!( - :date => DateTime.now, - :guid => SecureRandom.uuid, - :user_id => user && user.id, - :request => filter_sensitive_post_data_parameters(controller, request.parameters).inspect, - :action => controller.action_name, - :controller => controller.controller_name, - :backtrace => sanitize_backtrace(exception.backtrace).join("\n"), - :message => exception.message, - :url => "#{request.protocol}#{request.env["HTTP_X_FORWARDED_HOST"] || request.env["HTTP_HOST"]}#{request.fullpath}", - :exception_class => exception.class.to_s + date: DateTime.now, + guid: SecureRandom.uuid, + user_id: user && user.id, + request: filter_sensitive_post_data_parameters(controller, request.parameters).inspect, + action: controller.action_name, + controller: controller.controller_name, + backtrace: sanitize_backtrace(exception.backtrace).join("\n"), + message: exception.message, + url: "#{request.protocol}#{request.env["HTTP_X_FORWARDED_HOST"] || request.env["HTTP_HOST"]}#{request.fullpath}", + exception_class: exception.class.to_s ) end @@ -44,7 +43,7 @@ class ErrorLog data = hash.to_xml(skip_instruct: true) # use background thread to write the log cause it may block if it gets backed up @lock.synchronize do - File.open(self.filename, "a") do |f| + File.open(filename, "a") do |f| f.flock(File::LOCK_EX) f.write(data) f.close @@ -54,13 +53,12 @@ class ErrorLog def self.each(&blk) - skip(0,&blk) + skip(0, &blk) end def self.skip(skip=0) - data = nil pos = 0 - return [] unless File.exists?(self.filename) + return [] unless File.exists?(filename) loop do lines = "" @@ -107,5 +105,4 @@ class ErrorLog return PARAM_FILTER_REPLACEMENT if (env_key =~ /RAW_POST_DATA/i) return controller.__send__(:filter_parameters, {env_key => env_value}).values[0] end - end diff --git a/app/models/incoming_link.rb b/app/models/incoming_link.rb index 6c1f4be2a75..f5675d98478 100644 --- a/app/models/incoming_link.rb +++ b/app/models/incoming_link.rb @@ -1,13 +1,12 @@ class IncomingLink < ActiveRecord::Base belongs_to :topic - validates :domain, :length => { :in => 1..100 } - validates :referer, :length => { :in => 3..1000 } + validates :domain, length: { in: 1..100 } + validates :referer, length: { in: 3..1000 } validates_presence_of :url # Extract the domain before_validation do - # Referer (remote URL) if referer.present? parsed = URI.parse(referer) @@ -27,7 +26,6 @@ class IncomingLink < ActiveRecord::Base # If we can't route to the url, that's OK. Don't save those two fields. end end - end # Update appropriate incoming link counts @@ -43,5 +41,4 @@ class IncomingLink < ActiveRecord::Base end end end - end diff --git a/app/models/invite.rb b/app/models/invite.rb index 838be396282..abc954c9f08 100644 --- a/app/models/invite.rb +++ b/app/models/invite.rb @@ -2,7 +2,7 @@ class Invite < ActiveRecord::Base belongs_to :user belongs_to :topic - belongs_to :invited_by, class_name: User + belongs_to :invited_by, class_name: 'User' has_many :topic_invites has_many :topics, through: :topic_invites, source: :topic @@ -17,7 +17,7 @@ class Invite < ActiveRecord::Base end before_save do - self.email = self.email.downcase + self.email = email.downcase end validate :user_doesnt_already_exist @@ -45,13 +45,13 @@ class Invite < ActiveRecord::Base Invite.transaction do # Avoid a race condition row_count = Invite.update_all('redeemed_at = CURRENT_TIMESTAMP', - ['id = ? AND redeemed_at IS NULL AND created_at >= ?', self.id, SiteSetting.invite_expiry_days.days.ago]) + ['id = ? AND redeemed_at IS NULL AND created_at >= ?', id, SiteSetting.invite_expiry_days.days.ago]) if row_count == 1 # Create the user if we are redeeming the invite and the user doesn't exist result = User.where(email: email).first - result = User.create_for_email(email, trust_level: SiteSetting.default_invitee_trust_level) if result.blank? + result ||= User.create_for_email(email, trust_level: SiteSetting.default_invitee_trust_level) result.send_welcome_message = false # If there are topic invites for private topics @@ -61,19 +61,19 @@ class Invite < ActiveRecord::Base # Check for other invites by the same email. Don't redeem them, but approve their # topics. - Invite.where('invites.email = ? and invites.id != ?', self.email, self.id).includes(:topics).where('topics.archetype = ?', Archetype::private_message).each do |i| + Invite.where('invites.email = ? and invites.id != ?', email, id).includes(:topics).where(topics: { archetype: Archetype::private_message }).each do |i| i.topics.each do |t| t.topic_allowed_users.create(user_id: result.id) end end - if Invite.update_all(['user_id = ?', result.id], ['email = ?', self.email]) == 1 + if Invite.update_all(['user_id = ?', result.id], ['email = ?', email]) == 1 result.send_welcome_message = true end # Notify the invitee invited_by.notifications.create(notification_type: Notification.Types[:invitee_accepted], - data: {display_username: result.username}.to_json) + data: { display_username: result.username }.to_json) else # Otherwise return the existing user diff --git a/app/models/notification.rb b/app/models/notification.rb index a3920f015c2..6b1d87ef26b 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -6,6 +6,9 @@ class Notification < ActiveRecord::Base validates_presence_of :data validates_presence_of :notification_type + scope :unread, lambda { where(read: false) } + scope :recent, lambda { order('created_at desc').limit(10) } + def self.Types {:mentioned => 1, :replied => 2, @@ -23,16 +26,8 @@ class Notification < ActiveRecord::Base @inverted_types ||= Notification.Types.invert end - def self.unread - where(read: false) - end - def self.mark_posts_read(user, topic_id, post_numbers) - Notification.update_all "read = 't'", ["user_id = ? and topic_id = ? and post_number in (?) and read = ?", user.id, topic_id, post_numbers, false] - end - - def self.recent - order('created_at desc').limit(10) + Notification.update_all "read = 't'", user_id: user.id, topic_id: topic_id, post_number: post_numbers, read: false end def self.interesting_after(min_date) @@ -68,7 +63,7 @@ class Notification < ActiveRecord::Base def data_hash @data_hash ||= begin return nil if data.blank? - ::JSON.parse(data).with_indifferent_access + JSON.parse(data).with_indifferent_access end end @@ -81,15 +76,12 @@ class Notification < ActiveRecord::Base if topic.present? return topic.relative_url(post_number) end - nil end def post - return nil unless topic_id.present? - return nil unless post_number.present? + return if topic_id.blank? || post_number.blank? Post.where(topic_id: topic_id, post_number: post_number).first end - end diff --git a/app/models/onebox_render.rb b/app/models/onebox_render.rb index 9992d1dd80a..9da3cfffa11 100644 --- a/app/models/onebox_render.rb +++ b/app/models/onebox_render.rb @@ -1,10 +1,8 @@ class OneboxRender < ActiveRecord::Base - validates_presence_of :url validates_presence_of :cooked validates_presence_of :expires_at - has_many :post_onebox_renders, :dependent => :delete_all + has_many :post_onebox_renders, dependent: :delete_all has_many :posts, through: :post_onebox_renders - end diff --git a/app/models/post.rb b/app/models/post.rb index 4f5e4007fda..b926c203d34 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -29,7 +29,7 @@ class Post < ActiveRecord::Base has_many :post_actions validates_presence_of :raw, :user_id, :topic_id - validates :raw, stripped_length: {in: SiteSetting.min_post_length..SiteSetting.max_post_length} + validates :raw, stripped_length: { in: SiteSetting.post_length } validate :raw_quality validate :max_mention_validator validate :max_images_validator @@ -54,15 +54,14 @@ class Post < ActiveRecord::Base after_commit :store_unique_post_key, on: :create after_create do - TopicUser.auto_track(self.user_id, self.topic_id, TopicUser::NotificationReasons::CREATED_POST) + TopicUser.auto_track(user_id, topic_id, TopicUser::NotificationReasons::CREATED_POST) end scope :by_newest, order('created_at desc, id desc') scope :with_user, includes(:user) def raw_quality - - sentinel = TextSentinel.new(self.raw, min_entropy: SiteSetting.body_min_entropy) + sentinel = TextSentinel.new(raw, min_entropy: SiteSetting.body_min_entropy) if sentinel.valid? # It's possible the sentinel has cleaned up the title a bit self.raw = sentinel.text @@ -75,7 +74,7 @@ class Post < ActiveRecord::Base # Stop us from posting the same thing too quickly def unique_post_validator return if SiteSetting.unique_posts_mins == 0 - return if user.admin? or user.has_trust_level?(:moderator) + return if user.admin? || user.moderator? # If the post is empty, default to the validates_presence_of return if raw.blank? @@ -97,13 +96,13 @@ class Post < ActiveRecord::Base end def raw_hash - return nil if raw.blank? + return if raw.blank? Digest::SHA1.hexdigest(raw.gsub(/\s+/, "").downcase) end def cooked_document - self.cooked ||= cook(self.raw, topic_id: topic_id) - @cooked_document ||= Nokogiri::HTML.fragment(self.cooked) + self.cooked ||= cook(raw, topic_id: topic_id) + @cooked_document ||= Nokogiri::HTML.fragment(cooked) end def reset_cooked @@ -116,20 +115,18 @@ class Post < ActiveRecord::Base end def image_count - return 0 unless self.raw.present? + return 0 unless raw.present? - cooked_document.search("img").reject{ |t| + cooked_document.search("img").reject do |t| dom_class = t["class"] if dom_class (Post.white_listed_image_classes & dom_class.split(" ")).count > 0 - else - false end - }.count + end.count end def link_count - return 0 unless self.raw.present? + return 0 unless raw.present? cooked_document.search("a[href]").count end @@ -138,12 +135,12 @@ class Post < ActiveRecord::Base end def max_images_validator - return if user.present? and user.has_trust_level?(:basic) + return if user.present? && user.has_trust_level?(:basic) errors.add(:raw, I18n.t(:too_many_images)) if image_count > 0 end def max_links_validator - return if user.present? and user.has_trust_level?(:basic) + return if user.present? && user.has_trust_level?(:basic) errors.add(:raw, I18n.t(:too_many_links)) if link_count > 1 end @@ -161,22 +158,18 @@ class Post < ActiveRecord::Base doc.search("code").remove results = doc.to_html.scan(PrettyText.mention_matcher) - if results.present? - @raw_mentions = results.uniq.map {|un| un.first.downcase.gsub!(/^@/, '')} - else - @raw_mentions = [] - end + @raw_mentions = results.uniq.map { |un| un.first.downcase.gsub!(/^@/, '') } end # The rules for deletion change depending on who is doing it. def delete_by(deleted_by) - if deleted_by.has_trust_level?(:moderator) + if deleted_by.moderator? # As a moderator, delete the post. Post.transaction do self.destroy - Topic.reset_highest(self.topic_id) + Topic.reset_highest(topic_id) end - elsif deleted_by.id == self.user_id + elsif deleted_by.id == user_id # As the poster, make a revision that says deleted. Post.transaction do revise(deleted_by, I18n.t('js.post.deleted_by_author'), force_new_version: true) @@ -205,7 +198,7 @@ class Post < ActiveRecord::Base PostAction.update_flagged_posts_count end - def filter_quotes(parent_post=nil) + def filter_quotes(parent_post = nil) return cooked if parent_post.blank? # We only filter quotes when there is exactly 1 @@ -229,31 +222,30 @@ class Post < ActiveRecord::Base end def quoteless? - (quote_count == 0) and (reply_to_post_number.present?) + (quote_count == 0) && (reply_to_post_number.present?) end # Get the post that we reply to. def reply_to_user - return nil unless reply_to_post_number.present? - User.where('id = (select user_id from posts where topic_id = ? and post_number = ?)', topic_id, reply_to_post_number).first + return if reply_to_post_number.blank? + Post.where(topic_id: topic_id, post_number: reply_to_post_number).first.try(:user) end def reply_notification_target - return nil unless reply_to_post_number.present? - reply_post = Post.where("topic_id = :topic_id AND post_number = :post_number AND user_id <> :user_id", - topic_id: topic_id, - post_number: reply_to_post_number, - user_id: user_id).first - return reply_post.try(:user) + return if reply_to_post_number.blank? + Post.where("topic_id = :topic_id AND post_number = :post_number AND user_id <> :user_id", + topic_id: topic_id, + post_number: reply_to_post_number, + user_id: user_id).first.try(:user) end - def self.excerpt(cooked, maxlength=nil) + def self.excerpt(cooked, maxlength = nil) maxlength ||= SiteSetting.post_excerpt_maxlength PrettyText.excerpt(cooked, maxlength) end # Strip out most of the markup - def excerpt(maxlength=nil) + def excerpt(maxlength = nil) Post.excerpt(cooked, maxlength) end @@ -279,22 +271,22 @@ class Post < ActiveRecord::Base # A list of versions including the initial version def all_versions result = [] - result << {number: 1, display_username: user.name, created_at: created_at} + result << { number: 1, display_username: user.name, created_at: created_at } versions.order(:number).includes(:user).each do |v| - result << {number: v.number, display_username: v.user.name, created_at: v.created_at} + result << { number: v.number, display_username: v.user.name, created_at: v.created_at } end result end def is_flagged? - post_actions.where('post_action_type_id in (?) and deleted_at is null', PostActionType.FlagTypes).count != 0 + post_actions.where(post_action_type_id: PostActionType.FlagTypes, deleted_at: nil).count != 0 end def unhide! self.hidden = false self.hidden_reason_id = nil self.topic.update_attributes(visible: true) - self.save + save end def url @@ -305,7 +297,7 @@ class Post < ActiveRecord::Base user.readable_name end - def revise(updated_by, new_raw, opts={}) + def revise(updated_by, new_raw, opts = {}) PostRevisor.new(self).revise!(updated_by, new_raw, opts) end @@ -320,21 +312,20 @@ class Post < ActiveRecord::Base # TODO: Move some of this into an asynchronous job? after_create do - # Update attributes on the topic - featured users and last posted. - attrs = {last_posted_at: self.created_at, last_post_user_id: self.user_id} - attrs[:bumped_at] = self.created_at unless no_bump + attrs = {last_posted_at: created_at, last_post_user_id: user_id} + attrs[:bumped_at] = created_at unless no_bump topic.update_attributes(attrs) # Update the user's last posted at date - user.update_column(:last_posted_at, self.created_at) + user.update_column(:last_posted_at, created_at) # Update topic user data TopicUser.change(user, - topic.id, - posted: true, - last_read_post_number: self.post_number, - seen_post_count: self.post_number) + topic.id, + posted: true, + last_read_post_number: post_number, + seen_post_count: post_number) end def email_private_message @@ -371,57 +362,54 @@ class Post < ActiveRecord::Base end before_save do - self.last_editor_id ||= self.user_id + self.last_editor_id ||= user_id self.cooked = cook(raw, topic_id: topic_id) unless new_record? end before_destroy do # Update the last post id to the previous post if it exists - last_post = Post.where("topic_id = ? and id <> ?", self.topic_id, self.id).order('created_at desc').limit(1).first + last_post = Post.where("topic_id = ? and id <> ?", topic_id, id).order('created_at desc').limit(1).first if last_post.present? topic.update_attributes(last_posted_at: last_post.created_at, last_post_user_id: last_post.user_id, highest_post_number: last_post.post_number) # If the poster doesn't have any other posts in the topic, clear their posted flag - unless Post.exists?(["topic_id = ? and user_id = ? and id <> ?", self.topic_id, self.user_id, self.id]) - TopicUser.update_all 'posted = false', ['topic_id = ? and user_id = ?', self.topic_id, self.user_id] + unless Post.exists?(["topic_id = ? and user_id = ? and id <> ?", topic_id, user_id, id]) + TopicUser.update_all 'posted = false', topic_id: topic_id, user_id: user_id end end # Feature users in the topic - Jobs.enqueue(:feature_topic_users, topic_id: topic_id, except_post_id: self.id) + Jobs.enqueue(:feature_topic_users, topic_id: topic_id, except_post_id: id) end after_destroy do - # Remove any reply records that point to deleted posts - post_ids = PostReply.select(:post_id).where(reply_id: self.id).map(&:post_id) - PostReply.delete_all ["reply_id = ?", self.id] + post_ids = PostReply.select(:post_id).where(reply_id: id).map(&:post_id) + PostReply.delete_all reply_id: id if post_ids.present? - Post.where(id: post_ids).each {|p| p.update_column :reply_count, p.replies.count} + Post.where(id: post_ids).each { |p| p.update_column :reply_count, p.replies.count } end # Remove any notifications that point to this deleted post - Notification.delete_all ["topic_id = ? and post_number = ?", self.topic_id, self.post_number] + Notification.delete_all topic_id: topic_id, post_number: post_number end after_save do - - DraftSequence.next! self.last_editor_id, self.topic.draft_key if self.topic # could be deleted + DraftSequence.next! last_editor_id, topic.draft_key if topic # could be deleted quoted_post_numbers << reply_to_post_number if reply_to_post_number.present? # Create a reply relationship between quoted posts and this new post - if self.quoted_post_numbers.present? - self.quoted_post_numbers.map! {|pid| pid.to_i}.uniq! - self.quoted_post_numbers.each do |p| + if quoted_post_numbers.present? + quoted_post_numbers.map(&:to_i).uniq.each do |p| post = Post.where(topic_id: topic_id, post_number: p).first if post.present? - post_reply = post.post_replies.new(reply_id: self.id) + post_reply = post.post_replies.new(reply_id: id) if post_reply.save Post.update_all ['reply_count = reply_count + 1'], id: post.id end @@ -443,7 +431,7 @@ class Post < ActiveRecord::Base if args[:topic].present? # If the topic attribute is present, ensure it's the same topic - self.quoted_post_numbers << args[:post] if self.topic_id == args[:topic] + self.quoted_post_numbers << args[:post] if topic_id == args[:topic] else self.quoted_post_numbers << args[:post] end @@ -452,15 +440,14 @@ class Post < ActiveRecord::Base end self.quoted_post_numbers.uniq! - self.quote_count = self.quoted_post_numbers.size + self.quote_count = quoted_post_numbers.size end # Process this post after comitting it def trigger_post_process - args = {post_id: self.id} - args[:image_sizes] = self.image_sizes if self.image_sizes.present? - args[:invalidate_oneboxes] = true if self.invalidate_oneboxes.present? + args = { post_id: id } + args[:image_sizes] = image_sizes if image_sizes.present? + args[:invalidate_oneboxes] = true if invalidate_oneboxes.present? Jobs.enqueue(:process_post, args) end - end diff --git a/app/models/post_action.rb b/app/models/post_action.rb index 1d5f02e18fc..03b6567a033 100644 --- a/app/models/post_action.rb +++ b/app/models/post_action.rb @@ -19,7 +19,6 @@ class PostAction < ActiveRecord::Base validate :message_quality def self.update_flagged_posts_count - posts_flagged_count = PostAction.joins(post: :topic) .where('post_actions.post_action_type_id' => PostActionType.FlagTypes, 'posts.deleted_at' => nil, @@ -27,7 +26,7 @@ class PostAction < ActiveRecord::Base $redis.set('posts_flagged_count', posts_flagged_count) admins = User.where(admin: true).select(:id).map {|u| u.id} - MessageBus.publish('/flagged_counts', {total: posts_flagged_count}, {user_ids: admins}) + MessageBus.publish('/flagged_counts', { total: posts_flagged_count }, { user_ids: admins }) end def self.flagged_posts_count @@ -35,7 +34,6 @@ class PostAction < ActiveRecord::Base end def self.counts_for(collection, user) - return {} if collection.blank? collection_ids = collection.map {|p| p.id} @@ -53,7 +51,6 @@ class PostAction < ActiveRecord::Base end def self.clear_flags!(post, moderator_id, action_type_id = nil) - # -1 is the automatic system cleary actions = if action_type_id [action_type_id] @@ -61,10 +58,10 @@ class PostAction < ActiveRecord::Base moderator_id == -1 ? PostActionType.AutoActionFlagTypes : PostActionType.FlagTypes end - PostAction.update_all({deleted_at: Time.now, deleted_by: moderator_id}, {post_id: post.id, post_action_type_id: actions}) + PostAction.update_all({ deleted_at: Time.now, deleted_by: moderator_id }, { post_id: post.id, post_action_type_id: actions }) r = PostActionType.Types.invert - f = actions.map{|t| ["#{r[t]}_count", 0]} + f = actions.map { |t| ["#{r[t]}_count", 0] } Post.with_deleted.update_all(Hash[*f.flatten], id: post.id) @@ -82,7 +79,7 @@ class PostAction < ActiveRecord::Base end def self.remove_act(user, post, post_action_type_id) - if action = self.where(post_id: post.id, user_id: user.id, post_action_type_id: post_action_type_id).first + if action = where(post_id: post.id, user_id: user.id, post_action_type_id: post_action_type_id).first action.destroy action.deleted_at = Time.now action.run_callbacks(:save) @@ -103,7 +100,7 @@ class PostAction < ActiveRecord::Base # A custom rate limiter for this model def post_action_rate_limiter - return nil unless is_flag? or is_bookmark? or is_like? + return unless is_flag? || is_bookmark? || is_like? return @rate_limiter if @rate_limiter.present? @@ -127,20 +124,20 @@ class PostAction < ActiveRecord::Base end before_create do - raise AlreadyFlagged if is_flag? and PostAction.where(user_id: user_id, - post_id: post_id, - post_action_type_id: PostActionType.FlagTypes).exists? + raise AlreadyFlagged if is_flag? && PostAction.where(user_id: user_id, + post_id: post_id, + post_action_type_id: PostActionType.FlagTypes).exists? end after_save do # Update denormalized counts post_action_type = PostActionType.Types.invert[post_action_type_id] - column = "#{post_action_type.to_s}_count" + column = "#{post_action_type}_count" delta = deleted_at.nil? ? 1 : -1 # Voting also changes the sort_order if post_action_type == :vote - Post.update_all ["vote_count = vote_count + :delta, sort_order = :max - (vote_count + :delta)", delta: delta, max: Topic::MAX_SORT_ORDER], ["id = ?", post_id] + Post.update_all ["vote_count = vote_count + :delta, sort_order = :max - (vote_count + :delta)", delta: delta, max: Topic::MAX_SORT_ORDER], id: post_id else Post.update_all ["#{column} = #{column} + ?", delta], id: post_id end @@ -162,18 +159,16 @@ class PostAction < ActiveRecord::Base if new_flags >= SiteSetting.flags_required_to_hide_post reason = old_flags > 0 ? Post::HiddenReason::FLAG_THRESHOLD_REACHED_AGAIN : Post::HiddenReason::FLAG_THRESHOLD_REACHED Post.update_all(["hidden = true, hidden_reason_id = COALESCE(hidden_reason_id, ?)", reason], id: post_id) - Topic.update_all({visible: false}, + Topic.update_all({ visible: false }, ["id = :topic_id AND NOT EXISTS(SELECT 1 FROM POSTS WHERE topic_id = :topic_id AND NOT hidden)", topic_id: post.topic_id]) # inform user - if self.post.user - SystemMessage.create(self.post.user, :post_hidden, - url: self.post.url, + if post.user + SystemMessage.create(post.user, :post_hidden, + url: post.url, edit_delay: SiteSetting.cooldown_minutes_after_hiding_posts) end end - end - end end diff --git a/app/models/post_action_type.rb b/app/models/post_action_type.rb index 1319eafada7..ed9997facfa 100644 --- a/app/models/post_action_type.rb +++ b/app/models/post_action_type.rb @@ -1,19 +1,19 @@ class PostActionType < ActiveRecord::Base - attr_accessible :id, :is_flag, :name_key, :icon def self.ordered - self.order('position asc').all + order('position asc').all end def self.Types - @types ||= {:bookmark => 1, - :like => 2, - :off_topic => 3, - :inappropriate => 4, - :vote => 5, - :custom_flag => 6, - :spam => 8 + { + bookmark: 1, + like: 2, + off_topic: 3, + inappropriate: 4, + vote: 5, + custom_flag: 6, + spam: 8 } end @@ -28,5 +28,4 @@ class PostActionType < ActiveRecord::Base def self.FlagTypes @flag_types ||= self.AutoActionFlagTypes + [self.Types[:custom_flag]] end - end diff --git a/app/models/post_alert_observer.rb b/app/models/post_alert_observer.rb index 30e1777be2a..bb15c32020c 100644 --- a/app/models/post_alert_observer.rb +++ b/app/models/post_alert_observer.rb @@ -25,12 +25,11 @@ class PostAlertObserver < ActiveRecord::Observer def after_save_post_action(post_action) # We only care about deleting post actions for now - return unless post_action.deleted_at.present? - Notification.where(["post_action_id = ?", post_action.id]).each {|n| n.destroy} + return if post_action.deleted_at.blank? + Notification.where(post_action_id: post_action.id).each(&:destroy) end def after_create_post_action(post_action) - # We only notify on likes for now return unless post_action.is_like? @@ -59,7 +58,7 @@ class PostAlertObserver < ActiveRecord::Observer def after_create_post(post) if post.topic.private_message? # If it's a private message, notify the topic_allowed_users - post.topic.topic_allowed_users.reject{|a| a.user_id == post.user_id}.each do |a| + post.topic.topic_allowed_users.reject { |a| a.user_id == post.user_id }.each do |a| create_notification(a.user, Notification.Types[:private_message], post) end else @@ -91,13 +90,13 @@ class PostAlertObserver < ActiveRecord::Observer topic_id: post.topic_id, post_number: post.post_number, post_action_id: opts[:post_action_id], - data: {topic_title: post.topic.title, - display_username: opts[:display_username] || post.user.username}.to_json) + data: { topic_title: post.topic.title, + display_username: opts[:display_username] || post.user.username }.to_json) end # Returns a list users who have been mentioned def extract_mentioned_users(post) - User.where("username_lower in (?)", post.raw_mentions).where("id <> ?", post.user_id) + User.where(username_lower: post.raw_mentions).where("id <> ?", post.user_id) end # Returns a list of users who were quoted in the post @@ -121,24 +120,21 @@ class PostAlertObserver < ActiveRecord::Observer # TODO: This should use javascript for parsing rather than re-doing it this way. def notify_post_users(post) - # Is this post a reply to a user? reply_to_user = post.reply_notification_target notify_users(reply_to_user, :replied, post) - # find all users watching if post.post_number > 1 exclude_user_ids = [] exclude_user_ids << post.user_id exclude_user_ids << reply_to_user.id if reply_to_user.present? - exclude_user_ids << extract_mentioned_users(post).map{|u| u.id} - exclude_user_ids << extract_quoted_users(post).map{|u| u.id} + exclude_user_ids << extract_mentioned_users(post).map(&:id) + exclude_user_ids << extract_quoted_users(post).map(&:id) exclude_user_ids.flatten! TopicUser.where(topic_id: post.topic_id, notification_level: TopicUser::NotificationLevel::WATCHING).includes(:user).each do |tu| create_notification(tu.user, Notification.Types[:posted], post) unless exclude_user_ids.include?(tu.user_id) end end end - end diff --git a/app/models/post_reply.rb b/app/models/post_reply.rb index d5bf806ad47..251db65b48e 100644 --- a/app/models/post_reply.rb +++ b/app/models/post_reply.rb @@ -1,5 +1,4 @@ class PostReply < ActiveRecord::Base - belongs_to :post belongs_to :reply, class_name: 'Post' diff --git a/app/models/post_timing.rb b/app/models/post_timing.rb index b2f72b4fb61..1caeaf30737 100644 --- a/app/models/post_timing.rb +++ b/app/models/post_timing.rb @@ -1,5 +1,4 @@ class PostTiming < ActiveRecord::Base - belongs_to :topic belongs_to :user @@ -9,7 +8,6 @@ class PostTiming < ActiveRecord::Base # Increases a timer if a row exists, otherwise create it def self.record_timing(args) - rows = exec_sql_row_count("UPDATE post_timings SET msecs = msecs + :msecs WHERE topic_id = :topic_id @@ -28,7 +26,6 @@ class PostTiming < ActiveRecord::Base args) end - end @@ -43,7 +40,6 @@ class PostTiming < ActiveRecord::Base def self.process_timings(current_user, topic_id, highest_seen, topic_time, timings) current_user.update_time_read! - original_unread = current_user.unread_notifications_by_type timings.each do |post_number, time| if post_number >= 0 PostTiming.record_timing(topic_id: topic_id, @@ -64,7 +60,5 @@ class PostTiming < ActiveRecord::Base current_user.reload current_user.publish_notifications_state end - end - end diff --git a/app/models/search_observer.rb b/app/models/search_observer.rb index 0c346eddeda..4619dbcd9d3 100644 --- a/app/models/search_observer.rb +++ b/app/models/search_observer.rb @@ -58,7 +58,6 @@ class SearchObserver < ActiveRecord::Observer end - class HtmlScrubber < Nokogiri::XML::SAX::Document attr_reader :scrubbed @@ -67,7 +66,7 @@ class SearchObserver < ActiveRecord::Observer end def self.scrub(html) - me = self.new + me = new parser = Nokogiri::HTML::SAX::Parser.new(me) begin copy = "