Updated to work with Rails 0.14.1 (1.0 Release candidate) - fixes #145.

The bug where project associations didn't seem to be immediately displayed when next actions were added from the Context page is magically fixed! Fixes #142.



git-svn-id: http://www.rousette.org.uk/svn/tracks-repos/trunk@156 a4c988fc-2ded-0310-b66e-134b36920a42
This commit is contained in:
bsag 2005-10-30 12:21:50 +00:00
parent 551e767b5e
commit 9867ca01ad
35 changed files with 3007 additions and 1419 deletions

View file

@ -1,5 +1,110 @@
*0.14.1* (October 19th, 2005)
* Don't clean RAILS_ROOT on windows
* Remove trailing '/' from RAILS_ROOT [Nicholas Seckar]
* Upgraded to Active Record 1.12.1 and Action Pack 1.10.1
*0.14.0* (October 16th, 2005)
* Moved generator folder from RAILS_ROOT/generators to RAILS_ROOT/lib/generators [Tobias Luetke]
* Fix rake dev and related commands [Nicholas Seckar]
* The rails command tries to deduce your MySQL socket by running `mysql_config
--socket`. If it fails, default to /path/to/your/mysql.sock
* Made the rails command use the application name for database names in the tailored database.yml file. Example: "rails ~/projects/blog" will use "blog_development" instead of "rails_development". [Florian Weber]
* Added Rails framework freezing tasks: freeze_gems (freeze to current gems), freeze_edge (freeze to Rails SVN trunk), unfreeze_rails (float with newest gems on system)
* Added update_javascripts task which will fetch all the latest js files from your current rails install. Use after updating rails. [Tobias Luetke]
* Added cleaning of RAILS_ROOT to useless elements such as '../non-dot-dot/'. Provides cleaner backtraces and error messages. [Nicholas Seckar]
* Made the instantiated/transactional fixtures settings be controlled through Rails::Initializer. Transactional and non-instantiated fixtures are default from now on. [Florian Weber]
* Support using different database adapters for development and test with ActiveRecord::Base.schema_format = :ruby [Sam Stephenson]
* Make webrick work with session(:off)
* Add --version, -v option to the Rails command. Closes #1840. [stancell]
* Update Prototype to V1.4.0_pre11, script.aculo.us to V1.5_rc3 [2504] and fix the rails generator to include the new .js files [Thomas Fuchs]
* Make the generator skip a file if it already exists and is identical to the new file.
* Add experimental plugin support #2335
* Made Rakefile aware of new .js files in script.aculo.us [Thomas Fuchs]
* Make table_name and controller_name in generators honor AR::Base.pluralize_table_names. #1216 #2213 [kazuhiko@fdiary.net]
* Clearly label functional and unit tests in rake stats output. #2297 [lasse.koskela@gmail.com]
* Make the migration generator only check files ending in *.rb when calculating the next file name #2317 [Chad Fowler]
* Added prevention of duplicate migrations from the generator #2240 [fbeausoleil@ftml.net]
* Add db_schema_dump and db_schema_import rake tasks to work with the new ActiveRecord::SchemaDumper (for dumping a schema to and reading a schema from a ruby file).
* Reformed all the config/environments/* files to conform to the new Rails::Configuration approach. Fully backwards compatible.
* Added create_sessions_table, drop_sessions_table, and purge_sessions_table as rake tasks for databases that supports migrations (MySQL, PostgreSQL, SQLite) to get a table for use with CGI::Session::ActiveRecordStore
* Added dump of schema version to the db_structure_dump task for databases that support migrations #1835 [Rick Olson]
* Fixed script/profiler for Ruby 1.8.2 #1863 [Rick Olson]
* Fixed clone_structure_to_test task for SQLite #1864 [jon@burningbush.us]
* Added -m/--mime-types option to the WEBrick server, so you can specify a Apache-style mime.types file to load #2059 [ask@develooper.com]
* Added -c/--svn option to the generator that'll add new files and remove destroyed files using svn add/revert/remove as appropriate #2064 [kevin.clark@gmail.com]
* Added -c/--charset option to WEBrick server, so you can specify a default charset (which without changes is UTF-8) #2084 [wejn@box.cz]
* Make the default stats task extendable by modifying the STATS_DIRECTORIES constant
* Allow the selected environment to define RAILS_DEFAULT_LOGGER, and have Rails::Initializer use it if it exists.
* Moved all the shared tasks from Rakefile into Rails, so that the Rakefile is empty and doesn't require updating.
* Added Rails::Initializer and Rails::Configuration to abstract all of the common setup out of config/environment.rb (uses config/boot.rb to bootstrap the initializer and paths)
* Fixed the scaffold generator to fail right away if the database isn't accessible instead of in mid-air #1169 [Chad Fowler]
* Corrected project-local generator location in scripts.rb #2010 [Michael Schuerig]
* Don't require the environment just to clear the logs #2093 [Scott Barron]
* Make the default rakefile read *.rake files from config/tasks (for easy extension of the rakefile by e.g. generators)
* Only load breakpoint in development mode and when BREAKPOINT_SERVER_PORT is defined.
* Allow the --toggle-spin switch on process/reaper to be negated
* Replace render_partial with render :partial in scaffold generator [Nicholas Seckar]
* Added -w flag to ps in process/reaper #1934 [Scott Barron]
* Allow ERb in the database.yml file (just like with fixtures), so you can pull out the database configuration in environment variables #1822 [Duane Johnson]
* Added convenience controls for FCGI processes (especially when managed remotely): spinner, spawner, and reaper. They reside in script/process. More details can be had by calling them with -h/--help.
* Added load_fixtures task to the Rakefile, which will load all the fixtures into the database for the current environment #1791 [Marcel Molina]
* Added an empty robots.txt to public/, so that web servers asking for it won't trigger a dynamic call, like favicon.ico #1738 [michael@schubert]
* Dropped the 'immediate close-down' of FCGI processes since it didn't work consistently and produced bad responses when it didn't. So now a TERM ensures exit after the next request (just as if the process is handling a request when it receives the signal). This means that you'll have to 'nudge' all FCGI processes with a request in order to ensure that they have all reloaded. This can be done by something like ./script/process/repear --nudge 'http://www.myapp.com' --instances 10, which will load the myapp site 10 times (and thus hit all of the 10 FCGI processes once, enough to shut down).
*0.13.1* (11 July, 2005)
* Look for app-specific generators in RAILS_ROOT/generators rather than the clunky old RAILS_ROOT/script/generators. Nobody really uses this feature except for the unit tests, so it's a negligible-impact change. If you want to work with third-party generators, drop them in ~/.rails/generators or simply install gems.
* Fixed that each request with the WEBrick adapter would open a new database connection #1685 [Sam Stephenson]
* Added support for SQL Server in the database rake tasks #1652 [ken.barker@gmail.com] Note: osql and scptxfr may need to be installed on your development environment. This involves getting the .exes and a .rll (scptxfr) from a production SQL Server (not developer level SQL Server). Add their location to your Environment PATH and you are all set.

View file

@ -14,7 +14,7 @@ In Rails, the model is handled by what's called a object-relational mapping
layer entitled Active Record. This layer allows you to present the data from
database rows as objects and embellish these data objects with business logic
methods. You can read more about Active Record in
link:files/vendor/activerecord/README.html.
link:files/vendor/rails/activerecord/README.html.
The controller and view is handled by the Action Pack, which handles both
layers by its two parts: Action View and Action Controller. These two layers
@ -22,7 +22,7 @@ are bundled in a single package due to their heavy interdependence. This is
unlike the relationship between the Active Record and Action Pack that is much
more separate. Each of these packages can be used independently outside of
Rails. You can read more about Action Pack in
link:files/vendor/actionpack/README.html.
link:files/vendor/rails/actionpack/README.html.
== Requirements
@ -67,30 +67,30 @@ goes through FCGI (or mod_ruby) that requires restart to show changes.
== Example for lighttpd conf (with FastCGI)
server.port = 8080
server.bind = "127.0.0.1"
# server.event-handler = "freebsd-kqueue" # needed on OS X
server.modules = ( "mod_rewrite", "mod_fastcgi" )
url.rewrite = ( "^/$" => "index.html", "^([^.]+)$" => "$1.html" )
server.error-handler-404 = "/dispatch.fcgi"
server.document-root = "/path/application/public"
server.errorlog = "/path/application/log/server.log"
fastcgi.server = ( ".fcgi" =>
( "localhost" =>
(
"min-procs" => 1,
"max-procs" => 5,
"socket" => "/tmp/application.fcgi.socket",
"bin-path" => "/path/application/public/dispatch.fcgi",
"bin-environment" => ( "RAILS_ENV" => "development" )
)
server.port = 8080
server.bind = "127.0.0.1"
# server.event-handler = "freebsd-kqueue" # needed on OS X
server.modules = ( "mod_rewrite", "mod_fastcgi" )
url.rewrite = ( "^/$" => "index.html", "^([^.]+)$" => "$1.html" )
server.error-handler-404 = "/dispatch.fcgi"
server.document-root = "/path/application/public"
server.errorlog = "/path/application/log/server.log"
fastcgi.server = ( ".fcgi" =>
( "localhost" =>
(
"min-procs" => 1,
"max-procs" => 5,
"socket" => "/tmp/application.fcgi.socket",
"bin-path" => "/path/application/public/dispatch.fcgi",
"bin-environment" => ( "RAILS_ENV" => "development" )
)
)
)
)
== Debugging Rails
@ -139,7 +139,8 @@ Finally, when you're ready to resume execution, you press CTRL-D
You can interact with the domain model by starting the console through script/console.
Here you'll have all parts of the application configured, just like it is when the
application is running. You can inspect domain models, change values, and save to the
database. Start the script without arguments to see the options.
database. Start the script without arguments will launch it in the development environment.
Passing an argument will specify a different environment, like <tt>console production</tt>.
== Description of contents

View file

@ -1,234 +1,10 @@
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/switchtower.rake, and they will automatically be available to Rake.
require(File.join(File.dirname(__FILE__), 'config', 'boot'))
require 'rake'
require 'rake/testtask'
require 'rake/rdoctask'
require 'fileutils'
include FileUtils::Verbose
$VERBOSE = nil
TEST_CHANGES_SINCE = Time.now - 600
desc "Run all the tests on a fresh test database"
task :default => [ :test_units, :test_functional ]
desc 'Require application environment.'
task :environment do
unless defined? RAILS_ROOT
require File.dirname(__FILE__) + '/config/environment'
end
end
desc "Generate API documentation, show coding stats"
task :doc => [ :appdoc, :stats ]
# Look up tests for recently modified sources.
def recent_tests(source_pattern, test_path, touched_since = 10.minutes.ago)
FileList[source_pattern].map do |path|
if File.mtime(path) > touched_since
test = "#{test_path}/#{File.basename(path, '.rb')}_test.rb"
test if File.exists?(test)
end
end.compact
end
desc 'Test recent changes.'
Rake::TestTask.new(:recent => [ :clone_structure_to_test ]) do |t|
since = TEST_CHANGES_SINCE
touched = FileList['test/**/*_test.rb'].select { |path| File.mtime(path) > since } +
recent_tests('app/models/*.rb', 'test/unit', since) +
recent_tests('app/controllers/*.rb', 'test/functional', since)
t.libs << 'test'
t.verbose = true
t.test_files = touched.uniq
end
task :test_recent => [ :clone_structure_to_test ]
desc "Run the unit tests in test/unit"
Rake::TestTask.new("test_units") { |t|
t.libs << "test"
t.pattern = 'test/unit/**/*_test.rb'
t.verbose = true
}
task :test_units => [ :clone_structure_to_test ]
desc "Run the functional tests in test/functional"
Rake::TestTask.new("test_functional") { |t|
t.libs << "test"
t.pattern = 'test/functional/**/*_test.rb'
t.verbose = true
}
task :test_functional => [ :clone_structure_to_test ]
desc "Generate documentation for the application"
Rake::RDocTask.new("appdoc") { |rdoc|
rdoc.rdoc_dir = 'doc/app'
rdoc.title = "Tracks Documentation"
rdoc.options << '--line-numbers --inline-source'
rdoc.rdoc_files.include('doc/README_FOR_APP')
rdoc.rdoc_files.include('app/**/*.rb')
}
desc "Generate documentation for the Rails framework"
Rake::RDocTask.new("apidoc") { |rdoc|
rdoc.rdoc_dir = 'doc/api'
rdoc.template = "#{ENV['template']}.rb" if ENV['template']
rdoc.title = "Rails Framework Documentation"
rdoc.options << '--line-numbers --inline-source'
rdoc.rdoc_files.include('README')
rdoc.rdoc_files.include('CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/railties/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/railties/MIT-LICENSE')
rdoc.rdoc_files.include('vendor/rails/activerecord/README')
rdoc.rdoc_files.include('vendor/rails/activerecord/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/activerecord/lib/active_record/**/*.rb')
rdoc.rdoc_files.exclude('vendor/rails/activerecord/lib/active_record/vendor/*')
rdoc.rdoc_files.include('vendor/rails/actionpack/README')
rdoc.rdoc_files.include('vendor/rails/actionpack/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_controller/**/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_view/**/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionmailer/README')
rdoc.rdoc_files.include('vendor/rails/actionmailer/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/actionmailer/lib/action_mailer/base.rb')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/README')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service.rb')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/api/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/client/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/container/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/dispatcher/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/protocol/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/support/*.rb')
rdoc.rdoc_files.include('vendor/rails/activesupport/README')
rdoc.rdoc_files.include('vendor/rails/activesupport/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/activesupport/lib/active_support/**/*.rb')
}
desc "Report code statistics (KLOCs, etc) from the application"
task :stats => [ :environment ] do
require 'code_statistics'
CodeStatistics.new(
["Helpers", "app/helpers"],
["Controllers", "app/controllers"],
["APIs", "app/apis"],
["Components", "components"],
["Functionals", "test/functional"],
["Models", "app/models"],
["Units", "test/unit"]
).to_s
end
desc "Recreate the test databases from the development structure"
task :clone_structure_to_test => [ :db_structure_dump, :purge_test_database ] do
abcs = ActiveRecord::Base.configurations
case abcs["test"]["adapter"]
when "mysql"
ActiveRecord::Base.establish_connection(:test)
ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')
IO.readlines("db/#{RAILS_ENV}_structure.sql").join.split("\n\n").each do |table|
ActiveRecord::Base.connection.execute(table)
end
when "postgresql"
ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
`psql -U "#{abcs["test"]["username"]}" -f db/#{RAILS_ENV}_structure.sql #{abcs["test"]["database"]}`
when "sqlite", "sqlite3"
`#{abcs[RAILS_ENV]["adapter"]} #{abcs["test"]["dbfile"]} < db/#{RAILS_ENV}_structure.sql`
when "sqlserver"
`osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql`
else
raise "Unknown database adapter '#{abcs["test"]["adapter"]}'"
end
end
desc "Dump the database structure to a SQL file"
task :db_structure_dump => :environment do
abcs = ActiveRecord::Base.configurations
case abcs[RAILS_ENV]["adapter"]
when "mysql"
ActiveRecord::Base.establish_connection(abcs[RAILS_ENV])
File.open("db/#{RAILS_ENV}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump }
when "postgresql"
ENV['PGHOST'] = abcs[RAILS_ENV]["host"] if abcs[RAILS_ENV]["host"]
ENV['PGPORT'] = abcs[RAILS_ENV]["port"].to_s if abcs[RAILS_ENV]["port"]
ENV['PGPASSWORD'] = abcs[RAILS_ENV]["password"].to_s if abcs[RAILS_ENV]["password"]
`pg_dump -U "#{abcs[RAILS_ENV]["username"]}" -s -x -O -f db/#{RAILS_ENV}_structure.sql #{abcs[RAILS_ENV]["database"]}`
when "sqlite", "sqlite3"
`#{abcs[RAILS_ENV]["adapter"]} #{abcs[RAILS_ENV]["dbfile"]} .schema > db/#{RAILS_ENV}_structure.sql`
when "sqlserver"
`scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /f db\\#{RAILS_ENV}_structure.sql /q /A /r`
`scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /F db\ /q /A /r`
else
raise "Unknown database adapter '#{abcs["test"]["adapter"]}'"
end
end
desc "Empty the test database"
task :purge_test_database => :environment do
abcs = ActiveRecord::Base.configurations
case abcs["test"]["adapter"]
when "mysql"
ActiveRecord::Base.establish_connection(:test)
ActiveRecord::Base.connection.recreate_database(abcs["test"]["database"])
when "postgresql"
ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
`dropdb -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}`
`createdb -T template0 -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}`
when "sqlite","sqlite3"
File.delete(abcs["test"]["dbfile"]) if File.exist?(abcs["test"]["dbfile"])
when "sqlserver"
dropfkscript = "#{abcs["test"]["host"]}.#{abcs["test"]["database"]}.DP1".gsub(/\\/,'-')
`osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{dropfkscript}`
`osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql`
else
raise "Unknown database adapter '#{abcs["test"]["adapter"]}'"
end
end
desc "Clears all *.log files in log/"
task :clear_logs => :environment do
FileList["log/*.log"].each do |log_file|
f = File.open(log_file, "w")
f.close
end
end
desc "Migrate the database according to the migrate scripts in db/migrate (only supported on PG/MySQL). A specific version can be targetted with VERSION=x"
task :migrate => :environment do
ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/db/migrate/', ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
end
desc "Initialises the installation, copy the *.tmpl files and directories to versions named without the .tmpl extension. It won't overwrite the files and directories if you've already copied them. You need to manually copy database.yml.tmpl -> database.yml and fill in the details before you run this task."
task :setup_tracks => :environment do
# Check the root directory for template files
FileList["*.tmpl"].each do |template_file|
f = File.basename(template_file) # with suffix
f_only = File.basename(template_file,".tmpl") # without suffix
if File.exists?(f_only)
puts f_only + " already exists"
else
cp_r(f, f_only)
puts f_only + " created"
end
end
# Check the config dir for template files
# We can't convert the database.yml.tmpl file, because database.yml needs
# to exist for rake to run tasks!
cd("config") do
FileList["settings.yml.tmpl"].each do |template_file|
f = File.basename(template_file) # with suffix
f_only = File.basename(template_file,".tmpl") # without suffix
if File.exists?(f_only)
puts f_only + " already exists"
else
cp(f, f_only)
puts f_only + " created"
end
end
end
end
require 'tasks/rails'

17
tracks/config/boot.rb Normal file
View file

@ -0,0 +1,17 @@
unless defined?(RAILS_ROOT)
root_path = File.join(File.dirname(__FILE__), '..')
unless RUBY_PLATFORM =~ /mswin32/
require 'pathname'
root_path = Pathname.new(root_path).cleanpath.to_s
end
RAILS_ROOT = root_path
end
if File.directory?("#{RAILS_ROOT}/vendor/rails")
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
else
require 'rubygems'
require 'initializer'
end
Rails::Initializer.run(:set_load_path)

View file

@ -1,68 +1,54 @@
RAILS_ROOT = File.dirname(__FILE__) + "/../"
RAILS_ENV = ENV['RAILS_ENV'] || 'production'
# Be sure to restart your webserver when you modify this file.
# Uncomment below to force Rails into production mode
# (Use only when you can't set environment variables through your web/app server)
# ENV['RAILS_ENV'] = 'production'
# Mocks first.
ADDITIONAL_LOAD_PATHS = ["#{RAILS_ROOT}/test/mocks/#{RAILS_ENV}"]
# Bootstrap the Rails environment, frameworks, and default configuration
require File.join(File.dirname(__FILE__), 'boot')
# Then model subdirectories.
ADDITIONAL_LOAD_PATHS.concat(Dir["#{RAILS_ROOT}/app/models/[_a-z]*"])
ADDITIONAL_LOAD_PATHS.concat(Dir["#{RAILS_ROOT}/components/[_a-z]*"])
Rails::Initializer.run do |config|
# Skip frameworks you're not going to use
# config.frameworks -= [ :action_web_service, :action_mailer ]
# Followed by the standard includes.
ADDITIONAL_LOAD_PATHS.concat %w(
app
app/models
app/controllers
app/helpers
app/apis
config
components
lib
vendor
).map { |dir| "#{RAILS_ROOT}/#{dir}" }
# Add additional load paths for your own custom dirs
# config.load_paths += %W( #{RAILS_ROOT}/app/services )
# Prepend to $LOAD_PATH
ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) }
# Force all environments to use the same logger level
# (by default production uses :info, the others :debug)
# config.log_level = :debug
# Use the database for sessions instead of the file system
# (create the session table with 'rake create_sessions_table')
# config.action_controller.session_store = :active_record_store
# Require Rails gems.
require 'rubygems'
require_gem 'activesupport'
require_gem 'activerecord'
require_gem 'actionpack'
require_gem 'actionmailer'
require_gem 'actionwebservice'
require_gem 'rails'
# Enable page/fragment caching by setting a file-based store
# (remember to create the caching directory and make it readable to the application)
# config.action_controller.fragment_cache_store = :file_store, "#{RAILS_ROOT}/cache"
# Environment-specific configuration.
require_dependency "environments/#{RAILS_ENV}"
ActiveRecord::Base.configurations = YAML::load(File.open("#{RAILS_ROOT}/config/database.yml"))
ActiveRecord::Base.establish_connection
# Activate observers that should always be running
# config.active_record.observers = :cacher, :garbage_collector
# Make Active Record use UTC-base instead of local time
# config.active_record.default_timezone = :utc
# Use Active Record's schema dumper instead of SQL when creating the test database
# (enables use of different database adapters for development and test environments)
# config.active_record.schema_format = :ruby
# Configure defaults if the included environment did not.
begin
RAILS_DEFAULT_LOGGER = Logger.new("#{RAILS_ROOT}/log/#{RAILS_ENV}.log")
rescue StandardError
RAILS_DEFAULT_LOGGER = Logger.new(STDERR)
RAILS_DEFAULT_LOGGER.level = Logger::WARN
RAILS_DEFAULT_LOGGER.warn(
"Rails Error: Unable to access log file. Please ensure that log/#{RAILS_ENV}.log exists and is chmod 0666. " +
"The log level has been raised to WARN and the output directed to STDERR until the problem is fixed."
)
# See Rails::Configuration for more options
end
[ActiveRecord, ActionController, ActionMailer].each { |mod| mod::Base.logger ||= RAILS_DEFAULT_LOGGER }
[ActionController, ActionMailer].each { |mod| mod::Base.template_root ||= "#{RAILS_ROOT}/app/views/" }
ActionController::Routing::Routes.reload
# Add new inflection rules using the following format
# (all these examples are active by default):
# Inflector.inflections do |inflect|
# inflect.plural /^(ox)$/i, '\1en'
# inflect.singular /^(ox)en/i, '\1'
# inflect.irregular 'person', 'people'
# inflect.uncountable %w( fish sheep )
# end
Controllers = Dependencies::LoadingModule.root(
File.expand_path(File.join(RAILS_ROOT, 'app', 'controllers')),
File.expand_path(File.join(RAILS_ROOT, 'components'))
)
# Include your app's configuration here:
# Include your application configuration below
def app_configurations
YAML::load(File.open("#{RAILS_ROOT}/config/settings.yml"))
end
end

