|
| 1 | +# frozen_string_literal: true |
| 2 | + |
| 3 | +require "csv" |
| 4 | +require "fileutils" |
1 | 5 | require "faker"
|
2 | 6 |
|
| 7 | +require_relative "./seeds_impressions" |
| 8 | + |
3 | 9 | unless Rails.env.development?
|
4 | 10 | puts "SEEDS ARE FOR DEVELOPMENT ONLY!"
|
5 | 11 | exit 1
|
6 | 12 | end
|
7 | 13 |
|
8 |
| -user_attributes = { |
9 |
| - company_name: "CodeFund", |
10 |
| - confirmation_sent_at: 2.days.ago, |
11 |
| - confirmed_at: 1.day.ago, |
12 |
| - password: "secret", |
13 |
| - password_confirmation: "secret", |
14 |
| -} |
15 |
| - |
16 |
| -administrator = User.find_or_initialize_by(email: "chris.knight@codefund.io") |
17 |
| -administrator.assign_attributes( |
18 |
| - user_attributes.merge( |
19 |
| - roles: [ENUMS::USER_ROLES::ADMINISTRATOR], |
20 |
| - first_name: "Chris", |
21 |
| - last_name: "Knight", |
22 |
| - ) |
23 |
| -) |
24 |
| -administrator.save! |
25 |
| - |
26 |
| -publisher = User.find_or_initialize_by(email: "mitch.taylor@codefund.io") |
27 |
| -publisher.assign_attributes( |
28 |
| - user_attributes.merge( |
29 |
| - roles: [ENUMS::USER_ROLES::PUBLISHER], |
30 |
| - first_name: "Mitch", |
31 |
| - last_name: "Taylor", |
32 |
| - ) |
33 |
| -) |
34 |
| -publisher.save! |
35 |
| - |
36 |
| -advertiser = User.find_or_initialize_by(email: "jordan.cochran@codefund.io") |
37 |
| -advertiser.assign_attributes( |
38 |
| - user_attributes.merge( |
39 |
| - roles: [ENUMS::USER_ROLES::ADVERTISER], |
40 |
| - first_name: "Jordan", |
41 |
| - last_name: "Cochran", |
42 |
| - ) |
43 |
| -) |
44 |
| -advertiser.save! |
45 |
| - |
46 |
| -if advertiser.images.search_metadata_name("CodeFund Small").search_metadata_format(ENUMS::IMAGE_FORMATS::SMALL).count == 0 |
47 |
| - advertiser.images.attach io: File.open(Rails.root.join("app/assets/images/seeds/code-fund-100x100.png")), |
48 |
| - filename: "code-fund-100x100.png", |
49 |
| - content_type: "image/png", |
50 |
| - metadata: { |
51 |
| - identified: true, |
52 |
| - width: 100, |
53 |
| - height: 100, |
54 |
| - analyzed: true, |
55 |
| - name: "CodeFund Small", |
56 |
| - format: ENUMS::IMAGE_FORMATS::SMALL, |
| 14 | +class Seeder |
| 15 | + def self.run |
| 16 | + new.call |
| 17 | + end |
| 18 | + |
| 19 | + def initialize |
| 20 | + @user_id = User.last&.id.to_i + 1 |
| 21 | + @property_id = Property.last&.id.to_i + 1 |
| 22 | + @user_count = 0 |
| 23 | + @users = [] |
| 24 | + @publishers = [] |
| 25 | + @properties = [] |
| 26 | + end |
| 27 | + |
| 28 | + def call |
| 29 | + puts "[SEEDING DATABASE]: Started - This may take several minutes." |
| 30 | + seed_users |
| 31 | + seed_campaigns |
| 32 | + seed_properties |
| 33 | + ImpressionSeeder.run(ENV["MAX_IMPRESSIONS"].to_i) |
| 34 | + puts "[SEEDING DATABASE]: Completed" |
| 35 | + end |
| 36 | + |
| 37 | + private |
| 38 | + |
| 39 | + def seed_users |
| 40 | + @emails = User.all.pluck(:email).each_with_object({}) { |email, memo| |
| 41 | + memo[email] = true |
57 | 42 | }
|
58 |
| -end |
| 43 | + csv_path = Rails.root.join("tmp", "users.csv") |
| 44 | + @users << build_administrator |
| 45 | + @users.concat build_advertisers |
| 46 | + @users.concat build_publishers |
| 47 | + csv_created = create_csv(@users, csv_path) |
| 48 | + import_csv("users", csv_path) if csv_created |
| 49 | + end |
| 50 | + |
| 51 | + def build_administrator |
| 52 | + admin_count = User.where("? = ANY (roles)", ENUMS::USER_ROLES::ADMINISTRATOR).count |
| 53 | + return unless admin_count.zero? |
| 54 | + return if @emails["admin@codefund.io"] |
| 55 | + puts "[SEEDING DATABASE]: Building administrator" |
| 56 | + @user_count += 1 |
| 57 | + admin = user_attributes.merge( |
| 58 | + id: @user_id, |
| 59 | + company_name: "CodeFund", |
| 60 | + email: "admin@codefund.io", |
| 61 | + roles: "{#{ENUMS::USER_ROLES::ADMINISTRATOR}}", |
| 62 | + ).values |
| 63 | + @user_id += 1 |
| 64 | + admin |
| 65 | + end |
59 | 66 |
|
60 |
| -if advertiser.images.search_metadata_name("CodeFund Large").search_metadata_format(ENUMS::IMAGE_FORMATS::LARGE).count == 0 |
61 |
| - advertiser.images.attach io: File.open(Rails.root.join("app/assets/images/seeds/code-fund-260x200.png")), |
62 |
| - filename: "code-fund-100x100.png", |
63 |
| - content_type: "image/png", |
64 |
| - metadata: { |
65 |
| - identified: true, |
66 |
| - width: 260, |
67 |
| - height: 200, |
68 |
| - analyzed: true, |
69 |
| - name: "CodeFund Large", |
70 |
| - format: ENUMS::IMAGE_FORMATS::LARGE, |
| 67 | + def build_advertisers |
| 68 | + advertiser_count = User.where("? = ANY (roles)", ENUMS::USER_ROLES::ADVERTISER).count |
| 69 | + return [] if advertiser_count >= 100 |
| 70 | + print "[SEEDING DATABASE]: Building advertisers " |
| 71 | + advertisers = (advertiser_count..99).map { |
| 72 | + @user_count += 1 |
| 73 | + print "." if @user_count % 10 == 0 |
| 74 | + advertiser = user_attributes.merge(id: @user_id, roles: "{#{ENUMS::USER_ROLES::ADVERTISER}}").values |
| 75 | + @user_id += 1 |
| 76 | + advertiser |
71 | 77 | }
|
72 |
| -end |
| 78 | + puts |
| 79 | + advertisers |
| 80 | + end |
73 | 81 |
|
74 |
| -if advertiser.creatives.count == 0 |
75 |
| - 5.times do |
76 |
| - creative = Creative.create( |
77 |
| - user: advertiser, |
78 |
| - name: Faker::SiliconValley.company, |
79 |
| - headline: Faker::SiliconValley.invention, |
80 |
| - body: Faker::SiliconValley.motto, |
81 |
| - ) |
82 |
| - advertiser.images.each do |image| |
83 |
| - CreativeImage.create creative: creative, image: image |
| 82 | + def build_publishers |
| 83 | + publisher_count = User.where("? = ANY (roles)", ENUMS::USER_ROLES::PUBLISHER).count |
| 84 | + return [] if publisher_count >= 1000 |
| 85 | + print "[SEEDING DATABASE]: Building publishers " |
| 86 | + publishers = (publisher_count..999).map { |
| 87 | + @user_count += 1 |
| 88 | + print "." if @user_count % 10 == 0 |
| 89 | + publisher = user_attributes.merge(id: @user_id, roles: "{#{ENUMS::USER_ROLES::PUBLISHER}}").values |
| 90 | + @publishers << @user_id |
| 91 | + @user_id += 1 |
| 92 | + publisher |
| 93 | + } |
| 94 | + puts |
| 95 | + publishers |
| 96 | + end |
| 97 | + |
| 98 | + def seed_campaigns |
| 99 | + return if Campaign.count >= 1000 |
| 100 | + print "[SEEDING DATABASE]: Seeding campaigns " |
| 101 | + User.where("? = ANY (roles)", ENUMS::USER_ROLES::ADVERTISER).each do |advertiser| |
| 102 | + print "." |
| 103 | + add_small_image(advertiser) |
| 104 | + add_large_image(advertiser) |
| 105 | + generate_creatives(advertiser) |
| 106 | + generate_campaigns(advertiser) |
84 | 107 | end
|
| 108 | + puts |
85 | 109 | end
|
86 |
| -end |
87 | 110 |
|
88 |
| -if advertiser.campaigns.count == 0 |
89 |
| - 10.times do |
90 |
| - start_date = rand(3).months.from_now.to_date |
91 |
| - end_date = start_date.advance(months: 6) |
92 |
| - total_budget = ([*500..5000].sample / 100) * 100 |
93 |
| - daily_budget = total_budget / (end_date - start_date).to_i |
94 |
| - countries = ENUMS::DEVELOPED_MARKET_COUNTRIES.keys |
95 |
| - countries += ENUMS::EMERGING_MARKET_COUNTRIES.keys if rand(3).zero? |
96 |
| - countries += ENUMS::COUNTRIES.keys.sample(5) if rand(5).zero? |
97 |
| - keywords = ENUMS::KEYWORDS.values.sample(25) |
98 |
| - Campaign.create( |
99 |
| - user: advertiser, |
100 |
| - creative: advertiser.creatives.sample, |
101 |
| - status: ENUMS::CAMPAIGN_STATUSES.values.sample, |
102 |
| - name: Faker::SiliconValley.invention, |
103 |
| - url: Faker::SiliconValley.url, |
104 |
| - start_date: start_date, |
105 |
| - end_date: end_date, |
106 |
| - us_hours_only: rand(2).zero?, |
107 |
| - weekdays_only: rand(2).zero?, |
108 |
| - total_budget: total_budget, |
109 |
| - daily_budget: daily_budget, |
110 |
| - ecpm: 3, |
111 |
| - countries: countries, |
112 |
| - keywords: keywords, |
113 |
| - negative_keywords: ENUMS::KEYWORDS.values.sample(5) - keywords, |
114 |
| - ) |
| 111 | + def add_small_image(advertiser) |
| 112 | + advertiser.images.attach io: File.open(Rails.root.join("app/assets/images/seeds/code-fund-100x100.png")), |
| 113 | + filename: "code-fund-100x100.png", |
| 114 | + content_type: "image/png", |
| 115 | + metadata: { |
| 116 | + identified: true, |
| 117 | + width: 100, |
| 118 | + height: 100, |
| 119 | + analyzed: true, |
| 120 | + name: "CodeFund Small", |
| 121 | + format: ENUMS::IMAGE_FORMATS::SMALL, |
| 122 | + } |
| 123 | + end |
| 124 | + |
| 125 | + def add_large_image(advertiser) |
| 126 | + advertiser.images.attach io: File.open(Rails.root.join("app/assets/images/seeds/code-fund-260x200.png")), |
| 127 | + filename: "code-fund-100x100.png", |
| 128 | + content_type: "image/png", |
| 129 | + metadata: { |
| 130 | + identified: true, |
| 131 | + width: 260, |
| 132 | + height: 200, |
| 133 | + analyzed: true, |
| 134 | + name: "CodeFund Large", |
| 135 | + format: ENUMS::IMAGE_FORMATS::LARGE, |
| 136 | + } |
| 137 | + end |
| 138 | + |
| 139 | + def generate_creatives(advertiser) |
| 140 | + 5.times do |
| 141 | + creative = Creative.create( |
| 142 | + user: advertiser, |
| 143 | + name: Faker::SiliconValley.company, |
| 144 | + headline: Faker::SiliconValley.invention, |
| 145 | + body: Faker::SiliconValley.motto, |
| 146 | + ) |
| 147 | + advertiser.images.each do |image| |
| 148 | + CreativeImage.create creative: creative, image: image |
| 149 | + end |
| 150 | + end |
| 151 | + end |
| 152 | + |
| 153 | + def generate_campaigns(advertiser) |
| 154 | + 10.times do |
| 155 | + start_date = rand(3).months.from_now.to_date |
| 156 | + end_date = start_date.advance(months: 6) |
| 157 | + total_budget = ([*500..5000].sample / 100) * 100 |
| 158 | + daily_budget = total_budget / (end_date - start_date).to_i |
| 159 | + countries = ENUMS::DEVELOPED_MARKET_COUNTRIES.keys |
| 160 | + countries += ENUMS::EMERGING_MARKET_COUNTRIES.keys if rand(3).zero? |
| 161 | + countries += ENUMS::COUNTRIES.keys.sample(5) if rand(5).zero? |
| 162 | + keywords = ENUMS::KEYWORDS.values.sample(25) |
| 163 | + Campaign.create( |
| 164 | + user: advertiser, |
| 165 | + creative: advertiser.creatives.sample, |
| 166 | + status: ENUMS::CAMPAIGN_STATUSES.values.sample, |
| 167 | + name: Faker::SiliconValley.invention, |
| 168 | + url: Faker::SiliconValley.url, |
| 169 | + start_date: start_date, |
| 170 | + end_date: end_date, |
| 171 | + us_hours_only: rand(2).zero?, |
| 172 | + weekdays_only: rand(2).zero?, |
| 173 | + total_budget: total_budget, |
| 174 | + daily_budget: daily_budget, |
| 175 | + ecpm: 3, |
| 176 | + countries: countries, |
| 177 | + keywords: keywords, |
| 178 | + negative_keywords: ENUMS::KEYWORDS.values.sample(5) - keywords, |
| 179 | + ) |
| 180 | + end |
115 | 181 | end
|
116 |
| -end |
117 | 182 |
|
118 |
| -if publisher.properties.count == 0 |
119 |
| - 10.times do |
120 |
| - Property.create( |
121 |
| - user: publisher, |
122 |
| - property_type: ENUMS::PROPERTY_TYPES.values.sample, |
123 |
| - status: ENUMS::PROPERTY_STATUSES.values.sample, |
124 |
| - name: Faker::SiliconValley.invention, |
125 |
| - url: Faker::SiliconValley.url, |
126 |
| - ad_template: ENUMS::AD_TEMPLATES.values.sample, |
127 |
| - ad_theme: ENUMS::AD_THEMES.values.sample, |
128 |
| - language: ENUMS::LANGUAGES::ENGLISH, |
129 |
| - keywords: ENUMS::KEYWORDS.values.sample(25), |
130 |
| - ) |
| 183 | + def seed_properties |
| 184 | + return if Property.count >= 10_000 |
| 185 | + print "[SEEDING DATABASE]: Building properties" |
| 186 | + csv_path = Rails.root.join("tmp", "properties.csv") |
| 187 | + @publishers = User.where("? = ANY (roles)", ENUMS::USER_ROLES::PUBLISHER).pluck(:id) unless @publishers.present? |
| 188 | + @publishers.each do |publisher| |
| 189 | + print "." |
| 190 | + 10.times do |
| 191 | + @properties << { |
| 192 | + id: @property_id, |
| 193 | + user_id: publisher, |
| 194 | + property_type: ENUMS::PROPERTY_TYPES.values.sample, |
| 195 | + status: ENUMS::PROPERTY_STATUSES.values.sample, |
| 196 | + name: Faker::SiliconValley.invention, |
| 197 | + description: nil, |
| 198 | + url: Faker::SiliconValley.url, |
| 199 | + ad_template: ENUMS::AD_TEMPLATES.values.sample, |
| 200 | + ad_theme: ENUMS::AD_THEMES.values.sample, |
| 201 | + language: ENUMS::LANGUAGES::ENGLISH, |
| 202 | + keywords: "{#{ENUMS::KEYWORDS.values.sample(25).join(",")}}", |
| 203 | + prohibited_advertisers: nil, |
| 204 | + prohibit_fallback_campaigns: false, |
| 205 | + created_at: Time.now, |
| 206 | + updated_at: Time.now, |
| 207 | + }.values |
| 208 | + @property_id += 1 |
| 209 | + end |
| 210 | + end |
| 211 | + puts |
| 212 | + csv_created = create_csv(@properties, csv_path) |
| 213 | + import_csv("properties", csv_path) if csv_created |
| 214 | + end |
| 215 | + |
| 216 | + def create_csv(list, csv_path) |
| 217 | + return false unless list.compact.present? |
| 218 | + puts "Creating #{csv_path}" |
| 219 | + CSV.open(csv_path, "wb") do |csv| |
| 220 | + list.each do |record| |
| 221 | + csv << record |
| 222 | + end |
| 223 | + end |
| 224 | + true |
| 225 | + end |
| 226 | + |
| 227 | + def import_csv(table_name, csv_path) |
| 228 | + puts "Copying #{csv_path} to Postgres" |
| 229 | + ActiveRecord::Base.connection.execute "COPY \"#{table_name}\" FROM '#{csv_path}' CSV;" |
| 230 | + puts "Copy complete" |
| 231 | + rescue => e |
| 232 | + puts "Failed to copy #{csv_path} to Postgres! #{e}" |
| 233 | + ensure |
| 234 | + FileUtils.rm_f csv_path, verbose: true |
| 235 | + end |
| 236 | + |
| 237 | + def user_attributes |
| 238 | + first_name = Faker::Name.first_name |
| 239 | + last_name = Faker::Name.last_name |
| 240 | + email = Faker::Internet.email("#{first_name} #{last_name}", "-") |
| 241 | + { |
| 242 | + id: 1, |
| 243 | + roles: [], |
| 244 | + first_name: first_name, |
| 245 | + last_name: last_name, |
| 246 | + company_name: Faker::SiliconValley.company, |
| 247 | + address_1: nil, |
| 248 | + address_2: nil, |
| 249 | + city: nil, |
| 250 | + region: nil, |
| 251 | + postal_code: nil, |
| 252 | + country: nil, |
| 253 | + api_access: true, |
| 254 | + api_key: nil, |
| 255 | + paypal_email: nil, |
| 256 | + email: email, |
| 257 | + encrypted_password: User.new(password: "secret").encrypted_password, |
| 258 | + reset_password_token: nil, |
| 259 | + reset_password_sent_at: nil, |
| 260 | + remember_created_at: nil, |
| 261 | + sign_in_count: 1, |
| 262 | + current_sign_in_at: nil, |
| 263 | + last_sign_in_at: nil, |
| 264 | + current_sign_in_ip: nil, |
| 265 | + last_sign_in_ip: nil, |
| 266 | + confirmation_token: Devise.friendly_token, |
| 267 | + confirmed_at: 1.day.ago, |
| 268 | + confirmation_sent_at: 2.days.ago, |
| 269 | + unconfirmed_email: nil, |
| 270 | + failed_attempts: 0, |
| 271 | + unlock_token: nil, |
| 272 | + locked_at: nil, |
| 273 | + created_at: 3.days.ago, |
| 274 | + updated_at: 3.days.ago, |
| 275 | + } |
131 | 276 | end
|
132 | 277 | end
|
133 | 278 |
|
134 |
| -require_relative "./seeds_impressions" if ENV["IMPRESSIONS"] |
| 279 | +Seeder.run |
0 commit comments