sinsiliux-hornsby 0.1.0 → 0.2.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) 2007 Lachie Cox
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.rdoc CHANGED
@@ -44,6 +44,9 @@ Scenarios look like:
44
44
  end
45
45
  end
46
46
 
47
+ All scenarios are run only once, no matter how many times they were called, meaning that you don't need to worry about
48
+ duplicating data.
49
+
47
50
  == Setup
48
51
 
49
52
  Install the plugin:
@@ -89,7 +92,6 @@ If you'd like simply to load your scenarios into a database, use the rake task l
89
92
  == TODO
90
93
 
91
94
  * Add scenario namespaces for better organisation.
92
- * Detect scenario cycles.
93
95
 
94
96
  == Credits
95
97
 
data/lib/hornsby.rb CHANGED
@@ -1,21 +1,13 @@
1
1
  class Hornsby
2
- @@record_name_fields = %w( name title username login )
3
2
  @@delete_sql = "DELETE FROM %s"
4
-
3
+
5
4
  def self.framework_root
6
- if const_defined?(:RAILS_ROOT)
7
- puts "rails root"
8
- RAILS_ROOT
9
- elsif const_defined?(:Merb)
10
- puts "merb"
11
- Merb.root
12
- elsif const_defined?('Rails')
13
- Rails.root
14
- end
5
+ RAILS_ROOT rescue Rails.root rescue Merb.root rescue ''
15
6
  end
16
-
7
+
17
8
  cattr_reader :scenarios
18
9
  @@scenarios = {}
10
+ @@executed_scenarios = Set.new
19
11
  cattr_reader :global_scenarios
20
12
  # @@namespaces = {}
21
13
 
@@ -27,7 +19,8 @@ class Hornsby
27
19
  config.include(HornsbySpecHelper)
28
20
 
29
21
  config.before do
30
- @@global_scenarios.each {|s| s.copy_ivars(self)} if @@global_scenarios
22
+ @@executed_scenarios = Set.new(@@global_scenarios.collect {|s| s.scenario })
23
+ @@global_scenarios.each {|s| s.copy_ivars(self, true)} if @@global_scenarios
31
24
  ActiveRecord::Base.connection.increment_open_transactions
32
25
  ActiveRecord::Base.connection.transaction_joinable = false
33
26
  ActiveRecord::Base.connection.begin_db_transaction
@@ -38,64 +31,77 @@ class Hornsby
38
31
  ActiveRecord::Base.connection.decrement_open_transactions
39
32
  end
40
33
  end
41
-
34
+
42
35
  def self.build(*names)
43
36
  scenarios = names.map {|name| @@scenarios[name.to_sym] or raise "scenario #{name} not found"}
44
-
37
+
45
38
  scenarios.each {|s| s.build}
46
39
  end
47
-
40
+
48
41
  def self.[](name)
49
42
  end
50
-
43
+
51
44
  def self.load(scenarios_file=nil)
52
- delete_tables
53
45
  return unless @@scenarios.empty?
54
46
 
47
+ delete_tables
55
48
  scenarios_file ||= framework_root + '/spec/hornsby_scenarios.rb'
56
49
  self.module_eval File.read(scenarios_file)
57
50
  end
58
-
59
- def self.scenario(scenario,&block)
51
+
52
+ def self.scenario(scenario, &block)
60
53
  self.new(scenario, &block)
61
54
  end
62
-
63
- def self.namespace(name,&block)
55
+
56
+ def self.namespace(name, &block)
64
57
  end
65
-
58
+
66
59
  def self.reset!
67
60
  @@scenarios = {}
68
61
  end
69
-
62
+
63
+ def self.delete_tables
64
+ tables.each { |t| ActiveRecord::Base.connection.delete(@@delete_sql % t) }
65
+ end
66
+
67
+ def self.tables
68
+ ActiveRecord::Base.connection.tables - skip_tables
69
+ end
70
+
71
+ def self.skip_tables
72
+ %w( schema_info )
73
+ end
74
+
75
+ attr_reader :scenario
76
+
70
77
  def initialize(scenario, &block)