View file

@ -1,19 +1,21 @@
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the webserver when you make code changes.
config.cache_classes = false
# Log error messages when you accidentally call methods on nil.
require 'active_support/whiny_nil'
config.whiny_nils = true
# Reload code; show full error reports; disable caching.
Dependencies.mechanism = :load
ActionController::Base.consider_all_requests_local = true
ActionController::Base.perform_caching = false
# Enable the breakpoint server that script/breakpointer connects to
config.breakpoint_server = true
# The breakpoint server port that script/breakpointer connects to.
BREAKPOINT_SERVER_PORT = 42531
# Show full error reports and disable caching
config.action_controller.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false
# Unique cookies
ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:session_key] = "TrackDev"
ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:tmpdir] = "#{RAILS_ROOT}/tmp"
ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:tmpdir] = "#{RAILS_ROOT}/tmp"

View file

@ -1,8 +1,17 @@
# The production environment is meant for finished, "live" apps.
# Code is not reloaded between requests, full error reports are disabled,
# and caching is turned on.
# Code is not reloaded between requests
config.cache_classes = true
# Don't reload code; don't show full error reports; enable caching.
Dependencies.mechanism = :require
ActionController::Base.consider_all_requests_local = false
ActionController::Base.perform_caching = true
# Use a different logger for distributed setups
# config.logger = SyslogLogger.new
# Full error reports are disabled and caching is turned on
config.action_controller.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Enable serving of images, stylesheets, and javascripts from an asset server
# config.action_controller.asset_host = "http://assets.example.com"
# Disable delivery errors if you bad email addresses should just be ignored
# config.action_mailer.raise_delivery_errors = false

