# rubocop:disable Rails/Output return if Rails.env.production? # NOTE: when adding new data, please use the Seeder class to ensure the seed tasks # stays idempotent. require Rails.root.join("app/lib/seeder") # we use this to be able to increase the size of the seeded DB at will # eg.: `SEEDS_MULTIPLIER=2 rails db:seed` would double the amount of data seeder = Seeder.new SEEDS_MULTIPLIER = [1, ENV["SEEDS_MULTIPLIER"].to_i].max puts "Seeding with multiplication factor: #{SEEDS_MULTIPLIER}\n\n" ############################################################################## # Default development settings are different from production scenario Settings::UserExperience.public = true Settings::General.waiting_on_first_user = false Settings::Authentication.providers = Authentication::Providers.available Settings::Authentication.allow_email_password_registration = true ############################################################################## # Disable Redis cache while seeding Rails.cache = ActiveSupport::Cache.lookup_store(:null_store) # Put forem into "starter mode" if ENV["MODE"] == "STARTER" Settings::UserExperience.public = false Settings::General.waiting_on_first_user = true puts "Seeding forem in starter mode to replicate new creator experience" exit # We don't need any models if we're launching things from startup. end seeder.create_if_none(Organization) do 3.times do Organization.create!( name: Faker::Company.name, summary: Faker::Company.bs, profile_image: logo = Rails.root.join("app/assets/images/#{rand(1..40)}.png").open, url: Faker::Internet.url, slug: "org#{rand(10_000)}", github_username: "org#{rand(10_000)}", twitter_username: "org#{rand(10_000)}", bg_color_hex: Faker::Color.hex_color, text_color_hex: Faker::Color.hex_color, ) end end ############################################################################## num_users = 10 * SEEDS_MULTIPLIER users_in_random_order = seeder.create_if_none(User, num_users) do roles = %i[trusted] num_users.times do |i| fname = Faker::Name.unique.first_name # Including "\\:/" to help with identifying local issues with # character escaping. lname = Faker::Name.unique.last_name name = [fname, "\"The #{fname}\"", lname, " \\:/"].join(" ") username = "#{fname} #{lname}" user = User.create!( name: name, profile_image: Rails.root.join("app/assets/images/#{rand(1..40)}.png").open, # Twitter username should be always ASCII twitter_username: Faker::Internet.username(specifier: username.transliterate), # Emails limited to 50 characters email: Faker::Internet.email( name: username.transliterate, separators: "+", domain: Faker::Internet.domain_word.first(20), ), confirmed_at: Time.current, registered_at: Time.current, registered: true, password: "password", password_confirmation: "password", ) user.profile.update( summary: Faker::Lorem.paragraph_by_chars(number: 199, supplemental: false), website_url: Faker::Internet.url, ) if i.zero? user.add_role(:trusted) # guarantee at least one moderator elsif i == num_users - 1 next # guarantee at least one user with no role else role_index = rand(0..roles.length) user.add_role(roles[role_index]) if role_index != roles.length # increases chance of more no-role users end omniauth_info = OmniAuth::AuthHash::InfoHash.new( first_name: fname, last_name: lname, location: "location,state,country", name: name, nickname: user.username, email: user.email, verified: true, ) omniauth_extra_info = OmniAuth::AuthHash::InfoHash.new( raw_info: OmniAuth::AuthHash::InfoHash.new( email: user.email, first_name: fname, gender: "female", id: "123456", last_name: lname, link: "http://www.facebook.com/url”", lang: "fr", locale: "en_US", name: name, timezone: 5.5, updated_time: "2012-06-08T13:09:47+0000", username: user.username, verified: true, followers_count: 100, friends_count: 1000, created_at: "2017-06-08T13:09:47+0000", ), ) omniauth_basic_info = { uid: SecureRandom.hex(3), info: omniauth_info, extra: omniauth_extra_info, credentials: { token: SecureRandom.hex, secret: SecureRandom.hex } }.freeze info = omniauth_basic_info[:info].merge( image: "https://dummyimage.com/400x400_normal.jpg", urls: { "Twitter" => "https://example.com" }, ) extra = omniauth_basic_info[:extra].merge( access_token: "value", ) auth_dump = OmniAuth::AuthHash.new( omniauth_basic_info.merge( provider: "twitter", info: info, extra: extra, ), ) Identity.create!( provider: "twitter", uid: i.to_s, token: i.to_s, secret: i.to_s, user: user, auth_data_dump: auth_dump, ) end Organization.find_each do |organization| admins = [] admin_id = User.where.not(id: admins).order(Arel.sql("RANDOM()")).first.id OrganizationMembership.create!( user_id: admin_id, organization_id: organization.id, type_of_user: "admin", ) admins << admin_id 2.times do OrganizationMembership.create!( user_id: User.where.not(id: OrganizationMembership.pluck(:user_id)).order(Arel.sql("RANDOM()")).first.id, organization_id: organization.id, type_of_user: "member", ) end end User.order(Arel.sql("RANDOM()")) end seeder.create_if_doesnt_exist(User, "email", "admin@forem.local") do user = User.create!( name: "Admin \"The \\:/ Administrator\" McAdmin", email: "admin@forem.local", username: "Admin_McAdmin", profile_image: Rails.root.join("app/assets/images/#{rand(1..40)}.png").open, confirmed_at: Time.current, registered_at: Time.current, password: "password", password_confirmation: "password", ) user.profile.update( summary: Faker::Lorem.paragraph_by_chars(number: 199, supplemental: false), website_url: Faker::Internet.url, ) user.add_role(:super_admin) user.add_role(:trusted) user.add_role(:tech_admin) end Users::CreateMascotAccount.call unless Settings::General.mascot_user_id ############################################################################## seeder.create_if_none(Badge) do 5.times do Badge.create!( title: "#{Faker::Lorem.word} #{rand(100)}", description: Faker::Lorem.sentence, badge_image: Rails.root.join("app/assets/images/#{rand(1..40)}.png").open, ) end users_in_random_order.limit(10).each do |user| user.badge_achievements.create!( badge: Badge.order(Arel.sql("RANDOM()")).limit(1).take, rewarding_context_message_markdown: Faker::Markdown.random, ) end end ############################################################################## seeder.create_if_none(Tag) do tags = %w[beginners career computerscience git go java javascript linux productivity python security webdev] tags.each do |tag_name| Tag.create!( name: tag_name, short_summary: Faker::Lorem.sentence, bg_color_hex: Faker::Color.hex_color, text_color_hex: Faker::Color.hex_color, supported: true, badge: Badge.order(Arel.sql("RANDOM()")).limit(1).take, ) end end ############################################################################## num_articles = 25 * SEEDS_MULTIPLIER seeder.create_if_none(Article, num_articles) do user_ids = User.all.ids public_categories = %w[like unicorn] num_articles.times do |i| tags = [] tags << "discuss" if (i % 3).zero? tags.concat Tag.order(Arel.sql("RANDOM()")).limit(3).pluck(:name) markdown = <<~MARKDOWN --- title: #{Faker::Book.title} #{Faker::Lorem.sentence(word_count: 2).chomp('.')} published: true cover_image: #{Faker::Company.logo} tags: #{tags.join(', ')} --- #{Faker::Hipster.paragraph(sentence_count: 2)} #{Faker::Markdown.random} #{Faker::Hipster.paragraph(sentence_count: 2)} MARKDOWN article = Article.create!( body_markdown: markdown, featured: i.zero?, # only feature the first article, show_comments: true, user_id: User.order(Arel.sql("RANDOM()")).first.id, ) Random.random_number(10).times do |_t| article.reactions.create( user_id: user_ids.sample, category: public_categories.sample, ) end article.sync_reactions_count end end ############################################################################## num_comments = 30 * SEEDS_MULTIPLIER seeder.create_if_none(Comment, num_comments) do num_comments.times do attributes = { body_markdown: Faker::Hipster.paragraph(sentence_count: 1), user_id: User.order(Arel.sql("RANDOM()")).first.id, commentable_id: Article.order(Arel.sql("RANDOM()")).first.id, commentable_type: "Article" } Comment.create!(attributes) end end ############################################################################## seeder.create_if_none(Podcast) do image_file = Rails.root.join("spec/support/fixtures/images/image1.jpeg") podcast_objects = [ { title: "CodeNewbie", description: "", feed_url: "http://feeds.codenewbie.org/cnpodcast.xml", itunes_url: "https://itunes.apple.com/us/podcast/codenewbie/id919219256", slug: "codenewbie", twitter_username: "CodeNewbies", website_url: "https://www.codenewbie.org/podcast", main_color_hex: "2faa4a", overcast_url: "https://overcast.fm/itunes919219256/codenewbie", android_url: "https://subscribeonandroid.com/feeds.podtrac.com/q8s8ba9YtM6r", image: Pathname.new(image_file).open, published: true, featured: true }, { title: "CodingBlocks", description: "", feed_url: "https://www.codingblocks.net/podcast-feed.xml", slug: "codingblocks", twitter_username: "CodingBlocks", website_url: "http://codingblocks.net", main_color_hex: "111111", overcast_url: "https://overcast.fm/itunes769189585/coding-blocks", android_url: "http://subscribeonandroid.com/feeds.podtrac.com/c8yBGHRafqhz", image: Pathname.new(image_file).open, published: true, featured: true }, { title: "Talk Python", description: "", feed_url: "https://talkpython.fm/episodes/rss", slug: "talkpython", twitter_username: "TalkPython", website_url: "https://talkpython.fm", main_color_hex: "181a1c", overcast_url: "https://overcast.fm/itunes979020229/talk-python-to-me", android_url: "https://subscribeonandroid.com/talkpython.fm/episodes/rss", image: Pathname.new(image_file).open, published: true, featured: true }, { title: "Developer on Fire", description: "", feed_url: "http://developeronfire.com/rss.xml", itunes_url: "https://itunes.apple.com/us/podcast/developer-on-fire/id1006105326", slug: "developeronfire", twitter_username: "raelyard", website_url: "http://developeronfire.com", main_color_hex: "343d46", overcast_url: "https://overcast.fm/itunes1006105326/developer-on-fire", android_url: "http://subscribeonandroid.com/developeronfire.com/rss.xml", image: Pathname.new(image_file).open, published: true, featured: true }, ] podcast_objects.each do |attributes| podcast = Podcast.create!(attributes) Podcasts::GetEpisodesWorker.perform_async("podcast_id" => podcast.id) end end ############################################################################## seeder.create_if_none(Broadcast) do broadcast_messages = { set_up_profile: I18n.t("broadcast.welcome.set_up_profile"), welcome_thread: I18n.t("broadcast.welcome.welcome_thread"), twitter_connect: I18n.t("broadcast.connect.twitter"), facebook_connect: I18n.t("broadcast.connect.facebook"), github_connect: I18n.t("broadcast.connect.github"), google_oauth2_connect: I18n.t("broadcast.connect.google"), apple_connect: I18n.t("broadcast.connect.apple"), customize_feed: I18n.t("broadcast.welcome.customize_feed"), customize_experience: I18n.t("broadcast.welcome.customize_experience"), start_discussion: I18n.t("broadcast.welcome.start_discussion"), ask_question: I18n.t("broadcast.welcome.ask_question"), discuss_and_ask: I18n.t("broadcast.welcome.discuss_and_ask"), download_app: I18n.t("broadcast.welcome.download_app") } broadcast_messages.each do |type, message| Broadcast.create!( title: "Welcome Notification: #{type}", processed_html: message, type_of: "Welcome", active: true, ) end welcome_thread_content = <<~HEREDOC --- title: Welcome Thread - v0 published: true description: Introduce yourself to the community! tags: welcome --- Hey there! Welcome to #{Settings::Community.community_name}! Leave a comment below to introduce yourself to the community!✌️ HEREDOC Article.create!( body_markdown: welcome_thread_content, user: User.staff_account || User.first, ) end ############################################################################## seeder.create_if_none(HtmlVariant) do HtmlVariant.create!( name: rand(100).to_s, group: "badge_landing_page", html: rand(1000).to_s, published: true, approved: true, user_id: User.first.id, ) end ############################################################################## seeder.create_if_none(FeedbackMessage) do mod = User.with_role(:trusted).take FeedbackMessage.create!( reporter: User.last, feedback_type: "spam", message: Faker::Lorem.sentence, category: "spam", status: "Open", ) FeedbackMessage.create!( reporter: mod, feedback_type: "abuse-reports", message: Faker::Lorem.sentence, reported_url: "example.com", category: "harassment", status: "Open", ) Reaction.create!( category: "vomit", reactable_id: User.last.id, reactable_type: "User", user_id: mod.id, ) 3.times do article_id = Article .left_joins(:reactions) .where.not(articles: { id: Reaction.article_vomits.pluck(:reactable_id) }) .order(Arel.sql("RANDOM()")) .first .id Reaction.create!( category: "vomit", reactable_id: article_id, reactable_type: "Article", user_id: mod.id, ) end end ############################################################################## seeder.create_if_none(ListingCategory) do categories = [ { slug: "cfp", cost: 1, name: "Conference CFP", rules: "Currently open for proposals, with link to form." }, { slug: "education", cost: 1, name: "Education/Courses", rules: "Educational material and/or schools/bootcamps." }, { slug: "jobs", cost: 25, name: "Job Listings", rules: "Companies offering employment right now." }, { slug: "forsale", cost: 1, name: "Stuff for Sale", rules: "Personally owned physical items for sale." }, { slug: "events", cost: 1, name: "Upcoming Events", rules: "In-person or online events with date included." }, { slug: "misc", cost: 1, name: "Miscellaneous", rules: "Must not fit in any other category." }, ].freeze categories.each { |attributes| ListingCategory.create(attributes) } end ############################################################################## seeder.create_if_none(Listing) do users_in_random_order = User.order(Arel.sql("RANDOM()")) users_in_random_order.each { |user| Credit.add_to(user, rand(100)) } users = users_in_random_order.to_a listings_categories = ListingCategory.ids listings_categories.each.with_index(1) do |category_id, index| # rotate users if they are less than the categories user = users.at(index % users.length) 2.times do Listing.create!( user: user, title: Faker::Lorem.sentence, body_markdown: Faker::Markdown.random.lines.take(10).join, location: Faker::Address.city, organization_id: user.organizations.first&.id, listing_category_id: category_id, published: true, originally_published_at: Time.current, bumped_at: Time.current, tag_list: Tag.order(Arel.sql("RANDOM()")).first(2).pluck(:name), ) end end end ############################################################################## seeder.create_if_none(Billboard) do Billboard::ALLOWED_PLACEMENT_AREAS.each do |placement_area| Billboard.create!( name: "#{Faker::Lorem.word} #{placement_area}", body_markdown: Faker::Lorem.sentence, published: true, approved: true, placement_area: placement_area, ) end segment = AudienceSegment.create!(type_of: :manual) Billboard.create!( name: "#{Faker::Lorem.word} (Manually Managed Audience)", body_markdown: Faker::Lorem.sentence, published: true, approved: true, placement_area: Billboard::ALLOWED_PLACEMENT_AREAS.sample, audience_segment: segment, ) end ############################################################################## # change locale to en to work around non-ascii slug problem loc = I18n.locale Faker::Config.locale = "en" seeder.create_if_none(Page) do 5.times do Page.create!( title: Faker::Hacker.say_something_smart, body_markdown: Faker::Markdown.random, slug: Faker::Internet.slug, description: Faker::Books::Dune.quote, template: %w[contained full_within_layout nav_bar_included].sample, ) end end Faker::Config.locale = loc ############################################################################## seeder.create_if_none(NavigationLink) do Rake::Task["navigation_links:update"].invoke end ############################################################################## puts <<-ASCII :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::'########::'#######::'########::'########:'##::::'##:::: :::: ##.....::'##.... ##: ##.... ##: ##.....:: ###::'###:::: :::: ##::::::: ##:::: ##: ##:::: ##: ##::::::: ####'####:::: :::: ######::: ##:::: ##: ########:: ######::: ## ### ##:::: :::: ##...:::: ##:::: ##: ##.. ##::: ##...:::: ##. #: ##:::: :::: ##::::::: ##:::: ##: ##::. ##:: ##::::::: ##:.:: ##:::: :::: ##:::::::. #######:: ##:::. ##: ########: ##:::: ##:::: ::::..:::::::::.......:::..:::::..::........::..:::::..::::: :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: All done! ASCII # rubocop:enable Rails/Output