ruby fakeout.rake - 一个简单/可配置的rake任务,为应用程序(使用faker)生成各种大小的随机假数据

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ruby fakeout.rake - 一个简单/可配置的rake任务,为应用程序(使用faker)生成各种大小的随机假数据相关的知识,希望对你有一定的参考价值。

# a simple/configurable rake task that generates some random fake data for the app (using faker) at various sizes
# NOTE: requires the faker or ffaker gem 
#   sudo gem install faker - http://faker.rubyforge.org
#   OR
#   sudo gem install ffaker - http://github.com/EmmanuelOga/ffaker

require 'faker'

class Fakeout

  # START Customizing

  # 1. first these are the model names we're going to fake out, note in this example, we don't create tags/taggings specifically
  # but they are defined here so they get wiped on the clean operation
  # e.g. this example fakes out, Users, Questions and Answers, and in doing so fakes some Tags/Taggings
  MODELS = %w(User Question Answer Tag Tagging)

  # 2. now define a build method for each model, returning a list of attributes for Model.create! calls
  # check out the very excellent faker gem rdoc for faking out anything from emails, to full addresses; http://faker.rubyforge.org/rdoc
  # NOTE: a build_??? method MUST exist for each model you specify above
  def build_user(username = "#{Faker::Internet.user_name}_#{random_letters}", email = Faker::Internet.email, password = 'password')
    { :username              => username,
      :email                 => email,
      :password              => password,
      :password_confirmation => password }
  end

  # in this example i'm faking out time - like Marty McFly!
  def build_question
    question_time = fake_time_from(1.year.ago)

    { :title            => "#{Faker::Lorem.sentence(8+rand(8)).chop}?",
      :information      => Faker::Lorem.paragraph(rand(3)),
      :tag_list         => random_tag_list(all_tags),
      :notify_user      => false,
      :created_at       => question_time,
      :updated_at       => question_time,
      :spam_answer      => '2',
      :spam_question    => '1+1 is?',
      :possible_answers => [Digest::MD5.hexdigest('2')],
      :user             => pick_random(User, true) }
  end

  # in this example i'm faking out time again! - this time to be after the question's created at time
  def build_answer
    question    = pick_random(Question)
    answer_time = question.created_at+rand(168).hours

    { :title            => Faker::Lorem.paragraph(1+rand(4)),
      :question         => question,
      :created_at       => answer_time,
      :updated_at       => answer_time,
      :user             => pick_random(User, true),
      :spam_answer      => '2',
      :spam_question    => '1+1 is?',
      :possible_answers => [Digest::MD5.hexdigest('2')],
    }
  end

  # return nil, or an empty hash for models you don't want to be faked out on create, but DO want to be clearer away
  def build_tag; end

  def build_tagging; end
  
  # called after faking out, use this method for additional updates or additions
  def post_fake
    User.create!(build_user('matt', 'matt@hiddenloop.com', 'password'))
    User.update_all('email_confirmed = true')
  end

  # 3. optionally you can change these numbers, basically they are used to determine the number of models to create
  # and also the size of the tags array to choose from.  To check things work quickly use the tiny size (1 for everything)
  def tiny
    1
  end
  
  def small
    25+rand(50)
  end

  def medium
    250+rand(250)
  end

  def large
    1000+rand(500)
  end

  # END Customizing

  attr_accessor :all_tags, :size

  def initialize(size, prompt=true)
    self.size     = size
    self.all_tags = Faker::Lorem.words(send(size))
  end

  def fakeout
    puts "Faking it ... (#{size})"
    Fakeout.disable_mailers
    MODELS.each do |model|
      if !respond_to?("build_#{model.downcase}")
        puts "  * #{model.pluralize}: **warning** I couldn't find a build_#{model.downcase} method"
        next
      end
      1.upto(send(size)) do
        attributes = send("build_#{model.downcase}")
        model.constantize.create!(attributes) if attributes && !attributes.empty?
      end
      puts "  * #{model.pluralize}: #{model.constantize.count(:all)}"
    end
    post_fake
    puts "Done, I Faked it!"
  end
  
  def self.prompt
    puts "Really? This will clean all #{MODELS.map(&:pluralize).join(', ')} from your #{RAILS_ENV} database y/n? "
    STDOUT.flush
    (STDIN.gets =~ /^y|^Y/) ? true : exit(0)
  end

  def self.clean(prompt = true)
    self.prompt if prompt
    puts "Cleaning all ..."
    Fakeout.disable_mailers
    MODELS.each do |model|
      model.constantize.delete_all
    end
  end

  # by default, all mailings are disabled on faking out
  def self.disable_mailers
    ActionMailer::Base.perform_deliveries = false
  end
  
  
  private
  # pick a random model from the db, done this way to avoid differences in mySQL rand() and postgres random()
  def pick_random(model, optional = false)
    return nil if optional && (rand(2) > 0)
    ids = ActiveRecord::Base.connection.select_all("SELECT id FROM #{model.to_s.tableize}")
    model.find(ids[rand(ids.length)]["id"].to_i) unless ids.blank?
  end

  # useful for prepending to a string for getting a more unique string
  def random_letters(length = 2)
    Array.new(length) { (rand(122-97) + 97).chr }.join
  end

  # pick a random number of tags up to max_tags, from an array of words, join the result with seperator
  def random_tag_list(tags, max_tags = 5, seperator = ',')
    start = rand(tags.length)
    return '' if start < 1
    tags[start..(start+rand(max_tags))].join(seperator)
  end

  # fake a time from: time ago + 1-8770 (a year) hours after
  def fake_time_from(time_ago = 1.year.ago)
    time_ago+(rand(8770)).hours
  end
end


# the tasks, hook to class above - use like so;
# rake fakeout:clean
# rake fakeout:small[noprompt] - no confirm prompt asked, useful for heroku or non-interactive use
# rake fakeout:medium RAILS_ENV=bananas
#.. etc.
namespace :fakeout do

  desc "clean away all data"
  task :clean, [:no_prompt] => :environment do |t, args|
    Fakeout.clean(args.no_prompt.nil?)
  end
  
  desc "fake out a tiny dataset"
  task :tiny, [:no_prompt] => :clean do |t, args|
    Fakeout.new(:tiny).fakeout
  end

  desc "fake out a small dataset"
  task :small, [:no_prompt] => :clean do |t, args|
    Fakeout.new(:small).fakeout
  end

  desc "fake out a medium dataset"
  task :medium, [:no_prompt] => :clean do |t, args|
    Fakeout.new(:medium).fakeout
  end

  desc "fake out a large dataset"
  task :large, [:no_prompt] => :clean do |t, args|
    Fakeout.new(:large).fakeout
  end
end

以上是关于ruby fakeout.rake - 一个简单/可配置的rake任务,为应用程序(使用faker)生成各种大小的随机假数据的主要内容,如果未能解决你的问题,请参考以下文章

ruby 一个简单的redis orm

ruby 一个简单的递归示例。

Ruby 中的简单 DSL

ruby 一个简单的脚本来解码Rails 4会话cookie

ruby 一个简单的脚本来解码Rails 4会话cookie

ruby简单的基础 2