reactive-dev 0.2.0

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