dummy_data 0.9

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ ## 0.9 (August 10, 2010)
2
+
3
+ Features:
4
+ - generating data for Rails 3 applications by using dummy (functionality split up from old project)
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Gonçalo Silva
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # Dummy data
2
+
3
+ "Dummy data" uses dummy[http://github.com/goncalossilva/dummy] to generate clever data for your Rails 3 application; it also allows you to import it to the database.
4
+
5
+ ## Description
6
+
7
+ Check dummy's[http://github.com/goncalossilva/dummy] description for a better notion of what exactly is dummy data. This gem uses dummy to generate this data for your models and stores it in YAML files. It also provides a rake task for you to import it to the database.
8
+
9
+ ## Installation
10
+
11
+ $ gem install dummy_data
12
+
13
+ ## Usage
14
+
15
+ Add the following to the Gemfile of your Rails 3 application:
16
+ gem "dummy_data"
17
+
18
+ Now you have access to the generator:
19
+ rails generate dummy:data
20
+
21
+ You can change the base amount of records and the growth ratio (what these mean exactly is explained latter on):
22
+ rails generate dummy:data --base-amount 5 --growth-ratio 1.5
23
+
24
+ Also, you can manually define the amount of records to generate for each model (or just accept the defaults):
25
+ rails generate dummy:data --manual-amounts
26
+
27
+ And you can manually set the output folder for the dummy data (which defaults to test/dummy):
28
+ rails generate dummy:data --output-folder test/awesome_dummy
29
+
30
+ The files will be placed under _output-folder_/data.
31
+
32
+ Feel free to mix all of these options.
33
+
34
+ The fixtures are stored in _test/dummy/data_ (by default) while a rake file is placed in _lib/tasks/dummy\_data.rake_. It allows you to import the generated data into the database:
35
+ RAILS_ENV="dummy" rake dummy:data:import
36
+
37
+ Don't forget to change RAILS_ENV to whatever is appropriate for you (and is configured under databases.yml). Your database doesn't need to be empty.
38
+
39
+ ## More information
40
+
41
+ ### Smart data
42
+
43
+ "Dummy data" tells dummy to try to understand your database columns and generate data accordingly, instead of dumping "Lorem ipsum" all over the place.
44
+
45
+ For instance, if you have a field called _company\_name_, it will generate a company name. If you have a field called _awesome\_postal\_code_, it will generate a valid ZIP Code. If you have a field called _longitude_, it will generate a valid longitude, and so on. You get the picture.
46
+
47
+ Dummy cares about associations. It will create random associations between the automatically generated records, so you don't have to worry about that.
48
+
49
+ ### Smart amounts of data
50
+
51
+ "Dummy data" is aware that the amount of records that each model has in real world applications is different. For this reason, it will analyze your model associations to try to make a somewhat accurate estimation of the expected amount of records.
52
+
53
+ To illustrate this, consider an application with models for _Child_, _Parent_ and _GrandParent_. If the base amount is 10, the growth ratio is 2.0, and the models look like the following:
54
+
55
+ class GrandParent < ActiveRecord::Base
56
+ has_many :parents
57
+ end
58
+
59
+ class Parent < ActiveRecord::Base
60
+ belongs_to :grand_parent
61
+ has_many :children
62
+ end
63
+
64
+ class Child < ActiveRecord::Base
65
+ belongs_to :parent
66
+ end`
67
+
68
+ The generator will create dummy data for 10 _GrandParents_, 20 _Parents_ and 40 _Children_.
69
+
70
+ Copyright (c) 2010 Gonçalo Silva
data/lib/dummy_data.rb ADDED
@@ -0,0 +1,4 @@
1
+ require "rubygems"
2
+ require "dummy"
3
+ require "generators/common"
4
+ require "generators/data/data_generator"
@@ -0,0 +1,82 @@
1
+ module Dummy
2
+ module Generators
3
+ # Methods used by other dummy-related gems are grouped here
4
+ # Other generators will just "include Dummy::Generators::Common"
5
+ module Common
6
+ def gather_associations
7
+ @models.each_key do |model|
8
+ model_symbol = model.to_s.underscore.pluralize.to_sym
9
+ associations = model.reflect_on_all_associations(:belongs_to)
10
+
11
+ associations.each do |assoc|
12
+ assoc_name = assoc.name.to_s.camelcase
13
+ assoc_options = assoc.options
14
+
15
+ if assoc_options.empty?
16
+ @models[model][:associations].push({
17
+ :model => assoc_name.constantize,
18
+ :foreign_key => "#{assoc_name.underscore}_id"
19
+ })
20
+ elsif assoc_options.has_key?(:class_name) and assoc_options.has_key?(:foreign_key)
21
+ @models[model][:associations].push({
22
+ :model => assoc_options[:class_name].constantize, # TODO: handle class_name
23
+ :foreign_key => assoc_options[:foreign_key]
24
+ })
25
+ else
26
+ next
27
+ end
28
+
29
+ assoc_model = @models[model][:associations].last[:model]
30
+ assoc_reflections = assoc_model.reflect_on_all_associations(:has_one)
31
+ @models[model][:associations].pop if assoc_reflections.map(&:name).include?(model_symbol)
32
+ end
33
+ end
34
+ end
35
+
36
+ def generate_record_data(name, info, column, fixtures=true)
37
+ column_name = String.new(column.name) # this shouldn't be needed, ruby bug?
38
+ if(column_name =~ /_at$/ and column.type == :datetime) or column_name == "id"
39
+ return
40
+ end
41
+
42
+ associated_model = associated_class_name(info, column_name)
43
+
44
+ if associated_model
45
+ if fixtures
46
+ val = generate_association_data(associated_model)
47
+ column_name.gsub!(/_id$/, "")
48
+ else
49
+ val = Fixtures.identify(generate_association_data(associated_model))
50
+ end
51
+ else
52
+ val = generate_regular_data(column)
53
+ end
54
+
55
+ {column_name => val}
56
+ end
57
+
58
+ def associated_class_name(info, name)
59
+ info[:associations].each do |assoc|
60
+ return assoc[:model] if assoc[:foreign_key] == name
61
+ end
62
+ false
63
+ end
64
+
65
+ def generate_association_data(associated_model)
66
+ random_record_num = rand(@models[associated_model][:record_amount])
67
+ "#{associated_model.to_s.underscore}_#{random_record_num}"
68
+ end
69
+
70
+ def generate_regular_data(column)
71
+ val = Dummy.magic_data(column.name, column.type)
72
+
73
+ if val
74
+ val
75
+ else
76
+ say_status :failed, "data generation for '#{column.name}' with type '#{column.type.to_s.downcase}'", :red
77
+ ""
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,145 @@
1
+ require "yaml"
2
+ require "active_support"
3
+ require "active_support/core_ext/string/inflections"
4
+ require "active_record"
5
+ require "active_record/fixtures"
6
+ require "rails/generators"
7
+
8
+ module Dummy
9
+ module Generators
10
+ class DataGenerator < Rails::Generators::Base
11
+ include Dummy::Generators::Common
12
+
13
+ def self.source_root
14
+ @source_root ||= File.expand_path("../templates", __FILE__)
15
+ end
16
+
17
+ class_option :base_amount, :type => :numeric, :default => 10,
18
+ :desc => "The base amount of records to generate for each model."
19
+ class_option :growth_ratio, :type => :numeric, :default => 2.0,
20
+ :desc => "The growth ratio of each model, according to its associations."
21
+ class_option :manual_amounts, :type => :boolean, :default => false,
22
+ :desc => "Manually set the amount of records for each model."
23
+ class_option :output_folder, :type => :string, :default => "test/dummy",
24
+ :desc => "Dummy output folder, data/ will be used when storing the resulting YAML files."
25
+
26
+ def install_dummy_data
27
+ initialize_application
28
+ generate_dummy_data
29
+ copy_rake_file
30
+ create_dummyfile
31
+ end
32
+
33
+ private
34
+
35
+ def initialize_application
36
+ require File.expand_path("#{Rails.root}/config/environment.rb")
37
+ say_status :successful, "initialize Rails application"
38
+ end
39
+
40
+ def generate_dummy_data
41
+ get_table_names
42
+ gather_associations
43
+ predict_record_amounts
44
+ generate_and_write_data
45
+ end
46
+
47
+ def get_table_names
48
+ @models = Hash.new
49
+ Dir["app/models/*.rb"].each do |full_path|
50
+ model = File.basename(full_path).chomp(File.extname(full_path)).camelcase.constantize
51
+ @models.merge!({model => {
52
+ :record_amount => 0, :associations => []
53
+ }}) if model.respond_to?(:columns)
54
+ end
55
+ end
56
+
57
+ def predict_record_amounts
58
+ models = @models.dup
59
+ models.each do |model, info|
60
+ predict_record_amount(model, info, models, [])
61
+ end
62
+ end
63
+
64
+ def predict_record_amount(model, info, models, stacked_models)
65
+ info[:associations].each do |assoc|
66
+ next if stacked_models.include?(assoc[:model])
67
+
68
+ if model != assoc[:model]
69
+ stacked_models << assoc[:model]
70
+ predict_record_amount(assoc[:model], @models[assoc[:model]], models, stacked_models)
71
+ end
72
+ end
73
+
74
+ amount = options.base_amount
75
+ if not info[:associations].empty?
76
+ amount = info[:associations].map do |assoc|
77
+ @models[assoc[:model]][:record_amount]
78
+ end.max * options.growth_ratio # **info[:associations].size
79
+ end
80
+
81
+ if options.manual_amounts
82
+ user_defined = ask("Number of records for #{model} (default: #{amount}): ")
83
+ amount = user_defined unless user_defined.empty?
84
+ end
85
+
86
+ @models[model][:record_amount] = amount.to_i
87
+ stacked_models.delete(model)
88
+ models.delete(model)
89
+ end
90
+
91
+ def generate_and_write_data
92
+ empty_directory "#{options.output_folder}/data"
93
+ data = Hash.new
94
+
95
+ @models.each do |model, info|
96
+ name = model.to_s.underscore
97
+
98
+ (0..info[:record_amount]-1).each do |num|
99
+ key_value = Hash.new
100
+ fixture_data = Hash.new
101
+
102
+ model.columns.each do |column|
103
+ key_value = generate_record_data(name, info, column)
104
+ fixture_data.merge!(key_value) unless key_value.nil?
105
+ end
106
+
107
+ data[model.table_name] = Hash.new if data[model.table_name].nil?
108
+ data[model.table_name].merge!({ "#{name}_#{num}" => fixture_data })
109
+ end
110
+
111
+ say_status :successful, "generate #{info[:record_amount]} records for '#{name}'"
112
+ end
113
+
114
+ data.each do |name, fixtures|
115
+ content = "# '#{name}' data generated automatically by dummy at #{Time.now.strftime("%H:%M %m/%d/%Y")} (#{fixtures.size} records).\n"
116
+
117
+ content << YAML.dump(fixtures)
118
+
119
+ create_file "#{options.output_folder}/data/#{name}.yml", content
120
+ end
121
+ say_status :successful, "store fixtures"
122
+ end
123
+
124
+ def copy_rake_file
125
+ template "dummy_data.rake", "lib/tasks/dummy_data.rake"
126
+ end
127
+
128
+ def create_dummyfile
129
+ data = Hash.new
130
+ dummyfile_path = "#{options.output_folder}/Dummyfile"
131
+
132
+ @models.each do |model, info|
133
+ data[model.to_s.underscore.pluralize] = {:records => info[:record_amount]}
134
+ end
135
+
136
+ content = "# This file was automatically generated by Dummy. Do NOT change it.\n"
137
+ content << YAML.dump(data)
138
+
139
+ remove_file dummyfile_path, :verbose => false if File.exists?(dummyfile_path)
140
+ create_file dummyfile_path, content
141
+ end
142
+ end
143
+ end
144
+ end
145
+
@@ -0,0 +1,13 @@
1
+ require "active_record/fixtures"
2
+
3
+ namespace :dummy do
4
+ namespace :data do
5
+ desc "Load the generated dummy data into the current environment's database."
6
+ task :import => :environment do
7
+ Fixtures.reset_cache
8
+ fixtures_folder = File.join(Rails.root, "<%= options.output_folder %>/data")
9
+ fixtures = Dir[File.join(fixtures_folder, '*.yml')].map {|f| File.basename(f, '.yml') }
10
+ Fixtures.create_fixtures(fixtures_folder, fixtures)
11
+ end
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dummy_data
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 9
8
+ version: "0.9"
9
+ platform: ruby
10
+ authors:
11
+ - "Gon\xC3\xA7alo Silva"
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+
16
+ date: 2010-08-11 00:00:00 +01:00
17
+ default_executable:
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: dummy
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ - 9
30
+ version: "0.9"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: rails
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 3
43
+ - 0
44
+ - 0
45
+ - beta
46
+ version: 3.0.0.beta
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ description: Uses dummy to generate consistent fake data for your models (including associations) and provides a rake task to import it into the database
50
+ email:
51
+ - goncalossilva@gmail.com
52
+ executables: []
53
+
54
+ extensions: []
55
+
56
+ extra_rdoc_files: []
57
+
58
+ files:
59
+ - lib/generators/data/data_generator.rb
60
+ - lib/generators/common.rb
61
+ - lib/dummy_data.rb
62
+ - lib/generators/data/templates/dummy_data.rake
63
+ - LICENSE
64
+ - README.md
65
+ - CHANGELOG.md
66
+ has_rdoc: true
67
+ homepage: http://github.com/goncalossilva/dummy_data
68
+ licenses: []
69
+
70
+ post_install_message:
71
+ rdoc_options: []
72
+
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ segments:
81
+ - 0
82
+ version: "0"
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ segments:
89
+ - 1
90
+ - 3
91
+ - 7
92
+ version: 1.3.7
93
+ requirements: []
94
+
95
+ rubyforge_project: dummy_data
96
+ rubygems_version: 1.3.7
97
+ signing_key:
98
+ specification_version: 3
99
+ summary: Uses dummy to generate data for your models and allows you to import it
100
+ test_files: []
101
+