71
78
  case scenario
72
- when Hash
73
- parents = scenario.values.first
74
- @parents = Array === parents ? parents : [parents]
75
- scenario = scenario.keys.first
76
- when Symbol, String
77
- @parents = []
78
- else
79
- raise "I don't know how to build `#{scenario.inspect}'"
79
+ when Hash
80
+ parents = scenario.values.first
81
+ @parents = Array === parents ? parents : [parents]
82
+ scenario = scenario.keys.first
83
+ when Symbol, String
84
+ @parents = []
85
+ else
86
+ raise "I don't know how to build `#{scenario.inspect}'"
80
87
  end
81
-
88
+
82
89
  @scenario = scenario.to_sym
83
90
  @block = block
84
-
91
+
85
92
  @@scenarios[@scenario] = self
86
93
  end
87
-
94
+
88
95
  def say(*messages)
89
96
  puts messages.map { |message| "=> #{message}" }
90
97
  end
91
98
 
92
99
  def build
93
- #say "Building scenario `#{@scenario}'"
94
100
  @context = context = Module.new
95
-
101
+
96
102
  # TODO move this elsewhere
97
- context.module_eval do
98
- def self.method_missing(meth_id,*args,&block)
103
+ context.module_exec do
104
+ def self.method_missing(meth_id, *args, &block)
99
105
  begin
100
106
  rec = meth_id.to_s.classify.constantize.send(:create!, *args)
101
107
  yield(rec) if block_given?
@@ -104,21 +110,22 @@ class Hornsby
104
110
  end
105
111
  end
106
112
  end
107
-
113
+
108
114
  ivars = context.instance_variables
109
-
115
+
110
116
  build_parent_scenarios(context)
111
117
  build_scenario(context)
112
-
118
+
113
119
  @context_ivars = context.instance_variables - ivars
114
-
120
+
115
121
  self
116
122
  end
117
-
123
+
118
124
  def build_scenario(context)
119
- surface_errors { context.module_eval(&@block) }
125
+ surface_errors { context.module_eval(&@block) } unless @@executed_scenarios.include?(@scenario)
126
+ @@executed_scenarios << @scenario
120
127
  end
121
-
128
+
122
129
  def build_parent_scenarios(context)
123
130
  @parents.each do |p|
124
131
  parent = self.class.scenarios[p] or raise "parent scenario [#{p}] not found!"
@@ -128,33 +135,22 @@ class Hornsby
128
135
  end
129
136
  end
130
137
 
131
-
132
138
  def surface_errors
133
139
  yield
134
- rescue Object => error
135
- puts
140
+ rescue StandardError => error
141
+ puts
136
142
  say "There was an error building scenario `#{@scenario}'", error.inspect
137
- puts
143
+ puts
138
144
  puts error.backtrace
139
- puts
145
+ puts
140
146
  raise error
141
147
  end
142
-
143
- def self.delete_tables
144
- tables.each { |t| ActiveRecord::Base.connection.delete(@@delete_sql % t) }
145
- end
146
148
 
147
- def self.tables
148
- ActiveRecord::Base.connection.tables - skip_tables
149
- end
150
-
151
- def self.skip_tables
152
- %w( schema_info )
153
- end
154
-
155
- def copy_ivars(to)
149
+ def copy_ivars(to, reload = false)
156
150
  @context_ivars.each do |iv|
157
- to.instance_variable_set(iv, @context.instance_variable_get(iv))
151
+ v = @context.instance_variable_get(iv)
152
+ v.reload if reload and v.respond_to?(:reload)
153
+ to.instance_variable_set(iv, v)
158
154
  end
159
155
  end
160
156
  end
