reactive-dev 0.2.0

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.
@@ -0,0 +1,16 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # and they will automatically be available to Rake.
3
+
4
+ APP_PATH = File.dirname(__FILE__)
5
+ APP_NAME = APP_PATH.split('/').last
6
+
7
+ require ["#{File.dirname(__FILE__)}/config/boot.rb", "#{File.dirname(__FILE__)}/boot.rb"].find {|path| File.file? path}
8
+ Reactive.load(['--root', APP_PATH])
9
+ Reactive::Initializer.stages.delete(:check_plugins)
10
+ Reactive.init(:configure)
11
+
12
+ require 'rake'
13
+ require 'rake/testtask'
14
+ require 'rake/rdoctask'
15
+
16
+ require 'reactive-core/tasks/reactive'
@@ -0,0 +1,118 @@
1
+ module Reactive
2
+ class << self
3
+ def load(argv = ARGV)
4
+ return @bootstrapper if @bootstrapper
5
+ options = {}
6
+ options[:root_dir] = if index = argv.rindex(argv.find {|arg| arg == '--root' })
7
+ argv[index+1]
8
+ end
9
+ options[:config_file] = if index = argv.rindex(argv.find {|arg| arg == '--config-file' })
10
+ argv[index+1]
11
+ end
12
+ @argv = argv
13
+ @bootstrapper ||= Bootstrapper.new(options)
14
+ end
15
+
16
+ def loaded?
17
+ @bootstrapper
18
+ end
19
+
20
+ def init(stage = :final, argv = @argv || ARGV)
21
+ load(argv)
22
+ Reactive::Initializer.run(stage, Configuration.new(argv))
23
+ end
24
+
25
+ def run(argv = @argv || ARGV)
26
+ init(:final, argv)
27
+ Dispatcher::Base.dispatch(Reactive.configuration.initial_request.is_a?(Hash) ? Request.new(Reactive.configuration.initial_request) : Reactive.configuration.initial_request)
28
+ end
29
+ end
30
+
31
+ class Bootstrapper
32
+ def initialize(options)
33
+ @config_file = options[:config_file]
34
+ @root_dir = File.expand_path(options[:root_dir]) if options[:root_dir]
35
+ load_rubygems
36
+
37
+ # add apps gem directory to load path
38
+ if @root_dir
39
+ Gem.clear_paths
40
+ Gem.path.unshift("#{@root_dir}/gems")
41
+ end
42
+
43
+ load_reactive_gem
44
+ require 'reactive-core/initializer'
45
+ end
46
+
47
+ def load_reactive_gem
48
+ # load activesupport first
49
+ begin
50
+ if version = activesupport_gem_version
51
+ gem 'activesupport', version
52
+ end
53
+ rescue Gem::LoadError => load_error
54
+ $stderr.puts "Missing the activesupport #{version} gem. Either install the required version or choose an appropriate value for the ACTIVESUPPORT_GEM_VERSION setting in config/config.rb"
55
+ exit 1
56
+ end
57
+
58
+ if version = reactive_gem_version
59
+ gem 'reactive-core', version
60
+ else
61
+ gem 'reactive-core'
62
+ end
63
+ rescue Gem::LoadError => load_error
64
+ $stderr.puts "Missing the reactive-core #{version} gem. Please `gem install -v=#{version} reactive-core`, update your REACTIVE_GEM_VERSION setting in config/config.rb for the Reactive version you do have installed, or comment out REACTIVE_GEM_VERSION to use the latest version installed."
65
+ exit 1
66
+ end
67
+
68
+ def rubygems_version
69
+ Gem::RubyGemsVersion if defined? Gem::RubyGemsVersion
70
+ end
71
+
72
+ def reactive_gem_version
73
+ if defined? REACTIVE_GEM_VERSION
74
+ REACTIVE_GEM_VERSION
75
+ elsif ENV.include?('REACTIVE_GEM_VERSION')
76
+ ENV['REACTIVE_GEM_VERSION']
77
+ else
78
+ parse_gem_version('reactive', read_config_rb)
79
+ end
80
+ end
81
+
82
+ def activesupport_gem_version
83
+ parse_gem_version('activesupport', read_config_rb)
84
+ end
85
+
86
+ def load_rubygems
87
+ require 'rubygems'
88
+
89
+ unless rubygems_version >= '1.1.0'
90
+ $stderr.puts "Reactive requires RubyGems >= 1.1.0 (you have #{rubygems_version}). Please `gem update --system` and try again."
91
+ exit 1
92
+ end
93
+
94
+ rescue LoadError
95
+ $stderr.puts "Reactive requires RubyGems >= 1.1.0. Please install RubyGems and try again: http://rubygems.rubyforge.org"
96
+ exit 1
97
+ end
98
+
99
+ def parse_gem_version(gem_name, text)
100
+ $1 if text =~ Regexp.new(%Q{^[^#]*#{gem_name.upcase}_GEM_VERSION\\s*=\\s*["']([!~<>=]*\\s*[\\d.]+)["']})
101
+ end
102
+
103
+ private
104
+ def read_config_rb
105
+ return if @config_rb
106
+ files = [
107
+ @config_file,
108
+ @root_dir ? "#{@root_dir}/config/config.rb" : nil,
109
+ @root_dir ? "#{@root_dir}/config.rb" : nil,
110
+ "config.rb"
111
+ ].compact.select {|name| File.file? name}
112
+
113
+ raise StandardError, "No config file found, you may specify it with --config-file" if files.empty?
114
+ @config_rb = File.read(files.first)
115
+ end
116
+ end
117
+
118
+ end
@@ -0,0 +1,29 @@
1
+ # You may specify the activesupport gem version that will be used.
2
+ # It is provided to resolve dependency issues. Note that the minimum version is 2.0.0
3
+ # ACTIVESUPPORT_GEM_VERSION = "= 2.0.2"
4
+
5
+ # You may also specifiy the Reactive gem version to use
6
+ # REACTIVE_GEM_VERSION = ">= 0.2.0"
7
+
8
+ with Reactive.configuration do |config|
9
+ # Don't forget to specify the default dispatcher which is one of your plugins, ex:
10
+ # config.dispatcher.default_dispatcher = :mvc
11
+ # You also have to configure an inital request like so:
12
+ # config.initial_request = {:controller => 'application', :action => 'initial', :format => :wx}
13
+
14
+ # put the .gem statements in the order you want them loaded.
15
+ # You may add a version requirement for each of the gems, like:
16
+ # config.gem 'reactive-mvc', '>=0.2.0'
17
+ <% for plugin in plugins -%>
18
+ config.gem '<%= plugin %>'<% end %>
19
+
20
+ config.app_gem_spec do |s|
21
+ s.name = "<%= app_name %>"
22
+ s.version = "1.0.0"
23
+ s.author = "Your name"
24
+ s.email = "you@there.com"
25
+ s.homepage = "http://there.com"
26
+ s.summary = "My great application"
27
+ s.description = "Visit our website for further information"
28
+ end
29
+ end
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ boot_location = [
4
+ ["#{File.dirname(__FILE__)}/../config/boot.rb", ".."],
5
+ ["#{File.dirname(__FILE__)}/boot.rb", "."]
6
+ ].find{|path, root| File.file? path}
7
+
8
+ require boot_location.first
9
+ Reactive.load(['--root', File.join(File.dirname(__FILE__), boot_location.last)])
10
+
11
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
12
+
13
+ require 'optparse'
14
+
15
+ options = { :sandbox => false, :irb => irb }
16
+ OptionParser.new do |opt|
17
+ opt.banner = "Usage: console [environment] [options]"
18
+ opt.on("--irb=[#{irb}]", 'Invoke a different irb.') { |v| options[:irb] = v }
19
+ opt.on("--debugger", 'Enable ruby-debugging for the console.') { |v| options[:debugger] = v }
20
+ opt.parse!(ARGV)
21
+ end
22
+
23
+ libs = " -r irb/completion"
24
+ libs << %( -r "#{boot_location.first}")
25
+ libs << %( -r "#{Gem.loaded_specs['reactive-core'].full_gem_path}/lib/reactive-core/console_app")
26
+
27
+ if options[:debugger]
28
+ begin
29
+ require 'ruby-debug'
30
+ libs << " -r ruby-debug"
31
+ puts "=> Debugger enabled"
32
+ rescue Exception
33
+ puts "You need to install ruby-debug to run the console in debugging mode. With gems, use 'gem install ruby-debug'"
34
+ exit
35
+ end
36
+ end
37
+
38
+ ENV['REACTIVE_ENV'] = case ARGV.first
39
+ when "p"; "production"
40
+ when "d"; "development"
41
+ when "t"; "test"
42
+ else
43
+ ARGV.first || ENV['REACTIVE_ENV'] || 'development'
44
+ end
45
+
46
+ puts "Loading #{ENV['REACTIVE_ENV']} environment (Reactive #{Reactive::VERSION::STRING})"
47
+ exec "#{options[:irb]} #{libs} --simple-prompt"
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ boot_location = [
4
+ ["#{File.dirname(__FILE__)}/../config/boot.rb", ".."],
5
+ ["#{File.dirname(__FILE__)}/boot.rb", "."]
6
+ ].find{|path, root| File.file? path}
7
+
8
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), boot_location.last))
9
+ require boot_location.first
10
+
11
+ Reactive.init(:configure, ARGV + ['--root', APP_ROOT])
12
+
13
+ require 'rubigen'
14
+ require 'rubigen/scripts/destroy'
15
+
16
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
17
+ RubiGen::Base.use_plugin_sources! [:reactive, :reactive_app, :test_unit]
18
+ RubiGen::Scripts::Destroy.new.run(ARGV)
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ boot_location = [
4
+ ["#{File.dirname(__FILE__)}/../config/boot.rb", ".."],
5
+ ["#{File.dirname(__FILE__)}/boot.rb", "."]
6
+ ].find{|path, root| File.file? path}
7
+
8
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), boot_location.last))
9
+ require boot_location.first
10
+
11
+ Reactive.init(:configure, ARGV + ['--root', APP_ROOT])
12
+
13
+ require 'rubigen'
14
+ require 'rubigen/scripts/generate'
15
+
16
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
17
+ RubiGen::Base.use_plugin_sources! [:reactive, :reactive_app, :test_unit]
18
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ boot_location = [
4
+ ["#{File.dirname(__FILE__)}/../config/boot.rb", ".."],
5
+ ["#{File.dirname(__FILE__)}/boot.rb", "."]
6
+ ].find{|path, root| File.file? path}
7
+
8
+ require boot_location.first
9
+ Reactive.run(ARGV + ['--root', File.join(File.dirname(__FILE__), boot_location.last)])
@@ -0,0 +1 @@
1
+ @ruby <%= File.join("script", filename) %> %*
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'reactive-core/version'
5
+ if %w(--version -v).include? ARGV.first
6
+ puts "Reactive #{Reactive::VERSION::STRING}"
7
+ exit(0)
8
+ end
9
+
10
+ require 'reactive-dev'
11
+ require 'rubigen'
12
+ require 'rubigen/scripts/generate'
13
+ RubiGen::Base.reset_sources
14
+ RubiGen::Base.append_sources(RubiGen::PathSource.new(:application, File.join(File.dirname(__FILE__), "../app_generators")))
15
+ RubiGen::Scripts::Generate.new.run(ARGV, :generator => 'reactive')
@@ -0,0 +1,3 @@
1
+ require 'rubigen'
2
+ require 'reactive-dev/rubigen_plugin_sources'
3
+ require 'reactive-dev/named_base_generator'
@@ -0,0 +1,107 @@
1
+ class CodeStatistics #:nodoc:
2
+
3
+ TEST_TYPES = %w(Units Functionals Unit\ tests Functional\ tests Integration\ tests)
4
+
5
+ def initialize(*pairs)
6
+ @pairs = pairs
7
+ @statistics = calculate_statistics
8
+ @total = calculate_total if pairs.length > 1
9
+ end
10
+
11
+ def to_s
12
+ print_header
13
+ @pairs.each { |pair| print_line(pair.first, @statistics[pair.first]) }
14
+ print_splitter
15
+
16
+ if @total
17
+ print_line("Total", @total)
18
+ print_splitter
19
+ end
20
+
21
+ print_code_test_stats
22
+ end
23
+
24
+ private
25
+ def calculate_statistics
26
+ @pairs.inject({}) { |stats, pair| stats[pair.first] = calculate_directory_statistics(pair.last); stats }
27
+ end
28
+
29
+ def calculate_directory_statistics(directory, pattern = /.*\.rb$/)
30
+ stats = { "lines" => 0, "codelines" => 0, "classes" => 0, "methods" => 0 }
31
+
32
+ Dir.foreach(directory) do |file_name|
33
+ if File.stat(directory + "/" + file_name).directory? and (/^\./ !~ file_name)
34
+ newstats = calculate_directory_statistics(directory + "/" + file_name, pattern)
35
+ stats.each { |k, v| stats[k] += newstats[k] }
36
+ end
37
+
38
+ next unless file_name =~ pattern
39
+
40
+ f = File.open(directory + "/" + file_name)
41
+
42
+ while line = f.gets
43
+ stats["lines"] += 1
44
+ stats["classes"] += 1 if line =~ /class [A-Z]/
45
+ stats["methods"] += 1 if line =~ /def [a-z]/
46
+ stats["codelines"] += 1 unless line =~ /^\s*$/ || line =~ /^\s*#/
47
+ end
48
+ end
49
+
50
+ stats
51
+ end
52
+
53
+ def calculate_total
54
+ total = { "lines" => 0, "codelines" => 0, "classes" => 0, "methods" => 0 }
55
+ @statistics.each_value { |pair| pair.each { |k, v| total[k] += v } }
56
+ total
57
+ end
58
+
59
+ def calculate_code
60
+ code_loc = 0
61
+ @statistics.each { |k, v| code_loc += v['codelines'] unless TEST_TYPES.include? k }
62
+ code_loc
63
+ end
64
+
65
+ def calculate_tests
66
+ test_loc = 0
67
+ @statistics.each { |k, v| test_loc += v['codelines'] if TEST_TYPES.include? k }
68
+ test_loc
69
+ end
70
+
71
+ def print_header
72
+ print_splitter
73
+ puts "| Name | Lines | LOC | Classes | Methods | M/C | LOC/M |"
74
+ print_splitter
75
+ end
76
+
77
+ def print_splitter
78
+ puts "+----------------------+-------+-------+---------+---------+-----+-------+"
79
+ end
80
+
81
+ def print_line(name, statistics)
82
+ m_over_c = (statistics["methods"] / statistics["classes"]) rescue m_over_c = 0
83
+ loc_over_m = (statistics["codelines"] / statistics["methods"]) - 2 rescue loc_over_m = 0
84
+
85
+ start = if TEST_TYPES.include? name
86
+ "| #{name.ljust(20)} "
87
+ else
88
+ "| #{name.ljust(20)} "
89
+ end
90
+
91
+ puts start +
92
+ "| #{statistics["lines"].to_s.rjust(5)} " +
93
+ "| #{statistics["codelines"].to_s.rjust(5)} " +
94
+ "| #{statistics["classes"].to_s.rjust(7)} " +
95
+ "| #{statistics["methods"].to_s.rjust(7)} " +
96
+ "| #{m_over_c.to_s.rjust(3)} " +
97
+ "| #{loc_over_m.to_s.rjust(5)} |"
98
+ end
99
+
100
+ def print_code_test_stats
101
+ code = calculate_code
102
+ tests = calculate_tests
103
+
104
+ puts " Code LOC: #{code} Test LOC: #{tests} Code to Test Ratio: 1:#{sprintf("%.1f", tests.to_f/code)}"
105
+ puts ""
106
+ end
107
+ end
@@ -0,0 +1,40 @@
1
+ require 'optparse'
2
+
3
+ module Reactive
4
+ class GeneratedAttribute # :nodoc:
5
+ attr_accessor :name, :type, :column
6
+
7
+ def initialize(name, type)
8
+ @name, @type = name, type.to_sym
9
+ @column = ActiveRecord::ConnectionAdapters::Column.new(name, nil, @type)
10
+ end
11
+
12
+ def field_type
13
+ @field_type ||= case type
14
+ when :integer, :float, :decimal then :text_field
15
+ when :datetime, :timestamp, :time then :datetime_select
16
+ when :date then :date_select
17
+ when :string then :text_field
18
+ when :text then :text_area
19
+ when :boolean then :check_box
20
+ else
21
+ :text_field
22
+ end
23
+ end
24
+
25
+ def default
26
+ @default ||= case type
27
+ when :integer then 1
28
+ when :float then 1.5
29
+ when :decimal then "9.99"
30
+ when :datetime, :timestamp, :time then Time.now.to_s(:db)
31
+ when :date then Date.today.to_s(:db)
32
+ when :string then "MyString"
33
+ when :text then "MyText"
34
+ when :boolean then false
35
+ else
36
+ ""
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,79 @@
1
+ module Reactive
2
+ # The base generator for named components: models, controllers, etc.
3
+ # The target name is taken as the first argument and inflected to
4
+ # several forms, see the attributes below..
5
+ #
6
+ # If no name is provided, the generator raises a usage error with content
7
+ # optionally read from the USAGE file in the generator's base path.
8
+ #
9
+ # For example, the +controller+ generator takes the first argument as
10
+ # the name of the class and subsequent arguments as the names of
11
+ # actions to be generated:
12
+ #
13
+ # ./script/generate controller Article index new create
14
+ #
15
+ class NamedBaseGenerator < RubiGen::Base
16
+ attr_reader :name, :underscore_name, :singular_name, :plural_name, :class_name, :singular_class_name, :plural_class_name
17
+
18
+ # these are arrays containing parts (path parts and module parts respectively)
19
+ attr_reader :path, :class_nesting
20
+
21
+ # complete pathname
22
+ attr_reader :pathname
23
+
24
+ def initialize(runtime_args, runtime_options = {})
25
+ super
26
+
27
+ # Name argument is required.
28
+ usage if runtime_args.empty?
29
+
30
+ @args = runtime_args.dup
31
+ assign_names!(@args.shift)
32
+
33
+ self.class.use_plugin_sources! [:reactive, :test_unit]
34
+ end
35
+
36
+ protected
37
+ # Override with your own usage banner.
38
+ def banner
39
+ "Usage: #{$0} #{spec.name} #{spec.name.camelize}Name [options]"
40
+ end
41
+
42
+ private
43
+ def assign_names!(name)
44
+ @name, @underscore_name = name, name.underscore
45
+ base_name, @path, @pathname, @class_nesting = extract_modules(@name)
46
+ @class_name_without_nesting, @singular_name, @plural_name = inflect_names(base_name)
47
+ if @class_nesting.empty?
48
+ @class_name = @class_name_without_nesting
49
+ @singular_class_name = @class_name_without_nesting.singularize
50
+ @plural_class_name = @class_name_without_nesting.pluralize
51
+ else
52
+ @class_name = "#{@class_nesting}::#{@class_name_without_nesting}"
53
+ @singular_class_name = "#{@class_nesting}::#{@class_name_without_nesting.singularize}"
54
+ @plural_class_name = "#{@class_nesting}::#{@class_name_without_nesting.pluralize}"
55
+ end
56
+ end
57
+
58
+ # Extract modules from filesystem-style or ruby-style path:
59
+ # good/fun/stuff
60
+ # Good::Fun::Stuff
61
+ # produce the same results.
62
+ def extract_modules(name)
63
+ modules = name.include?('/') ? name.split('/') : name.split('::')
64
+ name = modules.pop
65
+ path = modules.map { |m| m.underscore }
66
+ file_path = (path + [name.underscore]).join('/')
67
+ nesting = modules.map { |m| m.camelize }.join('::')
68
+ [name, path, file_path, nesting]
69
+ end
70
+
71
+ def inflect_names(name)
72
+ camel = name.camelize
73
+ singular = camel.underscore.singularize
74
+ plural = singular.pluralize
75
+ [camel, singular, plural]
76
+ end
77
+ end
78
+
79
+ end