merb_seed 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Michael Bleigh, released under the MIT license
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 ADDED
@@ -0,0 +1,102 @@
1
+ merb_seed
2
+ =======
3
+
4
+ merb_seed is an attempt to once and for all solve the problem of inserting and
5
+ maintaining seed data in a database. It uses a variety of techniques gathered
6
+ from various places around the web and combines them to create what is
7
+ hopefully the most robust seed data system around.
8
+
9
+
10
+ Support
11
+ =======
12
+
13
+ merb_seed 0.1 currently only supports datamapper. ActiveRecord and Sequel support
14
+
15
+
16
+ Usage
17
+ =======
18
+
19
+ rake db:seed
20
+
21
+
22
+ Setting up Seed Data
23
+ =======
24
+ Seed data is taken from the schema/data directory. Simply make descriptive .rb
25
+ files in that directory (they can be named anything, but users.rb for the User
26
+ model seed data makes sense, etc.). These scripts will be run whenever the
27
+ db:seed rake task is called. You can put arbitrary Ruby code in these files,
28
+ but remember that it will be executed every time the rake task is called, so
29
+ it needs to be runnable multiple times on the same database.
30
+
31
+ You can also have environment-specific seed data placed in
32
+ schema/data/ENVIRONMENT that will only be loaded if that is the current
33
+ environment.
34
+
35
+ Let's say we want to populate a few default users. In schema/data/users.rb we
36
+ write the following code:
37
+
38
+ User.seed(:login, :email) do |s|
39
+ s.login = "bob"
40
+ s.email = "bob@bobson.com"
41
+ s.first_name = "Bob"
42
+ s.last_name = "Bobson"
43
+ end
44
+
45
+ User.seed(:login, :email) do |s|
46
+ s.login = "bob"
47
+ s.email = "bob@stevenson.com"
48
+ s.first_name = "Bob"
49
+ s.last_name = "Stevenson"
50
+ end
51
+
52
+ That's all you have to do! You will now have two users created in the system
53
+ and you can change their first and last names in the users.rb file and it will
54
+ be updated as such.
55
+
56
+ The arguments passed to the <ActiveRecord>.seed method are the constraining
57
+ attributes: these must remain unchanged between db:seed calls to avoid data
58
+ duplication. By default, seed data will constrain to the id like so:
59
+
60
+ Category.seed do |s|
61
+ s.id = 1
62
+ s.name = "Buttons"
63
+ end
64
+
65
+ Category.seed do |s|
66
+ s.id = 2
67
+ s.name = "Bobbins"
68
+ s.parent_id = 1
69
+ end
70
+
71
+ Note that any constraints that are passed in must be present in the subsequent
72
+ seed data setting.
73
+
74
+
75
+ Callbacks
76
+ =======
77
+
78
+ Seed data can also define callbacks that will run after the record is created
79
+
80
+ Category.seed do |s|
81
+ s.id = 2
82
+ s.name = "Bobbins"
83
+ s.parent_id = 1
84
+
85
+ # run code after creation (record is the newly created model)
86
+ s.after_seed do |record|
87
+ record.enable!
88
+ end
89
+ end
90
+
91
+ Source Code
92
+ =======
93
+
94
+ Need a change? Help out by forking and doing a pull request. I'll merge in any new features or bug fixes that you make.
95
+ http://github.com/merbjedi/merb_seed
96
+
97
+
98
+ Seed Fu
99
+ =======
100
+ merb_seed is a port of seed-fu to Merb
101
+
102
+ http://github.com/mbleigh/seed-fu
data/Rakefile ADDED
@@ -0,0 +1,54 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+
4
+ require 'merb-core'
5
+ require 'merb-core/tasks/merb'
6
+
7
+ GEM_NAME = "merb_seed"
8
+ GEM_VERSION = "0.1.0"
9
+ AUTHOR = "Jacques Crocker"
10
+ EMAIL = "merbjedi@gmil.com"
11
+ HOMEPAGE = "http://merbjedi.com/"
12
+ SUMMARY = "Merb plugin that provides RAKE tasks to easily initialize seed data in your database"
13
+
14
+ spec = Gem::Specification.new do |s|
15
+ s.rubyforge_project = 'merb'
16
+ s.name = GEM_NAME
17
+ s.version = GEM_VERSION
18
+ s.platform = Gem::Platform::RUBY
19
+ s.has_rdoc = true
20
+ s.extra_rdoc_files = ["README", "LICENSE"]
21
+ s.summary = SUMMARY
22
+ s.description = s.summary
23
+ s.author = AUTHOR
24
+ s.email = EMAIL
25
+ s.homepage = HOMEPAGE
26
+
27
+ # todo: allow merb_seed to support activerecord and sequel
28
+ s.add_dependency('merb_datamapper', '>= 1.0.8')
29
+
30
+ s.require_path = 'lib'
31
+ s.files = %w(LICENSE README Rakefile) + Dir.glob("{lib,spec}/**/*")
32
+
33
+ end
34
+
35
+ Rake::GemPackageTask.new(spec) do |pkg|
36
+ pkg.gem_spec = spec
37
+ end
38
+
39
+ desc "install the plugin as a gem"
40
+ task :install do
41
+ Merb::RakeHelper.install(GEM_NAME, :version => GEM_VERSION)
42
+ end
43
+
44
+ desc "Uninstall the gem"
45
+ task :uninstall do
46
+ Merb::RakeHelper.uninstall(GEM_NAME, :version => GEM_VERSION)
47
+ end
48
+
49
+ desc "Create a gemspec file"
50
+ task :gemspec do
51
+ File.open("#{GEM_NAME}.gemspec", "w") do |file|
52
+ file.puts spec.to_ruby
53
+ end
54
+ end
data/lib/merb_seed.rb ADDED
@@ -0,0 +1,19 @@
1
+ # make sure we're running inside Merb
2
+ if defined?(Merb::Plugins)
3
+
4
+ # Merb gives you a Merb::Plugins.config hash...feel free to put your stuff in your piece of it
5
+ Merb::Plugins.config[:merb_seed] = {
6
+ :seed_path => "schema/data"
7
+ }
8
+
9
+ Merb::BootLoader.before_app_loads do
10
+ # require code that must be loaded before the application
11
+ end
12
+
13
+ Merb::BootLoader.after_app_loads do
14
+ # code that can be required after the application loads
15
+ end
16
+
17
+ Merb::Plugins.add_rakefiles "merb_seed/merbtasks"
18
+ end
19
+
@@ -0,0 +1,24 @@
1
+ namespace :db do
2
+ desc "Loads seed data from schema/data for the current environment."
3
+ task :seed => :merb_env do
4
+ require File.join( File.dirname(__FILE__), "seeder")
5
+
6
+ # load ruby seed files
7
+ seed_path = ENV["SEED_PATH"] ? ENV["SEED_PATH"] : (Merb::Plugins.config[:merb_seed][:seed_path] || "schema/data")
8
+ Dir[File.join(Merb.root, seed_path, '*.rb')].sort.each { |seed|
9
+ puts "\n== Seeding from #{File.split(seed).last} " + ("=" * (60 - (17 + File.split(seed).last.length)))
10
+ load seed
11
+ puts "=" * 60 + "\n"
12
+ }
13
+
14
+ # load environment specific seed files
15
+ Dir[File.join(Merb.root, seed_path, Merb.env, '*.rb')].sort.each { |seed|
16
+ puts "\n== [#{Merb.env}] Seeding from #{File.split(seed).last} " + ("=" * (60 - (20 + File.split(seed).last.length + Merb.env.length)))
17
+ load seed
18
+ puts "=" * 60 + "\n"
19
+ }
20
+
21
+ # load seed files from yml
22
+ # TODO
23
+ end
24
+ end
@@ -0,0 +1 @@
1
+ # TODO
@@ -0,0 +1,27 @@
1
+ require 'datamapper'
2
+
3
+ module DataMapper::Model
4
+ # Creates a single record of seed data for use
5
+ # with the db:seed rake task.
6
+ #
7
+ # === Parameters
8
+ # constraints :: Immutable reference attributes. Defaults to :id
9
+ def seed(*constraints, &block)
10
+ MerbSeed::Seeder.plant(self, *constraints, &block)
11
+ end
12
+
13
+ def seed_many(*constraints)
14
+ seeds = constraints.pop
15
+ seeds.each do |seed_data|
16
+ seed(*constraints) do |s|
17
+ seed_data.each_pair do |k,v|
18
+ s.send "#{k}=", v
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ def column_names
25
+ properties.map{|i| i.field }
26
+ end
27
+ end
@@ -0,0 +1 @@
1
+ # TODO
@@ -0,0 +1,87 @@
1
+ require File.join( File.dirname(__FILE__), "orm", "dm_ext")
2
+
3
+ module MerbSeed
4
+ class Seeder
5
+ def self.plant(model_class, *constraints, &block)
6
+ constraints = [:id] if constraints.empty?
7
+ seed = Seeder.new(model_class)
8
+
9
+ options = constraints.last if (constraints.last.is_a? Hash)
10
+ constraints.delete_at(*constraints.length-1) if (constraints.last.is_a? Hash)
11
+
12
+ insert_only = constraints.last.is_a? TrueClass
13
+ constraints.delete_at(*constraints.length-1) if (constraints.last.is_a? TrueClass or constraints.last.is_a? FalseClass)
14
+ seed.set_constraints(*constraints)
15
+ yield seed
16
+ seed.plant!({:insert_only => insert_only}.merge(options||{}))
17
+ end
18
+
19
+ def initialize(model_class)
20
+ @model_class = model_class
21
+ @constraints = [:id]
22
+ @data = {}
23
+ end
24
+
25
+ def set_constraints(*constraints)
26
+ raise "You must set at least one constraint." if constraints.empty?
27
+ @constraints = []
28
+ constraints.each do |constraint|
29
+ raise "Your constraint `#{constraint}` is not a column in #{@model_class}. Valid columns are `#{@model_class.column_names.join("`, `")}`." unless @model_class.column_names.include?(constraint.to_s)
30
+ @constraints << constraint.to_sym
31
+ end
32
+ end
33
+
34
+ def set_attribute(name, value)
35
+ @data[name.to_sym] = value
36
+ end
37
+
38
+ def after_seed(&block)
39
+ if block
40
+ @after_seed_block = block
41
+ else
42
+ @after_seed_block
43
+ end
44
+ end
45
+
46
+ def plant!(options)
47
+ insert_only = options[:insert_only].nil? ? false : options[:insert_only]
48
+
49
+ record = get
50
+ return if !record.new_record? and insert_only
51
+ @data.each do |k, v|
52
+ record.send("#{k}=", v)
53
+ end
54
+ record.save || raise("Validation Failed. Use :validate => false in order to skip this:\n#{record.errors.inspect}")
55
+ puts " - #{@model_class} #{condition_hash.inspect}"
56
+
57
+ # fire off after_seed event
58
+ self.after_seed.call(record) if self.after_seed
59
+
60
+ record
61
+ end
62
+
63
+ def method_missing(method_name, *args) #:nodoc:
64
+ if (match = method_name.to_s.match(/(.*)=$/)) && args.size == 1
65
+ set_attribute(match[1], args.first)
66
+ else
67
+ super
68
+ end
69
+ end
70
+
71
+ protected
72
+
73
+ def get
74
+ records = @model_class.all(:conditions => condition_hash)
75
+ raise "Given constraints yielded multiple records." unless records.size < 2
76
+ if records.any?
77
+ return records.first
78
+ else
79
+ return @model_class.new
80
+ end
81
+ end
82
+
83
+ def condition_hash
84
+ @data.reject{|a,v| !@constraints.include?(a)}
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,17 @@
1
+ require 'datamapper'
2
+
3
+ # setup repository
4
+ DataMapper.setup(:default, "sqlite3::memory:")
5
+
6
+ # setup models
7
+ class User
8
+ include DataMapper::Resource
9
+
10
+ property :id, Serial
11
+ property :login, String
12
+ property :first_name, String
13
+ property :last_name, String
14
+ property :title, String
15
+ end
16
+
17
+ User.auto_migrate!
@@ -0,0 +1,63 @@
1
+ require File.join( File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe "merb_seed" do
4
+
5
+ describe "datamapper support" do
6
+ before(:each) do
7
+ load File.join( File.dirname(__FILE__), "fixtures", "dm_models.rb")
8
+ end
9
+
10
+ it "should create a model if one doesn't exist" do
11
+ User.seed(:id) do |s|
12
+ s.id = 1
13
+ s.login = "bob"
14
+ s.first_name = "Bob"
15
+ s.last_name = "Bobson"
16
+ s.title = "Peon"
17
+ end
18
+
19
+ bob = User.get(1)
20
+ bob.first_name.should == "Bob"
21
+ bob.last_name.should == "Bobson"
22
+ end
23
+
24
+ it "should be able to handle multiple constraints" do
25
+ User.seed(:title, :login) do |s|
26
+ s.login = "bob"
27
+ s.title = "Peon"
28
+ s.first_name = "Bob"
29
+ end
30
+
31
+ User.count.should == 1
32
+
33
+ User.seed(:title, :login) do |s|
34
+ s.login = "frank"
35
+ s.title = "Peon"
36
+ s.first_name = "Frank"
37
+ end
38
+
39
+ User.count.should == 2
40
+
41
+ User.first(:first_name => "Bob").first_name.should == "Bob"
42
+ User.seed(:title, :login) do |s|
43
+ s.login = "bob"
44
+ s.title = "Peon"
45
+ s.first_name = "Steve"
46
+ end
47
+ User.first(:first_name => "Steve").first_name.should == "Steve"
48
+ end
49
+
50
+ it "should be able to create models from an array of seed attributes" do
51
+ User.seed_many(:title, :login, [
52
+ {:login => "bob", :title => "Peon", :first_name => "Steve"},
53
+ {:login => "frank", :title => "Peasant", :first_name => "Francis"},
54
+ {:login => "harry", :title => "Noble", :first_name => "Harry"}
55
+ ])
56
+
57
+ User.first(:login => "bob").first_name.should == "Steve"
58
+ User.first(:login => "frank").first_name.should == "Francis"
59
+ User.first(:login => "harry").first_name.should == "Harry"
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,6 @@
1
+ $:.push File.join(File.dirname(__FILE__), '..', 'lib')
2
+
3
+ require 'rubygems'
4
+ require 'spec'
5
+
6
+ require 'merb_seed/seeder'
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: merb_seed
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jacques Crocker
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-15 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: merb_datamapper
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.0.8
24
+ version:
25
+ description: Merb plugin that provides RAKE tasks to easily initialize seed data in your database
26
+ email: merbjedi@gmil.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README
33
+ - LICENSE
34
+ files:
35
+ - LICENSE
36
+ - README
37
+ - Rakefile
38
+ - lib/merb_seed
39
+ - lib/merb_seed/merbtasks.rb
40
+ - lib/merb_seed/orm
41
+ - lib/merb_seed/orm/ar_ext.rb
42
+ - lib/merb_seed/orm/dm_ext.rb
43
+ - lib/merb_seed/orm/sequel_ext.rb
44
+ - lib/merb_seed/seeder.rb
45
+ - lib/merb_seed.rb
46
+ - spec/fixtures
47
+ - spec/fixtures/dm_models.rb
48
+ - spec/merb_seed_spec.rb
49
+ - spec/spec_helper.rb
50
+ has_rdoc: true
51
+ homepage: http://merbjedi.com/
52
+ post_install_message:
53
+ rdoc_options: []
54
+
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ version:
69
+ requirements: []
70
+
71
+ rubyforge_project: merb
72
+ rubygems_version: 1.3.1
73
+ signing_key:
74
+ specification_version: 2
75
+ summary: Merb plugin that provides RAKE tasks to easily initialize seed data in your database
76
+ test_files: []
77
+