Class: Virgo::Post

Inherits:
ActiveRecord::Base
  • Object
show all
Extended by:
FriendlyId
Includes:
ActionView::Helpers::SanitizeHelper, Common::SlugHistory, Common::Uuid, Recommendations, Search
Defined in:
app/models/virgo/post.rb,
app/models/concerns/virgo/post/search.rb,
app/models/concerns/virgo/post/recommendations.rb

Defined Under Namespace

Modules: Recommendations, Search

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#ordered_tag_idsObject

Returns the value of attribute ordered_tag_ids.



13
14
15
# File 'app/models/virgo/post.rb', line 13

def ordered_tag_ids
  @ordered_tag_ids
end

Class Method Details

.cache_keyObject



209
210
211
# File 'app/models/virgo/post.rb', line 209

def self.cache_key
  "posts-#{maximum(:updated_at).try(:to_i)}-#{all.size}"
end

.category_feature(category) ⇒ Object



114
115
116
# File 'app/models/virgo/post.rb', line 114

def self.category_feature(category)
  category.posts.publicly_viewable.where(feature_on_category_page: true).order(publish_at: :asc).last
end

.front_page_featureObject



118
119
120
# File 'app/models/virgo/post.rb', line 118

def self.front_page_feature
  posts.publicly_viewable.where(feature_on_front_page: true).order(publish_at: :asc).last
end

.publish_scheduled!Object



168
169
170
171
172
173
174
# File 'app/models/virgo/post.rb', line 168

def self.publish_scheduled!
  candidates = Post.where.not(live: true).where("publish_at <= ?", Time.now.to_datetime)

  candidates.each do |post|
    post.update(live: true)
  end
end

.status_namesObject



154
155
156
157
158
159
160
161
162
# File 'app/models/virgo/post.rb', line 154

def self.status_names
  {
    'Draft' => :draft,
    'Assigned' => :assigned,
    'Published' => :published,
    'Killed' => :killed,
    'Hidden' => :hidden
  }
end

Instance Method Details

#apply_tag_ordering!Object



248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'app/models/virgo/post.rb', line 248

def apply_tag_ordering!
  if ordered_tag_ids.present?
    if ordered_tag_ids.first.is_a?(String)
      cleaned = ordered_tag_ids.first.gsub("[", "").gsub("]", "").split(",").map(&:to_i)
      ordered_tag_ids = cleaned
    end

    ordered_tag_ids.each_with_index do |tag_id, index|
      existing = .find_by(tag_id: tag_id)

      if existing
        existing.update!(position: index)
      else
        tag = Tag.find_by(id: tag_id)

        if tag
          .create!(tag_id: tag_id, position: index)
        end
      end
    end

    .where.not(tag_id: ordered_tag_ids).map &:destroy
  end

  true
end

#assigned?Boolean

Returns:

  • (Boolean)


130
131
132
# File 'app/models/virgo/post.rb', line 130

def assigned?
  status == :assigned
end

#attempt_edit_lock(user) ⇒ Object



197
198
199
200
201
202
203
# File 'app/models/virgo/post.rb', line 197

def attempt_edit_lock(user)
  if is_mid_edit? && editing_user != user
    false
  else
    lock_for_editing!(user) if persisted?
  end
end

#calc_popularityObject

based on reddit “hot” algorithm: gist.github.com/jrochkind/2636355



230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'app/models/virgo/post.rb', line 230

def calc_popularity
  unless publish_at.nil?
    s = view_count
    displacement = Math.log( [s.abs, 1].max,  10 )
    sign = if s > 0
      1
    elsif s < 0
      -1
    else
      0
    end

    rank = (displacement * sign.to_f) + ( epoch_seconds(publish_at) / 45000 )
  else
    0
  end
end

#descriptionObject



279
280
281
282
283
284
285
286
287
# File 'app/models/virgo/post.rb', line 279

def description
  if meta_description_tag_value.present?
    meta_description_tag_value
  elsif excerpt.present?
    view_help.truncate(excerpt, length: 160)
  else
    view_help.truncate(view_help.strip_tags(rendered_body || ''), length: 160)
  end
end

#disqus_identifierObject



164
165
166
# File 'app/models/virgo/post.rb', line 164

def disqus_identifier
  "post_#{id}"
end

#draft?Boolean

Returns:

  • (Boolean)


126
127
128
# File 'app/models/virgo/post.rb', line 126

def draft?
  status == :draft
end

#edit_lock_timeoutObject



205
206
207
# File 'app/models/virgo/post.rb', line 205

def edit_lock_timeout
  Rails.application.config.edit_lock_timeout
end

#epochObject



224
225
226
# File 'app/models/virgo/post.rb', line 224

def epoch
  DateTime.zero.to_time
end

#epoch_seconds(t) ⇒ Object



220
221
222
# File 'app/models/virgo/post.rb', line 220

def epoch_seconds(t)
  (t.to_i - epoch.to_i).to_f
end

#has_citation?Boolean

Returns:

  • (Boolean)


176
177
178
# File 'app/models/virgo/post.rb', line 176

def has_citation?
  citation_name.present? && citation_url.present?
end

#hidden?Boolean

Returns:

  • (Boolean)


142
143
144
# File 'app/models/virgo/post.rb', line 142

def hidden?
  status == :hidden
end

#is_mid_edit?Boolean

i.e. if the lock timeout is “15 seconds” but the post’s “editing_timestamp” has been bumped less than 15 seconds ago, we say the post is “mid-edit”

Returns:

  • (Boolean)


189
190
191
# File 'app/models/virgo/post.rb', line 189

def is_mid_edit?
  editing_timestamp && editing_timestamp > edit_lock_timeout.ago
end

#killed?Boolean

Returns:

  • (Boolean)


138
139
140
# File 'app/models/virgo/post.rb', line 138

def killed?
  status == :killed
end

#lock_for_editing!(user) ⇒ Object



193
194
195
# File 'app/models/virgo/post.rb', line 193

def lock_for_editing!(user)
  update!(editing_timestamp: Time.now.to_datetime, editing_user: user)
end

#page?Boolean

Returns:

  • (Boolean)


146
147
148
# File 'app/models/virgo/post.rb', line 146

def page?
  post_type == :page
end

#post?Boolean

Returns:

  • (Boolean)


150
151
152
# File 'app/models/virgo/post.rb', line 150

def post?
  post_type == :post
end

#primary_categoryObject



275
276
277
# File 'app/models/virgo/post.rb', line 275

def primary_category
  categories.first
end

#published?Boolean

Returns:

  • (Boolean)


134
135
136
# File 'app/models/virgo/post.rb', line 134

def published?
  status == :published
end

#rendered_bodyObject



122
123
124
# File 'app/models/virgo/post.rb', line 122

def rendered_body
  @rendered_body ||= Shortcode.process(body || '').html_safe
end

#thumb_imageObject



289
290
291
292
293
294
295
# File 'app/models/virgo/post.rb', line 289

def thumb_image
  if thumbnail_image.present?
    thumbnail_image
  else
    featured_image
  end
end

#track_view!Object



213
214
215
216
217
218
# File 'app/models/virgo/post.rb', line 213

def track_view!
  update_columns({
    view_count: (view_count + 1),
    popularity: calc_popularity
  })
end

#unscoped_versionsObject

need to explicitly unscope this because papertrail imposes a forward chronological order with a default scope



182
183
184
# File 'app/models/virgo/post.rb', line 182

def unscoped_versions
  PaperTrail::Version.unscoped.where(item_id: id)
end