File without changes
@@ -0,0 +1,8 @@
1
+ test:
2
+ adapter: mysql
3
+ socket: /var/run/mysqld/mysqld.sock
4
+ encoding: utf8
5
+ database: hornsby_test
6
+ username: root
7
+ password:
8
+ host: localhost
data/spec/db/fruit.rb ADDED
@@ -0,0 +1,2 @@
1
+ class Fruit < ActiveRecord::Base
2
+ end
data/spec/db/schema.rb ADDED
@@ -0,0 +1,6 @@
1
+ ActiveRecord::Schema.define(:version => 0) do
2
+ create_table :fruits, :force => true do |t|
3
+ t.string :species
4
+ t.integer :average_diameter
5
+ end
6
+ end
@@ -0,0 +1,36 @@
1
+ scenario(:just_apple) do
2
+ @apple = Fruit.create! :species => 'apple'
3
+ end
4
+
5
+ scenario(:many_apples => [:just_apple, :just_apple, :just_apple]) do
6
+ end
7
+
8
+ scenario(:bananas_and_apples => :just_apple) do
9
+ @banana = Fruit.create! :species => 'banana'
10
+ end
11
+
12
+ scenario(:just_orange) do
13
+ @orange = Fruit.create! :species => 'orange'
14
+ end
15
+
16
+ scenario(:fruit => [:just_apple,:just_orange]) do
17
+ @fruit = [@orange,@apple]
18
+ end
19
+
20
+ scenario(:bananas_and_apples_and_oranges => [:bananas_and_apples,:just_orange]) do
21
+ @fruit = [@orange,@apple,@banana]
22
+ end
23
+
24
+ scenario(:cherry) do
25
+ @cherry = Fruit.create! :species => 'cherry', :average_diameter => 3
26
+ end
27
+
28
+ # Hornsby.namespace(:pitted_fruit) do
29
+ # scenario(:peach) do
30
+ # @peach = Fruit.create! :species => 'peach'
31
+ # end
32
+ #
33
+ # scenario(:nectarine) do
34
+ # @nectarine = Fruit.create! :species => 'nectarine'
35
+ # end
36
+ # end
data/spec/hornsby_spec.rb CHANGED
@@ -1,42 +1,8 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper'
2
2
 
3
- class Fruit < ActiveRecord::Base
4
- end
5
-
6
- Hornsby.scenario(:just_apple) do
7
- @apple = Fruit.create! :species => 'apple'
8
- end
9
-
10
- Hornsby.scenario(:bananas_and_apples => :just_apple) do
11
- @banana = Fruit.create! :species => 'banana'
12
- end
13
-
14
- Hornsby.scenario(:just_orange) do
15
- @orange = Fruit.create! :species => 'orange'
16
- end
17
-
18
- Hornsby.scenario(:fruit => [:just_apple,:just_orange]) do
19
- @fruit = [@orange,@apple]
20
- end
21
-
22
- Hornsby.scenario(:bananas_and_apples_and_oranges => [:bananas_and_apples,:just_orange]) do
23
- @fruit = [@orange,@apple,@banana]
24
- end
25
-
26
-
27
- # Hornsby.namespace(:pitted_fruit) do
28
- # scenario(:peach) do
29
- # @peach = Fruit.create! :species => 'peach'
30
- # end
31
- #
32
- # scenario(:nectarine) do
33
- # @nectarine = Fruit.create! :species => 'nectarine'
34
- # end
35
- # end
36
-
37
3
  describe Hornsby, "with just_apple scenario" do
38
4
  before do
39
- Hornsby.build(:just_apple).each {|s| s.copy_ivars(self)}
5
+ hornsby_scenario :just_apple
40
6
  end
41
7
 
42
8
  it "should create @apple" do
@@ -58,7 +24,7 @@ end
58
24
 
59
25
  describe Hornsby, "with bananas_and_apples scenario" do
60
26
  before do
61
- Hornsby.build(:bananas_and_apples).each {|s| s.copy_ivars(self)}
27
+ hornsby_scenario :bananas_and_apples
62
28
  end
63
29
 
64
30
  it "should have correct @apple species" do
@@ -72,7 +38,7 @@ end
72
38
 
73
39
  describe Hornsby, "with fruit scenario" do
74
40
  before do
75
- Hornsby.build(:fruit).each {|s| s.copy_ivars(self)}
41
+ hornsby_scenario :fruit
76
42
  end
77
43
 
78
44
  it "should have 2 fruits" do
@@ -92,6 +58,35 @@ describe Hornsby, "with fruit scenario" do
92
58
  end
93
59
  end
94
60
 
61
+ describe Hornsby, 'with preloaded cherry scenario' do
62
+ it "should have correct size after changed by second test" do
63
+ @cherry.average_diameter.should == 3
64
+ @cherry.update_attribute(:average_diameter, 1)
65
+ @cherry.average_diameter.should == 1
66
+ end
67
+
68
+ it "should have correct size" do
69
+ @cherry.average_diameter.should == 3
70
+ @cherry.update_attribute(:average_diameter, 5)
71
+ @cherry.average_diameter.should == 5
72
+ end
73
+ end
74
+
75
+ describe Hornsby, 'with many apples scenario' do
76
+ before do
77
+ hornsby_scenario :many_apples, :cherry
78
+ end
79
+
80
+ it "should create only one apple" do
81
+ puts Hornsby.send(:class_variable_get, :@@executed_scenarios).inspect
82
+ Fruit.all(:conditions => 'species = "apple"').count.should == 1
83
+ end
84
+
85
+ it "should create only one cherry even if it was preloaded" do
86
+ Fruit.all(:conditions => 'species = "cherry"').count.should == 1
87
+ end
88
+ end
89
+
95
90
  #describe Hornsby, "with pitted namespace" do
96
91
  # before do
97
92
  # Hornsby.build('pitted:peach').copy_ivars(self)
data/spec/spec_helper.rb CHANGED
@@ -1,17 +1,20 @@
1
1
  require 'fileutils'
2
- require File.dirname(__FILE__) + '/../../../../spec/spec_helper'
2
+ require 'activerecord'
3
3
 
4
- plugin_spec_dir = File.dirname(__FILE__)
4
+ spec_dir = File.dirname(__FILE__)
5
+ Dir.chdir spec_dir
5
6
 
6
- ActiveRecord::Base.logger = Logger.new(plugin_spec_dir + "/debug.log")
7
-
8
- databases = YAML::load(IO.read(plugin_spec_dir + "/db/database.yml"))
9
-
10
- db_info = databases[ENV["DB"] || "sqlite3"]
11
-
12
- FileUtils::rm(RAILS_ROOT+"/"+db_info[:dbfile])
7
+ ActiveRecord::Base.logger = Logger.new(spec_dir + "/debug.log")
13
8
 
9
+ databases = YAML::load(IO.read(spec_dir + "/db/database.yml"))
10
+ db_info = databases[ENV["DB"] || "test"]
14
11
  ActiveRecord::Base.establish_connection(db_info)
12
+ load(File.join(spec_dir, "db", "schema.rb"))
15
13
 
16
- load(File.join(plugin_spec_dir, "db", "schema.rb"))
14
+ require 'spec/autorun'
15
+ require '../lib/hornsby'
16
+ require 'db/fruit'
17
17
 
18
+ Spec::Runner.configure do |config|
19
+ Hornsby.configure_rspec(config, :filename => File.join(spec_dir, 'hornsby_scenario.rb'), :scenarios => :cherry)
20
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinsiliux-hornsby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrius Chamentauskas
@@ -43,8 +43,9 @@ extra_rdoc_files: []
43
43
 
44
44
  files:
45
45
  - lib/hornsby.rb
46
- - tasks/hornsby_tasks.rake
46
+ - lib/tasks/hornsby_tasks.rake
47
47
  - README.rdoc
48
+ - LICENSE
48
49
  has_rdoc: false
49
50
  homepage: http://github.com/sinsiliux/hornsby
50
51
  post_install_message:
@@ -70,7 +71,11 @@ rubyforge_project:
70
71
  rubygems_version: 1.2.0
71
72
  signing_key:
72
73
  specification_version: 2
73
- summary: Fixtures replacement
74
+ summary: Fixtures replacement with scenarios
74
75
  test_files:
75
76
  - spec/spec_helper.rb
76
77
  - spec/hornsby_spec.rb
78
+ - spec/hornsby_scenario.rb
79
+ - spec/db/fruit.rb
80
+ - spec/db/database.yml.example
81
+ - spec/db/schema.rb