ぼざクリタグ広場 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.
 
 
 
 

161 lines
4.2 KiB

  1. class Post < ApplicationRecord
  2. require 'mini_magick'
  3. belongs_to :uploaded_user, class_name: 'User', optional: true
  4. has_many :post_tags, dependent: :destroy, inverse_of: :post
  5. has_many :active_post_tags, -> { kept }, class_name: 'PostTag', inverse_of: :post
  6. has_many :post_tags_with_discarded, -> { with_discarded }, class_name: 'PostTag'
  7. has_many :tags, through: :active_post_tags
  8. has_many :user_post_views, dependent: :delete_all
  9. has_many :post_similarities, dependent: :delete_all
  10. has_many :post_versions
  11. has_many :parent_post_implications,
  12. class_name: 'PostImplication',
  13. foreign_key: :post_id,
  14. dependent: :destroy,
  15. inverse_of: :post
  16. has_many :parents, through: :parent_post_implications, source: :parent_post
  17. has_many :child_post_implications,
  18. class_name: 'PostImplication',
  19. foreign_key: :parent_post_id,
  20. dependent: :destroy,
  21. inverse_of: :parent_post
  22. has_many :children, through: :child_post_implications, source: :post
  23. has_one_attached :thumbnail
  24. attribute :version_no, :integer, default: 1
  25. before_validation :normalise_url
  26. validates :url, presence: true, uniqueness: true
  27. validate :validate_original_created_range
  28. validate :url_must_be_http_url
  29. def parent_posts = parents
  30. def child_posts = children
  31. def sibling_posts
  32. parent_post_ids = parent_posts.order(:id).pluck(:id)
  33. parent_post_ids.to_h { [_1, PostImplication.where(parent_post: _1).map(&:post)] }
  34. end
  35. def as_json options = { }
  36. super(options).merge(thumbnail: thumbnail.attached? ?
  37. Rails.application.routes.url_helpers.rails_blob_url(
  38. thumbnail, only_path: false) :
  39. nil)
  40. rescue
  41. super(options).merge(thumbnail: nil)
  42. end
  43. def snapshot_tag_names
  44. post_tags
  45. .kept
  46. .joins(tag: :tag_name)
  47. .includes(:sections, tag: :tag_name)
  48. .order('tag_names.name')
  49. .map do |post_tag|
  50. name = post_tag.tag.tag_name.name
  51. sections = post_tag.sections.sort_by(&:begin_ms)
  52. next name if sections.empty?
  53. "#{ name }#{ sections.map { Post.section_literal(_1) }.join }"
  54. end
  55. end
  56. def self.section_literal section
  57. "[#{ Post.ms_to_time(section.begin_ms) }-#{ Post.ms_to_time(section.end_ms) }]"
  58. end
  59. def self.ms_to_time ms
  60. total_s = ms / 1_000
  61. s = total_s % 60
  62. min = (total_s / 60) % 60
  63. h = total_s / 3_600
  64. if h.positive?
  65. '%d:%02d:%02d' % [h, min, s]
  66. else
  67. '%d:%02d' % [min, s]
  68. end
  69. end
  70. def snapshot_parent_post_ids = parents.order(:id).pluck(:id)
  71. def related limit: nil
  72. ids = post_similarities.order(cos: :desc)
  73. ids = ids.limit(limit) if limit
  74. ids = ids.pluck(:target_post_id)
  75. return Post.none if ids.empty?
  76. Post.where(id: ids)
  77. .with_attached_thumbnail
  78. .order(Arel.sql("FIELD(posts.id, #{ ids.join(',') })"))
  79. end
  80. def resized_thumbnail!
  81. return unless thumbnail.attached?
  82. image = MiniMagick::Image.read(thumbnail.download)
  83. image.resize '180x180'
  84. thumbnail.purge
  85. thumbnail.attach(io: File.open(image.path),
  86. filename: 'resized_thumbnail.jpg',
  87. content_type: 'image/jpeg')
  88. end
  89. private
  90. def validate_original_created_range
  91. f = original_created_from
  92. b = original_created_before
  93. return if f.blank? || b.blank?
  94. f = Time.zone.parse(f) if String === f
  95. b = Time.zone.parse(b) if String === b
  96. return if !(f) || !(b)
  97. if f >= b
  98. errors.add :original_created_before, 'オリジナルの作成日時の順番がをかしぃです.'
  99. end
  100. end
  101. def url_must_be_http_url
  102. begin
  103. u = URI.parse(url)
  104. rescue URI::InvalidURIError
  105. errors.add(:url, 'URL が不正です.')
  106. return
  107. end
  108. if !(u in URI::HTTP) || u.host.blank?
  109. errors.add(:url, 'URL が不正です.')
  110. return
  111. end
  112. end
  113. def normalise_url
  114. return if url.blank?
  115. self.url = url.strip
  116. u = URI.parse(url)
  117. return unless u in URI::HTTP
  118. u.host = u.host.downcase if u.host
  119. u.path = u.path.sub(/\/\Z/, '') if u.path.present?
  120. self.url = u.to_s
  121. rescue URI::InvalidURIError
  122. ;
  123. end
  124. end