add option to automatically space out boosts over configurable random intervals
parent
a8475313b8
commit
ef04f3879a
|
@ -56,6 +56,10 @@ class Settings::PreferencesController < Settings::BaseController
|
||||||
:setting_roar_lifespan,
|
:setting_roar_lifespan,
|
||||||
:setting_delayed_roars,
|
:setting_delayed_roars,
|
||||||
:setting_delayed_for,
|
:setting_delayed_for,
|
||||||
|
:setting_boost_interval,
|
||||||
|
:setting_boost_random,
|
||||||
|
:setting_boost_interval_from,
|
||||||
|
:setting_boost_interval_to,
|
||||||
:setting_show_cursor,
|
:setting_show_cursor,
|
||||||
|
|
||||||
:setting_default_privacy,
|
:setting_default_privacy,
|
||||||
|
|
|
@ -40,6 +40,10 @@ class UserSettingsDecorator
|
||||||
user.settings['roar_lifespan'] = roar_lifespan_preference if change?('setting_roar_lifespan')
|
user.settings['roar_lifespan'] = roar_lifespan_preference if change?('setting_roar_lifespan')
|
||||||
user.settings['delayed_roars'] = delayed_roars_preference if change?('setting_delayed_roars')
|
user.settings['delayed_roars'] = delayed_roars_preference if change?('setting_delayed_roars')
|
||||||
user.settings['delayed_for'] = delayed_for_preference if change?('setting_delayed_for')
|
user.settings['delayed_for'] = delayed_for_preference if change?('setting_delayed_for')
|
||||||
|
user.settings['boost_interval'] = boost_interval_preference if change?('setting_boost_interval')
|
||||||
|
user.settings['boost_random'] = boost_random_preference if change?('setting_boost_random')
|
||||||
|
user.settings['boost_interval_from'] = boost_interval_from_preference if change?('setting_boost_interval_from')
|
||||||
|
user.settings['boost_interval_to'] = boost_interval_to_preference if change?('setting_boost_interval_to')
|
||||||
user.settings['show_cursor'] = show_cursor_preference if change?('setting_show_cursor')
|
user.settings['show_cursor'] = show_cursor_preference if change?('setting_show_cursor')
|
||||||
|
|
||||||
user.settings['notification_emails'] = merged_notification_emails if change?('notification_emails')
|
user.settings['notification_emails'] = merged_notification_emails if change?('notification_emails')
|
||||||
|
@ -150,6 +154,26 @@ class UserSettingsDecorator
|
||||||
boolean_cast_setting 'setting_delayed_roars'
|
boolean_cast_setting 'setting_delayed_roars'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def boost_interval_preference
|
||||||
|
boolean_cast_setting 'setting_boost_interval'
|
||||||
|
end
|
||||||
|
|
||||||
|
def boost_random_preference
|
||||||
|
boolean_cast_setting 'setting_boost_random'
|
||||||
|
end
|
||||||
|
|
||||||
|
def boost_interval_from_preference
|
||||||
|
settings['setting_boost_interval_from']
|
||||||
|
end
|
||||||
|
|
||||||
|
def boost_interval_to_preference
|
||||||
|
settings['setting_boost_interval_to']
|
||||||
|
end
|
||||||
|
|
||||||
|
def delayed_for_preference
|
||||||
|
settings['setting_delayed_for']
|
||||||
|
end
|
||||||
|
|
||||||
def merged_notification_emails
|
def merged_notification_emails
|
||||||
user.settings['notification_emails'].merge coerced_settings('notification_emails').to_h
|
user.settings['notification_emails'].merge coerced_settings('notification_emails').to_h
|
||||||
end
|
end
|
||||||
|
|
|
@ -58,5 +58,8 @@ module AccountAssociations
|
||||||
# Hashtags
|
# Hashtags
|
||||||
has_and_belongs_to_many :tags
|
has_and_belongs_to_many :tags
|
||||||
has_many :featured_tags, -> { includes(:tag) }, dependent: :destroy, inverse_of: :account
|
has_many :featured_tags, -> { includes(:tag) }, dependent: :destroy, inverse_of: :account
|
||||||
|
|
||||||
|
# queued boosts
|
||||||
|
has_many :queued_boosts, dependent: :destroy, inverse_of: :account
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
# == Schema Information
|
||||||
|
#
|
||||||
|
# Table name: queued_boosts
|
||||||
|
#
|
||||||
|
# id :bigint(8) not null, primary key
|
||||||
|
# account_id :bigint(8)
|
||||||
|
# status_id :bigint(8)
|
||||||
|
# created_at :datetime not null
|
||||||
|
# updated_at :datetime not null
|
||||||
|
#
|
||||||
|
|
||||||
|
class QueuedBoost < ApplicationRecord
|
||||||
|
belongs_to :account, inverse_of: :queued_boosts
|
||||||
|
belongs_to :status, inverse_of: :queued_boosts
|
||||||
|
|
||||||
|
validates :account_id, uniqueness: { scope: :status_id }
|
||||||
|
end
|
|
@ -76,6 +76,8 @@ class Status < ApplicationRecord
|
||||||
has_many :active_mentions, -> { active }, class_name: 'Mention', inverse_of: :status
|
has_many :active_mentions, -> { active }, class_name: 'Mention', inverse_of: :status
|
||||||
has_many :media_attachments, dependent: :nullify
|
has_many :media_attachments, dependent: :nullify
|
||||||
|
|
||||||
|
has_many :queued_boosts, dependent: :destroy, inverse_of: :status
|
||||||
|
|
||||||
has_and_belongs_to_many :tags
|
has_and_belongs_to_many :tags
|
||||||
has_and_belongs_to_many :preview_cards
|
has_and_belongs_to_many :preview_cards
|
||||||
|
|
||||||
|
|
|
@ -131,6 +131,10 @@ class User < ApplicationRecord
|
||||||
:roar_lifespan,
|
:roar_lifespan,
|
||||||
:delayed_roars,
|
:delayed_roars,
|
||||||
:delayed_for,
|
:delayed_for,
|
||||||
|
:boost_interval,
|
||||||
|
:boost_random,
|
||||||
|
:boost_interval_from,
|
||||||
|
:boost_interval_to,
|
||||||
:show_cursor,
|
:show_cursor,
|
||||||
|
|
||||||
:auto_play_gif,
|
:auto_play_gif,
|
||||||
|
@ -303,11 +307,11 @@ class User < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def max_public_history
|
def max_public_history
|
||||||
@_max_public_history ||= (settings.max_public_history || 6)
|
@_max_public_history ||= [1, (settings.max_public_history || 6).to_i].max
|
||||||
end
|
end
|
||||||
|
|
||||||
def roar_lifespan
|
def roar_lifespan
|
||||||
@_roar_lifespan ||= (settings.roar_lifespan || 0)
|
@_roar_lifespan ||= [0, (settings.roar_lifespan || 0).to_i].max
|
||||||
end
|
end
|
||||||
|
|
||||||
def delayed_roars?
|
def delayed_roars?
|
||||||
|
@ -315,7 +319,23 @@ class User < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def delayed_for
|
def delayed_for
|
||||||
@_delayed_for ||= (settings.delayed_for || 60)
|
@_delayed_for ||= [5, (settings.delayed_for || 60).to_i].max
|
||||||
|
end
|
||||||
|
|
||||||
|
def boost_interval?
|
||||||
|
@boost_interval ||= (settings.boost_interval || false)
|
||||||
|
end
|
||||||
|
|
||||||
|
def boost_random?
|
||||||
|
@boost_random ||= (settings.boost_random || false)
|
||||||
|
end
|
||||||
|
|
||||||
|
def boost_interval_from
|
||||||
|
@boost_interval_from ||= [1, (settings.boost_interval_from || 1).to_i].max
|
||||||
|
end
|
||||||
|
|
||||||
|
def boost_interval_to
|
||||||
|
@boost_interval_to ||= [2, (settings.boost_interval_to || 15).to_i].max
|
||||||
end
|
end
|
||||||
|
|
||||||
def shows_cursor?
|
def shows_cursor?
|
||||||
|
|
|
@ -14,22 +14,30 @@ class ReblogService < BaseService
|
||||||
authorize_with account, reblogged_status, :reblog?
|
authorize_with account, reblogged_status, :reblog?
|
||||||
|
|
||||||
reblog = account.statuses.find_by(reblog: reblogged_status)
|
reblog = account.statuses.find_by(reblog: reblogged_status)
|
||||||
|
new_reblog = reblog.nil?
|
||||||
|
|
||||||
return reblog unless reblog.nil?
|
if new_reblog
|
||||||
|
visibility = options[:visibility] || account.user&.setting_default_privacy
|
||||||
visibility = options[:visibility] || account.user&.setting_default_privacy
|
visibility = reblogged_status.visibility if reblogged_status.hidden?
|
||||||
visibility = reblogged_status.visibility if reblogged_status.hidden?
|
reblog = account.statuses.create!(reblog: reblogged_status, text: '', visibility: visibility)
|
||||||
reblog = account.statuses.create!(reblog: reblogged_status, text: '', visibility: visibility)
|
|
||||||
|
|
||||||
DistributionWorker.perform_async(reblog.id)
|
|
||||||
|
|
||||||
unless reblogged_status.local_only?
|
|
||||||
ActivityPub::DistributionWorker.perform_async(reblog.id)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
curate_status(reblogged_status)
|
if !options[:distribute] && account&.user&.boost_interval?
|
||||||
create_notification(reblog) unless options[:skip_notify]
|
QueuedBoost.find_or_create_by!(account_id: account.id, status_id: reblogged_status.id) if account&.user&.boost_interval?
|
||||||
bump_potential_friendship(account, reblog)
|
elsif !options[:nodistribute]
|
||||||
|
return reblog unless options[:distribute] || new_reblog
|
||||||
|
|
||||||
|
DistributionWorker.perform_async(reblog.id)
|
||||||
|
|
||||||
|
unless reblogged_status.local_only?
|
||||||
|
ActivityPub::DistributionWorker.perform_async(reblog.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
curate_status(reblogged_status)
|
||||||
|
|
||||||
|
create_notification(reblog) unless options[:skip_notify]
|
||||||
|
bump_potential_friendship(account, reblog)
|
||||||
|
end
|
||||||
|
|
||||||
reblog
|
reblog
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,6 +17,7 @@ class RemoveStatusService < BaseService
|
||||||
|
|
||||||
RedisLock.acquire(lock_options) do |lock|
|
RedisLock.acquire(lock_options) do |lock|
|
||||||
if lock.acquired?
|
if lock.acquired?
|
||||||
|
remove_from_queued
|
||||||
remove_from_self if status.account.local?
|
remove_from_self if status.account.local?
|
||||||
remove_from_followers
|
remove_from_followers
|
||||||
remove_from_lists
|
remove_from_lists
|
||||||
|
@ -46,6 +47,11 @@ class RemoveStatusService < BaseService
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def remove_from_queued
|
||||||
|
QueuedBoost.where(account_id: @account.id, status_id: @status.proper.id).destroy_all
|
||||||
|
QueuedBoost.where(status_id: @status.id).destroy_all
|
||||||
|
end
|
||||||
|
|
||||||
def remove_from_self
|
def remove_from_self
|
||||||
FeedManager.instance.unpush_from_home(@account, @status)
|
FeedManager.instance.unpush_from_home(@account, @status)
|
||||||
end
|
end
|
||||||
|
|
|
@ -35,7 +35,13 @@
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :setting_delayed_roars, as: :boolean, wrapper: :with_label
|
= f.input :setting_delayed_roars, as: :boolean, wrapper: :with_label
|
||||||
= f.input :setting_delayed_for, collection: [5, 10, 15, 30, 60, 120, 180, 300, 360, 600, 1800, 3600], wrapper: :with_label, include_blank: false, label_method: lambda { |item| safe_join([t("simple_form.labels.delayed_for.#{item}")]) }, selected: [5, current_user.delayed_for.to_i].max
|
= f.input :setting_delayed_for, collection: [5, 10, 15, 30, 60, 120, 180, 300, 360, 600, 1800, 3600], wrapper: :with_label, include_blank: false, label_method: lambda { |item| safe_join([t("simple_form.labels.delayed_for.#{item}")]) }, selected: current_user.delayed_for
|
||||||
|
|
||||||
|
.fields-group
|
||||||
|
= f.input :setting_boost_interval, as: :boolean, wrapper: :with_label
|
||||||
|
= f.input :setting_boost_random, as: :boolean, wrapper: :with_label
|
||||||
|
= f.input :setting_boost_interval_from, collection: [1, 2, 3, 4, 5, 6, 10, 15, 30, 60, 120, 180, 300, 360, 720, 1440], wrapper: :with_label, include_blank: false, label_method: lambda { |item| safe_join([t("simple_form.labels.boost_interval.#{item}")]) }, selected: current_user.boost_interval_from
|
||||||
|
= f.input :setting_boost_interval_to, collection: [1, 2, 3, 4, 5, 6, 10, 15, 30, 60, 120, 180, 300, 360, 720, 1440], wrapper: :with_label, include_blank: false, label_method: lambda { |item| safe_join([t("simple_form.labels.boost_interval.#{item}")]) }, selected: current_user.boost_interval_to
|
||||||
|
|
||||||
%hr#settings_other/
|
%hr#settings_other/
|
||||||
|
|
||||||
|
@ -54,8 +60,8 @@
|
||||||
%hr/
|
%hr/
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :setting_max_public_history, collection: [1, 3, 6, 7, 14, 30, 60, 90, 180, 365, 730, 1095, 2190], wrapper: :with_label, include_blank: false, label_method: lambda { |item| safe_join([t("simple_form.labels.lifespan.#{item}")]) }, selected: current_user.max_public_history.to_i
|
= f.input :setting_max_public_history, collection: [1, 3, 6, 7, 14, 30, 60, 90, 180, 365, 730, 1095, 2190], wrapper: :with_label, include_blank: false, label_method: lambda { |item| safe_join([t("simple_form.labels.lifespan.#{item}")]) }, selected: current_user.max_public_history
|
||||||
= f.input :setting_roar_lifespan, collection: [0, 1, 3, 6, 7, 14, 30, 60, 90, 180, 365, 730, 1095, 2190], wrapper: :with_label, include_blank: false, label_method: lambda { |item| safe_join([t("simple_form.labels.lifespan.#{item}")]) }, selected: current_user.roar_lifespan.to_i
|
= f.input :setting_roar_lifespan, collection: [0, 1, 3, 6, 7, 14, 30, 60, 90, 180, 365, 730, 1095, 2190], wrapper: :with_label, include_blank: false, label_method: lambda { |item| safe_join([t("simple_form.labels.lifespan.#{item}")]) }, selected: current_user.roar_lifespan
|
||||||
= f.input :setting_hide_public_profile, as: :boolean, wrapper: :with_label
|
= f.input :setting_hide_public_profile, as: :boolean, wrapper: :with_label
|
||||||
= f.input :setting_hide_public_outbox, as: :boolean, wrapper: :with_label
|
= f.input :setting_hide_public_outbox, as: :boolean, wrapper: :with_label
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class ReblogStatusWorker
|
||||||
|
include Sidekiq::Worker
|
||||||
|
|
||||||
|
sidekiq_options unique: :until_executed
|
||||||
|
|
||||||
|
def perform(account_id, status_id, reblog_params = {})
|
||||||
|
account = Account.find(account_id)
|
||||||
|
status = Status.find(status_id)
|
||||||
|
return false if status.destroyed?
|
||||||
|
ReblogService.new.call(account, status, reblog_params.symbolize_keys)
|
||||||
|
true
|
||||||
|
rescue ActiveRecord::RecordNotFound, ActiveRecord::RecordInvalid
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,49 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Scheduler::BoostsScheduler
|
||||||
|
include Sidekiq::Worker
|
||||||
|
include Redisable
|
||||||
|
|
||||||
|
sidekiq_options unique: :until_executed, retry: 0
|
||||||
|
|
||||||
|
def perform
|
||||||
|
process_queued_boosts!
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def process_queued_boosts!
|
||||||
|
queued_accounts.find_each do |account|
|
||||||
|
next if redis.exists("queued_boost:#{account.id}") || account&.user.nil?
|
||||||
|
|
||||||
|
q = next_boost(account.id, account.user.boost_random?)
|
||||||
|
next if q.empty?
|
||||||
|
|
||||||
|
from_interval = account.user.boost_interval_from
|
||||||
|
to_interval = account.user.boost_interval_to
|
||||||
|
|
||||||
|
if from_interval > to_interval
|
||||||
|
from_interval, to_interval = [to_interval, from_interval]
|
||||||
|
end
|
||||||
|
|
||||||
|
interval = rand(from_interval .. to_interval).minutes
|
||||||
|
|
||||||
|
redis.setex("queued_boost:#{account.id}", interval, 1)
|
||||||
|
ReblogStatusWorker.perform_async(account.id, q.first.status_id, distribute: true)
|
||||||
|
q.destroy_all
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def queued_accounts
|
||||||
|
Account.where(id: queued_account_ids)
|
||||||
|
end
|
||||||
|
|
||||||
|
def queued_account_ids
|
||||||
|
QueuedBoost.distinct.pluck(:account_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_boost(account_id, boost_random = false)
|
||||||
|
q = QueuedBoost.where(account_id: account_id)
|
||||||
|
(boost_random ? q.order(Arel.sql('RANDOM()')) : q.order(:id)).limit(1)
|
||||||
|
end
|
||||||
|
end
|
|
@ -127,6 +127,10 @@ en:
|
||||||
setting_roar_lifespan: Auto-delete new roars after
|
setting_roar_lifespan: Auto-delete new roars after
|
||||||
setting_delayed_roars: Delayed publishing of roars for proofreading
|
setting_delayed_roars: Delayed publishing of roars for proofreading
|
||||||
setting_delayed_for: Delay for
|
setting_delayed_for: Delay for
|
||||||
|
setting_boost_interval: Automatically space out consecutive boosts
|
||||||
|
setting_boost_random: Boost in random order
|
||||||
|
setting_boost_interval_from: Minimum boost interval
|
||||||
|
setting_boost_interval_to: Maximum boost interval
|
||||||
setting_default_local: Default to Monsterpit-only roars (in Glitch flavour)
|
setting_default_local: Default to Monsterpit-only roars (in Glitch flavour)
|
||||||
setting_always_local: Don't send your roars outside Monsterpit
|
setting_always_local: Don't send your roars outside Monsterpit
|
||||||
setting_rawr_federated: Show raw world timeline (may contain offensive content!)
|
setting_rawr_federated: Show raw world timeline (may contain offensive content!)
|
||||||
|
@ -176,6 +180,23 @@ en:
|
||||||
username: Username
|
username: Username
|
||||||
username_or_email: Username or Email
|
username_or_email: Username or Email
|
||||||
whole_word: Whole word
|
whole_word: Whole word
|
||||||
|
boost_interval:
|
||||||
|
1: 1 minute
|
||||||
|
2: 2 minutes
|
||||||
|
3: 3 minutes
|
||||||
|
4: 4 minutes
|
||||||
|
5: 5 minutes
|
||||||
|
6: 6 minutes
|
||||||
|
10: 10 minutes
|
||||||
|
15: 15 minutes
|
||||||
|
30: 30 minutes
|
||||||
|
60: 1 hour
|
||||||
|
120: 2 hours
|
||||||
|
180: 3 hours
|
||||||
|
300: 5 hours
|
||||||
|
360: 6 hours
|
||||||
|
720: 12 hours
|
||||||
|
1440: 1 day
|
||||||
delayed_for:
|
delayed_for:
|
||||||
5: 5 seconds
|
5: 5 seconds
|
||||||
10: 10 seconds
|
10: 10 seconds
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
destructing_statuses_scheduler:
|
destructing_statuses_scheduler:
|
||||||
every: '1m'
|
every: '1m'
|
||||||
class: Scheduler::DestructingStatusesScheduler
|
class: Scheduler::DestructingStatusesScheduler
|
||||||
|
boosts_scheduler:
|
||||||
|
every: '1m'
|
||||||
|
class: Scheduler::BoostsScheduler
|
||||||
janitor_scheduler:
|
janitor_scheduler:
|
||||||
every: '1h'
|
every: '1h'
|
||||||
class: Scheduler::JanitorScheduler
|
class: Scheduler::JanitorScheduler
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
class CreateQueuedBoosts < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
create_table :queued_boosts do |t|
|
||||||
|
t.references :account, foreign_key: { on_delete: :cascade }
|
||||||
|
t.references :status, foreign_key: { on_delete: :cascade }
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
|
||||||
|
add_index :queued_boosts, [:account_id, :status_id], unique: true
|
||||||
|
end
|
||||||
|
end
|
14
db/schema.rb
14
db/schema.rb
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 2019_08_05_203816) do
|
ActiveRecord::Schema.define(version: 2019_08_06_195913) do
|
||||||
|
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
@ -554,6 +554,16 @@ ActiveRecord::Schema.define(version: 2019_08_05_203816) do
|
||||||
t.index ["status_id", "preview_card_id"], name: "index_preview_cards_statuses_on_status_id_and_preview_card_id"
|
t.index ["status_id", "preview_card_id"], name: "index_preview_cards_statuses_on_status_id_and_preview_card_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table "queued_boosts", force: :cascade do |t|
|
||||||
|
t.bigint "account_id"
|
||||||
|
t.bigint "status_id"
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.index ["account_id", "status_id"], name: "index_queued_boosts_on_account_id_and_status_id", unique: true
|
||||||
|
t.index ["account_id"], name: "index_queued_boosts_on_account_id"
|
||||||
|
t.index ["status_id"], name: "index_queued_boosts_on_status_id"
|
||||||
|
end
|
||||||
|
|
||||||
create_table "relays", force: :cascade do |t|
|
create_table "relays", force: :cascade do |t|
|
||||||
t.string "inbox_url", default: "", null: false
|
t.string "inbox_url", default: "", null: false
|
||||||
t.string "follow_activity_id"
|
t.string "follow_activity_id"
|
||||||
|
@ -861,6 +871,8 @@ ActiveRecord::Schema.define(version: 2019_08_05_203816) do
|
||||||
add_foreign_key "poll_votes", "polls", on_delete: :cascade
|
add_foreign_key "poll_votes", "polls", on_delete: :cascade
|
||||||
add_foreign_key "polls", "accounts", on_delete: :cascade
|
add_foreign_key "polls", "accounts", on_delete: :cascade
|
||||||
add_foreign_key "polls", "statuses", on_delete: :cascade
|
add_foreign_key "polls", "statuses", on_delete: :cascade
|
||||||
|
add_foreign_key "queued_boosts", "accounts", on_delete: :cascade
|
||||||
|
add_foreign_key "queued_boosts", "statuses", on_delete: :cascade
|
||||||
add_foreign_key "report_notes", "accounts", on_delete: :cascade
|
add_foreign_key "report_notes", "accounts", on_delete: :cascade
|
||||||
add_foreign_key "report_notes", "reports", on_delete: :cascade
|
add_foreign_key "report_notes", "reports", on_delete: :cascade
|
||||||
add_foreign_key "reports", "accounts", column: "action_taken_by_account_id", name: "fk_bca45b75fd", on_delete: :nullify
|
add_foreign_key "reports", "accounts", column: "action_taken_by_account_id", name: "fk_bca45b75fd", on_delete: :nullify
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Fabricator(:queued_boost) do
|
||||||
|
account nil
|
||||||
|
status nil
|
||||||
|
end
|
|
@ -0,0 +1,5 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe QueuedBoost, type: :model do
|
||||||
|
pending "add some examples to (or delete) #{__FILE__}"
|
||||||
|
end
|
Loading…
Reference in New Issue