remi-scenarios 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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
+