View file

@ -2,16 +2,22 @@
# test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped
# and recreated between test runs. Don't rely on the data there!
config.cache_classes = true
# Log error messages when you accidentally call methods on nil.
require 'active_support/whiny_nil'
config.whiny_nils = true
# Don't reload code; show full error reports; disable caching.
Dependencies.mechanism = :require
ActionController::Base.consider_all_requests_local = true
ActionController::Base.perform_caching = false
# Show full error reports and disable caching
config.action_controller.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Tell ActionMailer not to deliver emails to the real world.
# The :test delivery method accumulates sent emails in the
# ActionMailer::Base.deliveries array.
ActionMailer::Base.delivery_method = :test
config.action_mailer.delivery_method = :test
# Overwrite the default settings for fixtures in tests. See Fixtures
# for more details about these settings.
# config.transactional_fixtures = true
# config.instantiated_fixtures = false
# config.pre_loaded_fixtures = false

View file

@ -6,10 +6,14 @@ ActionController::Routing::Routes.draw do |map|
# map.connect 'products/:id', :controller => 'catalog', :action => 'view'
# Keep in mind you can assign values other than :controller and :action
# You can have the root of your site routed by hooking up ''
# -- just remember to delete public/index.html.
# map.connect '', :controller => "welcome"
# Allow downloading Web Service WSDL as a file with an extension
# instead of a file named 'wsdl'
#map.connect ':controller/service.wsdl', :action => 'wsdl'
# Index Route
map.connect '', :controller => 'todo', :action => 'list'
@ -52,6 +56,6 @@ ActionController::Routing::Routes.draw do |map|
map.connect 'add_item', :controller => 'todo', :action => 'add_item'
# Install the default route as the lowest priority.
map.connect ':controller/:action'
map.connect ':controller/:action/:id'
end

View file

