populator 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +8 -2
- data/Manifest +1 -0
- data/README +3 -3
- data/Rakefile +2 -2
- data/TODO +0 -2
- data/lib/populator.rb +4 -0
- data/lib/populator/adapters/abstract.rb +1 -1
- data/lib/populator/adapters/sqlite.rb +7 -2
- data/lib/populator/factory.rb +13 -0
- data/lib/populator/model_additions.rb +22 -1
- data/lib/populator/random.rb +9 -0
- data/lib/populator/record.rb +29 -9
- data/populator.gemspec +3 -3
- data/spec/spec_helper.rb +1 -1
- metadata +2 -2
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
*0.2.2* (September 1st, 2008)
|
2
|
+
|
3
|
+
* performance improvements
|
4
|
+
|
5
|
+
* improving inline documentation
|
6
|
+
|
1
7
|
*0.2.1* (August 30th, 2008)
|
2
8
|
|
3
9
|
* wrap sqlite inserts in transaction to improve performance
|
@@ -10,9 +16,9 @@
|
|
10
16
|
|
11
17
|
* improving performance when nesting factories
|
12
18
|
|
13
|
-
* adding
|
19
|
+
* adding Populator.sentences to generate a lot of text
|
14
20
|
|
15
|
-
* adding
|
21
|
+
* adding Populator.words to fetch some random words
|
16
22
|
|
17
23
|
*0.1.0* (August 27th, 2008)
|
18
24
|
|
data/Manifest
CHANGED
data/README
CHANGED
@@ -10,7 +10,7 @@ this code is loosely based on.
|
|
10
10
|
|
11
11
|
Install the gem:
|
12
12
|
|
13
|
-
|
13
|
+
gem install populator
|
14
14
|
|
15
15
|
And then load it in your project:
|
16
16
|
|
@@ -64,7 +64,7 @@ If you need to generate fake data, there are a few methods to do this.
|
|
64
64
|
|
65
65
|
For fancier data generation, try the Faker gem.
|
66
66
|
|
67
|
-
|
67
|
+
http://faker.rubyforge.org
|
68
68
|
|
69
69
|
|
70
70
|
== Important
|
@@ -80,7 +80,7 @@ See spec/README for instructions on running specs.
|
|
80
80
|
|
81
81
|
This project can be found on github at the following URL.
|
82
82
|
|
83
|
-
http://github.com/ryanb/populator
|
83
|
+
http://github.com/ryanb/populator
|
84
84
|
|
85
85
|
If you would like to contribute to this project, please fork the
|
86
86
|
repository and send me a pull request.
|
data/Rakefile
CHANGED
@@ -2,13 +2,13 @@ require 'rubygems'
|
|
2
2
|
require 'rake'
|
3
3
|
require 'echoe'
|
4
4
|
|
5
|
-
Echoe.new('populator', '0.2.
|
5
|
+
Echoe.new('populator', '0.2.2') do |p|
|
6
6
|
p.summary = "Mass populate an Active Record database."
|
7
7
|
p.description = "Mass populate an Active Record database."
|
8
8
|
p.url = "http://github.com/ryanb/populator"
|
9
9
|
p.author = 'Ryan Bates'
|
10
10
|
p.email = "ryan (at) railscasts (dot) com"
|
11
|
-
p.ignore_pattern = ["script/*", "**/*.sqlite3"]
|
11
|
+
p.ignore_pattern = ["script/*", "**/*.sqlite3", "tmp/*"]
|
12
12
|
end
|
13
13
|
|
14
14
|
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
data/TODO
CHANGED
@@ -8,8 +8,6 @@ Possible
|
|
8
8
|
- add random_foo method to record for randomly generating content
|
9
9
|
|
10
10
|
Performance
|
11
|
-
- ruby-prof to see where the bottlenecks are
|
12
|
-
- benchmark to find faster solutions
|
13
11
|
- ensure instantiating the model is really that much of a performance hit.
|
14
12
|
|
15
13
|
Support Environments
|
data/lib/populator.rb
CHANGED
@@ -21,6 +21,11 @@ module Populator
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
|
25
|
-
|
24
|
+
# TODO find a better way to load the SQLite adapter
|
25
|
+
module ActiveRecord # :nodoc: all
|
26
|
+
module ConnectionAdapters
|
27
|
+
class SQLiteAdapter < ActiveRecord::ConnectionAdapters::AbstractAdapter
|
28
|
+
include Populator::Adapters::Sqlite
|
29
|
+
end
|
30
|
+
end
|
26
31
|
end
|
data/lib/populator/factory.rb
CHANGED
@@ -1,14 +1,19 @@
|
|
1
1
|
module Populator
|
2
|
+
# Builds multiple Populator::Record instances and saves them to the database
|
2
3
|
class Factory
|
3
4
|
DEFAULT_RECORDS_PER_QUERY = 1000
|
4
5
|
|
5
6
|
@factories = {}
|
6
7
|
@depth = 0
|
7
8
|
|
9
|
+
# Fetches the factory dedicated to a given model class. You should always use this
|
10
|
+
# method instead of instatiating a factory directly so that a single factory is
|
11
|
+
# shared on multiple calls.
|
8
12
|
def self.for_model(model_class)
|
9
13
|
@factories[model_class] ||= new(model_class)
|
10
14
|
end
|
11
15
|
|
16
|
+
# Find all remaining factories and call save_records on them.
|
12
17
|
def self.save_remaining_records
|
13
18
|
@factories.values.each do |factory|
|
14
19
|
factory.save_records
|
@@ -16,6 +21,9 @@ module Populator
|
|
16
21
|
@factories = {}
|
17
22
|
end
|
18
23
|
|
24
|
+
# Keep track of nested factory calls so we can save the remaining records once we
|
25
|
+
# are done with the base factory. This makes Populator more efficient when nesting
|
26
|
+
# factories.
|
19
27
|
def self.remember_depth
|
20
28
|
@depth += 1
|
21
29
|
yield
|
@@ -23,17 +31,21 @@ module Populator
|
|
23
31
|
save_remaining_records if @depth.zero?
|
24
32
|
end
|
25
33
|
|
34
|
+
# Use for_model instead of instatiating a record directly.
|
26
35
|
def initialize(model_class)
|
27
36
|
@model_class = model_class
|
28
37
|
@records = []
|
29
38
|
end
|
30
39
|
|
40
|
+
# Entry method for building records. Delegates to build_records after remember_depth.
|
31
41
|
def populate(amount, options = {}, &block)
|
32
42
|
self.class.remember_depth do
|
33
43
|
build_records(Populator.interpret_value(amount), options[:per_query] || DEFAULT_RECORDS_PER_QUERY, &block)
|
34
44
|
end
|
35
45
|
end
|
36
46
|
|
47
|
+
# Builds multiple Populator::Record instances and calls save_records them when
|
48
|
+
# :per_query limit option is reached.
|
37
49
|
def build_records(amount, per_query, &block)
|
38
50
|
amount.times do
|
39
51
|
record = Record.new(@model_class, last_id_in_database + @records.size + 1)
|
@@ -43,6 +55,7 @@ module Populator
|
|
43
55
|
end
|
44
56
|
end
|
45
57
|
|
58
|
+
# Saves the records to the database by calling populate on the current database adapter.
|
46
59
|
def save_records
|
47
60
|
unless @records.empty?
|
48
61
|
@model_class.connection.populate(@model_class.quoted_table_name, columns_sql, rows_sql_arr, "#{@model_class.name} Populate")
|
@@ -1,11 +1,32 @@
|
|
1
1
|
module Populator
|
2
2
|
module ModelAdditions
|
3
|
+
# Call populate on any ActiveRecord model to fill it with data.
|
4
|
+
# Pass the number of records you want to create, and a block to
|
5
|
+
# set the attributes. You can nest calls to handle associations
|
6
|
+
# and use ranges or arrays to randomize the values.
|
7
|
+
#
|
8
|
+
# Person.populate(3000) do |person|
|
9
|
+
# person.name = "John Doe"
|
10
|
+
# person.gender = ['male', 'female']
|
11
|
+
# Project.populate(10..30, :per_query => 100) do |project|
|
12
|
+
# project.person_id = person.id
|
13
|
+
# project.due_at = 5.days.from_now..2.years.from_now
|
14
|
+
# project.name = Populator.words(1..3).titleize
|
15
|
+
# project.description = Populator.sentences(2..10)
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# The following options are supported.
|
20
|
+
#
|
21
|
+
# * <tt>:per_query</tt> - limit how many records are inserted per query, defaults to 1000
|
22
|
+
#
|
23
|
+
# Populator::Factory is where all the work happens.
|
3
24
|
def populate(amount, options = {}, &block)
|
4
25
|
Factory.for_model(self).populate(amount, options, &block)
|
5
26
|
end
|
6
27
|
end
|
7
28
|
end
|
8
29
|
|
9
|
-
|
30
|
+
ActiveRecord::Base.class_eval do
|
10
31
|
extend Populator::ModelAdditions
|
11
32
|
end
|
data/lib/populator/random.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
module Populator
|
2
|
+
# This module adds several methods for generating random data which can be
|
3
|
+
# called directly on Populator.
|
2
4
|
module Random
|
3
5
|
WORDS = %w(alias consequatur aut perferendis sit voluptatem accusantium doloremque aperiam eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo aspernatur aut odit aut fugit sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt neque dolorem ipsum quia dolor sit amet consectetur adipisci velit sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem ut enim ad minima veniam quis nostrum exercitationem ullam corporis nemo enim ipsam voluptatem quia voluptas sit suscipit laboriosam nisi ut aliquid ex ea commodi consequatur quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae et iusto odio dignissimos ducimus qui blanditiis praesentium laudantium totam rem voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident sed ut perspiciatis unde omnis iste natus error similique sunt in culpa qui officia deserunt mollitia animi id est laborum et dolorum fuga et harum quidem rerum facilis est et expedita distinctio nam libero tempore cum soluta nobis est eligendi optio cumque nihil impedit quo porro quisquam est qui minus id quod maxime placeat facere possimus omnis voluptas assumenda est omnis dolor repellendus temporibus autem quibusdam et aut consequatur vel illum qui dolorem eum fugiat quo voluptas nulla pariatur at vero eos et accusamus officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae itaque earum rerum hic tenetur a sapiente delectus ut aut reiciendis voluptatibus maiores doloribus asperiores repellat)
|
4
6
|
|
7
|
+
# Pick a random value out of a given range.
|
5
8
|
def value_in_range(range)
|
6
9
|
case range.first
|
7
10
|
when Integer then number_in_range(range)
|
@@ -11,16 +14,22 @@ module Populator
|
|
11
14
|
end
|
12
15
|
end
|
13
16
|
|
17
|
+
# Generate a given number of words. If a range is passed, it will generate
|
18
|
+
# a random number of words within that range.
|
14
19
|
def words(total)
|
15
20
|
(1..interpret_value(total)).map { WORDS.rand }.join(' ')
|
16
21
|
end
|
17
22
|
|
23
|
+
# Generate a given number of sentences. If a range is passed, it will generate
|
24
|
+
# a random number of sentences within that range.
|
18
25
|
def sentences(total)
|
19
26
|
(1..interpret_value(total)).map do
|
20
27
|
words(5..20).capitalize
|
21
28
|
end.join('. ')
|
22
29
|
end
|
23
30
|
|
31
|
+
# If an array or range is passed, a random value will be selected to match.
|
32
|
+
# All other values are simply returned.
|
24
33
|
def interpret_value(value)
|
25
34
|
case value
|
26
35
|
when Array then value.rand
|
data/lib/populator/record.rb
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
module Populator
|
2
|
+
# This is what is passed to the block when calling populate.
|
2
3
|
class Record
|
3
4
|
attr_accessor :attributes
|
4
5
|
|
6
|
+
# Creates a new instance of Record. Some attributes are set by default:
|
7
|
+
#
|
8
|
+
# * <tt>id</tt> - defaults to id passed
|
9
|
+
# * <tt>created_at</tt> - defaults to current time
|
10
|
+
# * <tt>updated_at</tt> - defaults to current time
|
11
|
+
# * <tt>created_on</tt> - defaults to current date
|
12
|
+
# * <tt>updated_on</tt> - defaults to current date
|
5
13
|
def initialize(model_class, id)
|
6
14
|
@attributes = { :id => id }
|
7
15
|
@columns = model_class.column_names
|
@@ -12,22 +20,34 @@ module Populator
|
|
12
20
|
if column == 'created_on' || column == 'updated_on'
|
13
21
|
@attributes[column.to_sym] = Date.today
|
14
22
|
end
|
15
|
-
self.instance_eval <<-EOS
|
16
|
-
def #{column}=(value)
|
17
|
-
@attributes[:#{column}] = Populator.interpret_value(value)
|
18
|
-
end
|
19
|
-
|
20
|
-
def #{column}
|
21
|
-
@attributes[:#{column}]
|
22
|
-
end
|
23
|
-
EOS
|
24
23
|
end
|
25
24
|
end
|
26
25
|
|
26
|
+
# override id since method_missing won't catch this column name
|
27
|
+
def id
|
28
|
+
@attributes[:id]
|
29
|
+
end
|
30
|
+
|
31
|
+
# Return values for all columns inside an array.
|
27
32
|
def attribute_values
|
28
33
|
@columns.map do |column|
|
29
34
|
@attributes[column.to_sym]
|
30
35
|
end
|
31
36
|
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def method_missing(sym, *args, &block)
|
41
|
+
name = sym.to_s
|
42
|
+
if @columns.include?(name.sub('=', ''))
|
43
|
+
if name.include? '='
|
44
|
+
@attributes[name.sub('=', '').to_sym] = Populator.interpret_value(args.first)
|
45
|
+
else
|
46
|
+
@attributes[sym]
|
47
|
+
end
|
48
|
+
else
|
49
|
+
super
|
50
|
+
end
|
51
|
+
end
|
32
52
|
end
|
33
53
|
end
|
data/populator.gemspec
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
|
2
|
-
# Gem::Specification for Populator-0.2.
|
2
|
+
# Gem::Specification for Populator-0.2.2
|
3
3
|
# Originally generated by Echoe
|
4
4
|
|
5
5
|
--- !ruby/object:Gem::Specification
|
6
6
|
name: populator
|
7
7
|
version: !ruby/object:Gem::Version
|
8
|
-
version: 0.2.
|
8
|
+
version: 0.2.2
|
9
9
|
platform: ruby
|
10
10
|
authors:
|
11
11
|
- Ryan Bates
|
@@ -57,6 +57,7 @@ files:
|
|
57
57
|
- LICENSE
|
58
58
|
- Manifest
|
59
59
|
- populator.gemspec
|
60
|
+
- Rakefile
|
60
61
|
- README
|
61
62
|
- spec/database.yml
|
62
63
|
- spec/example_database.yml
|
@@ -72,7 +73,6 @@ files:
|
|
72
73
|
- tasks/deployment.rake
|
73
74
|
- tasks/spec.rake
|
74
75
|
- TODO
|
75
|
-
- Rakefile
|
76
76
|
has_rdoc: true
|
77
77
|
homepage: http://github.com/ryanb/populator
|
78
78
|
post_install_message:
|
data/spec/spec_helper.rb
CHANGED
@@ -5,7 +5,7 @@ require 'active_record'
|
|
5
5
|
require File.dirname(__FILE__) + '/../lib/populator.rb'
|
6
6
|
|
7
7
|
adapter = ENV['POPULATOR_ADAPTER'] || 'sqlite3'
|
8
|
-
puts "Running
|
8
|
+
puts "Running on #{adapter}"
|
9
9
|
|
10
10
|
# setup database adapter
|
11
11
|
ActiveRecord::Base.establish_connection(
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: populator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Bates
|
@@ -54,6 +54,7 @@ files:
|
|
54
54
|
- LICENSE
|
55
55
|
- Manifest
|
56
56
|
- populator.gemspec
|
57
|
+
- Rakefile
|
57
58
|
- README
|
58
59
|
- spec/database.yml
|
59
60
|
- spec/example_database.yml
|
@@ -69,7 +70,6 @@ files:
|
|
69
70
|
- tasks/deployment.rake
|
70
71
|
- tasks/spec.rake
|
71
72
|
- TODO
|
72
|
-
- Rakefile
|
73
73
|
has_rdoc: true
|
74
74
|
homepage: http://github.com/ryanb/populator
|
75
75
|
post_install_message:
|