Sponsorship: add model (step 1) (#3438)
* Add Sponsorship model * Add Sponsorship to admin * Add correct relationships between models * Add temporary script to migrate sponsorship data
This commit is contained in:
parent
11be56f38c
commit
ad79116366
13 changed files with 275 additions and 3 deletions
21
app/controllers/admin/sponsorships_controller.rb
Normal file
21
app/controllers/admin/sponsorships_controller.rb
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
module Admin
|
||||
class SponsorshipsController < Admin::ApplicationController
|
||||
# To customize the behavior of this controller,
|
||||
# you can overwrite any of the RESTful actions. For example:
|
||||
#
|
||||
# def index
|
||||
# super
|
||||
# @resources = Sponsorship.
|
||||
# page(params[:page]).
|
||||
# per(10)
|
||||
# end
|
||||
|
||||
# Define a custom finder by overriding the `find_resource` method:
|
||||
# def find_resource(param)
|
||||
# Sponsorship.find_by!(slug: param)
|
||||
# end
|
||||
|
||||
# See https://administrate-prototype.herokuapp.com/customizing_controller_actions
|
||||
# for more information
|
||||
end
|
||||
end
|
||||
|
|
@ -36,6 +36,7 @@ module Admin
|
|||
text_color_hex
|
||||
keywords_for_search
|
||||
buffer_profile_id_code
|
||||
sponsor_organization_id
|
||||
]
|
||||
convert_empty_string_to_nil
|
||||
params.require(:tag).permit(accessible)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ class DashboardManifest
|
|||
badges
|
||||
badge_achievements
|
||||
html_variants
|
||||
sponsorships
|
||||
].freeze
|
||||
# DASHBOARDS = [
|
||||
# :users,
|
||||
|
|
|
|||
87
app/dashboards/sponsorship_dashboard.rb
Normal file
87
app/dashboards/sponsorship_dashboard.rb
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
require "administrate/base_dashboard"
|
||||
|
||||
class SponsorshipDashboard < Administrate::BaseDashboard
|
||||
# ATTRIBUTE_TYPES
|
||||
# a hash that describes the type of each of the model's fields.
|
||||
#
|
||||
# Each different type represents an Administrate::Field object,
|
||||
# which determines how the attribute is displayed
|
||||
# on pages throughout the dashboard.
|
||||
ATTRIBUTE_TYPES = {
|
||||
user: Field::BelongsTo,
|
||||
organization: Field::BelongsTo,
|
||||
id: Field::Number,
|
||||
level: Field::String,
|
||||
status: Field::String,
|
||||
expires_at: Field::DateTime,
|
||||
blurb_html: Field::Text,
|
||||
featured_number: Field::Number,
|
||||
instructions: Field::Text,
|
||||
instructions_updated_at: Field::DateTime,
|
||||
tagline: Field::String,
|
||||
url: Field::String,
|
||||
sponsorable_id: Field::Number,
|
||||
sponsorable_type: Field::String,
|
||||
created_at: Field::DateTime,
|
||||
updated_at: Field::DateTime
|
||||
}.freeze
|
||||
|
||||
# COLLECTION_ATTRIBUTES
|
||||
# an array of attributes that will be displayed on the model's index page.
|
||||
#
|
||||
# By default, it's limited to four items to reduce clutter on index pages.
|
||||
# Feel free to add, remove, or rearrange items.
|
||||
COLLECTION_ATTRIBUTES = %i[
|
||||
user
|
||||
organization
|
||||
id
|
||||
level
|
||||
].freeze
|
||||
|
||||
# SHOW_PAGE_ATTRIBUTES
|
||||
# an array of attributes that will be displayed on the model's show page.
|
||||
SHOW_PAGE_ATTRIBUTES = %i[
|
||||
user
|
||||
organization
|
||||
id
|
||||
level
|
||||
status
|
||||
expires_at
|
||||
blurb_html
|
||||
featured_number
|
||||
instructions
|
||||
instructions_updated_at
|
||||
tagline
|
||||
url
|
||||
sponsorable_id
|
||||
sponsorable_type
|
||||
created_at
|
||||
updated_at
|
||||
].freeze
|
||||
|
||||
# FORM_ATTRIBUTES
|
||||
# an array of attributes that will be displayed
|
||||
# on the model's form (`new` and `edit`) pages.
|
||||
FORM_ATTRIBUTES = %i[
|
||||
user
|
||||
organization
|
||||
level
|
||||
status
|
||||
expires_at
|
||||
blurb_html
|
||||
featured_number
|
||||
instructions
|
||||
instructions_updated_at
|
||||
tagline
|
||||
url
|
||||
sponsorable_id
|
||||
sponsorable_type
|
||||
].freeze
|
||||
|
||||
# Overwrite this method to customize how sponsorships are displayed
|
||||
# across all pages of the admin dashboard.
|
||||
#
|
||||
# def display_resource(sponsorship)
|
||||
# "Sponsorship ##{sponsorship.id}"
|
||||
# end
|
||||
end
|
||||
|
|
@ -22,7 +22,7 @@ class TagDashboard < Administrate::BaseDashboard
|
|||
pretty_name: Field::String,
|
||||
profile_image: CarrierwaveField,
|
||||
social_image: CarrierwaveField,
|
||||
sponsorship_organization_id: Field::Number,
|
||||
sponsor_organization: Field::BelongsTo.with_options(class_name: "Organization"),
|
||||
sponsorship_status: Field::String,
|
||||
bg_color_hex: Field::String,
|
||||
text_color_hex: Field::String,
|
||||
|
|
@ -41,6 +41,7 @@ class TagDashboard < Administrate::BaseDashboard
|
|||
name
|
||||
supported
|
||||
taggings_count
|
||||
sponsor_organization
|
||||
].freeze
|
||||
|
||||
# SHOW_PAGE_ATTRIBUTES
|
||||
|
|
@ -64,6 +65,7 @@ class TagDashboard < Administrate::BaseDashboard
|
|||
text_color_hex
|
||||
keywords_for_search
|
||||
buffer_profile_id_code
|
||||
sponsor_organization
|
||||
].freeze
|
||||
|
||||
# FORM_ATTRIBUTES
|
||||
|
|
@ -83,7 +85,7 @@ class TagDashboard < Administrate::BaseDashboard
|
|||
social_image
|
||||
bg_color_hex
|
||||
text_color_hex
|
||||
sponsorship_organization_id
|
||||
sponsor_organization
|
||||
sponsorship_status
|
||||
keywords_for_search
|
||||
buffer_profile_id_code
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ class Organization < ApplicationRecord
|
|||
has_many :unspent_credits, -> { where spent: false }, class_name: "Credit", inverse_of: :organization
|
||||
has_many :classified_listings
|
||||
has_many :profile_pins, as: :profile, inverse_of: :profile
|
||||
has_many :sponsorships
|
||||
|
||||
validates :name, :summary, :url, :profile_image, presence: true
|
||||
validates :name,
|
||||
|
|
|
|||
10
app/models/sponsorship.rb
Normal file
10
app/models/sponsorship.rb
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
class Sponsorship < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :organization, inverse_of: :sponsorships
|
||||
belongs_to :sponsorable, polymorphic: true, optional: true
|
||||
|
||||
validates :user, :organization, :featured_number, presence: true
|
||||
validates :level, inclusion: { in: %w[gold silver bronze tag media devrel] }
|
||||
validates :status, inclusion: { in: %w[none pending live] }
|
||||
validates :url, url: { allow_blank: true, no_local: true, schemes: %w[http https] }
|
||||
end
|
||||
24
db/migrate/20190710081915_create_new_sponsorships.rb
Normal file
24
db/migrate/20190710081915_create_new_sponsorships.rb
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
class CreateNewSponsorships < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :sponsorships do |t|
|
||||
t.references :user, foreign_key: true
|
||||
t.references :organization, foreign_key: true
|
||||
t.string :level, null: false
|
||||
t.string :status, null: false, default: "none"
|
||||
t.datetime :expires_at
|
||||
t.text :blurb_html
|
||||
t.integer :featured_number, null: false, default: 0
|
||||
t.text :instructions
|
||||
t.datetime :instructions_updated_at
|
||||
t.string :tagline
|
||||
t.string :url
|
||||
t.bigint :sponsorable_id
|
||||
t.string :sponsorable_type
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
add_index :sponsorships, :level
|
||||
add_index :sponsorships, :status
|
||||
add_index :sponsorships, [:sponsorable_id, :sponsorable_type]
|
||||
end
|
||||
end
|
||||
27
db/schema.rb
27
db/schema.rb
|
|
@ -12,7 +12,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2019_07_09_192214) do
|
||||
ActiveRecord::Schema.define(version: 2019_07_10_081915) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
||||
|
|
@ -820,6 +820,29 @@ ActiveRecord::Schema.define(version: 2019_07_09_192214) do
|
|||
t.index ["google_result_path"], name: "index_search_keywords_on_google_result_path"
|
||||
end
|
||||
|
||||
create_table "sponsorships", force: :cascade do |t|
|
||||
t.text "blurb_html"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "expires_at"
|
||||
t.integer "featured_number", default: 0, null: false
|
||||
t.text "instructions"
|
||||
t.datetime "instructions_updated_at"
|
||||
t.string "level", null: false
|
||||
t.bigint "organization_id"
|
||||
t.bigint "sponsorable_id"
|
||||
t.string "sponsorable_type"
|
||||
t.string "status", default: "none", null: false
|
||||
t.string "tagline"
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "url"
|
||||
t.bigint "user_id"
|
||||
t.index ["level"], name: "index_sponsorships_on_level"
|
||||
t.index ["organization_id"], name: "index_sponsorships_on_organization_id"
|
||||
t.index ["sponsorable_id", "sponsorable_type"], name: "index_sponsorships_on_sponsorable_id_and_sponsorable_type"
|
||||
t.index ["status"], name: "index_sponsorships_on_status"
|
||||
t.index ["user_id"], name: "index_sponsorships_on_user_id"
|
||||
end
|
||||
|
||||
create_table "tag_adjustments", force: :cascade do |t|
|
||||
t.string "adjustment_type"
|
||||
t.integer "article_id"
|
||||
|
|
@ -1079,4 +1102,6 @@ ActiveRecord::Schema.define(version: 2019_07_09_192214) do
|
|||
add_foreign_key "messages", "chat_channels"
|
||||
add_foreign_key "messages", "users"
|
||||
add_foreign_key "push_notification_subscriptions", "users"
|
||||
add_foreign_key "sponsorships", "organizations"
|
||||
add_foreign_key "sponsorships", "users"
|
||||
end
|
||||
|
|
|
|||
51
lib/tasks/temporary/sponsorships.rake
Normal file
51
lib/tasks/temporary/sponsorships.rake
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
namespace :sponsorships do
|
||||
desc "Migrate existing sponsorships data to the Sponsorship model"
|
||||
task migrate_data: :environment do
|
||||
ActiveRecord::Base.transaction do
|
||||
puts "Migrating organization data..."
|
||||
Organization.find_each do |org|
|
||||
next unless org.sponsorship_level
|
||||
|
||||
org_admin = org.users.where(organization_memberships: { type_of_user: "admin" }).take!
|
||||
|
||||
Sponsorship.create!(
|
||||
organization: org,
|
||||
user: org_admin,
|
||||
level: org.sponsorship_level,
|
||||
status: org.sponsorship_status,
|
||||
expires_at: org.sponsorship_expires_at,
|
||||
blurb_html: org.sponsorship_blurb_html,
|
||||
featured_number: org.sponsorship_featured_number,
|
||||
instructions: org.sponsorship_instructions,
|
||||
instructions_updated_at: org.sponsorship_instructions_updated_at,
|
||||
tagline: org.sponsorship_tagline,
|
||||
url: org.sponsorship_url,
|
||||
)
|
||||
|
||||
puts "Migrated organization '#{org.name}'"
|
||||
end
|
||||
|
||||
puts "Migrating Tag sponsorship data..."
|
||||
Tag.where.not(sponsor_organization_id: nil).includes(:sponsor_organization).find_each do |tag|
|
||||
org = tag.sponsor_organization
|
||||
|
||||
org_admin = org.users.where(organization_memberships: { type_of_user: "admin" }).take!
|
||||
|
||||
Sponsorship.create!(
|
||||
organization: org,
|
||||
user: org_admin,
|
||||
level: "tag",
|
||||
# when an org purchases a tag sponsorship, its status isn't set
|
||||
# so I ise tag.sponsorship_status (which was previously checked in app/views/tags/index.html.erb)
|
||||
status: tag.sponsorship_status,
|
||||
sponsorable: tag,
|
||||
)
|
||||
|
||||
puts "Migrated tag '#{tag.name}' sponsorship by '#{org.name}'"
|
||||
end
|
||||
end
|
||||
|
||||
puts "All done now!"
|
||||
puts "Sponsorships without any traceable info in the DB need to be created manually!"
|
||||
end
|
||||
end
|
||||
7
spec/factories/sponsorships.rb
Normal file
7
spec/factories/sponsorships.rb
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
FactoryBot.define do
|
||||
factory :sponsorship do
|
||||
user
|
||||
organization
|
||||
level { "bronze" }
|
||||
end
|
||||
end
|
||||
|
|
@ -4,6 +4,8 @@ RSpec.describe Organization, type: :model do
|
|||
let(:user) { create(:user) }
|
||||
let(:organization) { create(:organization) }
|
||||
|
||||
it { is_expected.to have_many(:sponsorships) }
|
||||
|
||||
describe "#name" do
|
||||
it "rejects names with over 50 characters" do
|
||||
organization.name = Faker::Lorem.characters(51)
|
||||
|
|
|
|||
40
spec/models/sponsorship_spec.rb
Normal file
40
spec/models/sponsorship_spec.rb
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Sponsorship, type: :model do
|
||||
it { is_expected.to belong_to(:user) }
|
||||
it { is_expected.to belong_to(:organization).inverse_of(:sponsorships) }
|
||||
it { is_expected.to belong_to(:sponsorable).optional }
|
||||
it { is_expected.to validate_presence_of(:user) }
|
||||
it { is_expected.to validate_presence_of(:organization) }
|
||||
it { is_expected.to validate_inclusion_of(:level).in_array(%w[gold silver bronze tag media devrel]) }
|
||||
it { is_expected.to validate_inclusion_of(:status).in_array(%w[none pending live]) }
|
||||
it { is_expected.to allow_values(nil).for(:expires_at) }
|
||||
it { is_expected.not_to allow_values(nil).for(:featured_number) }
|
||||
it { is_expected.to have_db_index(:level) }
|
||||
it { is_expected.to have_db_index(:status) }
|
||||
it { is_expected.to have_db_index(%i[sponsorable_id sponsorable_type]) }
|
||||
|
||||
describe "#url" do
|
||||
let(:sponsorship) { build(:sponsorship) }
|
||||
|
||||
it "accepts a blank url" do
|
||||
sponsorship.url = ""
|
||||
expect(sponsorship).to be_valid
|
||||
end
|
||||
|
||||
it "accepts a HTTP url" do
|
||||
sponsorship.url = "http://example.com"
|
||||
expect(sponsorship).to be_valid
|
||||
end
|
||||
|
||||
it "accepts a HTTPS url" do
|
||||
sponsorship.url = "https://example.com"
|
||||
expect(sponsorship).to be_valid
|
||||
end
|
||||
|
||||
it "does not accept an invalid url" do
|
||||
sponsorship.url = "example.com"
|
||||
expect(sponsorship).not_to be_valid
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue