remi-scenarios 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/MIT-LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2009 remi Taylor, Encyclopedia of Life project (www.eol.org), Marine Biological Lab
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,51 @@
1
+ scenarios
2
+ =========
3
+
4
+ The idea behind 'scenarios' is simple. Scenarions are basically just organized bits of arbitrary ruby code.
5
+
6
+
7
+ why?
8
+ ----
9
+
10
+ Here's why scenarios were originally written ... you may use them however you wish!
11
+
12
+ I had a Rails application and I wanted to be able to do something like this:
13
+
14
+ $ rake scenarios:load SCENARIO=one_thousand_users
15
+
16
+ ... which would put 1,000 users in the database.
17
+
18
+ Sometimes, while testing out my application's functionality in a browser, I would
19
+ want to setup some scenario to test. Maybe I'm working on X feature and it would
20
+ be helpful if I had Y data in the database to work with. Typically, I would
21
+ open up `script/console` and create abunchof Y data manually. But ... wouldn't it
22
+ be useful if we could automate that?
23
+
24
+ Also, our application requires *some* data to be in the database for the app to
25
+ load properly. So we created a scenario that loads up the minimum amount of
26
+ data required to run the app!
27
+
28
+
29
+ how?
30
+ ----
31
+
32
+ $ sudo gem install remi-scenarios -s http://gems.github.com
33
+
34
+ then, if you're in a Rails project ...
35
+
36
+ $ ./script/generate scenario Foo
37
+
38
+ to see all defined scenarios ...
39
+
40
+ $ rake scenarios
41
+
42
+ to load a particular scenario ...
43
+
44
+ $ rake scenarios:load NAME=my_scenario
45
+ $ rake scenarios:load NAME=my_scenario,and_some_more_scenarios
46
+
47
+
48
+ what else?
49
+ ----------
50
+
51
+ more documentation to come soon!
data/Rakefile ADDED
@@ -0,0 +1,55 @@
1
+ require 'rake'
2
+ require 'rubygems'
3
+ require 'rake/rdoctask'
4
+ require 'spec/rake/spectask'
5
+
6
+ begin
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |s|
9
+ s.name = "scenarios"
10
+ s.summary = "Create, Organize, and Run arbitrary snippets of Ruby code"
11
+ s.email = "remi@remitaylor.com"
12
+ s.homepage = "http://github.com/remi/scenarios"
13
+ s.description = "Create, Organize, and Run arbitrary snippets of Ruby code"
14
+ s.authors = %w( remi )
15
+ s.files = FileList["[A-Z]*", "{lib,spec,examples,rails_generators}/**/*"]
16
+ end
17
+ rescue LoadError
18
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
19
+ end
20
+
21
+ Spec::Rake::SpecTask.new do |t|
22
+ t.spec_files = FileList['spec/**/*_spec.rb']
23
+ end
24
+
25
+ desc "Run all examples with RCov"
26
+ Spec::Rake::SpecTask.new('rcov') do |t|
27
+ t.spec_files = FileList['spec/**/*_spec.rb']
28
+ t.rcov = true
29
+ end
30
+
31
+ Rake::RDocTask.new do |rdoc|
32
+ rdoc.rdoc_dir = 'rdoc'
33
+ rdoc.title = 'scenarios'
34
+ rdoc.options << '--line-numbers' << '--inline-source'
35
+ rdoc.rdoc_files.include('README*')
36
+ rdoc.rdoc_files.include('lib/**/*.rb')
37
+ end
38
+
39
+ desc 'Confirm that gemspec is $SAFE'
40
+ task :safe do
41
+ require 'yaml'
42
+ require 'rubygems/specification'
43
+ data = File.read('scenarios.gemspec')
44
+ spec = nil
45
+ if data !~ %r{!ruby/object:Gem::Specification}
46
+ Thread.new { spec = eval("$SAFE = 3\n#{data}") }.join
47
+ else
48
+ spec = YAML.load(data)
49
+ end
50
+ spec.validate
51
+ puts spec
52
+ puts "OK"
53
+ end
54
+
55
+ task :default => :spec
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 1
4
+ :patch: 1
@@ -0,0 +1,2 @@
1
+ # foo!
2
+ $set_by_foo = 'hello from foo!'
@@ -0,0 +1,4 @@
1
+ # i am the description
2
+ # only the first line
3
+ # should be included in the description
4
+ $set_by_first_scenario = 'hello from first scenario!'
@@ -0,0 +1,63 @@
1
+ # here be rake tasks for scenarios
2
+ #
3
+ # you can get them in your Rakefile by:
4
+ # require 'scenarios/tasks'
5
+ # Scenario.load_paths = [ 'path/to/my/scenarios/**/*' ]
6
+
7
+ require 'scenarios'
8
+ Scenario.verbose = true
9
+
10
+ desc 'Print all available scenarios'
11
+ task :scenarios do
12
+ if Scenario.all.empty?
13
+ puts "there are no scenarios. add some to one of the Scenario.load_paths: #{ Scenario.load_paths.inspect }"
14
+ else
15
+ Scenario.all.each do |scenario|
16
+ puts "#{ scenario.name }: #{ scenario.description }"
17
+ end
18
+ end
19
+ end
20
+
21
+ namespace :scenarios do
22
+
23
+ desc 'scenarios:load NAME=foo OR NAME=a,b,c'
24
+ task :load => ( (defined?RAILS_ENV) ? :environment : nil ) do
25
+ if ENV['NAME']
26
+ names = ENV['NAME'].split(',')
27
+ Scenario.load *names
28
+ else
29
+ puts "you need to pass NAME=scenario_name to load a scenario"
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ =begin
36
+ if defined?RAILS_ENV
37
+ # rails-specific task
38
+
39
+ desc 'this will clear the database, load scenarios, & run the site'
40
+ task :run => :environment do
41
+ if RAILS_ENV == 'test'
42
+ if ENV['NAME']
43
+
44
+ puts "clearing database ..."
45
+ Rake::Task[:truncate].invoke # this isn't defined in scenarios! need to not call this or include a :truncate task
46
+
47
+ puts "loading scenarios ..."
48
+ names = ENV['NAME'].split(',')
49
+ Scenario.load *names
50
+
51
+ puts "running the site ..."
52
+ require 'commands/server'
53
+
54
+ else
55
+ puts "Usage: rake:run NAME=the_names,of_some,scenarios_to_load RAILS_ENV=test"
56
+ end
57
+ else
58
+ puts "sorry, i'm not comfortable doing this in any environment but 'test'"
59
+ end
60
+ end
61
+
62
+ end
63
+ =end
data/lib/scenarios.rb ADDED
@@ -0,0 +1,121 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ # a Scenario is some set of data/logic that can be loaded up easily
4
+ # to run an application against.
5
+ #
6
+ # if you need to enter abunchof data manually into the a website
7
+ # to test something you're working on, this is a good candidate for
8
+ # a scenario.
9
+ #
10
+ # we can also use scenarios for loading up the base foundation of
11
+ # data that's required to load the web application
12
+ #
13
+ # TODO define what is public/private and document public API in README and
14
+ # actually give private methods a private visibility
15
+ #
16
+ class Scenario
17
+
18
+ attr_accessor :file_path
19
+
20
+ def initialize file_path
21
+ @file_path = file_path
22
+ end
23
+
24
+ def name
25
+ File.basename(file_path).sub(/\.rb$/, '')
26
+ end
27
+ alias to_s name
28
+
29
+ # if the first line of the scenario's source code
30
+ # is a comment, we use it as the scenario's description
31
+ #
32
+ # ideally, all scenarios should have a short simple description
33
+ #
34
+ def description
35
+ if first_line =~ /^#/
36
+ first_line.sub(/^#*/, '').strip
37
+ else
38
+ ''
39
+ end
40
+ end
41
+
42
+ def first_line
43
+ source_code.split("\n").first
44
+ end
45
+
46
+ def source_code
47
+ File.read file_path
48
+ end
49
+
50
+ # evaluates the code of the scenario
51
+ def load
52
+ self.class.load self # pass the loading off to the class
53
+ end
54
+
55
+ class << self
56
+
57
+ # an array of the paths where scenarios can be found
58
+ #
59
+ # any .rb file found in these directories is assumed to
60
+ # be a scenario
61
+ #
62
+ attr_accessor :load_paths, :verbose, :before_blocks
63
+
64
+ # returns all Scenarios found using Scenario#load_paths
65
+ def all
66
+ load_paths.inject([]) do |all_scenarios, load_path|
67
+ Dir[ File.join(load_path, '**', '*.rb') ].each do |found_scenario_file|
68
+ all_scenarios << Scenario.new(found_scenario_file)
69
+ end
70
+ all_scenarios
71
+ end
72
+ end
73
+
74
+ # run some block of code before any scenarios run
75
+ #
76
+ # good for last-minute require statements and whatnot
77
+ #
78
+ def before &block
79
+ @before_blocks ||= []
80
+ @before_blocks << block if block
81
+ end
82
+
83
+ # returns a scenario by name, eg. Scenario[:foo]
84
+ #
85
+ # if 1 name is passed in, we'll return that scenario or nil
86
+ #
87
+ # if more than 1 name is passed in, we'll return an array of
88
+ # scenarios (or an empty array)
89
+ #
90
+ def [] *names
91
+ if names.length == 1
92
+ all.find {|scenario| scenario.name.downcase == names.first.to_s.downcase }
93
+ else
94
+ names.map {|name| self[ name ] }.compact
95
+ end
96
+ end
97
+
98
+ # loads a Scenario, evaluating its code
99
+ #
100
+ # we do this here so we can easily eval in a certain context,
101
+ # if we want to add a context later
102
+ #
103
+ # Scenario.load @scenario1, @scenario2
104
+ # Scenario.load :names, 'work', :too
105
+ #
106
+ def load *scenarios
107
+ @before_blocks.each { |b| b.call } if @before_blocks and not @before_blocks.empty?
108
+ # TODO should be able to define some block that scenarios get evaluated in!
109
+ # or some things that scenarios might want to require or ...
110
+ scenarios.each do |scenario|
111
+ scenario = self[scenario] unless scenario.is_a?Scenario # try getting using self[] if not a scenario
112
+ puts "loading #{ scenario.name } (#{ scenario.description })" if Scenario.verbose && scenario.is_a?(Scenario)
113
+ eval scenario.source_code if scenario.is_a?Scenario
114
+ end
115
+ end
116
+ end
117
+
118
+ Scenario.load_paths ||= [ 'scenarios' ] # default to a 'scenarios' directory relative to your current location
119
+ Scenario.verbose = false
120
+
121
+ end
@@ -0,0 +1,5 @@
1
+ Description:
2
+ Creates a new scenario
3
+
4
+ Examples:
5
+ `./script/generate scenario Foo`
@@ -0,0 +1,36 @@
1
+ # This generator creates a new 'scenario'
2
+ class ScenarioGenerator < Rails::Generator::Base
3
+
4
+ attr_accessor :name_of_scenario_to_create, :name_of_scenario_file_to_create
5
+
6
+ # `./script/generate scenario foo` will result in:
7
+ #
8
+ # runtime_args: ['foo']
9
+ # runtime_options: {:quiet=>false, :generator=>"scenario", :command=>:create, :collision=>:ask}
10
+ #
11
+ def initialize(runtime_args, runtime_options = {})
12
+ # setup_rails_to_run_scenarios
13
+ @name_of_scenario_to_create = runtime_args.join(' ')
14
+ @name_of_scenario_file_to_create = runtime_args.join('_').downcase
15
+ super
16
+ end
17
+
18
+ # this should be done by ./script/generate blackbox
19
+ def setup_rails_to_run_scenarios
20
+ # bootstrap
21
+ end
22
+
23
+ def manifest
24
+ record do |m|
25
+ m.directory 'scenarios'
26
+ m.template 'scenario.erb', "scenarios/#{ name_of_scenario_file_to_create }.rb"
27
+ end
28
+ end
29
+
30
+ protected
31
+
32
+ def banner
33
+ "Usage: #{$0} _scenario Name of Scenario to Create"
34
+ end
35
+
36
+ end
@@ -0,0 +1,3 @@
1
+ # my one-line description of the <%= name_of_scenario_to_create %> scenario
2
+
3
+ $foo = "the <%= name_of_scenario_file_to_create %> scenario sets a global variable!"
@@ -0,0 +1,112 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ # this isn't exactly a model ... just something that helps
4
+ # with out development and speccing
5
+ describe Scenario do
6
+
7
+ def path_to_test_scenarios
8
+ File.join File.dirname(__FILE__), '..', 'examples', 'scenarios'
9
+ end
10
+ def path_to_more_scenarios
11
+ File.join File.dirname(__FILE__), '..', 'examples', 'more_scenarios'
12
+ end
13
+
14
+ before do
15
+ Scenario.load_paths = [ path_to_test_scenarios ]
16
+ $set_by_first_scenario = nil
17
+ $set_by_foo = nil
18
+ end
19
+
20
+ before :all do
21
+ @original_scenario_paths = Scenario.load_paths
22
+ end
23
+ after :all do
24
+ Scenario.load_paths = @original_scenario_paths
25
+ end
26
+
27
+ it 'should find scenario files properly' do
28
+ Scenario.load_paths = []
29
+ Scenario.all.should be_empty
30
+
31
+ Scenario.load_paths = [ path_to_test_scenarios ]
32
+ Scenario.all.length.should == 1
33
+ Scenario.all.first.name.should == 'first'
34
+
35
+ Scenario.load_paths << path_to_more_scenarios
36
+ Scenario.all.length.should == 2
37
+ Scenario.all.map(&:name).should include('first')
38
+ Scenario.all.map(&:name).should include('foo')
39
+ end
40
+
41
+ it 'should be easy to get a scenario by name' do
42
+ Scenario[:first].name.should == 'first'
43
+ Scenario['first'].name.should == 'first'
44
+
45
+ Scenario[:foo].should be_nil
46
+ Scenario.load_paths << path_to_more_scenarios
47
+ Scenario[:foo].should_not be_nil
48
+ end
49
+
50
+ it 'should be easy to get multiple scenarios by name' do
51
+ Scenario[:first, :nonexistent, :notfound].length.should == 1
52
+ Scenario[:first, :nonexistent, :notfound].first.name.should == 'first'
53
+
54
+ Scenario[:first, :nonexistent, :foo].length.should == 1
55
+ Scenario.load_paths << path_to_more_scenarios
56
+ Scenario[:first, :nonexistent, :foo].length.should == 2
57
+ Scenario[:first, :nonexistent, :foo].map(&:name).should include('first')
58
+ Scenario[:first, :nonexistent, :foo].map(&:name).should include('foo')
59
+ end
60
+
61
+ it 'should have a name' do
62
+ Scenario.all.first.should be_a_kind_of(Scenario)
63
+ Scenario.all.first.name.should == 'first'
64
+ end
65
+
66
+ it 'should have a description' do
67
+ Scenario.all.first.description.should == 'i am the description'
68
+ end
69
+
70
+ it 'should be loadable' do
71
+ $set_by_first_scenario.should be_nil
72
+ Scenario[:first].load
73
+ $set_by_first_scenario.should == 'hello from first scenario!'
74
+ end
75
+
76
+ it 'should be able to load multiple scenarios' do
77
+ Scenario.load_paths << path_to_more_scenarios
78
+
79
+ $set_by_first_scenario.should be_nil
80
+ $set_by_foo.should be_nil
81
+
82
+ Scenario[:first, :foo].each {|scenario| scenario.load }
83
+
84
+ $set_by_first_scenario.should == 'hello from first scenario!'
85
+ $set_by_foo.should == 'hello from foo!'
86
+ end
87
+
88
+ it 'should be really easy to load multiple scenarios' do
89
+ Scenario.load_paths << path_to_more_scenarios
90
+
91
+ $set_by_first_scenario.should be_nil
92
+ $set_by_foo.should be_nil
93
+
94
+ Scenario.load :first, :foo
95
+
96
+ $set_by_first_scenario.should == 'hello from first scenario!'
97
+ $set_by_foo.should == 'hello from foo!'
98
+ end
99
+
100
+ it 'to_s should be the scenario name' do
101
+ Scenario[:first].to_s.should == 'first'
102
+ end
103
+
104
+ it 'should allow globbing in load_paths' do
105
+ Scenario.load_paths = [ File.join(File.dirname(__FILE__), '..', 'examp*', '**') ]
106
+
107
+ Scenario.all.length.should == 2
108
+ Scenario.all.map(&:name).should include('first')
109
+ Scenario.all.map(&:name).should include('foo')
110
+ end
111
+
112
+ end
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__) + '/../lib/scenarios'
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: remi-scenarios
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - remi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-03 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Create, Organize, and Run arbitrary snippets of Ruby code
17
+ email: remi@remitaylor.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - MIT-LICENSE
26
+ - Rakefile
27
+ - VERSION.yml
28
+ - README.markdown
29
+ - lib/scenarios
30
+ - lib/scenarios/tasks.rb
31
+ - lib/scenarios.rb
32
+ - spec/scenario_spec.rb
33
+ - spec/spec_helper.rb
34
+ - examples/scenarios
35
+ - examples/scenarios/first.rb
36
+ - examples/more_scenarios
37
+ - examples/more_scenarios/foo.rb
38
+ - rails_generators/scenario
39
+ - rails_generators/scenario/USAGE
40
+ - rails_generators/scenario/scenario_generator.rb
41
+ - rails_generators/scenario/templates
42
+ - rails_generators/scenario/templates/scenario.erb
43
+ has_rdoc: true
44
+ homepage: http://github.com/remi/scenarios
45
+ post_install_message:
46
+ rdoc_options:
47
+ - --inline-source
48
+ - --charset=UTF-8
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ version:
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ requirements: []
64
+
65
+ rubyforge_project:
66
+ rubygems_version: 1.2.0
67
+ signing_key:
68
+ specification_version: 2
69
+ summary: Create, Organize, and Run arbitrary snippets of Ruby code
70
+ test_files: []
71
+