ぼざクリタグ広場 https://hub.nizika.monster
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.
 
 
 
 
 
 

107 lines
3.1 KiB

  1. class Post < ApplicationRecord
  2. require 'mini_magick'
  3. belongs_to :parent, class_name: 'Post', optional: true, foreign_key: 'parent_id'
  4. belongs_to :uploaded_user, class_name: 'User', optional: true
  5. has_many :post_tags, dependent: :destroy, inverse_of: :post
  6. has_many :active_post_tags, -> { kept }, class_name: 'PostTag', inverse_of: :post
  7. has_many :post_tags_with_discarded, -> { with_discarded }, class_name: 'PostTag'
  8. has_many :tags, through: :active_post_tags
  9. has_many :user_post_views, dependent: :destroy
  10. has_many :post_similarities_as_post,
  11. class_name: 'PostSimilarity',
  12. foreign_key: :post_id
  13. has_many :post_similarities_as_target_post,
  14. class_name: 'PostSimilarity',
  15. foreign_key: :target_post_id
  16. has_one_attached :thumbnail
  17. before_validation :normalise_url
  18. validates :url, presence: true, uniqueness: true
  19. validate :validate_original_created_range
  20. validate :url_must_be_http_url
  21. def as_json options = { }
  22. super(options).merge({ thumbnail: thumbnail.attached? ?
  23. Rails.application.routes.url_helpers.rails_blob_url(
  24. thumbnail, only_path: false) :
  25. nil })
  26. rescue
  27. super(options).merge(thumbnail: nil)
  28. end
  29. def related(limit: nil)
  30. ids_with_cos =
  31. post_similarities_as_post.select(:target_post_id, :cos)
  32. .map { |ps| [ps.target_post_id, ps.cos] } +
  33. post_similarities_as_target_post.select(:post_id, :cos)
  34. .map { |ps| [ps.post_id, ps.cos] }
  35. sorted = ids_with_cos.sort_by { |_, cos| -cos }
  36. ids = sorted.map(&:first)
  37. ids = ids.first(limit) if limit
  38. Post.where(id: ids).index_by(&:id).values_at(*ids)
  39. end
  40. def resized_thumbnail!
  41. return unless thumbnail.attached?
  42. image = MiniMagick::Image.read(thumbnail.download)
  43. image.resize '180x180'
  44. thumbnail.purge
  45. thumbnail.attach(io: File.open(image.path),
  46. filename: 'resized_thumbnail.jpg',
  47. content_type: 'image/jpeg')
  48. end
  49. private
  50. def validate_original_created_range
  51. f = original_created_from
  52. b = original_created_before
  53. return if f.blank? || b.blank?
  54. f = Time.zone.parse(f) if String === f
  55. b = Time.zone.parse(b) if String === b
  56. return if !(f) || !(b)
  57. if f >= b
  58. errors.add :original_created_before, 'オリジナルの作成日時の順番がをかしぃです.'
  59. end
  60. end
  61. def url_must_be_http_url
  62. begin
  63. u = URI.parse(url)
  64. rescue URI::InvalidURIError
  65. errors.add(:url, 'URL が不正です.')
  66. return
  67. end
  68. if !(u in URI::HTTP) || u.host.blank?
  69. errors.add(:url, 'URL が不正です.')
  70. return
  71. end
  72. end
  73. def normalise_url
  74. return if url.blank?
  75. self.url = url.strip
  76. u = URI.parse(url)
  77. return unless u in URI::HTTP
  78. u.host = u.host.downcase if u.host
  79. u.path = u.path.sub(/\/\Z/, '') if u.path.present?
  80. self.url = u.to_s
  81. rescue URI::InvalidURIError
  82. ;
  83. end
  84. end