@ -2,7 +2,7 @@
* Homepage: http://www.rousette.org.uk/projects/
* Author: bsag (http://www.rousette.org.uk/)
* Contributors: Nicholas Lee, Lolindrath, Jim Ray, Arnaud Limbourg, Timothy Martens, Luke
* Contributors: Nicholas Lee, Lolindrath, Jim Ray, Arnaud Limbourg, Timothy Martens, Luke, John Leonard (for great installation tutorials on Windows XP)
* Version: 1.03
* Copyright: (cc) 2004-2005 rousette.org.uk
* License: GNU GPL

View file

@ -2,7 +2,7 @@
* Homepage: http://www.rousette.org.uk/projects/
* Author: bsag (http://www.rousette.org.uk/)
* Contributors: Nicholas Lee, Lolindrath, Jim Ray, Arnaud Limbourg, Timothy Martens, Luke
* Contributors: Nicholas Lee, Lolindrath, Jim Ray, Arnaud Limbourg, Timothy Martens, Luke, John Leonard (for great installation tutorials on Windows XP)
* Version: 1.031
* Copyright: (cc) 2004-2005 rousette.org.uk
* License: GNU GPL

View file

@ -0,0 +1,4 @@
desc "Migrate the database according to the migrate scripts in db/migrate (only supported on PG/MySQL). A specific version can be targetted with VERSION=x"
task :migrate => :environment do
ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/db/migrate/', ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
end

View file

@ -0,0 +1,29 @@
desc "Initialises the installation, copy the *.tmpl files and directories to versions named without the .tmpl extension. It won't overwrite the files and directories if you've already copied them. You need to manually copy database.yml.tmpl -> database.yml and fill in the details before you run this task."
task :setup_tracks => :environment do
# Check the root directory for template files
FileList["*.tmpl"].each do |template_file|
f = File.basename(template_file) # with suffix
f_only = File.basename(template_file,".tmpl") # without suffix
if File.exists?(f_only)
puts f_only + " already exists"
else
cp_r(f, f_only)
puts f_only + " created"
end
end
# Check the config dir for template files
# We can't convert the database.yml.tmpl file, because database.yml needs
# to exist for rake to run tasks!
cd("config") do
FileList["settings.yml.tmpl"].each do |template_file|
f = File.basename(template_file) # with suffix
f_only = File.basename(template_file,".tmpl") # without suffix
if File.exists?(f_only)
puts f_only + " already exists"
else
cp(f, f_only)
puts f_only + " created"
end
end
end
end

View file

@ -3,12 +3,38 @@ AddHandler fastcgi-script .fcgi
AddHandler cgi-script .cgi
Options +FollowSymLinks +ExecCGI
# If you don't want Rails to look in certain directories,
# use the following rewrite rules so that Apache won't rewrite certain requests
#
# Example:
# RewriteCond %{REQUEST_URI} ^/notrails.*
# RewriteRule .* - [L]
# Redirect all requests not available on the filesystem to Rails
# By default the cgi dispatcher is used which is very slow
#
# For better performance replace the dispatcher with the fastcgi one
#
# Example:
# RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
RewriteEngine On
# If your Rails application is accessed via an Alias directive,
# then you MUST also set the RewriteBase in this htaccess file.
#
# Example:
# Alias /myrailsapp /path/to/myrailsapp/public
# RewriteBase /myrailsapp
RewriteRule ^$ index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /dispatch.cgi?$1 [QSA,L]
RewriteRule ^(.*)$ dispatch.cgi [QSA,L]
# In case Rails experiences terminal errors
ErrorDocument 500 /500.html
# Instead of displaying this message you can supply a file here which will be rendered instead
#
# Example:
# ErrorDocument 500 /500.html
ErrorDocument 500 "<h2>Application error</h2>Rails application failed to start properly"

View file

@ -21,4 +21,4 @@
require File.dirname(__FILE__) + "/../config/environment"
require 'fcgi_handler'
RailsFCGIHandler.process!
RailsFCGIHandler.process!

View file

@ -1,4 +1,4 @@
#!/usr/bin/ruby1.8
#!/usr/bin/env ruby
require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)

View file

@ -1,41 +1,12 @@
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
// (c) 2005 Jon Tirsen (http://www.tirsen.com)
// Contributors:
// Richard Livsey
// Rahul Bhargava
// Rob Wills
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Element.collectTextNodesIgnoreClass = function(element, ignoreclass) {
var children = $(element).childNodes;
var text = "";
var classtest = new RegExp("^([^ ]+ )*" + ignoreclass+ "( [^ ]+)*$","i");
for (var i = 0; i < children.length; i++) {
if(children[i].nodeType==3) {
text+=children[i].nodeValue;
} else {
if((!children[i].className.match(classtest)) && children[i].hasChildNodes())
text += Element.collectTextNodesIgnoreClass(children[i], ignoreclass);
}
}
return text;
}
// See scriptaculous.js for full license.
// Autocompleter.Base handles all the autocompletion functionality
// that's independent of the data source for autocompletion. This
@ -46,7 +17,7 @@ Element.collectTextNodesIgnoreClass = function(element, ignoreclass) {
// a getUpdatedChoices function that will be invoked every time
// the text inside the monitored textbox changes. This method
// should get the text for which to provide autocompletion by
// invoking this.getEntry(), NOT by directly accessing
// invoking this.getToken(), NOT by directly accessing
// this.element.value. This is to allow incremental tokenized
// autocompletion. Specific auto-completion logic (AJAX, etc)
// belongs in getUpdatedChoices.
@ -57,7 +28,7 @@ Element.collectTextNodesIgnoreClass = function(element, ignoreclass) {
// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
// will incrementally autocomplete with a comma as the token.
// Additionally, ',' in the above example can be replaced with
// a token array, e.g. { tokens: new Array (',', '\n') } which
// a token array, e.g. { tokens: [',', '\n'] } which
// enables autocompletion on multiple tokens. This is most
// useful when one of the tokens is \n (a newline), as it
// allows smart autocompletion after linebreaks.
@ -65,79 +36,79 @@ Element.collectTextNodesIgnoreClass = function(element, ignoreclass) {
var Autocompleter = {}
Autocompleter.Base = function() {};
Autocompleter.Base.prototype = {
base_initialize: function(element, update, options) {
baseInitialize: function(element, update, options) {
this.element = $(element);
this.update = $(update);
this.has_focus = false;
this.hasFocus = false;
this.changed = false;
this.active = false;
this.index = 0;
this.entry_count = 0;
this.entryCount = 0;
if (this.setOptions)
this.setOptions(options);
else
this.options = {}
this.options.tokens = this.options.tokens || new Array();
this.options = options || {};
this.options.paramName = this.options.paramName || this.element.name;
this.options.tokens = this.options.tokens || [];
this.options.frequency = this.options.frequency || 0.4;
this.options.min_chars = this.options.min_chars || 1;
this.options.minChars = this.options.minChars || 1;
this.options.onShow = this.options.onShow ||
function(element, update){
if(!update.style.position || update.style.position=='absolute') {
update.style.position = 'absolute';
var offsets = Position.cumulativeOffset(element);
update.style.left = offsets[0] + 'px';
update.style.top = (offsets[1] + element.offsetHeight) + 'px';
update.style.width = element.offsetWidth + 'px';
Position.clone(element, update, {setHeight: false, offsetTop: element.offsetHeight});
}
new Effect.Appear(update,{duration:0.15});
Effect.Appear(update,{duration:0.15});
};
this.options.onHide = this.options.onHide ||
function(element, update){ new Effect.Fade(update,{duration:0.15}) };
if(this.options.indicator)
this.indicator = $(this.options.indicator);
if (typeof(this.options.tokens) == 'string')
this.options.tokens = new Array(this.options.tokens);
this.observer = null;
this.element.setAttribute('autocomplete','off');
Element.hide(this.update);
Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this));
Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this));
},
show: function() {
if(this.update.style.display=='none') this.options.onShow(this.element, this.update);
if(!this.iefix && (navigator.appVersion.indexOf('MSIE')>0) && this.update.style.position=='absolute') {
if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
if(!this.iefix && (navigator.appVersion.indexOf('MSIE')>0) && (Element.getStyle(this.update, 'position')=='absolute')) {
new Insertion.After(this.update,
'<iframe id="' + this.update.id + '_iefix" '+
'style="display:none;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
this.iefix = $(this.update.id+'_iefix');
}
if(this.iefix) {
Position.clone(this.update, this.iefix);
this.iefix.style.zIndex = 1;
this.update.style.zIndex = 2;
Element.show(this.iefix);
}
if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
},
fixIEOverlapping: function() {
Position.clone(this.update, this.iefix);
this.iefix.style.zIndex = 1;
this.update.style.zIndex = 2;
Element.show(this.iefix);
},
hide: function() {
if(this.update.style.display=='') this.options.onHide(this.element, this.update);
this.stopIndicator();
if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
if(this.iefix) Element.hide(this.iefix);
},
startIndicator: function() {
if(this.indicator) Element.show(this.indicator);
if(this.options.indicator) Element.show(this.options.indicator);
},
stopIndicator: function() {
if(this.indicator) Element.hide(this.indicator);
if(this.options.indicator) Element.hide(this.options.indicator);
},
onKeyPress: function(event) {
@ -145,22 +116,23 @@ Autocompleter.Base.prototype = {
switch(event.keyCode) {
case Event.KEY_TAB:
case Event.KEY_RETURN:
this.select_entry();
this.selectEntry();
Event.stop(event);
case Event.KEY_ESC:
this.hide();
this.active = false;
Event.stop(event);
return;
case Event.KEY_LEFT:
case Event.KEY_RIGHT:
return;
case Event.KEY_UP:
this.mark_previous();
this.markPrevious();
this.render();
if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
return;
case Event.KEY_DOWN:
this.mark_next();
this.markNext();
this.render();
if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
return;
@ -168,15 +140,15 @@ Autocompleter.Base.prototype = {
else
if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN)
return;
this.changed = true;
this.has_focus = true;
this.hasFocus = true;
if(this.observer) clearTimeout(this.observer);
this.observer =
setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
},
onHover: function(event) {
var element = Event.findElement(event, 'LI');
if(this.index != element.autocompleteIndex)
@ -190,92 +162,97 @@ Autocompleter.Base.prototype = {
onClick: function(event) {
var element = Event.findElement(event, 'LI');
this.index = element.autocompleteIndex;
this.select_entry();
Event.stop(event);
this.selectEntry();
this.hide();
},
onBlur: function(event) {
// needed to make click events working
setTimeout(this.hide.bind(this), 250);
this.has_focus = false;
this.hasFocus = false;
this.active = false;
},
render: function() {
if(this.entry_count > 0) {
for (var i = 0; i < this.entry_count; i++)
if(this.entryCount > 0) {
for (var i = 0; i < this.entryCount; i++)
this.index==i ?
Element.addClassName(this.get_entry(i),"selected") :
Element.removeClassName(this.get_entry(i),"selected");
if(this.has_focus) {
if(this.get_current_entry().scrollIntoView)
this.get_current_entry().scrollIntoView(false);
Element.addClassName(this.getEntry(i),"selected") :
Element.removeClassName(this.getEntry(i),"selected");
if(this.hasFocus) {
this.show();
this.active = true;
}
} else this.hide();
},
mark_previous: function() {
markPrevious: function() {
if(this.index > 0) this.index--
else this.index = this.entry_count-1;
else this.index = this.entryCount-1;
},
mark_next: function() {
if(this.index < this.entry_count-1) this.index++
markNext: function() {
if(this.index < this.entryCount-1) this.index++
else this.index = 0;
},
get_entry: function(index) {
getEntry: function(index) {
return this.update.firstChild.childNodes[index];
},
get_current_entry: function() {
return this.get_entry(this.index);
getCurrentEntry: function() {
return this.getEntry(this.index);
},
select_entry: function() {
selectEntry: function() {
this.active = false;
value = Element.collectTextNodesIgnoreClass(this.get_current_entry(), 'informal').unescapeHTML();
this.updateElement(value);
this.element.focus();
this.updateElement(this.getCurrentEntry());
},
updateElement: function(value) {
var last_token_pos = this.findLastToken();
if (last_token_pos != -1) {
var new_value = this.element.value.substr(0, last_token_pos + 1);
var whitespace = this.element.value.substr(last_token_pos + 1).match(/^\s+/);
updateElement: function(selectedElement) {
if (this.options.updateElement) {
this.options.updateElement(selectedElement);
return;
}
var value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
var lastTokenPos = this.findLastToken();
if (lastTokenPos != -1) {
var newValue = this.element.value.substr(0, lastTokenPos + 1);
var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/);
if (whitespace)
new_value += whitespace[0];
this.element.value = new_value + value;
newValue += whitespace[0];
this.element.value = newValue + value;
} else {
this.element.value = value;
}
}
this.element.focus();
if (this.options.afterUpdateElement)
this.options.afterUpdateElement(this.element, selectedElement);
},
updateChoices: function(choices) {
if(!this.changed && this.has_focus) {
if(!this.changed && this.hasFocus) {
this.update.innerHTML = choices;
Element.cleanWhitespace(this.update);
Element.cleanWhitespace(this.update.firstChild);
if(this.update.firstChild && this.update.firstChild.childNodes) {
this.entry_count =
this.entryCount =
this.update.firstChild.childNodes.length;
for (var i = 0; i < this.entry_count; i++) {
entry = this.get_entry(i);
for (var i = 0; i < this.entryCount; i++) {
var entry = this.getEntry(i);
entry.autocompleteIndex = i;
this.addObservers(entry);
}
} else {
this.entry_count = 0;
this.entryCount = 0;
}
this.stopIndicator();
this.index = 0;
this.render();
}
@ -288,7 +265,7 @@ Autocompleter.Base.prototype = {
onObserverEvent: function() {
this.changed = false;
if(this.getEntry().length>=this.options.min_chars) {
if(this.getToken().length>=this.options.minChars) {
this.startIndicator();
this.getUpdatedChoices();
} else {
@ -297,58 +274,56 @@ Autocompleter.Base.prototype = {
}
},
getEntry: function() {
var token_pos = this.findLastToken();
if (token_pos != -1)
var ret = this.element.value.substr(token_pos + 1).replace(/^\s+/,'').replace(/\s+$/,'');
getToken: function() {
var tokenPos = this.findLastToken();
if (tokenPos != -1)
var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,'');
else
var ret = this.element.value;
return /\n/.test(ret) ? '' : ret;
},
findLastToken: function() {
var last_token_pos = -1;
var lastTokenPos = -1;
for (var i=0; i<this.options.tokens.length; i++) {
var this_token_pos = this.element.value.lastIndexOf(this.options.tokens[i]);
if (this_token_pos > last_token_pos)
last_token_pos = this_token_pos;
var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]);
if (thisTokenPos > lastTokenPos)
lastTokenPos = thisTokenPos;
}
return last_token_pos;
return lastTokenPos;
}
}
Ajax.Autocompleter = Class.create();
Ajax.Autocompleter.prototype = Object.extend(new Autocompleter.Base(),
Object.extend(new Ajax.Base(), {
Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), {
initialize: function(element, update, url, options) {
this.base_initialize(element, update, options);
this.baseInitialize(element, update, options);
this.options.asynchronous = true;
this.options.onComplete = this.onComplete.bind(this)
this.options.method = 'post';
this.options.onComplete = this.onComplete.bind(this);
this.options.defaultParams = this.options.parameters || null;
this.url = url;
},
getUpdatedChoices: function() {
entry = encodeURIComponent(this.element.name) + '=' +
encodeURIComponent(this.getEntry());
entry = encodeURIComponent(this.options.paramName) + '=' +
encodeURIComponent(this.getToken());
this.options.parameters = this.options.callback ?
this.options.callback(this.element, entry) : entry;
if(this.options.defaultParams)
this.options.parameters += '&' + this.options.defaultParams;
new Ajax.Request(this.url, this.options);
},
onComplete: function(request) {
this.updateChoices(request.responseText);
}
}));
});
// The local array autocompleter. Used when you'd prefer to
// inject an array of autocompletion options into the page, rather
@ -362,22 +337,22 @@ Object.extend(new Ajax.Base(), {
// Extra local autocompletion options:
// - choices - How many autocompletion choices to offer
//
// - partial_search - If false, the autocompleter will match entered
// - partialSearch - If false, the autocompleter will match entered
// text only at the beginning of strings in the
// autocomplete array. Defaults to true, which will
// match text at the beginning of any *word* in the
// strings in the autocomplete array. If you want to
// search anywhere in the string, additionally set
// the option full_search to true (default: off).
// the option fullSearch to true (default: off).
//
// - full_search - Search anywhere in autocomplete array strings.
// - fullSsearch - Search anywhere in autocomplete array strings.
//
// - partial_chars - How many characters to enter before triggering
// a partial match (unlike min_chars, which defines
// - partialChars - How many characters to enter before triggering
// a partial match (unlike minChars, which defines
// how many characters are required to do any match
// at all). Defaults to 2.
//
// - ignore_case - Whether to ignore case when autocompleting.
// - ignoreCase - Whether to ignore case when autocompleting.
// Defaults to true.
//
// It's possible to pass in a custom function as the 'selector'
@ -388,7 +363,7 @@ Object.extend(new Ajax.Base(), {
Autocompleter.Local = Class.create();
Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
initialize: function(element, update, array, options) {
this.base_initialize(element, update, options);
this.baseInitialize(element, update, options);
this.options.array = array;
},
@ -399,41 +374,42 @@ Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
setOptions: function(options) {
this.options = Object.extend({
choices: 10,
partial_search: true,
partial_chars: 2,
ignore_case: true,
full_search: false,
partialSearch: true,
partialChars: 2,
ignoreCase: true,
fullSearch: false,
selector: function(instance) {
var ret = new Array(); // Beginning matches
var partial = new Array(); // Inside matches
var entry = instance.getEntry();
var ret = []; // Beginning matches
var partial = []; // Inside matches
var entry = instance.getToken();
var count = 0;
for (var i = 0; i < instance.options.array.length &&
ret.length < instance.options.choices ; i++) {
ret.length < instance.options.choices ; i++) {
var elem = instance.options.array[i];
var found_pos = instance.options.ignore_case ?
var foundPos = instance.options.ignoreCase ?
elem.toLowerCase().indexOf(entry.toLowerCase()) :
elem.indexOf(entry);
while (found_pos != -1) {
if (found_pos == 0 && elem.length != entry.length) {
while (foundPos != -1) {
if (foundPos == 0 && elem.length != entry.length) {
ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
elem.substr(entry.length) + "</li>");
break;
} else if (entry.length >= instance.options.partial_chars &&
instance.options.partial_search && found_pos != -1) {
if (instance.options.full_search || /\s/.test(elem.substr(found_pos-1,1))) {
partial.push("<li>" + elem.substr(0, found_pos) + "<strong>" +
elem.substr(found_pos, entry.length) + "</strong>" + elem.substr(
found_pos + entry.length) + "</li>");
} else if (entry.length >= instance.options.partialChars &&
instance.options.partialSearch && foundPos != -1) {
if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
foundPos + entry.length) + "</li>");
break;
}
}
found_pos = instance.options.ignore_case ?
elem.toLowerCase().indexOf(entry.toLowerCase(), found_pos + 1) :
elem.indexOf(entry, found_pos + 1);
foundPos = instance.options.ignoreCase ?
elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
elem.indexOf(entry, foundPos + 1);
}
}
@ -444,3 +420,289 @@ Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
}, options || {});
}
});
// AJAX in-place editor
//
// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor
Ajax.InPlaceEditor = Class.create();
Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99";
Ajax.InPlaceEditor.prototype = {
initialize: function(element, url, options) {
this.url = url;
this.element = $(element);
this.options = Object.extend({
okText: "ok",
cancelText: "cancel",
savingText: "Saving...",
clickToEditText: "Click to edit",
okText: "ok",
rows: 1,
onComplete: function(transport, element) {
new Effect.Highlight(element, {startcolor: this.options.highlightcolor});
},
onFailure: function(transport) {
alert("Error communicating with the server: " + transport.responseText.stripTags());
},
callback: function(form) {
return Form.serialize(form);
},
handleLineBreaks: true,
loadingText: 'Loading...',
savingClassName: 'inplaceeditor-saving',
loadingClassName: 'inplaceeditor-loading',
formClassName: 'inplaceeditor-form',
highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
highlightendcolor: "#FFFFFF",
externalControl: null,
ajaxOptions: {}
}, options || {});
if(!this.options.formId && this.element.id) {
this.options.formId = this.element.id + "-inplaceeditor";
if ($(this.options.formId)) {
// there's already a form with that name, don't specify an id
this.options.formId = null;
}
}
if (this.options.externalControl) {
this.options.externalControl = $(this.options.externalControl);
}
this.originalBackground = Element.getStyle(this.element, 'background-color');
if (!this.originalBackground) {
this.originalBackground = "transparent";
}
this.element.title = this.options.clickToEditText;
this.onclickListener = this.enterEditMode.bindAsEventListener(this);
this.mouseoverListener = this.enterHover.bindAsEventListener(this);
this.mouseoutListener = this.leaveHover.bindAsEventListener(this);
Event.observe(this.element, 'click', this.onclickListener);
Event.observe(this.element, 'mouseover', this.mouseoverListener);
Event.observe(this.element, 'mouseout', this.mouseoutListener);
if (this.options.externalControl) {
Event.observe(this.options.externalControl, 'click', this.onclickListener);
Event.observe(this.options.externalControl, 'mouseover', this.mouseoverListener);
Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener);
}
},
enterEditMode: function() {
if (this.saving) return;
if (this.editing) return;
this.editing = true;
this.onEnterEditMode();
if (this.options.externalControl) {
Element.hide(this.options.externalControl);
}
Element.hide(this.element);
this.createForm();
this.element.parentNode.insertBefore(this.form, this.element);
Field.focus(this.editField);
// stop the event to avoid a page refresh in Safari
if (arguments.length > 1) {
Event.stop(arguments[0]);
}
},
createForm: function() {
this.form = document.createElement("form");
this.form.id = this.options.formId;
Element.addClassName(this.form, this.options.formClassName)
this.form.onsubmit = this.onSubmit.bind(this);
this.createEditField();
if (this.options.textarea) {
var br = document.createElement("br");
this.form.appendChild(br);
}
okButton = document.createElement("input");
okButton.type = "submit";
okButton.value = this.options.okText;
this.form.appendChild(okButton);
cancelLink = document.createElement("a");
cancelLink.href = "#";
cancelLink.appendChild(document.createTextNode(this.options.cancelText));
cancelLink.onclick = this.onclickCancel.bind(this);
this.form.appendChild(cancelLink);
},
hasHTMLLineBreaks: function(string) {
if (!this.options.handleLineBreaks) return false;
return string.match(/<br/i) || string.match(/<p>/i);
},
convertHTMLLineBreaks: function(string) {
return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, "");
},
createEditField: function() {
var text;
if(this.options.loadTextURL) {
text = this.options.loadingText;
} else {
text = this.getText();
}
if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) {
this.options.textarea = false;
var textField = document.createElement("input");
textField.type = "text";
textField.name = "value";
textField.value = text;
textField.style.backgroundColor = this.options.highlightcolor;
var size = this.options.size || this.options.cols || 0;
if (size != 0) textField.size = size;
this.editField = textField;
} else {
this.options.textarea = true;
var textArea = document.createElement("textarea");
textArea.name = "value";
textArea.value = this.convertHTMLLineBreaks(text);
textArea.rows = this.options.rows;
textArea.cols = this.options.cols || 40;
this.editField = textArea;
}
if(this.options.loadTextURL) {
this.loadExternalText();
}
this.form.appendChild(this.editField);
},
getText: function() {
return this.element.innerHTML;
},
loadExternalText: function() {
Element.addClassName(this.form, this.options.loadingClassName);
this.editField.disabled = true;
new Ajax.Request(
this.options.loadTextURL,
Object.extend({
asynchronous: true,
onComplete: this.onLoadedExternalText.bind(this)
}, this.options.ajaxOptions)
);
},
onLoadedExternalText: function(transport) {
Element.removeClassName(this.form, this.options.loadingClassName);
this.editField.disabled = false;
this.editField.value = transport.responseText.stripTags();
},
onclickCancel: function() {
this.onComplete();
this.leaveEditMode();
return false;
},
onFailure: function(transport) {
this.options.onFailure(transport);
if (this.oldInnerHTML) {
this.element.innerHTML = this.oldInnerHTML;
this.oldInnerHTML = null;
}
return false;
},
onSubmit: function() {
// onLoading resets these so we need to save them away for the Ajax call
var form = this.form;
var value = this.editField.value;
// do this first, sometimes the ajax call returns before we get a chance to switch on Saving...
// which means this will actually switch on Saving... *after* we've left edit mode causing Saving...
// to be displayed indefinitely
this.onLoading();
new Ajax.Updater(
{
success: this.element,
// don't update on failure (this could be an option)
failure: null
},
this.url,
Object.extend({
parameters: this.options.callback(form, value),
onComplete: this.onComplete.bind(this),
onFailure: this.onFailure.bind(this)
}, this.options.ajaxOptions)
);
// stop the event to avoid a page refresh in Safari
if (arguments.length > 1) {
Event.stop(arguments[0]);
}
return false;
},
onLoading: function() {
this.saving = true;
this.removeForm();
this.leaveHover();
this.showSaving();
},
showSaving: function() {
this.oldInnerHTML = this.element.innerHTML;
this.element.innerHTML = this.options.savingText;
Element.addClassName(this.element, this.options.savingClassName);
this.element.style.backgroundColor = this.originalBackground;
Element.show(this.element);
},
removeForm: function() {
if(this.form) {
if (this.form.parentNode) Element.remove(this.form);
this.form = null;
}
},
enterHover: function() {
if (this.saving) return;
this.element.style.backgroundColor = this.options.highlightcolor;
if (this.effect) {
this.effect.cancel();
}
Element.addClassName(this.element, this.options.hoverClassName)
},
leaveHover: function() {
if (this.options.backgroundColor) {
this.element.style.backgroundColor = this.oldBackground;
}
Element.removeClassName(this.element, this.options.hoverClassName)
if (this.saving) return;
this.effect = new Effect.Highlight(this.element, {
startcolor: this.options.highlightcolor,
endcolor: this.options.highlightendcolor,
restorecolor: this.originalBackground
});
},
leaveEditMode: function() {
Element.removeClassName(this.element, this.options.savingClassName);
this.removeForm();
this.leaveHover();
this.element.style.backgroundColor = this.originalBackground;
Element.show(this.element);
if (this.options.externalControl) {
Element.show(this.options.externalControl);
}
this.editing = false;
this.saving = false;
this.oldInnerHTML = null;
this.onLeaveEditMode();
},
onComplete: function(transport) {
this.leaveEditMode();
this.options.onComplete.bind(this)(transport, this.element);
},
onEnterEditMode: function() {},
onLeaveEditMode: function() {},
dispose: function() {
if (this.oldInnerHTML) {
this.element.innerHTML = this.oldInnerHTML;
}
this.leaveEditMode();
Event.stopObserving(this.element, 'click', this.onclickListener);
Event.stopObserving(this.element, 'mouseover', this.mouseoverListener);
Event.stopObserving(this.element, 'mouseout', this.mouseoutListener);
if (this.options.externalControl) {
Event.stopObserving(this.options.externalControl, 'click', this.onclickListener);
Event.stopObserving(this.options.externalControl, 'mouseover', this.mouseoverListener);
Event.stopObserving(this.options.externalControl, 'mouseout', this.mouseoutListener);
}
}
};

View file

@ -2,193 +2,79 @@
//
// Element.Class part Copyright (c) 2005 by Rick Olson
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Element.Class = {
// Element.toggleClass(element, className) toggles the class being on/off
// Element.toggleClass(element, className1, className2) toggles between both classes,
// defaulting to className1 if neither exist
toggle: function(element, className) {
if(Element.Class.has(element, className)) {
Element.Class.remove(element, className);
if(arguments.length == 3) Element.Class.add(element, arguments[2]);
} else {
Element.Class.add(element, className);
if(arguments.length == 3) Element.Class.remove(element, arguments[2]);
}
},
// gets space-delimited classnames of an element as an array
get: function(element) {
element = $(element);
return element.className.split(' ');
},
// functions adapted from original functions by Gavin Kistner
remove: function(element) {
element = $(element);
var regEx;
for(var i = 1; i < arguments.length; i++) {
regEx = new RegExp("^" + arguments[i] + "\\b\\s*|\\s*\\b" + arguments[i] + "\\b", 'g');
element.className = element.className.replace(regEx, '')
}
},
add: function(element) {
element = $(element);
for(var i = 1; i < arguments.length; i++) {
Element.Class.remove(element, arguments[i]);
element.className += (element.className.length > 0 ? ' ' : '') + arguments[i];
}
},
// returns true if all given classes exist in said element
has: function(element) {
element = $(element);
if(!element || !element.className) return false;
var regEx;
for(var i = 1; i < arguments.length; i++) {
regEx = new RegExp("\\b" + arguments[i] + "\\b");
if(!regEx.test(element.className)) return false;
}
return true;
},
// expects arrays of strings and/or strings as optional paramters
// Element.Class.has_any(element, ['classA','classB','classC'], 'classD')
has_any: function(element) {
element = $(element);
if(!element || !element.className) return false;
var regEx;
for(var i = 1; i < arguments.length; i++) {
if((typeof arguments[i] == 'object') &&
(arguments[i].constructor == Array)) {
for(var j = 0; j < arguments[i].length; j++) {
regEx = new RegExp("\\b" + arguments[i][j] + "\\b");
if(regEx.test(element.className)) return true;
}
} else {
regEx = new RegExp("\\b" + arguments[i] + "\\b");
if(regEx.test(element.className)) return true;
}
}
return false;
},
childrenWith: function(element, className) {
var children = $(element).getElementsByTagName('*');
var elements = new Array();
for (var i = 0; i < children.length; i++) {
if (Element.Class.has(children[i], className)) {
elements.push(children[i]);
break;
}
}
return elements;
}
}
// See scriptaculous.js for full license.
/*--------------------------------------------------------------------------*/
var Droppables = {
drops: false,
drops: [],
remove: function(element) {
for(var i = 0; i < this.drops.length; i++)
if(this.drops[i].element == element)
this.drops.splice(i,1);
this.drops = this.drops.reject(function(d) { return d.element==element });
},
add: function(element) {
var element = $(element);
element = $(element);
var options = Object.extend({
greedy: true,
hoverclass: null
}, arguments[1] || {});
// cache containers
if(options.containment) {
options._containers = new Array();
options._containers = [];
var containment = options.containment;
if((typeof containment == 'object') &&
(containment.constructor == Array)) {
for(var i=0; i<containment.length; i++)
options._containers.push($(containment[i]));
containment.each( function(c) { options._containers.push($(c)) });
} else {
options._containers.push($(containment));
}
options._containers_length =
options._containers.length-1;
}
Element.makePositioned(element); // fix IE
options.element = element;
// activate the droppable
if(!this.drops) this.drops = [];
this.drops.push(options);
},
is_contained: function(element, drop) {
var containers = drop._containers;
isContained: function(element, drop) {
var parentNode = element.parentNode;
var i = drop._containers_length;
do { if(parentNode==containers[i]) return true; } while (i--);
return false;
return drop._containers.detect(function(c) { return parentNode == c });
},
is_affected: function(pX, pY, element, drop) {
isAffected: function(pX, pY, element, drop) {
return (
(drop.element!=element) &&
((!drop._containers) ||
this.is_contained(element, drop)) &&
this.isContained(element, drop)) &&
((!drop.accept) ||
(Element.Class.has_any(element, drop.accept))) &&
Position.within(drop.element, pX, pY) );
},
deactivate: function(drop) {
Element.Class.remove(drop.element, drop.hoverclass);
if(drop.hoverclass)
Element.Class.remove(drop.element, drop.hoverclass);
this.last_active = null;
},
activate: function(drop) {
if(this.last_active) this.deactivate(this.last_active);
if(drop.hoverclass) {
if(drop.hoverclass)
Element.Class.add(drop.element, drop.hoverclass);
this.last_active = drop;
}
this.last_active = drop;
},
show: function(event, element) {
if(!this.drops) return;
if(!this.drops.length) return;
var pX = Event.pointerX(event);
var pY = Event.pointerY(event);
Position.prepare();
var i = this.drops.length-1; do {
var drop = this.drops[i];
if(this.is_affected(pX, pY, element, drop)) {
if(this.isAffected(pX, pY, element, drop)) {
if(drop.onHover)
drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
if(drop.greedy) {
@ -197,43 +83,41 @@ var Droppables = {
}
}
} while (i--);
if(this.last_active) this.deactivate(this.last_active);
},
fire: function(event, element) {
if(!this.last_active) return;
Position.prepare();
if (this.is_affected(Event.pointerX(event), Event.pointerY(event), element, this.last_active))
if (this.isAffected(Event.pointerX(event), Event.pointerY(event), element, this.last_active))
if (this.last_active.onDrop)
this.last_active.onDrop(element, this.last_active);
this.last_active.onDrop(element, this.last_active.element, event);
},
reset: function() {
if(this.last_active)
this.deactivate(this.last_active);
}
}
Draggables = {
observers: new Array(),
var Draggables = {
observers: [],
addObserver: function(observer) {
this.observers.push(observer);
},
removeObserver: function(element) { // element instead of obsever fixes mem leaks
for(var i = 0; i < this.observers.length; i++)
if(this.observers[i].element && (this.observers[i].element == element))
this.observers.splice(i,1);
this.observers = this.observers.reject( function(o) { return o.element==element });
},
notify: function(eventName, draggable) { // 'onStart', 'onEnd'
for(var i = 0; i < this.observers.length; i++)
this.observers[i][eventName](draggable);
this.observers.invoke(eventName, draggable);
}
}
/*--------------------------------------------------------------------------*/
Draggable = Class.create();
var Draggable = Class.create();
Draggable.prototype = {
initialize: function(element) {
var options = Object.extend({
@ -242,7 +126,8 @@ Draggable.prototype = {
new Effect.Opacity(element, {duration:0.2, from:1.0, to:0.7});
},
reverteffect: function(element, top_offset, left_offset) {
new Effect.MoveBy(element, -top_offset, -left_offset, {duration:0.4});
var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
new Effect.MoveBy(element, -top_offset, -left_offset, {duration:dur});
},
endeffect: function(element) {
new Effect.Opacity(element, {duration:0.2, from:0.7, to:1.0});
@ -250,40 +135,50 @@ Draggable.prototype = {
zindex: 1000,
revert: false
}, arguments[1] || {});
this.element = $(element);
this.handle = options.handle ? $(options.handle) : this.element;
Element.makePositioned(this.element); // fix IE
if(options.handle && (typeof options.handle == 'string'))
this.handle = Element.Class.childrenWith(this.element, options.handle)[0];
if(!this.handle) this.handle = $(options.handle);
if(!this.handle) this.handle = this.element;
Element.makePositioned(this.element); // fix IE
this.offsetX = 0;
this.offsetY = 0;
this.originalLeft = this.currentLeft();
this.originalTop = this.currentTop();
this.originalX = this.element.offsetLeft;
this.originalY = this.element.offsetTop;
this.originalZ = parseInt(this.element.style.zIndex || "0");
this.options = options;
this.active = false;
this.dragging = false;
this.eventMouseDown = this.startDrag.bindAsEventListener(this);
this.eventMouseUp = this.endDrag.bindAsEventListener(this);
this.eventMouseMove = this.update.bindAsEventListener(this);
this.eventKeypress = this.keyPress.bindAsEventListener(this);
Event.observe(this.handle, "mousedown", this.eventMouseDown);
Event.observe(document, "mouseup", this.eventMouseUp);
Event.observe(document, "mousemove", this.eventMouseMove);
Event.observe(document, "keypress", this.eventKeypress);
this.registerEvents();
},
destroy: function() {
Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
Event.stopObserving(document, "mouseup", this.eventMouseUp);
Event.stopObserving(document, "mousemove", this.eventMouseMove);
Event.stopObserving(document, "keypress", this.eventKeypress);
this.unregisterEvents();
},
registerEvents: function() {
Event.observe(document, "mouseup", this.eventMouseUp);
Event.observe(document, "mousemove", this.eventMouseMove);
Event.observe(document, "keypress", this.eventKeypress);
Event.observe(this.handle, "mousedown", this.eventMouseDown);
},
unregisterEvents: function() {
//if(!this.active) return;
//Event.stopObserving(document, "mouseup", this.eventMouseUp);
//Event.stopObserving(document, "mousemove", this.eventMouseMove);
//Event.stopObserving(document, "keypress", this.eventKeypress);
},
currentLeft: function() {
return parseInt(this.element.style.left || '0');
@ -293,27 +188,42 @@ Draggable.prototype = {
},
startDrag: function(event) {
if(Event.isLeftClick(event)) {
// abort on form elements, fixes a Firefox issue
var src = Event.element(event);
if(src.tagName && (
src.tagName=='INPUT' ||
src.tagName=='SELECT' ||
src.tagName=='BUTTON' ||
src.tagName=='TEXTAREA')) return;
// this.registerEvents();
this.active = true;
var style = this.element.style;
this.originalY = this.element.offsetTop - this.currentTop() - this.originalTop;
this.originalX = this.element.offsetLeft - this.currentLeft() - this.originalLeft;
this.offsetY = event.clientY - this.originalY - this.originalTop;
this.offsetX = event.clientX - this.originalX - this.originalLeft;
var pointer = [Event.pointerX(event), Event.pointerY(event)];
var offsets = Position.cumulativeOffset(this.element);
this.offsetX = (pointer[0] - offsets[0]);
this.offsetY = (pointer[1] - offsets[1]);
Event.stop(event);
}
},
finishDrag: function(event, success) {
// this.unregisterEvents();
this.active = false;
this.dragging = false;
if(this.options.ghosting) {
Position.relativize(this.element);
Element.remove(this._clone);
this._clone = null;
}
if(success) Droppables.fire(event, this.element);
Draggables.notify('onEnd', this);
var revert = this.options.revert;
if(revert && typeof revert == 'function') revert = revert(this.element);
if(revert && this.options.reverteffect) {
this.options.reverteffect(this.element,
this.currentTop()-this.originalTop,
@ -322,12 +232,14 @@ Draggable.prototype = {
this.originalLeft = this.currentLeft();
this.originalTop = this.currentTop();
}
this.element.style.zIndex = this.originalZ;
if(this.options.zindex)
this.element.style.zIndex = this.originalZ;
if(this.options.endeffect)
this.options.endeffect(this.element);
Droppables.reset();
},
keyPress: function(event) {
@ -347,13 +259,15 @@ Draggable.prototype = {
this.dragging = false;
},
draw: function(event) {
var pointer = [Event.pointerX(event), Event.pointerY(event)];
var offsets = Position.cumulativeOffset(this.element);
offsets[0] -= this.currentLeft();
offsets[1] -= this.currentTop();
var style = this.element.style;
this.originalX = this.element.offsetLeft - this.currentLeft() - this.originalLeft;
this.originalY = this.element.offsetTop - this.currentTop() - this.originalTop;
if((!this.options.constraint) || (this.options.constraint=='horizontal'))
style.left = ((event.clientX - this.originalX) - this.offsetX) + "px";
style.left = (pointer[0] - offsets[0] - this.offsetX) + "px";
if((!this.options.constraint) || (this.options.constraint=='vertical'))
style.top = ((event.clientY - this.originalY) - this.offsetY) + "px";
style.top = (pointer[1] - offsets[1] - this.offsetY) + "px";
if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
},
update: function(event) {
@ -361,19 +275,32 @@ Draggable.prototype = {
if(!this.dragging) {
var style = this.element.style;
this.dragging = true;
if(style.position=="") style.position = "relative";
style.zIndex = this.options.zindex;
if(Element.getStyle(this.element,'position')=='')
style.position = "relative";
if(this.options.zindex) {
this.options.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
style.zIndex = this.options.zindex;
}
if(this.options.ghosting) {
this._clone = this.element.cloneNode(true);
Position.absolutize(this.element);
this.element.parentNode.insertBefore(this._clone, this.element);
}
Draggables.notify('onStart', this);
if(this.options.starteffect) this.options.starteffect(this.element);
}
Droppables.show(event, this.element);
this.draw(event);
if(this.options.change) this.options.change(this);
// fix AppleWebKit rendering
if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
Event.stop(event);
}
}
@ -381,7 +308,7 @@ Draggable.prototype = {
/*--------------------------------------------------------------------------*/
SortableObserver = Class.create();
var SortableObserver = Class.create();
SortableObserver.prototype = {
initialize: function(element, observer) {
this.element = $(element);
@ -391,147 +318,199 @@ SortableObserver.prototype = {
onStart: function() {
this.lastValue = Sortable.serialize(this.element);
},
onEnd: function() {
onEnd: function() {
Sortable.unmark();
if(this.lastValue != Sortable.serialize(this.element))
this.observer(this.element)
}
}
Sortable = {
var Sortable = {
sortables: new Array(),
options: function(element){
var element = $(element);
for(var i=0;i<this.sortables.length;i++)
if(this.sortables[i].element == element)
return this.sortables[i];
return null;
element = $(element);
return this.sortables.detect(function(s) { return s.element == element });
},
destroy: function(element){
var element = $(element);
for(var i=0;i<this.sortables.length;i++) {
if(this.sortables[i].element == element) {
var s = this.sortables[i];
Draggables.removeObserver(s.element);
for(var j=0;j<s.droppables.length;j++)
Droppables.remove(s.droppables[j]);
for(var j=0;j<s.draggables.length;j++)
s.draggables[j].destroy();
this.sortables.splice(i,1);
}
}
element = $(element);
this.sortables.findAll(function(s) { return s.element == element }).each(function(s){
Draggables.removeObserver(s.element);
s.droppables.each(function(d){ Droppables.remove(d) });
s.draggables.invoke('destroy');
});
this.sortables = this.sortables.reject(function(s) { return s.element == element });
},
create: function(element) {
var element = $(element);
element = $(element);
var options = Object.extend({
element: element,
tag: 'li', // assumes li children, override with tag: 'tagname'
dropOnEmpty: false,
tree: false, // fixme: unimplemented
overlap: 'vertical', // one of 'vertical', 'horizontal'
constraint: 'vertical', // one of 'vertical', 'horizontal', false
containment: element, // also takes array of elements (or id's); or false
handle: false, // or a CSS class
only: false,
hoverclass: null,
ghosting: false,
format: null,
onChange: function() {},
onUpdate: function() {}
}, arguments[1] || {});
// clear any old sortable with same element
this.destroy(element);
// build options for the draggables
var options_for_draggable = {
revert: true,
ghosting: options.ghosting,
constraint: options.constraint,
handle: handle };
handle: options.handle };
if(options.starteffect)
options_for_draggable.starteffect = options.starteffect;
if(options.reverteffect)
options_for_draggable.reverteffect = options.reverteffect;
else
if(options.ghosting) options_for_draggable.reverteffect = function(element) {
element.style.top = 0;
element.style.left = 0;
};
if(options.endeffect)
options_for_draggable.endeffect = options.endeffect;
if(options.zindex)
options_for_draggable.zindex = options.zindex;
// build options for the droppables
var options_for_droppable = {
overlap: options.overlap,
containment: options.containment,
hoverclass: options.hoverclass,
onHover: function(element, dropon, overlap) {
if(overlap>0.5) {
if(dropon.previousSibling != element) {
var oldParentNode = element.parentNode;
element.style.visibility = "hidden"; // fix gecko rendering
dropon.parentNode.insertBefore(element, dropon);
if(dropon.parentNode!=oldParentNode && oldParentNode.sortable)
oldParentNode.sortable.onChange(element);
if(dropon.parentNode.sortable)
dropon.parentNode.sortable.onChange(element);
}
} else {
var nextElement = dropon.nextSibling || null;
if(nextElement != element) {
var oldParentNode = element.parentNode;
element.style.visibility = "hidden"; // fix gecko rendering
dropon.parentNode.insertBefore(element, nextElement);
if(dropon.parentNode!=oldParentNode && oldParentNode.sortable)
oldParentNode.sortable.onChange(element);
if(dropon.parentNode.sortable)
dropon.parentNode.sortable.onChange(element);
}
}
}
onHover: Sortable.onHover,
greedy: !options.dropOnEmpty
}
// fix for gecko engine
Element.cleanWhitespace(element);
options.draggables = [];
options.droppables = [];
// make it so
var elements = element.childNodes;
for (var i = 0; i < elements.length; i++)
if(elements[i].tagName && elements[i].tagName==options.tag.toUpperCase() &&
(!options.only || (Element.Class.has(elements[i], options.only)))) {
// handles are per-draggable
var handle = options.handle ?
Element.Class.childrenWith(elements[i], options.handle)[0] : elements[i];
options.draggables.push(new Draggable(elements[i], Object.extend(options_for_draggable, { handle: handle })));
Droppables.add(elements[i], options_for_droppable);
options.droppables.push(elements[i]);
}
// make it so
// drop on empty handling
if(options.dropOnEmpty) {
Droppables.add(element,
{containment: options.containment, onHover: Sortable.onEmptyHover, greedy: false});
options.droppables.push(element);
}
(this.findElements(element, options) || []).each( function(e) {
// handles are per-draggable
var handle = options.handle ?
Element.Class.childrenWith(e, options.handle)[0] : e;
options.draggables.push(
new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
Droppables.add(e, options_for_droppable);
options.droppables.push(e);
});
// keep reference
this.sortables.push(options);
// for onupdate
Draggables.addObserver(new SortableObserver(element, options.onUpdate));
},
// return all suitable-for-sortable elements in a guaranteed order
findElements: function(element, options) {
if(!element.hasChildNodes()) return null;
var elements = [];
$A(element.childNodes).each( function(e) {
if(e.tagName && e.tagName==options.tag.toUpperCase() &&
(!options.only || (Element.Class.has(e, options.only))))
elements.push(e);
if(options.tree) {
var grandchildren = this.findElements(e, options);
if(grandchildren) elements.push(grandchildren);
}
});
return (elements.length>0 ? elements.flatten() : null);
},
onHover: function(element, dropon, overlap) {
if(overlap>0.5) {
Sortable.mark(dropon, 'before');
if(dropon.previousSibling != element) {
var oldParentNode = element.parentNode;
element.style.visibility = "hidden"; // fix gecko rendering
dropon.parentNode.insertBefore(element, dropon);
if(dropon.parentNode!=oldParentNode)
Sortable.options(oldParentNode).onChange(element);
Sortable.options(dropon.parentNode).onChange(element);
}
} else {
Sortable.mark(dropon, 'after');
var nextElement = dropon.nextSibling || null;
if(nextElement != element) {
var oldParentNode = element.parentNode;
element.style.visibility = "hidden"; // fix gecko rendering
dropon.parentNode.insertBefore(element, nextElement);
if(dropon.parentNode!=oldParentNode)
Sortable.options(oldParentNode).onChange(element);
Sortable.options(dropon.parentNode).onChange(element);
}
}
},
onEmptyHover: function(element, dropon) {
if(element.parentNode!=dropon) {
dropon.appendChild(element);
}
},
unmark: function() {
if(Sortable._marker) Element.hide(Sortable._marker);
},
mark: function(dropon, position) {
// mark on ghosting only
var sortable = Sortable.options(dropon.parentNode);
if(sortable && !sortable.ghosting) return;
if(!Sortable._marker) {
Sortable._marker = $('dropmarker') || document.createElement('DIV');
Element.hide(Sortable._marker);
Element.Class.add(Sortable._marker, 'dropmarker');
Sortable._marker.style.position = 'absolute';
document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
}
var offsets = Position.cumulativeOffset(dropon);
Sortable._marker.style.top = offsets[1] + 'px';
if(position=='after') Sortable._marker.style.top = (offsets[1]+dropon.clientHeight) + 'px';
Sortable._marker.style.left = offsets[0] + 'px';
Element.show(Sortable._marker);
},
serialize: function(element) {
var element = $(element);
element = $(element);
var sortableOptions = this.options(element);
var options = Object.extend({
tag: sortableOptions.tag,
only: sortableOptions.only,
name: element.id
name: element.id,
format: sortableOptions.format || /^[^_]*_(.*)$/
}, arguments[1] || {});
var items = $(element).childNodes;
var queryComponents = new Array();
for(var i=0; i<items.length; i++)
if(items[i].tagName && items[i].tagName==options.tag.toUpperCase() &&
(!options.only || (Element.Class.has(items[i], options.only))))
queryComponents.push(
encodeURIComponent(options.name) + "[]=" +
encodeURIComponent(items[i].id.split("_")[1]));
return queryComponents.join("&");
return $(this.findElements(element, options) || []).collect( function(item) {
return (encodeURIComponent(options.name) + "[]=" +
encodeURIComponent(item.id.match(options.format) ? item.id.match(options.format)[1] : ''));
}).join("&");
}
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,47 @@
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
var Scriptaculous = {
Version: '1.5_rc3',
require: function(libraryName) {
// inserting via DOM fails in Safari 2.0, so brute force approach
document.write('<script type="text/javascript" src="'+libraryName+'"></script>');
},
load: function() {
if((typeof Prototype=='undefined') ||
parseFloat(Prototype.Version.split(".")[0] + "." +
Prototype.Version.split(".")[1]) < 1.4)
throw("script.aculo.us requires the Prototype JavaScript framework >= 1.4.0");
var scriptTags = document.getElementsByTagName("script");
for(var i=0;i<scriptTags.length;i++) {
if(scriptTags[i].src && scriptTags[i].src.match(/scriptaculous\.js(\?.*)?$/)) {
var path = scriptTags[i].src.replace(/scriptaculous\.js(\?.*)?$/,'');
this.require(path + 'effects.js');
this.require(path + 'dragdrop.js');
this.require(path + 'controls.js');
this.require(path + 'slider.js');
break;
}
}
}
}
Scriptaculous.load();

View file

@ -0,0 +1,258 @@
// Copyright (c) 2005 Marty Haught
//
// See scriptaculous.js for full license.
if(!Control) var Control = {};
Control.Slider = Class.create();
// options:
// axis: 'vertical', or 'horizontal' (default)
// increment: (default: 1)
// step: (default: 1)
//
// callbacks:
// onChange(value)
// onSlide(value)
Control.Slider.prototype = {
initialize: function(handle, track, options) {
this.handle = $(handle);
this.track = $(track);
this.options = options || {};
this.axis = this.options.axis || 'horizontal';
this.increment = this.options.increment || 1;
this.step = parseInt(this.options.step) || 1;
this.value = 0;
var defaultMaximum = Math.round(this.track.offsetWidth / this.increment);
if(this.isVertical()) defaultMaximum = Math.round(this.track.offsetHeight / this.increment);
this.maximum = this.options.maximum || defaultMaximum;
this.minimum = this.options.minimum || 0;
// Will be used to align the handle onto the track, if necessary
this.alignX = parseInt (this.options.alignX) || 0;
this.alignY = parseInt (this.options.alignY) || 0;
// Zero out the slider position
this.setCurrentLeft(Position.cumulativeOffset(this.track)[0] - Position.cumulativeOffset(this.handle)[0] + this.alignX);
this.setCurrentTop(this.trackTop() - Position.cumulativeOffset(this.handle)[1] + this.alignY);
this.offsetX = 0;
this.offsetY = 0;
this.originalLeft = this.currentLeft();
this.originalTop = this.currentTop();
this.originalZ = parseInt(this.handle.style.zIndex || "0");
// Prepopulate Slider value
this.setSliderValue(parseInt(this.options.sliderValue) || 0);
this.active = false;
this.dragging = false;
this.disabled = false;
// FIXME: use css
this.handleImage = $(this.options.handleImage) || false;
this.handleDisabled = this.options.handleDisabled || false;
this.handleEnabled = false;
if(this.handleImage)
this.handleEnabled = this.handleImage.src || false;
if(this.options.disabled)
this.setDisabled();
// Value Array
this.values = this.options.values || false; // Add method to validate and sort??
Element.makePositioned(this.handle); // fix IE
this.eventMouseDown = this.startDrag.bindAsEventListener(this);
this.eventMouseUp = this.endDrag.bindAsEventListener(this);
this.eventMouseMove = this.update.bindAsEventListener(this);
this.eventKeypress = this.keyPress.bindAsEventListener(this);
Event.observe(this.handle, "mousedown", this.eventMouseDown);
Event.observe(document, "mouseup", this.eventMouseUp);
Event.observe(document, "mousemove", this.eventMouseMove);
Event.observe(document, "keypress", this.eventKeypress);
},
dispose: function() {
Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
Event.stopObserving(document, "mouseup", this.eventMouseUp);
Event.stopObserving(document, "mousemove", this.eventMouseMove);
Event.stopObserving(document, "keypress", this.eventKeypress);
},
setDisabled: function(){
this.disabled = true;
if(this.handleDisabled)
this.handleImage.src = this.handleDisabled;
},
setEnabled: function(){
this.disabled = false;
if(this.handleEnabled)
this.handleImage.src = this.handleEnabled;
},
currentLeft: function() {
return parseInt(this.handle.style.left || '0');
},
currentTop: function() {
return parseInt(this.handle.style.top || '0');
},
setCurrentLeft: function(left) {
this.handle.style.left = left +"px";
},
setCurrentTop: function(top) {
this.handle.style.top = top +"px";
},
trackLeft: function(){
return Position.cumulativeOffset(this.track)[0];
},
trackTop: function(){
return Position.cumulativeOffset(this.track)[1];
},
getNearestValue: function(value){
if(this.values){
var i = 0;
var offset = Math.abs(this.values[0] - value);
var newValue = this.values[0];
for(i=0; i < this.values.length; i++){
var currentOffset = Math.abs(this.values[i] - value);
if(currentOffset < offset){
newValue = this.values[i];
offset = currentOffset;
}
}
return newValue;
}
return value;
},
setSliderValue: function(sliderValue){
// First check our max and minimum and nearest values
sliderValue = this.getNearestValue(sliderValue);
if(sliderValue > this.maximum) sliderValue = this.maximum;
if(sliderValue < this.minimum) sliderValue = this.minimum;
var offsetDiff = (sliderValue - (this.value||this.minimum)) * this.increment;
if(this.isVertical()){
this.setCurrentTop(offsetDiff + this.currentTop());
} else {
this.setCurrentLeft(offsetDiff + this.currentLeft());
}
this.value = sliderValue;
this.updateFinished();
},
minimumOffset: function(){
return(this.isVertical() ?
this.trackTop() + this.alignY :
this.trackLeft() + this.alignX);
},
maximumOffset: function(){
return(this.isVertical() ?
this.trackTop() + this.alignY + (this.maximum - this.minimum) * this.increment :
this.trackLeft() + this.alignX + (this.maximum - this.minimum) * this.increment);
},
isVertical: function(){
return (this.axis == 'vertical');
},
startDrag: function(event) {
if(Event.isLeftClick(event)) {
if(!this.disabled){
this.active = true;
var pointer = [Event.pointerX(event), Event.pointerY(event)];
var offsets = Position.cumulativeOffset(this.handle);
this.offsetX = (pointer[0] - offsets[0]);
this.offsetY = (pointer[1] - offsets[1]);
this.originalLeft = this.currentLeft();
this.originalTop = this.currentTop();
}
Event.stop(event);
}
},
update: function(event) {
if(this.active) {
if(!this.dragging) {
var style = this.handle.style;
this.dragging = true;
if(style.position=="") style.position = "relative";
style.zIndex = this.options.zindex;
}
this.draw(event);
// fix AppleWebKit rendering
if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
Event.stop(event);
}
},
draw: function(event) {
var pointer = [Event.pointerX(event), Event.pointerY(event)];
var offsets = Position.cumulativeOffset(this.handle);
offsets[0] -= this.currentLeft();
offsets[1] -= this.currentTop();
// Adjust for the pointer's position on the handle
pointer[0] -= this.offsetX;
pointer[1] -= this.offsetY;
var style = this.handle.style;
if(this.isVertical()){
if(pointer[1] > this.maximumOffset())
pointer[1] = this.maximumOffset();
if(pointer[1] < this.minimumOffset())
pointer[1] = this.minimumOffset();
// Increment by values
if(this.values){
this.value = this.getNearestValue(Math.round((pointer[1] - this.minimumOffset()) / this.increment) + this.minimum);
pointer[1] = this.trackTop() + this.alignY + (this.value - this.minimum) * this.increment;
} else {
this.value = Math.round((pointer[1] - this.minimumOffset()) / this.increment) + this.minimum;
}
style.top = pointer[1] - offsets[1] + "px";
} else {
if(pointer[0] > this.maximumOffset()) pointer[0] = this.maximumOffset();
if(pointer[0] < this.minimumOffset()) pointer[0] = this.minimumOffset();
// Increment by values
if(this.values){
this.value = this.getNearestValue(Math.round((pointer[0] - this.minimumOffset()) / this.increment) + this.minimum);
pointer[0] = this.trackLeft() + this.alignX + (this.value - this.minimum) * this.increment;
} else {
this.value = Math.round((pointer[0] - this.minimumOffset()) / this.increment) + this.minimum;
}
style.left = (pointer[0] - offsets[0]) + "px";
}
if(this.options.onSlide) this.options.onSlide(this.value);
},
endDrag: function(event) {
if(this.active && this.dragging) {
this.finishDrag(event, true);
Event.stop(event);
}
this.active = false;
this.dragging = false;
},
finishDrag: function(event, success) {
this.active = false;
this.dragging = false;
this.handle.style.zIndex = this.originalZ;
this.originalLeft = this.currentLeft();
this.originalTop = this.currentTop();
this.updateFinished();
},
updateFinished: function() {
if(this.options.onChange) this.options.onChange(this.value);
},
keyPress: function(event) {
if(this.active && !this.disabled) {
switch(event.keyCode) {
case Event.KEY_ESC:
this.finishDrag(event, false);
Event.stop(event);
break;
}
if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
}
}
}

1
tracks/public/robots.txt Normal file
View file

@ -0,0 +1 @@
# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file

View file

@ -1,4 +1,3 @@
#!/usr/bin/env ruby
require 'rubygems'
require_gem 'rails'
require 'breakpoint_client'
#!/usr/bin/ruby
require File.dirname(__FILE__) + '/../config/boot'
require 'commands/breakpointer'

View file

@ -1,23 +1,3 @@
#!/usr/bin/env ruby
irb = RUBY_PLATFORM =~ /mswin32/ ? 'irb.bat' : 'irb'
require 'optparse'
options = { :sandbox => false, :irb => irb }
OptionParser.new do |opt|
opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |options[:sandbox]| }
opt.on("--irb=[#{irb}]", 'Invoke a different irb.') { |options[:irb]| }
opt.parse!(ARGV)
end
libs = " -r irb/completion"
libs << " -r #{File.dirname(__FILE__)}/../config/environment"
libs << " -r console_sandbox" if options[:sandbox]
ENV['RAILS_ENV'] = ARGV.first || 'development'
if options[:sandbox]
puts "Loading #{ENV['RAILS_ENV']} environment in sandbox."
puts "Any modifications you make will be rolled back on exit."
else
puts "Loading #{ENV['RAILS_ENV']} environment."
end
exec "#{options[:irb]} #{libs} --prompt-mode simple"
#!/usr/bin/ruby
require File.dirname(__FILE__) + '/../config/boot'
require 'commands/console'

View file

@ -1,7 +1,3 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../config/environment'
require 'rails_generator'
require 'rails_generator/scripts/destroy'
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
Rails::Generator::Scripts::Destroy.new.run(ARGV)
#!/usr/bin/ruby
require File.dirname(__FILE__) + '/../config/boot'
require 'commands/destroy'

View file

@ -1,7 +1,3 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../config/environment'
require 'rails_generator'
require 'rails_generator/scripts/generate'
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
Rails::Generator::Scripts::Generate.new.run(ARGV)
#!/usr/bin/ruby
require File.dirname(__FILE__) + '/../config/boot'
require 'commands/generate'

View file

@ -0,0 +1,3 @@
#!/usr/bin/ruby
require File.dirname(__FILE__) + '/../../config/boot'
require 'commands/performance/benchmarker'

View file

@ -0,0 +1,3 @@
#!/usr/bin/ruby
require File.dirname(__FILE__) + '/../../config/boot'
require 'commands/performance/profiler'

3
tracks/script/process/reaper Executable file
View file

@ -0,0 +1,3 @@
#!/usr/bin/ruby
require File.dirname(__FILE__) + '/../../config/boot'
require 'commands/process/reaper'

3
tracks/script/process/spawner Executable file
View file

@ -0,0 +1,3 @@
#!/usr/bin/ruby
require File.dirname(__FILE__) + '/../../config/boot'
require 'commands/process/spawner'

3
tracks/script/process/spinner Executable file
View file

@ -0,0 +1,3 @@
#!/usr/bin/ruby
require File.dirname(__FILE__) + '/../../config/boot'
require 'commands/process/spinner'

View file

@ -1,29 +1,3 @@
#!/usr/bin/env ruby
require 'optparse'
options = { :environment => "development" }
ARGV.options do |opts|
script_name = File.basename($0)
opts.banner = "Usage: runner 'puts Person.find(1).name' [options]"
opts.separator ""
opts.on("-e", "--environment=name", String,
"Specifies the environment for the runner to operate under (test/development/production).",
"Default: development") { |options[:environment]| }
opts.separator ""
opts.on("-h", "--help",
"Show this help message.") { puts opts; exit }
opts.parse!
end
ENV["RAILS_ENV"] = options[:environment]
#!/usr/local/bin/ruby
require File.dirname(__FILE__) + '/../config/environment'
eval(ARGV.first)
#!/usr/bin/ruby
require File.dirname(__FILE__) + '/../config/boot'
require 'commands/runner'

View file

@ -1,49 +1,3 @@
#!/usr/bin/env ruby
require 'webrick'
require 'optparse'
OPTIONS = {
:port => 3000,
:ip => "0.0.0.0",
:environment => "development",
:server_root => File.expand_path(File.dirname(__FILE__) + "/../public/"),
:server_type => WEBrick::SimpleServer
}
ARGV.options do |opts|
script_name = File.basename($0)
opts.banner = "Usage: ruby #{script_name} [options]"
opts.separator ""
opts.on("-p", "--port=port", Integer,
"Runs Rails on the specified port.",
"Default: 3000") { |OPTIONS[:port]| }
opts.on("-b", "--binding=ip", String,
"Binds Rails to the specified ip.",
"Default: 0.0.0.0") { |OPTIONS[:ip]| }
opts.on("-e", "--environment=name", String,
"Specifies the environment to run this server under (test/development/production).",
"Default: development") { |OPTIONS[:environment]| }
opts.on("-d", "--daemon",
"Make Rails run as a Daemon (only works if fork is available -- meaning on *nix)."
) { OPTIONS[:server_type] = WEBrick::Daemon }
opts.separator ""
opts.on("-h", "--help",
"Show this help message.") { puts opts; exit }
opts.parse!
end
ENV["RAILS_ENV"] = OPTIONS[:environment]
require File.dirname(__FILE__) + "/../config/environment"
require 'webrick_server'
OPTIONS['working_directory'] = File.expand_path(RAILS_ROOT)
puts "=> Rails application started on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}"
puts "=> Ctrl-C to shutdown server; call with --help for options" if OPTIONS[:server_type] == WEBrick::SimpleServer
DispatchServlet.dispatch(OPTIONS)
#!/usr/bin/ruby
require File.dirname(__FILE__) + '/../config/boot'
require 'commands/server'

View file

@ -1,27 +1,15 @@
ENV["RAILS_ENV"] = "test"
# Expand the path to environment so that Ruby does not load it multiple times
# File.expand_path can be removed if Ruby 1.9 is in use.
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
require 'application'
require 'test/unit'
require 'active_record/fixtures'
require 'action_controller/test_process'
require 'action_web_service/test_invoke'
require 'breakpoint'
Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
require 'test_help'
class Test::Unit::TestCase
# Turn these on to use transactional fixtures with table_name(:fixture_name) instantiation of fixtures
# self.use_transactional_fixtures = true
# self.use_instantiated_fixtures = false
def create_fixtures(*table_names)
Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures", table_names)
end
# Turn off transactional fixtures if you're working with MyISAM tables in MySQL
self.use_transactional_fixtures = true
# Instantiated fixtures are slow, but give you @david where you otherwise would need people(:david)
self.use_instantiated_fixtures = false
# Add more helper methods to be used by all tests here...
# Logs in a user and returns the user object found in the session object
#
def login(login,password)
@ -43,5 +31,4 @@ class Test::Unit::TestCase
end
return string
end
end