Commit d4faecd1b9164c86146c2a5ea235c2540ceeab46

Authored by Antonio Terceiro
1 parent 509aeab0

rails3: development + packaging updates

Some specific points:

- ./script/quick-start not works from start to end on a clean Debian
  wheezy system
- Gemfile: remove checking for programs since the Gemfile is not really
  the right place to do this
- Gemfile.lock: lock gem versions against Debian wheezy.  This assumes
  package versions in Debian wheezy + some backported packages available
  at http://people.debian.org/~terceiro/noosfero-wheezy-backports/
- db:data:minimal: add an explicit contact email to the new environment.
  This fixes a long standing issue: when installing Noosfero on a brand
  new system, exim MTA will choke on a malformed sender address, and
  abort the entire installation.
- added a simple Vagrantfile for development purposes

Pending:

- provide proper backports for packages and drop the temporary
  http://people.debian.org/~terceiro/noosfero-wheezy-backports/
@@ -3,11 +3,18 @@ gem 'rails' @@ -3,11 +3,18 @@ gem 'rails'
3 gem 'fast_gettext' 3 gem 'fast_gettext'
4 gem 'acts-as-taggable-on' 4 gem 'acts-as-taggable-on'
5 gem 'prototype-rails' 5 gem 'prototype-rails'
6 -gem 'prototype_legacy_helper', '0.0.0', :git => 'http://git.github.com/rails/prototype_legacy_helper.git' 6 +gem 'prototype_legacy_helper', '0.0.0', :path => 'vendor/prototype_legacy_helper'
7 gem 'rails_autolink' 7 gem 'rails_autolink'
8 gem 'pg' 8 gem 'pg'
9 -  
10 -# TODO needs a rebuild diff-lcs wrt wheezy 9 +gem 'rmagick'
  10 +gem 'RedCloth'
  11 +gem 'will_paginate'
  12 +gem 'ruby-feedparser'
  13 +gem 'daemons'
  14 +gem 'thin'
  15 +gem 'hpricot'
  16 +gem 'nokogiri'
  17 +gem 'rake', :require => false
11 18
12 # FIXME list here all actual dependencies (i.e. the ones in debian/control), 19 # FIXME list here all actual dependencies (i.e. the ones in debian/control),
13 # with their GEM names (not the Debian package names) 20 # with their GEM names (not the Debian package names)
@@ -35,12 +42,3 @@ Dir.glob(File.join('config', 'plugins', '*')).each do |plugin| @@ -35,12 +42,3 @@ Dir.glob(File.join('config', 'plugins', '*')).each do |plugin|
35 plugin_gemfile = File.join(plugin, 'Gemfile') 42 plugin_gemfile = File.join(plugin, 'Gemfile')
36 eval File.read(plugin_gemfile) if File.exists?(plugin_gemfile) 43 eval File.read(plugin_gemfile) if File.exists?(plugin_gemfile)
37 end 44 end
38 -  
39 -def program(name)  
40 - unless system("which #{name} > /dev/null")  
41 - puts "W: Program #{name} is needed, but was not found in your PATH"  
42 - end  
43 -end  
44 -  
45 -program 'java'  
46 -program 'firefox'  
1 -GIT  
2 - remote: http://git.github.com/rails/prototype_legacy_helper.git  
3 - revision: a2cd95c3e3c1a4f7a9566efdab5ce59c886cb05f 1 +PATH
  2 + remote: vendor/prototype_legacy_helper
4 specs: 3 specs:
5 prototype_legacy_helper (0.0.0) 4 prototype_legacy_helper (0.0.0)
6 5
7 GEM 6 GEM
8 remote: https://rubygems.org/ 7 remote: https://rubygems.org/
9 specs: 8 specs:
  9 + RedCloth (4.2.9)
10 actionmailer (3.2.6) 10 actionmailer (3.2.6)
11 actionpack (= 3.2.6) 11 actionpack (= 3.2.6)
12 mail (~> 2.4.4) 12 mail (~> 2.4.4)
@@ -34,49 +34,51 @@ GEM @@ -34,49 +34,51 @@ GEM
34 activesupport (3.2.6) 34 activesupport (3.2.6)
35 i18n (~> 0.6) 35 i18n (~> 0.6)
36 multi_json (~> 1.0) 36 multi_json (~> 1.0)
37 - acts-as-taggable-on (3.0.1) 37 + acts-as-taggable-on (3.0.2)
38 rails (>= 3, < 5) 38 rails (>= 3, < 5)
39 arel (3.0.2) 39 arel (3.0.2)
40 builder (3.0.0) 40 builder (3.0.0)
41 - capybara (2.2.1) 41 + capybara (2.1.0)
42 mime-types (>= 1.16) 42 mime-types (>= 1.16)
43 nokogiri (>= 1.3.3) 43 nokogiri (>= 1.3.3)
44 rack (>= 1.0.0) 44 rack (>= 1.0.0)
45 rack-test (>= 0.5.4) 45 rack-test (>= 0.5.4)
46 xpath (~> 2.0) 46 xpath (~> 2.0)
47 - childprocess (0.4.0)  
48 - ffi (~> 1.0, >= 1.0.11)  
49 - cucumber (1.3.2) 47 + childprocess (0.3.3)
  48 + ffi (~> 1.0.6)
  49 + cucumber (1.0.6)
50 builder (>= 2.1.2) 50 builder (>= 2.1.2)
51 - diff-lcs (>= 1.1.3)  
52 - gherkin (~> 2.12.0)  
53 - multi_json (~> 1.3)  
54 - cucumber-rails (1.4.0)  
55 - capybara (>= 1.1.2)  
56 - cucumber (>= 1.2.0) 51 + diff-lcs (>= 1.1.2)
  52 + gherkin (~> 2.4.18)
  53 + json (>= 1.4.6)
  54 + term-ansicolor (>= 1.0.6)
  55 + cucumber-rails (1.0.6)
  56 + capybara (>= 1.1.1)
  57 + cucumber (>= 1.0.6)
57 nokogiri (>= 1.5.0) 58 nokogiri (>= 1.5.0)
58 - rails (>= 3.0.0) 59 + daemons (1.1.5)
59 dalli (2.7.0) 60 dalli (2.7.0)
60 database_cleaner (1.2.0) 61 database_cleaner (1.2.0)
61 - diff-lcs (1.2.5) 62 + diff-lcs (1.1.3)
62 erubis (2.7.0) 63 erubis (2.7.0)
  64 + eventmachine (0.12.11)
63 fast_gettext (0.6.8) 65 fast_gettext (0.6.8)
64 - ffi (1.9.3)  
65 - gherkin (2.12.2)  
66 - multi_json (~> 1.3) 66 + ffi (1.0.11)
  67 + gherkin (2.4.21)
  68 + json (>= 1.4.6)
67 hike (1.2.1) 69 hike (1.2.1)
  70 + hpricot (0.8.6)
68 i18n (0.6.0) 71 i18n (0.6.0)
69 journey (1.0.3) 72 journey (1.0.3)
  73 + json (1.7.3)
70 mail (2.4.4) 74 mail (2.4.4)
71 i18n (>= 0.4.0) 75 i18n (>= 0.4.0)
72 mime-types (~> 1.16) 76 mime-types (~> 1.16)
73 treetop (~> 1.4.8) 77 treetop (~> 1.4.8)
74 mime-types (1.19) 78 mime-types (1.19)
75 - mini_portile (0.5.2)  
76 multi_json (1.3.6) 79 multi_json (1.3.6)
77 - nokogiri (1.6.1)  
78 - mini_portile (~> 0.5.0)  
79 - pg (0.17.1) 80 + nokogiri (1.5.5)
  81 + pg (0.13.2)
80 polyglot (0.3.3) 82 polyglot (0.3.3)
81 prototype-rails (3.2.1) 83 prototype-rails (3.2.1)
82 rails (~> 3.2) 84 rails (~> 3.2)
@@ -106,23 +108,22 @@ GEM @@ -106,23 +108,22 @@ GEM
106 thor (>= 0.14.6, < 2.0) 108 thor (>= 0.14.6, < 2.0)
107 rake (0.9.2.2) 109 rake (0.9.2.2)
108 rdoc (3.9.4) 110 rdoc (3.9.4)
109 - rspec (2.14.1)  
110 - rspec-core (~> 2.14.0)  
111 - rspec-expectations (~> 2.14.0)  
112 - rspec-mocks (~> 2.14.0)  
113 - rspec-core (2.14.7)  
114 - rspec-expectations (2.14.5)  
115 - diff-lcs (>= 1.1.3, < 2.0)  
116 - rspec-mocks (2.14.5)  
117 - rspec-rails (2.14.1) 111 + rmagick (2.13.1)
  112 + rspec (2.10.0)
  113 + rspec-core (~> 2.10.0)
  114 + rspec-expectations (~> 2.10.0)
  115 + rspec-mocks (~> 2.10.0)
  116 + rspec-core (2.10.1)
  117 + rspec-expectations (2.10.0)
  118 + diff-lcs (~> 1.1.3)
  119 + rspec-mocks (2.10.1)
  120 + rspec-rails (2.10.1)
118 actionpack (>= 3.0) 121 actionpack (>= 3.0)
119 - activemodel (>= 3.0)  
120 activesupport (>= 3.0) 122 activesupport (>= 3.0)
121 railties (>= 3.0) 123 railties (>= 3.0)
122 - rspec-core (~> 2.14.0)  
123 - rspec-expectations (~> 2.14.0)  
124 - rspec-mocks (~> 2.14.0)  
125 - rubyzip (1.1.0) 124 + rspec (~> 2.10.0)
  125 + ruby-feedparser (0.7)
  126 + rubyzip (1.1.2)
126 selenium-webdriver (2.39.0) 127 selenium-webdriver (2.39.0)
127 childprocess (>= 0.2.5) 128 childprocess (>= 0.2.5)
128 multi_json (~> 1.0) 129 multi_json (~> 1.0)
@@ -133,6 +134,11 @@ GEM @@ -133,6 +134,11 @@ GEM
133 multi_json (~> 1.0) 134 multi_json (~> 1.0)
134 rack (~> 1.0) 135 rack (~> 1.0)
135 tilt (~> 1.1, != 1.3.0) 136 tilt (~> 1.1, != 1.3.0)
  137 + term-ansicolor (1.0.7)
  138 + thin (1.3.1)
  139 + daemons (>= 1.0.9)
  140 + eventmachine (>= 0.12.6)
  141 + rack (>= 1.0.0)
136 thor (0.15.3) 142 thor (0.15.3)
137 tilt (1.3.3) 143 tilt (1.3.3)
138 treetop (1.4.10) 144 treetop (1.4.10)
@@ -140,6 +146,7 @@ GEM @@ -140,6 +146,7 @@ GEM
140 polyglot (>= 0.3.1) 146 polyglot (>= 0.3.1)
141 tzinfo (0.3.33) 147 tzinfo (0.3.33)
142 websocket (1.0.7) 148 websocket (1.0.7)
  149 + will_paginate (3.0.3)
143 xpath (2.0.0) 150 xpath (2.0.0)
144 nokogiri (~> 1.3) 151 nokogiri (~> 1.3)
145 152
@@ -147,19 +154,27 @@ PLATFORMS @@ -147,19 +154,27 @@ PLATFORMS
147 ruby 154 ruby
148 155
149 DEPENDENCIES 156 DEPENDENCIES
  157 + RedCloth
150 acts-as-taggable-on 158 acts-as-taggable-on
151 capybara 159 capybara
152 cucumber 160 cucumber
153 cucumber-rails 161 cucumber-rails
  162 + daemons
154 dalli 163 dalli
155 database_cleaner 164 database_cleaner
156 fast_gettext 165 fast_gettext
  166 + hpricot
  167 + nokogiri
157 pg 168 pg
158 prototype-rails 169 prototype-rails
159 prototype_legacy_helper (= 0.0.0)! 170 prototype_legacy_helper (= 0.0.0)!
160 rails 171 rails
161 rails_autolink 172 rails_autolink
162 rake 173 rake
  174 + rmagick
163 rspec 175 rspec
164 rspec-rails 176 rspec-rails
  177 + ruby-feedparser
165 selenium-webdriver 178 selenium-webdriver
  179 + thin
  180 + will_paginate
Vagrantfile 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +# -*- mode: ruby -*-
  2 +# vi: set ft=ruby :
  3 +
  4 +VAGRANTFILE_API_VERSION = "2"
  5 +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  6 + config.vm.box = "debian-wheezy"
  7 + config.vm.network :forwarded_port, host: 3000, guest: 3000
  8 + config.vm.provision :shell do |shell|
  9 + shell.inline = 'su vagrant -c /vagrant/script/vagrant'
  10 + end
  11 +end
config/initializers/01_load_config.rb
1 file = Rails.root.join('config', 'noosfero.yml') 1 file = Rails.root.join('config', 'noosfero.yml')
2 -NOOSFERO_CONF = File.exists?(file) ? YAML.load_file(file)[RAILS_ENV] || {} : {} 2 +NOOSFERO_CONF = File.exists?(file) ? YAML.load_file(file)[Rails.env] || {} : {}
debian/bundle/config 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +---
  2 +BUNDLE_WITHOUT: test:cucumber
  3 +
debian/control
@@ -10,9 +10,19 @@ Build-Depends: @@ -10,9 +10,19 @@ Build-Depends:
10 ruby-sqlite3, 10 ruby-sqlite3,
11 rake, 11 rake,
12 rails3 (>= 3.2.6-1~), 12 rails3 (>= 3.2.6-1~),
  13 + ruby-rspec,
  14 + ruby-rspec-rails,
13 ruby-will-paginate, 15 ruby-will-paginate,
  16 + cucumber,
  17 + ruby-cucumber-rails,
  18 + ruby-capybara,
  19 + ruby-database-cleaner,
  20 + ruby-selenium-webdriver,
  21 + ruby-tidy,
  22 + ruby-mocha,
  23 + imagemagick,
  24 + xvfb,
14 tango-icon-theme, 25 tango-icon-theme,
15 - rcov  
16 Standards-Version: 3.8.4 26 Standards-Version: 3.8.4
17 Homepage: http://noosfero.org/ 27 Homepage: http://noosfero.org/
18 Vcs-Git: git://git.colivre.coop.br/noosfero.git 28 Vcs-Git: git://git.colivre.coop.br/noosfero.git
@@ -25,8 +35,8 @@ Depends: @@ -25,8 +35,8 @@ Depends:
25 ruby, 35 ruby,
26 ruby1.9.3, 36 ruby1.9.3,
27 rake, 37 rake,
  38 + ruby-dalli,
28 ruby-fast-gettext, 39 ruby-fast-gettext,
29 - ruby-sqlite3,  
30 ruby-pg, 40 ruby-pg,
31 ruby-rmagick, 41 ruby-rmagick,
32 ruby-redcloth, 42 ruby-redcloth,
@@ -34,12 +44,15 @@ Depends: @@ -34,12 +44,15 @@ Depends:
34 iso-codes, 44 iso-codes,
35 ruby-feedparser, 45 ruby-feedparser,
36 ruby-daemons, 46 ruby-daemons,
37 - rcov,  
38 thin, 47 thin,
39 tango-icon-theme, 48 tango-icon-theme,
40 ruby-hpricot, 49 ruby-hpricot,
41 ruby-nokogiri, 50 ruby-nokogiri,
  51 + ruby-acts-as-taggable-on,
  52 + ruby-prototype-rails,
  53 + ruby-rails-autolink,
42 memcached, 54 memcached,
  55 + ruby-memcache-client,
43 debconf, 56 debconf,
44 dbconfig-common, 57 dbconfig-common,
45 adduser, 58 adduser,
debian/noosfero.dirs
1 etc/noosfero 1 etc/noosfero
2 etc/noosfero/plugins 2 etc/noosfero/plugins
3 usr/share/noosfero/locale 3 usr/share/noosfero/locale
  4 +usr/share/noosfero/.bundle
debian/noosfero.install
@@ -5,18 +5,20 @@ lib usr/share/noosfero @@ -5,18 +5,20 @@ lib usr/share/noosfero
5 script usr/share/noosfero 5 script usr/share/noosfero
6 util usr/share/noosfero 6 util usr/share/noosfero
7 Rakefile usr/share/noosfero 7 Rakefile usr/share/noosfero
8 -vendor/cardmagic-contacts-f66219e6589ccaf3ab9e3574fdd41225d0dd5073 usr/share/noosfero/vendor  
9 -vendor/gdata-1.1.1 usr/share/noosfero/vendor  
10 -vendor/plugins usr/share/noosfero/vendor  
11 -vendor/terceiro-fast_gettext-fe7bb09e30f7b1b5876a3b7a18fe8a254c6f59cb usr/share/noosfero/vendor  
12 -vendor/ezcrypto-0.7.2 usr/share/noosfero/vendor 8 +vendor usr/share/noosfero
13 9
  10 +Gemfile usr/share/noosfero
  11 +Gemfile.lock usr/share/noosfero
  12 +debian/bundle/config usr/share/noosfero/.bundle
  13 +
  14 +config/application.rb usr/share/noosfero/config
14 config/boot.rb usr/share/noosfero/config 15 config/boot.rb usr/share/noosfero/config
15 config/environment.rb usr/share/noosfero/config 16 config/environment.rb usr/share/noosfero/config
16 config/environments usr/share/noosfero/config 17 config/environments usr/share/noosfero/config
17 config/initializers usr/share/noosfero/config 18 config/initializers usr/share/noosfero/config
18 config/routes.rb usr/share/noosfero/config 19 config/routes.rb usr/share/noosfero/config
19 config/locales usr/share/noosfero/config 20 config/locales usr/share/noosfero/config
  21 +config.ru usr/share/noosfero
20 22
21 plugins usr/share/noosfero 23 plugins usr/share/noosfero
22 24
gitignore.example
1 .gitignore 1 .gitignore
2 .rbenv-* 2 .rbenv-*
  3 +.vagrant
3 vendor/rails 4 vendor/rails
4 doc/api 5 doc/api
5 doc/noosfero/plugins 6 doc/noosfero/plugins
lib/tasks/data.rake
1 namespace :db do 1 namespace :db do
2 namespace :data do 2 namespace :data do
3 task :minimal do 3 task :minimal do
4 - sh 'rails', 'runner', "Environment.create!(:name => 'Noosfero', :is_default => true)" 4 + sh 'rails', 'runner', "Environment.create!(:name => 'Noosfero', :contact_email => 'noosfero@localhost.localdomain', :is_default => true)"
5 unless ENV['NOOSFERO_DOMAIN'].blank? 5 unless ENV['NOOSFERO_DOMAIN'].blank?
6 sh 'rails', 'runner', "Environment.default.domains << Domain.new(:name => ENV['NOOSFERO_DOMAIN'])" 6 sh 'rails', 'runner', "Environment.default.domains << Domain.new(:name => ENV['NOOSFERO_DOMAIN'])"
7 end 7 end
lib/tasks/doc.rake
@@ -41,8 +41,8 @@ namespace :noosfero do @@ -41,8 +41,8 @@ namespace :noosfero do
41 toc_sections.each do |toc| 41 toc_sections.each do |toc|
42 section_topics = Dir.glob(File.dirname(toc) + '/*.textile').map {|item| item.sub('.textile', '.en.xhtml') }.reject {|item| ['index.en.xhtml', 'toc.en.xhtml' ].include?(File.basename(item))} 42 section_topics = Dir.glob(File.dirname(toc) + '/*.textile').map {|item| item.sub('.textile', '.en.xhtml') }.reject {|item| ['index.en.xhtml', 'toc.en.xhtml' ].include?(File.basename(item))}
43 file toc => section_topics do |t| 43 file toc => section_topics do |t|
44 - require 'app/models/doc_item'  
45 - require 'app/models/doc_topic' 44 + require './app/models/doc_item'
  45 + require './app/models/doc_topic'
46 begin 46 begin
47 File.open(toc, 'w') do |output_file| 47 File.open(toc, 'w') do |output_file|
48 section = File.basename(File.dirname(toc)) 48 section = File.basename(File.dirname(toc))
@@ -67,8 +67,9 @@ namespace :noosfero do @@ -67,8 +67,9 @@ namespace :noosfero do
67 67
68 top_level_toc = 'doc/noosfero/toc.en.xhtml' 68 top_level_toc = 'doc/noosfero/toc.en.xhtml'
69 file top_level_toc => index_sections do 69 file top_level_toc => index_sections do
70 - require 'app/models/doc_item'  
71 - require 'app/models/doc_topic' 70 + $LOAD_PATH << '.'
  71 + require './app/models/doc_item'
  72 + require './app/models/doc_topic'
72 begin 73 begin
73 File.open(top_level_toc, 'w') do |output_file| 74 File.open(top_level_toc, 'w') do |output_file|
74 output_file.puts "<!-- THIS FILE IS AUTOGENERATED. DO NOT EDIT -->" 75 output_file.puts "<!-- THIS FILE IS AUTOGENERATED. DO NOT EDIT -->"
lib/tasks/gettext.rake
@@ -6,7 +6,7 @@ makemo_stamp = &#39;tmp/makemo.stamp&#39; @@ -6,7 +6,7 @@ makemo_stamp = &#39;tmp/makemo.stamp&#39;
6 desc "Create mo-files for L10n" 6 desc "Create mo-files for L10n"
7 task :makemo => makemo_stamp 7 task :makemo => makemo_stamp
8 file makemo_stamp => Dir.glob('po/*/noosfero.po') do 8 file makemo_stamp => Dir.glob('po/*/noosfero.po') do
9 - ruby '-rconfig/boot -e \'require "gettext"; require "gettext/utils"; GetText.create_mofiles(true, "po", "locale")\' 2>/dev/null' 9 + ruby '-I. -rconfig/boot -e \'require "gettext"; require "gettext/utils"; GetText.create_mofiles(true, "po", "locale")\''
10 Rake::Task['symlinkmo'].invoke 10 Rake::Task['symlinkmo'].invoke
11 FileUtils.mkdir_p 'tmp' 11 FileUtils.mkdir_p 'tmp'
12 FileUtils.touch makemo_stamp 12 FileUtils.touch makemo_stamp
lib/tasks/multitenancy.rake
@@ -19,7 +19,7 @@ end @@ -19,7 +19,7 @@ end
19 namespace :db do 19 namespace :db do
20 20
21 task :migrate_other_environments => :environment do 21 task :migrate_other_environments => :environment do
22 - envs = ActiveRecord::Base.configurations.keys.select{ |k| k.match(/_#{RAILS_ENV}$/) } 22 + envs = ActiveRecord::Base.configurations.keys.select{ |k| k.match(/_#{Rails.env}$/) }
23 envs.each do |e| 23 envs.each do |e|
24 puts "*** Migrating #{e}" if Rake.application.options.trace 24 puts "*** Migrating #{e}" if Rake.application.options.trace
25 system "rake db:migrate RAILS_ENV=#{e}" 25 system "rake db:migrate RAILS_ENV=#{e}"
po/eo/noosfero-doc.po
@@ -7,12 +7,12 @@ msgid &quot;&quot; @@ -7,12 +7,12 @@ msgid &quot;&quot;
7 msgstr "" 7 msgstr ""
8 "Project-Id-Version: PACKAGE VERSION\n" 8 "Project-Id-Version: PACKAGE VERSION\n"
9 "POT-Creation-Date: 2013-12-10 15:48-0300\n" 9 "POT-Creation-Date: 2013-12-10 15:48-0300\n"
10 -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 10 +"PO-Revision-Date: 2014-03-23 17:11-0300\n"
11 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" 11 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12 "Language-Team: LANGUAGE <LL@li.org>\n" 12 "Language-Team: LANGUAGE <LL@li.org>\n"
13 "Language: eo\n" 13 "Language: eo\n"
14 "MIME-Version: 1.0\n" 14 "MIME-Version: 1.0\n"
15 -"Content-Type: text/plain; charset=CHARSET\n" 15 +"Content-Type: text/plain; charset=UTF-8\n"
16 "Content-Transfer-Encoding: 8bit\n" 16 "Content-Transfer-Encoding: 8bit\n"
17 "Plural-Forms: nplurals=2; plural=(n != 1);\n" 17 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
18 18
po/es/noosfero-doc.po
@@ -7,14 +7,14 @@ msgid &quot;&quot; @@ -7,14 +7,14 @@ msgid &quot;&quot;
7 msgstr "" 7 msgstr ""
8 "Project-Id-Version: PACKAGE VERSION\n" 8 "Project-Id-Version: PACKAGE VERSION\n"
9 "POT-Creation-Date: 2013-12-10 15:48-0300\n" 9 "POT-Creation-Date: 2013-12-10 15:48-0300\n"
10 -"PO-Revision-Date: 2012-10-04 13:01-0600\n" 10 +"PO-Revision-Date: 2014-03-23 17:11-0300\n"
11 "Last-Translator: Luis David Aguilar Carlos <ludwig9003@gmail.com>, Freddy " 11 "Last-Translator: Luis David Aguilar Carlos <ludwig9003@gmail.com>, Freddy "
12 "Martn Hernndez Facio <fmhf14@gmail.com>, Pedro Alonzo Ramrez Tovar <pedro." 12 "Martn Hernndez Facio <fmhf14@gmail.com>, Pedro Alonzo Ramrez Tovar <pedro."
13 "alonzo709@gmail.com>\n" 13 "alonzo709@gmail.com>\n"
14 "Language-Team: Spanish <LL@li.org>\n" 14 "Language-Team: Spanish <LL@li.org>\n"
15 "Language: \n" 15 "Language: \n"
16 "MIME-Version: 1.0\n" 16 "MIME-Version: 1.0\n"
17 -"Content-Type: text/plain; charset=CHARSET\n" 17 +"Content-Type: text/plain; charset=UTF-8\n"
18 "Content-Transfer-Encoding: ENCODING\n" 18 "Content-Transfer-Encoding: ENCODING\n"
19 19
20 # type: Content of: <h1> 20 # type: Content of: <h1>
po/it/noosfero-doc.po
@@ -8,12 +8,12 @@ msgid &quot;&quot; @@ -8,12 +8,12 @@ msgid &quot;&quot;
8 msgstr "" 8 msgstr ""
9 "Project-Id-Version: noosfero 0.36.6\n" 9 "Project-Id-Version: noosfero 0.36.6\n"
10 "POT-Creation-Date: 2013-12-10 15:48-0300\n" 10 "POT-Creation-Date: 2013-12-10 15:48-0300\n"
11 -"PO-Revision-Date: 2012-06-05 10:32-0300\n" 11 +"PO-Revision-Date: 2014-03-23 17:10-0300\n"
12 "Last-Translator: Daniela Feitosa <danielafeitosa@colivre.coop.br>\n" 12 "Last-Translator: Daniela Feitosa <danielafeitosa@colivre.coop.br>\n"
13 "Language-Team: LANGUAGE TEAM <LL@li.org>\n" 13 "Language-Team: LANGUAGE TEAM <LL@li.org>\n"
14 "Language: \n" 14 "Language: \n"
15 "MIME-Version: 1.0\n" 15 "MIME-Version: 1.0\n"
16 -"Content-Type: text/plain; charset=CHARSET\n" 16 +"Content-Type: text/plain; charset=UTF-8\n"
17 "Content-Transfer-Encoding: 8bit\n" 17 "Content-Transfer-Encoding: 8bit\n"
18 18
19 #. type: Content of: <h1> 19 #. type: Content of: <h1>
po/noosfero-doc.pot
@@ -13,7 +13,7 @@ msgstr &quot;&quot; @@ -13,7 +13,7 @@ msgstr &quot;&quot;
13 "Language-Team: LANGUAGE <LL@li.org>\n" 13 "Language-Team: LANGUAGE <LL@li.org>\n"
14 "Language: \n" 14 "Language: \n"
15 "MIME-Version: 1.0\n" 15 "MIME-Version: 1.0\n"
16 -"Content-Type: text/plain; charset=CHARSET\n" 16 +"Content-Type: text/plain; charset=UTF-8\n"
17 "Content-Transfer-Encoding: 8bit\n" 17 "Content-Transfer-Encoding: 8bit\n"
18 18
19 #. type: Content of: <h1> 19 #. type: Content of: <h1>
script/install-dependencies/debian-wheezy.sh
1 -# needed to run noosfero  
2 -runtime_dependencies=$(sed -e '/^\s*#/d; 1,/^Depends:/d; /^Recommends:/,$ d; s/([^)]*)//g; s/,\s*/\n/g' debian/control | grep -v 'memcached\|debconf\|dbconfig-common\|postgresql\|misc:Depends\|adduser\|mail-transport-agent')  
3 -run sudo apt-get -y install $runtime_dependencies  
4 -sudo apt-get -y install iceweasel || sudo apt-get -y install firefox 1 +# FIXME upload to a more official repository and sign with an existing key
  2 +if [ ! -e /etc/apt/sources.list.d/noosfero.list ]; then
  3 + sudo tee /etc/apt/sources.list.d/noosfero.list <<EOF
  4 +deb http://people.debian.org/~terceiro/noosfero-wheezy-backports/ ./
  5 +EOF
  6 + sudo apt-key add - <<EOF
  7 +-----BEGIN PGP PUBLIC KEY BLOCK-----
  8 +Version: GnuPG v1
5 9
6 -# needed for development  
7 -run sudo apt-get -y install ruby-tidy ruby-mocha imagemagick po4a xvfb libxml2-dev libxslt1-dev 10 +mQINBEo1mTQBEAD29YIKM0hM2IsB+TzBOpQja6h5hJ1gVeP7IWhC8E11jwaaoP1K
  11 +SXESKFMVPt0es0aCSDftm5TVTvLl08MG9fZBFT8pERfkWTEWWhY1MJ28sV8PRBHf
  12 +nhN0mv5aduvgVx32+aCD0mWhI/3XHObf6c/X9WMwEaH+6A9UFiXRCyflra9YOfHU
  13 +inXj5aYllc2UNiNxPhJ5sQTv97hdVbb/dFa+t9A2LFgPADbwUW+ShJN8zGR3XMne
  14 +lXTcOgPhBadiNPPi8PztfOgcUk/NqZ5H4i0cXXbZB6leWcGMMMiWNexapgea/Hvp
  15 +aXT2kSIug7OySFXM4nhM4xGo426+r9QHx1dzndHP5AW+WRuJmi3hMEdj22ifIFrV
  16 +XtwovTb6/R2nG7WLVSHKg1AuFvIfG1RrTaVUVMcXVGX83CB2qKjfMHFRyMKUxoK7
  17 +cZZkgD+sst47L+P3MlrRPfuB6selEySIrcwXTxFiuhLf74Zc8AZZeOi5ae2GObGr
  18 +b40wIT4HpJZO9M2YfZkMcnFsAqB8D4tPz9OjXiZdqNrXBMKJo0nsOFsYqkOCpnXP
  19 +ic4HQvmEaEWzNuPlWFH54AQf3zAWMoawLXOfgAOYAc8gf1dxYOTMJEBIplBBj8ch
  20 +E7WeiTv/f9vxuyX4CfTuuX/EEPTvkJ69bcBExtSm+bNs7fgwQwju0sHE7QARAQAB
  21 +tC1BbnRvbmlvIFRlcmNlaXJvIDx0ZXJjZWlyb0Bzb2Z0d2FyZWxpdnJlLm9yZz6J
  22 +AjoEEwEIACQCGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AFAko1mzkCGQEACgkQ
  23 +/A2xu81GC96yww/9HLaTgFTwnKZUhFEgcR9uOyZrb87NvCuXRkGAcy9sr5axSewh
  24 +Fibf0I6eFWvq2goOMaPp4rKAFI8UDm/clFUrO62LRKUXy+1/8KWvTJm4c7p7mg9f
  25 +Yhs8DPdQAKhl1AOqsT0m93ck+rQcYfAmSkBkX3usu+xEECrVH7oxD0nv3K+UDupT
  26 +TXHYYvSBb2xjB8H7MQqEM04utbZb8osRFBKlz7TEbwuxyacvZPEq9qlchStPVMCm
  27 +sr/sxeSSZawjKl3oZBG58JPj4+/nLkK+ADVP8E/lEtK45u47576QxgA8YHiNYtFm
  28 +lmsrvCyHNaS2g4Pj9gYamYDeFehdH2roQnp28829b/VEs2sUMltj/hZQ58QQNdqe
  29 +CpQVuHELD9tIw7CjGwjUYEMD8sow2ebwnl+ZNj5gz4PtOfetTR+0VBJG69kug1GC
  30 +lD5SsRrdUp3dSfFAIoMG0LTDnfobjDX/VbJ24hBbCAkdE/1io/57X6GSlDg2tZ4+
  31 +gwIexMXzoRSl+to3XQBXSi8CdU99ePlf7MRNIJHpCZnFKZIMVlWpDckqvrGn4Ubv
  32 +UfDBnS7K7lBOKxWvOX+uvYxSD0Deo5tbCPKH40pYmDT9R87QQhzI8QnrUUaUEcM0
  33 +G28XNcamChJFH/mEU3+Is9fSV4eyoN1sKi0gbvtgha0AZewFbeUkCH5aLae0J0Fu
  34 +dG9uaW8gVGVyY2Vpcm8gPHRlcmNlaXJvQGRjYy51ZmJhLmJyPokCNwQTAQgAIQUC
  35 +SjWa4AIbAwULCQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRD8DbG7zUYL3u4FD/4x
  36 +qv8lFOEc8so7Iktp/1b3wLJ6jCyQ1XtgC2Bem91Rda0VGCoTj83nh1NXW2tV1Phi
  37 +yIo82LA8/oRqsQnMVZZLe1kRX7vnpLzOjUG17kVOwpt7KwuK2VpXFoSYlntSR8cH
  38 +P/vfyhuySN5Gd9RN/liSJLEMUb+r16ibm56mOSWpHFddiQtCGYkqP7Iz1w6L2axq
  39 ++d+LPtD4jKVvQHTh9WPMDjZLNn4+glNOCXWj24GjWzdwsJuUJnOybDbgEpNLdpV0
  40 +I1Tr52ObTB4V1JmMQQ33pPwe70xeV9FcyIhKJKy+6NE/S7yiJDqYd1a10pDQDNvJ
  41 +H2t+d6bxuI6+E3AEhvoOw6mTNrbLWIBciNGEWFSZc18gkmOLEijiu5cmFbvp6btu
  42 +6glgPphTJGkGqkS96KKJcohCYtok9s6QFNr4+yb3iXb1nB2j484vCdukjEg0xoxE
  43 +4sfhf/QRDuKfl5SWwebIhTxv50pJ+WCdXCTneK19SZO86EaGYInNdjZkEF4dO51O
  44 +cLYvbcy+zMMpINdZu+yp2eaaAtJbFPBaMtbY2KJGDp4gzfRiYhyGcujZ3vJ1u5Ch
  45 +KWqtPDsIXsr6a5hy9xI0WFeZ2CeHVO1UvW6i7qj+bgSDI9riAuub4ksk1LJvEL08
  46 +48yC3EZ5Vdai0PY40lVm7+u7Guq8WJku2LnTx2owUbQrQW50b25pbyBUZXJjZWly
  47 +byA8dGVyY2Vpcm9AY29saXZyZS5jb29wLmJyPokCNwQTAQgAIQUCSjWazAIbAwUL
  48 +CQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRD8DbG7zUYL3o7ND/9yesmfkHbrezjL
  49 +nTthjgFizm96wDqCpX9Vif6/YNjorXxy5Yrd+Q3XHrPwkDvJQtrIbuG9IfQDvFRQ
  50 +OdvieMquBDbCfIxFVfi8Vbvji6WyR5NU81TbcIw3MC9HXZP9fKJ7ZtFeqjXdjJEs
  51 +stfoi4LmNPzPZqAD8DlV3gpTZ2gIPivA4QxxRR+tX3DHktklbLr8cektLzi1LJIH
  52 +eXYMpVR9l0TyCmaszQiQOzVBUETmANuSgKOvs9qK80bvjrkuA5R7gx5py/VUOFht
  53 +SJzjutL/eVlW/mqJQ/D7l6Je8XhX+niCw0HhbnHMtUruP8pwjcRkdf1b9ikxC1ib
  54 +zpcxw0b6hn5tbcFZxcGWKQYv3H37ve4JJ74ZUnQPwbLKGhxXYi5UpNb1D1gePE/+
  55 +685bwDYI+4r9NB8Wqm7D+Qthaucmwg44lBscXtqUYZJqKGBR8PNH05j83H9q6FLy
  56 +6M0/XYe9dDv6+PJ8QdtRe9ovQ5CibJZV/BERehm4g66k0t6WXofcDuw9mipLz+Os
  57 +YUcx5MSnlbCGFtJjDlgNGaFh7S3cnWf1MX8lAJvftuzbtNq5FWKG0YihxhzMOiUf
  58 +0BTWrh4DYmf3wVs8EGL6JVhTZK6bJRYQjyUrwQ1LuAJ8C40N0bjAnMEMBi5Sratn
  59 +3uZRWXmoqepFn1D4nin/vXxI3p3ZN7QmQW50b25pbyBUZXJjZWlybyA8dGVyY2Vp
  60 +cm9AZGViaWFuLm9yZz6JAjcEEwEIACEFAk4ocKwCGwMFCwkIBwMFFQoJCAsFFgID
  61 +AQACHgECF4AACgkQ/A2xu81GC94nahAA8/gqJeozduayDxTWF/iNnC8PMOD0Stnn
  62 +8GxuoamLmxspmu6etbwSm2FBBrBBZOGOVx6rV6OvtmzYnyIallEqY0lMEi7yySA/
  63 +spPvvEihB8KkVj8CW55BE8vaNhynXzneVzHpheV6zoH8o6YzBzg84LB4X3+IG3EZ
  64 +52SUVMUoek6ZSUrTXLA0AuJE/LrchzRsVzEQj6Y9h5gpCsj9P/8n+4y403k26tuO
  65 +sZWqLv/Sb3byinB0hdrg4U9sm9fk4yDB9fmFWQUaj5nUDxxPgWjdKrvI+y9+d4nP
  66 +09Jg0fgG8viiQTer/Kg0n3Pwka7zGEn2o2BvZ/1LQBF0h+0BqNM0uXxoJoGVyOgY
  67 +P1CIgfy/LZyl9f9kxDN8IYco0sCAjq8ZYIfjc0TLOI6F3StZZaEXDpXfFGfROh2e
  68 +0/1gNEIKicgdLWYQNzcNf3Y7GqJtigRQaGSXpqN2WVL54vTpR55+IPEGgZUNlEU+
  69 +cG366pk9gj8gJo3Myhtm8jibXsPfVbVMz7QPJR/DfBte6s3maFdTDM4X8VbuMGRm
  70 +PqH/6P7+KNVXdOBBMZMk223sZ2xdFVrrFE0njVSnXq+0kX6qmmG323YBm76XNdBO
  71 +4a2s3weSJAboygKJ7uLUGgt2/6FZt2eMlUizta9eGxzkQ0c5e5MVBxHoC0BD1jTu
  72 +FkQeKfqTDH60LkFudG9uaW8gVGVyY2Vpcm8gPGFudG9uaW8udGVyY2Vpcm9AbGlu
  73 +YXJvLm9yZz6JAjcEEwEIACEFAlBGLZoCGwMFCwkIBwMFFQoJCAsFFgIDAQACHgEC
  74 +F4AACgkQ/A2xu81GC96aExAAgz2svW9mADXyLLUEOFMbpNR6G4gtXRTKZNmOsJBe
  75 +7DRewKFWdKlXbtxLs77uZPqzX7S/sNFXetOieg1C2MBM1rL5artKpaXrHxWZEyCa
  76 +DbWVeDdnCC0/WYn6hqrIyqjAJx9h+e3fpGTqxOuztMcp2uiMijuYVaPyCN0z6Hnj
  77 +Y7p/IUTAUtUDU8dLQqzYimKrmsioIEPWlzt44g1MOLt2znQjedMTrDwQOstJj2G7
  78 +9v0meFVllTpMBSECKnt1I4SQEk0kq/R3cPqqLBJ75K+DH0fsGlqb6tW0oIB2BZDn
  79 +nGnttUphS3xgSd1qy3/wTB047w2i5DqrHfleUgyWOMydSck8PK11i1x9UYdV0137
  80 +foVbTnRdY8/uoH32r4SjlRCeQA5VSeBxIq4EDW+G6tGEDawRji4x94TDgXYm54hO
  81 +OzFhkL7zi0wtWc1GFQF7vZyLE93hYkhID70MnajqU0umZL+losmBiOvQGkIt9hSC
  82 +iL+oTlmRw+SXtu7aPmu7Ue9s1ieaeivTMlFf7OD3tB1m/YiRbQH/XcBMaQp0GELI
  83 +QeSzYmmY03E8E/X5IPtF0tRCvfp9GmUn3lfBDWcYhaWy6k3YqvLw8FS+uhmYwfhx
  84 +j5bUV6MRIfNv06rXklhjgX22FUL9p0qilYqJmYQqVYku2Ff431dyDuzv7q0AkMoP
  85 +N6+0JUFudG9uaW8gVGVyY2Vpcm8gPHRlcmNlaXJvQGNzLnViYy5jYT6JAjcEEwEI
  86 +ACEFAk2SGLsCGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQ/A2xu81GC95+
  87 +mg/+MGbOb7ntM05SO95GNKP8fTQXEnYa6xYIkASkHY7wPfBhYWdYE8kLajWdD1ec
  88 +hDIS3nJ/4fVDUrF1ZJM37lIWJZhhQWwLPONCTlxWYTScosYzKkTeQ0PzBBrrsqOF
  89 +xTtANvb8N9fE6rxkzl7cT48Ty+B0o+U2BolgtM/lmzdu44c7Wr9QIkCpE3wqMfj2
  90 +kw3JUMojOSVDTwavZyPHGa1wibH6R59rQ+WhG6OxiZAXCh8QIEbe6Z50R5Araqc4
  91 +x9/yvBN03j7YCSOJ0hDpRS9VWRWiGNEnn20My0mZRPI+VjvnYmR9w6cHWU33LwQ1
  92 +/xmpJfhJg989/rDRZlJZ4nYgGZoope+5+HcrOud+wrXBUXht3mMDuZTBoBMM5ey/
  93 +Z4Rl1FikNYgD58MDt3bNUyrb+MsUjNuCDPmmdH5CLTG0abxaSjRJ4dR6AZDVqt2x
  94 +KVlhzkGEEBRyKRDmphMoC6AG+kIYuJqfnr1zh35QDuBZNRytt22HzDQk8RcMslrd
  95 +nx94X/53LRvkdXNXoijhMMz4bt6exBz1GbRcW1Oe3JNeW3btekEgSizTfj5rFxQG
  96 +Z8syg28WfQscpY4ffl+YlFALj+8ZqpIzezxa2aB0WqMq8BcFUe7+6NZliDwbOC35
  97 +ufMBt8SqCJd/o4Egmz09AZxVfWHlmQfApzKs3ARXnSkLeoK5Ag0ETXvdtwEQAOjS
  98 +WZVeJx12YPlaz4ylULBrVpgbcSucTIYkx5sPFc0cJCRseG7AKBOG+Me4SfLma25/
  99 +IhcmoEsxCgo9eNM5XMysg3jo7Pui6g8OEw5wNIlKHsrOXk0ITSZpimxltrEMLm5a
  100 +eaF95Ne35VNyr285H/AL1qM+Ubwfmpwd1Eu49z39/aY/0IDymdO11Aai8kz2OHED
  101 +Rkx/Fe95Xx4JhdkwSYoaE3Tzz8GGU6Rig+MwJZeb9YiFSXHqRgP1+IjI+Ht1APvH
  102 +kUKwXfmM1IuGBLE6pw0a6V4mWASW4Dy2+0PE/jR1R5AVxh03sd5eUC/BPQ/wFKH7
  103 +0+EryemO5181YLoOv3/RRDHmsxSk9C1BDLboSFbO9Mo5e78xYHkFHonm7iGejYto
  104 +DLE9xHixOiyc86jbAkdL7Qjc6NJVNtCvTU58/4aArFBVzfEvWdz1umFcPmJKaCEp
  105 +8YI8LalWK5meTbVUDuRWE/mtu8/k3jaCzHhj83GFIoFP6YNWGWlAZJGklhvM5Spr
  106 +tvaD78hoaNpuPCh+u0Atuv3uWBHIsczIVxJYbSNvpLu+EN7O4DNnxkFI6GBDhHX+
  107 +lGEJdHn5JXmD43c2JVykS9d3XJcWdlyXgwdwRviXz2/kYdP7iAVLhl7T0skk8/A4
  108 +xv6p2FRMgixM/PIp1GZu915egPlilrFxYAg1xMGLABEBAAGJAh8EGAEIAAkFAk17
  109 +3bcCGwwACgkQ/A2xu81GC97B0w//QT1SS/s1fgJ8IDmbcUrfk3Y5+PvDnmHr8gsJ
  110 +8A8hMJ2OLdxa2lrcWXebmiSPConAJlzBUKqYm+WZItjJYqEvRfLjKpzTJuxxSae1
  111 +v5v7Y2kUPKgIKmaD9EYl3c3SsyQB8lJ9cBhU6vSdo2L7/nckKSheiEw99MnJBK3B
  112 +iyTYikt2NILuInZ0RErZ7xz1jpinCfkvZSYwJ+IiGxCFefYzDFECjj9bWjIE6vz6
  113 +4HyrXjtSdXsCcFrL+fSnhWOpdgmUuzdUWBH84mAWM6aXqNzAHOIrp5VatDWpHBPH
  114 +bi3M/TIHyjrKnsaYrYU5fmhnTdLig2LMZhKg3vHAqvZfb1XbRgYTSuayGW9sGFG5
  115 +AWZDUOuv+E9FAvHGlv7EZJsy+yhQh4cNWlJQJnGEA/HxA2sRZlwGawwjbZ0xF6MG
  116 +0Dj8x+9Eu3/nRYO0VYgzAYVKMF5cBfblNnWG8p5Npz6lfr1sLY1W9E/2XWkwvnr5
  117 +KDSaDo9iTj+Bhk60vWFDjD69oY1HpAZMGuBd/Z0qy0W/l+ovuMAIU6vH9gHtizdY
  118 +uZe/53J8oBHx+zXgPxzCE7mylVCrVgq6MV6NZtEBQSa5PjPrzu12HAnfzHhV/z3Y
  119 +o9boBnVcNoOCGxUTqpg1aCDvzH8B8Y6hQKVETA077iYfLMFcqMaMLGwAXxGGJbCy
  120 +y/cBuQY=
  121 +=oYoG
  122 +-----END PGP PUBLIC KEY BLOCK-----
  123 +EOF
  124 + run sudo apt-get update
  125 +fi
8 126
9 -sudo apt-get -y install bundler apt-file  
10 -sudo apt-file update 127 +run sudo apt-get -y install dctrl-tools
11 128
12 -run ./script/debundler 129 +# needed to run noosfero
  130 +packages=$(grep-dctrl -n -s Build-Depends,Depends,Recommends -S -X noosfero debian/control | sed -e 's/([^)]*)//g; s/,\s*/\n/g' | grep -v 'memcached\|debconf\|dbconfig-common\|misc:Depends\|adduser\|mail-transport-agent')
  131 +run sudo apt-get -y install $packages
  132 +sudo apt-get -y install iceweasel || sudo apt-get -y install firefox
13 133
14 run bundle --local 134 run bundle --local
script/vagrant 0 → 100755
@@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
  1 +#!/bin/sh
  2 +
  3 +set -e
  4 +sudo apt-get install netcat-traditional
  5 +
  6 +# apt-cacher-ng running on the host
  7 +# 10.0.2.2 = host ip on virtualbox/qemu
  8 +# 192.168..122.1 = host ip on default libvirt bridge
  9 +for ip in 10.0.2.2 192.168.122.1; do
  10 + if nc -z -w 1 $ip 3142; then
  11 + echo "Acquire::http::Proxy \"http://$ip:3142\";" | sudo tee /etc/apt/apt.conf.d/01proxy
  12 + fi
  13 +done
  14 +
  15 +cd /vagrant
  16 +./script/quick-start
vendor/prototype_legacy_helper/README.markdown 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +# Prototype Legacy Helper
  2 +
  3 +This plugin adds support for `form_remote_tag`, etc from Rails 2 to Rails 3.
  4 +
  5 +## Installation
  6 +
  7 +Either add the following to your `Gemfile` and run `bundle`:
  8 +
  9 + gem 'prototype_legacy_helper', '0.0.0', :git => 'git://github.com/rails/prototype_legacy_helper.git'
  10 +
  11 +or run the following command to vendor the plugin within your app:
  12 +
  13 + rails plugin install git://github.com/rails/prototype_legacy_helper.git
vendor/prototype_legacy_helper/init.rb 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +require 'prototype_legacy_helper'
vendor/prototype_legacy_helper/lib/prototype_legacy_helper.rb 0 → 100644
@@ -0,0 +1,432 @@ @@ -0,0 +1,432 @@
  1 +module PrototypeHelper
  2 + # Creates a button with an onclick event which calls a remote action
  3 + # via XMLHttpRequest
  4 + # The options for specifying the target with :url
  5 + # and defining callbacks is the same as link_to_remote.
  6 + def button_to_remote(name, options = {}, html_options = {})
  7 + button_to_function(name, remote_function(options), html_options)
  8 + end
  9 +
  10 + # Returns a button input tag with the element name of +name+ and a value (i.e., display text) of +value+
  11 + # that will submit form using XMLHttpRequest in the background instead of a regular POST request that
  12 + # reloads the page.
  13 + #
  14 + # # Create a button that submits to the create action
  15 + # #
  16 + # # Generates: <input name="create_btn" onclick="new Ajax.Request('/testing/create',
  17 + # # {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)});
  18 + # # return false;" type="button" value="Create" />
  19 + # <%= submit_to_remote 'create_btn', 'Create', :url => { :action => 'create' } %>
  20 + #
  21 + # # Submit to the remote action update and update the DIV succeed or fail based
  22 + # # on the success or failure of the request
  23 + # #
  24 + # # Generates: <input name="update_btn" onclick="new Ajax.Updater({success:'succeed',failure:'fail'},
  25 + # # '/testing/update', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)});
  26 + # # return false;" type="button" value="Update" />
  27 + # <%= submit_to_remote 'update_btn', 'Update', :url => { :action => 'update' },
  28 + # :update => { :success => "succeed", :failure => "fail" }
  29 + #
  30 + # <tt>options</tt> argument is the same as in form_remote_tag.
  31 + def submit_to_remote(name, value, options = {})
  32 + options[:with] ||= 'Form.serialize(this.form)'
  33 +
  34 + html_options = options.delete(:html) || {}
  35 + html_options[:name] = name
  36 +
  37 + button_to_remote(value, options, html_options)
  38 + end
  39 +
  40 + # Returns a link to a remote action defined by <tt>options[:url]</tt>
  41 + # (using the url_for format) that's called in the background using
  42 + # XMLHttpRequest. The result of that request can then be inserted into a
  43 + # DOM object whose id can be specified with <tt>options[:update]</tt>.
  44 + # Usually, the result would be a partial prepared by the controller with
  45 + # render :partial.
  46 + #
  47 + # Examples:
  48 + # # Generates: <a href="#" onclick="new Ajax.Updater('posts', '/blog/destroy/3', {asynchronous:true, evalScripts:true});
  49 + # # return false;">Delete this post</a>
  50 + # link_to_remote "Delete this post", :update => "posts",
  51 + # :url => { :action => "destroy", :id => post.id }
  52 + #
  53 + # # Generates: <a href="#" onclick="new Ajax.Updater('emails', '/mail/list_emails', {asynchronous:true, evalScripts:true});
  54 + # # return false;"><img alt="Refresh" src="/images/refresh.png?" /></a>
  55 + # link_to_remote(image_tag("refresh"), :update => "emails",
  56 + # :url => { :action => "list_emails" })
  57 + #
  58 + # You can override the generated HTML options by specifying a hash in
  59 + # <tt>options[:html]</tt>.
  60 + #
  61 + # link_to_remote "Delete this post", :update => "posts",
  62 + # :url => post_url(@post), :method => :delete,
  63 + # :html => { :class => "destructive" }
  64 + #
  65 + # You can also specify a hash for <tt>options[:update]</tt> to allow for
  66 + # easy redirection of output to an other DOM element if a server-side
  67 + # error occurs:
  68 + #
  69 + # Example:
  70 + # # Generates: <a href="#" onclick="new Ajax.Updater({success:'posts',failure:'error'}, '/blog/destroy/5',
  71 + # # {asynchronous:true, evalScripts:true}); return false;">Delete this post</a>
  72 + # link_to_remote "Delete this post",
  73 + # :url => { :action => "destroy", :id => post.id },
  74 + # :update => { :success => "posts", :failure => "error" }
  75 + #
  76 + # Optionally, you can use the <tt>options[:position]</tt> parameter to
  77 + # influence how the target DOM element is updated. It must be one of
  78 + # <tt>:before</tt>, <tt>:top</tt>, <tt>:bottom</tt>, or <tt>:after</tt>.
  79 + #
  80 + # The method used is by default POST. You can also specify GET or you
  81 + # can simulate PUT or DELETE over POST. All specified with <tt>options[:method]</tt>
  82 + #
  83 + # Example:
  84 + # # Generates: <a href="#" onclick="new Ajax.Request('/person/4', {asynchronous:true, evalScripts:true, method:'delete'});
  85 + # # return false;">Destroy</a>
  86 + # link_to_remote "Destroy", :url => person_url(:id => person), :method => :delete
  87 + #
  88 + # By default, these remote requests are processed asynchronous during
  89 + # which various JavaScript callbacks can be triggered (for progress
  90 + # indicators and the likes). All callbacks get access to the
  91 + # <tt>request</tt> object, which holds the underlying XMLHttpRequest.
  92 + #
  93 + # To access the server response, use <tt>request.responseText</tt>, to
  94 + # find out the HTTP status, use <tt>request.status</tt>.
  95 + #
  96 + # Example:
  97 + # # Generates: <a href="#" onclick="new Ajax.Request('/words/undo?n=33', {asynchronous:true, evalScripts:true,
  98 + # # onComplete:function(request){undoRequestCompleted(request)}}); return false;">hello</a>
  99 + # word = 'hello'
  100 + # link_to_remote word,
  101 + # :url => { :action => "undo", :n => word_counter },
  102 + # :complete => "undoRequestCompleted(request)"
  103 + #
  104 + # The callbacks that may be specified are (in order):
  105 + #
  106 + # <tt>:loading</tt>:: Called when the remote document is being
  107 + # loaded with data by the browser.
  108 + # <tt>:loaded</tt>:: Called when the browser has finished loading
  109 + # the remote document.
  110 + # <tt>:interactive</tt>:: Called when the user can interact with the
  111 + # remote document, even though it has not
  112 + # finished loading.
  113 + # <tt>:success</tt>:: Called when the XMLHttpRequest is completed,
  114 + # and the HTTP status code is in the 2XX range.
  115 + # <tt>:failure</tt>:: Called when the XMLHttpRequest is completed,
  116 + # and the HTTP status code is not in the 2XX
  117 + # range.
  118 + # <tt>:complete</tt>:: Called when the XMLHttpRequest is complete
  119 + # (fires after success/failure if they are
  120 + # present).
  121 + #
  122 + # You can further refine <tt>:success</tt> and <tt>:failure</tt> by
  123 + # adding additional callbacks for specific status codes.
  124 + #
  125 + # Example:
  126 + # # Generates: <a href="#" onclick="new Ajax.Request('/testing/action', {asynchronous:true, evalScripts:true,
  127 + # # on404:function(request){alert('Not found...? Wrong URL...?')},
  128 + # # onFailure:function(request){alert('HTTP Error ' + request.status + '!')}}); return false;">hello</a>
  129 + # link_to_remote word,
  130 + # :url => { :action => "action" },
  131 + # 404 => "alert('Not found...? Wrong URL...?')",
  132 + # :failure => "alert('HTTP Error ' + request.status + '!')"
  133 + #
  134 + # A status code callback overrides the success/failure handlers if
  135 + # present.
  136 + #
  137 + # If you for some reason or another need synchronous processing (that'll
  138 + # block the browser while the request is happening), you can specify
  139 + # <tt>options[:type] = :synchronous</tt>.
  140 + #
  141 + # You can customize further browser side call logic by passing in
  142 + # JavaScript code snippets via some optional parameters. In their order
  143 + # of use these are:
  144 + #
  145 + # <tt>:confirm</tt>:: Adds confirmation dialog.
  146 + # <tt>:condition</tt>:: Perform remote request conditionally
  147 + # by this expression. Use this to
  148 + # describe browser-side conditions when
  149 + # request should not be initiated.
  150 + # <tt>:before</tt>:: Called before request is initiated.
  151 + # <tt>:after</tt>:: Called immediately after request was
  152 + # initiated and before <tt>:loading</tt>.
  153 + # <tt>:submit</tt>:: Specifies the DOM element ID that's used
  154 + # as the parent of the form elements. By
  155 + # default this is the current form, but
  156 + # it could just as well be the ID of a
  157 + # table row or any other DOM element.
  158 + # <tt>:with</tt>:: A JavaScript expression specifying
  159 + # the parameters for the XMLHttpRequest.
  160 + # Any expressions should return a valid
  161 + # URL query string.
  162 + #
  163 + # Example:
  164 + #
  165 + # :with => "'name=' + $('name').value"
  166 + #
  167 + # You can generate a link that uses AJAX in the general case, while
  168 + # degrading gracefully to plain link behavior in the absence of
  169 + # JavaScript by setting <tt>html_options[:href]</tt> to an alternate URL.
  170 + # Note the extra curly braces around the <tt>options</tt> hash separate
  171 + # it as the second parameter from <tt>html_options</tt>, the third.
  172 + #
  173 + # Example:
  174 + # link_to_remote "Delete this post",
  175 + # { :update => "posts", :url => { :action => "destroy", :id => post.id } },
  176 + # :href => url_for(:action => "destroy", :id => post.id)
  177 + def link_to_remote(name, options = {}, html_options = nil)
  178 + link_to_function(name, remote_function(options), html_options || options.delete(:html))
  179 + end
  180 +
  181 + # Returns a form tag that will submit using XMLHttpRequest in the
  182 + # background instead of the regular reloading POST arrangement. Even
  183 + # though it's using JavaScript to serialize the form elements, the form
  184 + # submission will work just like a regular submission as viewed by the
  185 + # receiving side (all elements available in <tt>params</tt>). The options for
  186 + # specifying the target with <tt>:url</tt> and defining callbacks is the same as
  187 + # +link_to_remote+.
  188 + #
  189 + # A "fall-through" target for browsers that doesn't do JavaScript can be
  190 + # specified with the <tt>:action</tt>/<tt>:method</tt> options on <tt>:html</tt>.
  191 + #
  192 + # Example:
  193 + # # Generates:
  194 + # # <form action="/some/place" method="post" onsubmit="new Ajax.Request('',
  195 + # # {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">
  196 + # form_remote_tag :html => { :action =>
  197 + # url_for(:controller => "some", :action => "place") }
  198 + #
  199 + # The Hash passed to the <tt>:html</tt> key is equivalent to the options (2nd)
  200 + # argument in the FormTagHelper.form_tag method.
  201 + #
  202 + # By default the fall-through action is the same as the one specified in
  203 + # the <tt>:url</tt> (and the default method is <tt>:post</tt>).
  204 + #
  205 + # form_remote_tag also takes a block, like form_tag:
  206 + # # Generates:
  207 + # # <form action="/" method="post" onsubmit="new Ajax.Request('/',
  208 + # # {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)});
  209 + # # return false;"> <div><input name="commit" type="submit" value="Save" /></div>
  210 + # # </form>
  211 + # <% form_remote_tag :url => '/posts' do -%>
  212 + # <div><%= submit_tag 'Save' %></div>
  213 + # <% end -%>
  214 + def form_remote_tag(options = {}, &block)
  215 + options[:form] = true
  216 +
  217 + options[:html] ||= {}
  218 + options[:html][:onsubmit] =
  219 + (options[:html][:onsubmit] ? options[:html][:onsubmit] + "; " : "") +
  220 + "#{remote_function(options)}; return false;"
  221 +
  222 + form_tag(options[:html].delete(:action) || url_for(options[:url]), options[:html], &block)
  223 + end
  224 +
  225 + # Creates a form that will submit using XMLHttpRequest in the background
  226 + # instead of the regular reloading POST arrangement and a scope around a
  227 + # specific resource that is used as a base for questioning about
  228 + # values for the fields.
  229 + #
  230 + # === Resource
  231 + #
  232 + # Example:
  233 + # <% remote_form_for(@post) do |f| %>
  234 + # ...
  235 + # <% end %>
  236 + #
  237 + # This will expand to be the same as:
  238 + #
  239 + # <% remote_form_for :post, @post, :url => post_path(@post), :html => { :method => :put, :class => "edit_post", :id => "edit_post_45" } do |f| %>
  240 + # ...
  241 + # <% end %>
  242 + #
  243 + # === Nested Resource
  244 + #
  245 + # Example:
  246 + # <% remote_form_for([@post, @comment]) do |f| %>
  247 + # ...
  248 + # <% end %>
  249 + #
  250 + # This will expand to be the same as:
  251 + #
  252 + # <% remote_form_for :comment, @comment, :url => post_comment_path(@post, @comment), :html => { :method => :put, :class => "edit_comment", :id => "edit_comment_45" } do |f| %>
  253 + # ...
  254 + # <% end %>
  255 + #
  256 + # If you don't need to attach a form to a resource, then check out form_remote_tag.
  257 + #
  258 + # See FormHelper#form_for for additional semantics.
  259 + def remote_form_for(record_or_name_or_array, *args, &proc)
  260 + options = args.extract_options!
  261 +
  262 + case record_or_name_or_array
  263 + when String, Symbol
  264 + object_name = record_or_name_or_array
  265 + when Array
  266 + object = record_or_name_or_array.last
  267 + object_name = ActiveModel::Naming.singular(object)
  268 + apply_form_for_options!(record_or_name_or_array, options)
  269 + args.unshift object
  270 + else
  271 + object = record_or_name_or_array
  272 + object_name = ActiveModel::Naming.singular(record_or_name_or_array)
  273 + apply_form_for_options!(object, options)
  274 + args.unshift object
  275 + end
  276 +
  277 + form_remote_tag options do
  278 + fields_for object_name, *(args << options), &proc
  279 + end
  280 + end
  281 + alias_method :form_remote_for, :remote_form_for
  282 +
  283 + # Returns '<tt>eval(request.responseText)</tt>' which is the JavaScript function
  284 + # that +form_remote_tag+ can call in <tt>:complete</tt> to evaluate a multiple
  285 + # update return document using +update_element_function+ calls.
  286 + def evaluate_remote_response
  287 + "eval(request.responseText)"
  288 + end
  289 +
  290 + # Observes the field with the DOM ID specified by +field_id+ and calls a
  291 + # callback when its contents have changed. The default callback is an
  292 + # Ajax call. By default the value of the observed field is sent as a
  293 + # parameter with the Ajax call.
  294 + #
  295 + # Example:
  296 + # # Generates: new Form.Element.Observer('suggest', 0.25, function(element, value) {new Ajax.Updater('suggest',
  297 + # # '/testing/find_suggestion', {asynchronous:true, evalScripts:true, parameters:'q=' + value})})
  298 + # <%= observe_field :suggest, :url => { :action => :find_suggestion },
  299 + # :frequency => 0.25,
  300 + # :update => :suggest,
  301 + # :with => 'q'
  302 + # %>
  303 + #
  304 + # Required +options+ are either of:
  305 + # <tt>:url</tt>:: +url_for+-style options for the action to call
  306 + # when the field has changed.
  307 + # <tt>:function</tt>:: Instead of making a remote call to a URL, you
  308 + # can specify javascript code to be called instead.
  309 + # Note that the value of this option is used as the
  310 + # *body* of the javascript function, a function definition
  311 + # with parameters named element and value will be generated for you
  312 + # for example:
  313 + # observe_field("glass", :frequency => 1, :function => "alert('Element changed')")
  314 + # will generate:
  315 + # new Form.Element.Observer('glass', 1, function(element, value) {alert('Element changed')})
  316 + # The element parameter is the DOM element being observed, and the value is its value at the
  317 + # time the observer is triggered.
  318 + #
  319 + # Additional options are:
  320 + # <tt>:frequency</tt>:: The frequency (in seconds) at which changes to
  321 + # this field will be detected. Not setting this
  322 + # option at all or to a value equal to or less than
  323 + # zero will use event based observation instead of
  324 + # time based observation.
  325 + # <tt>:update</tt>:: Specifies the DOM ID of the element whose
  326 + # innerHTML should be updated with the
  327 + # XMLHttpRequest response text.
  328 + # <tt>:with</tt>:: A JavaScript expression specifying the parameters
  329 + # for the XMLHttpRequest. The default is to send the
  330 + # key and value of the observed field. Any custom
  331 + # expressions should return a valid URL query string.
  332 + # The value of the field is stored in the JavaScript
  333 + # variable +value+.
  334 + #
  335 + # Examples
  336 + #
  337 + # :with => "'my_custom_key=' + value"
  338 + # :with => "'person[name]=' + prompt('New name')"
  339 + # :with => "Form.Element.serialize('other-field')"
  340 + #
  341 + # Finally
  342 + # :with => 'name'
  343 + # is shorthand for
  344 + # :with => "'name=' + value"
  345 + # This essentially just changes the key of the parameter.
  346 + #
  347 + # Additionally, you may specify any of the options documented in the
  348 + # <em>Common options</em> section at the top of this document.
  349 + #
  350 + # Example:
  351 + #
  352 + # # Sends params: {:title => 'Title of the book'} when the book_title input
  353 + # # field is changed.
  354 + # observe_field 'book_title',
  355 + # :url => 'http://example.com/books/edit/1',
  356 + # :with => 'title'
  357 + #
  358 + #
  359 + def observe_field(field_id, options = {})
  360 + if options[:frequency] && options[:frequency] > 0
  361 + build_observer('Form.Element.Observer', field_id, options)
  362 + else
  363 + build_observer('Form.Element.EventObserver', field_id, options)
  364 + end
  365 + end
  366 +
  367 + # Observes the form with the DOM ID specified by +form_id+ and calls a
  368 + # callback when its contents have changed. The default callback is an
  369 + # Ajax call. By default all fields of the observed field are sent as
  370 + # parameters with the Ajax call.
  371 + #
  372 + # The +options+ for +observe_form+ are the same as the options for
  373 + # +observe_field+. The JavaScript variable +value+ available to the
  374 + # <tt>:with</tt> option is set to the serialized form by default.
  375 + def observe_form(form_id, options = {})
  376 + if options[:frequency]
  377 + build_observer('Form.Observer', form_id, options)
  378 + else
  379 + build_observer('Form.EventObserver', form_id, options)
  380 + end
  381 + end
  382 +
  383 + # Periodically calls the specified url (<tt>options[:url]</tt>) every
  384 + # <tt>options[:frequency]</tt> seconds (default is 10). Usually used to
  385 + # update a specified div (<tt>options[:update]</tt>) with the results
  386 + # of the remote call. The options for specifying the target with <tt>:url</tt>
  387 + # and defining callbacks is the same as link_to_remote.
  388 + # Examples:
  389 + # # Call get_averages and put its results in 'avg' every 10 seconds
  390 + # # Generates:
  391 + # # new PeriodicalExecuter(function() {new Ajax.Updater('avg', '/grades/get_averages',
  392 + # # {asynchronous:true, evalScripts:true})}, 10)
  393 + # periodically_call_remote(:url => { :action => 'get_averages' }, :update => 'avg')
  394 + #
  395 + # # Call invoice every 10 seconds with the id of the customer
  396 + # # If it succeeds, update the invoice DIV; if it fails, update the error DIV
  397 + # # Generates:
  398 + # # new PeriodicalExecuter(function() {new Ajax.Updater({success:'invoice',failure:'error'},
  399 + # # '/testing/invoice/16', {asynchronous:true, evalScripts:true})}, 10)
  400 + # periodically_call_remote(:url => { :action => 'invoice', :id => customer.id },
  401 + # :update => { :success => "invoice", :failure => "error" }
  402 + #
  403 + # # Call update every 20 seconds and update the new_block DIV
  404 + # # Generates:
  405 + # # new PeriodicalExecuter(function() {new Ajax.Updater('news_block', 'update', {asynchronous:true, evalScripts:true})}, 20)
  406 + # periodically_call_remote(:url => 'update', :frequency => '20', :update => 'news_block')
  407 + #
  408 + def periodically_call_remote(options = {})
  409 + frequency = options[:frequency] || 10 # every ten seconds by default
  410 + code = "new PeriodicalExecuter(function() {#{remote_function(options)}}, #{frequency})"
  411 + javascript_tag(code)
  412 + end
  413 +
  414 + protected
  415 + def build_observer(klass, name, options = {})
  416 + if options[:with] && (options[:with] !~ /[\{=(.]/)
  417 + options[:with] = "'#{options[:with]}=' + encodeURIComponent(value)"
  418 + else
  419 + options[:with] ||= 'value' unless options[:function]
  420 + end
  421 +
  422 + callback = options[:function] || remote_function(options)
  423 + javascript = "new #{klass}('#{name}', "
  424 + javascript << "#{options[:frequency]}, " if options[:frequency]
  425 + javascript << "function(element, value) {"
  426 + javascript << "#{callback}}"
  427 + javascript << ")"
  428 + javascript_tag(javascript)
  429 + end
  430 +end
  431 +
  432 +ActionController::Base.helper PrototypeHelper
vendor/prototype_legacy_helper/test/test_prototype_helper.rb 0 → 100644
@@ -0,0 +1,297 @@ @@ -0,0 +1,297 @@
  1 +if ENV['RAILS_ROOT']
  2 + environment = File.expand_path('vendor/gems/environment', ENV['RAILS_ROOT'])
  3 + require environment if File.exist?("#{environment}.rb")
  4 +end
  5 +
  6 +$:.unshift File.expand_path('../../lib', __FILE__)
  7 +
  8 +require 'test/unit'
  9 +require 'action_view'
  10 +require 'action_controller'
  11 +require 'active_model'
  12 +require 'prototype_helper'
  13 +
  14 +class Bunny < Struct.new(:Bunny, :id)
  15 +end
  16 +
  17 +class Author
  18 + extend ActiveModel::Naming
  19 +
  20 + attr_reader :id
  21 + def save; @id = 1 end
  22 + def new_record?; @id.nil? end
  23 + def name
  24 + @id.nil? ? 'new author' : "author ##{@id}"
  25 + end
  26 +end
  27 +
  28 +class Article
  29 + extend ActiveModel::Naming
  30 +
  31 + attr_reader :id
  32 + attr_reader :author_id
  33 + def save; @id = 1; @author_id = 1 end
  34 + def new_record?; @id.nil? end
  35 + def name
  36 + @id.nil? ? 'new article' : "article ##{@id}"
  37 + end
  38 +end
  39 +
  40 +class Author::Nested < Author; end
  41 +
  42 +class PrototypeHelperTest < ActionView::TestCase
  43 + attr_accessor :formats, :output_buffer, :template_format
  44 +
  45 + def _evaluate_assigns_and_ivars() end
  46 +
  47 + def reset_formats(format)
  48 + @format = format
  49 + end
  50 +
  51 + def setup
  52 + @record = @author = Author.new
  53 + @article = Article.new
  54 + super
  55 + @template = self
  56 + @controller = Class.new do
  57 + def url_for(options)
  58 + if options.is_a?(String)
  59 + options
  60 + else
  61 + url = "http://www.example.com/"
  62 + url << options[:action].to_s if options and options[:action]
  63 + url << "?a=#{options[:a]}" if options && options[:a]
  64 + url << "&b=#{options[:b]}" if options && options[:a] && options[:b]
  65 + url
  66 + end
  67 + end
  68 + end.new
  69 + end
  70 +
  71 +
  72 + def test_observe_form
  73 + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Observer('cart', 2, function(element, value) {new Ajax.Request('http://www.example.com/cart_changed', {asynchronous:true, evalScripts:true, parameters:value})})\n//]]>\n</script>),
  74 + observe_form("cart", :frequency => 2, :url => { :action => "cart_changed" })
  75 + end
  76 +
  77 + def test_observe_form_using_function_for_callback
  78 + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Observer('cart', 2, function(element, value) {alert('Form changed')})\n//]]>\n</script>),
  79 + observe_form("cart", :frequency => 2, :function => "alert('Form changed')")
  80 + end
  81 +
  82 + def test_observe_field
  83 + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {new Ajax.Request('http://www.example.com/reorder_if_empty', {asynchronous:true, evalScripts:true, parameters:value})})\n//]]>\n</script>),
  84 + observe_field("glass", :frequency => 5.minutes, :url => { :action => "reorder_if_empty" })
  85 + end
  86 +
  87 + def test_observe_field_using_with_option
  88 + expected = %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {new Ajax.Request('http://www.example.com/check_value', {asynchronous:true, evalScripts:true, parameters:'id=' + encodeURIComponent(value)})})\n//]]>\n</script>)
  89 + assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => 'id')
  90 + assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => "'id=' + encodeURIComponent(value)")
  91 + end
  92 +
  93 + def test_observe_field_using_json_in_with_option
  94 + expected = %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {new Ajax.Request('http://www.example.com/check_value', {asynchronous:true, evalScripts:true, parameters:{'id':value}})})\n//]]>\n</script>)
  95 + assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => "{'id':value}")
  96 + end
  97 +
  98 + def test_observe_field_using_function_for_callback
  99 + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {alert('Element changed')})\n//]]>\n</script>),
  100 + observe_field("glass", :frequency => 5.minutes, :function => "alert('Element changed')")
  101 + end
  102 +
  103 + def test_observe_field_without_frequency
  104 + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.EventObserver('glass', function(element, value) {new Ajax.Request('http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:value})})\n//]]>\n</script>),
  105 + observe_field("glass")
  106 + end
  107 +
  108 +
  109 + def test_periodically_call_remote
  110 + assert_dom_equal %(<script type="text/javascript">\n//<![CDATA[\nnew PeriodicalExecuter(function() {new Ajax.Updater('schremser_bier', 'http://www.example.com/mehr_bier', {asynchronous:true, evalScripts:true})}, 10)\n//]]>\n</script>),
  111 + periodically_call_remote(:update => "schremser_bier", :url => { :action => "mehr_bier" })
  112 + end
  113 +
  114 + def test_periodically_call_remote_with_frequency
  115 + assert_dom_equal(
  116 + "<script type=\"text/javascript\">\n//<![CDATA[\nnew PeriodicalExecuter(function() {new Ajax.Request('http://www.example.com/', {asynchronous:true, evalScripts:true})}, 2)\n//]]>\n</script>",
  117 + periodically_call_remote(:frequency => 2)
  118 + )
  119 + end
  120 +
  121 +
  122 + def test_form_remote_tag
  123 + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">),
  124 + form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast })
  125 + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({success:'glass_of_beer'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">),
  126 + form_remote_tag(:update => { :success => "glass_of_beer" }, :url => { :action => :fast })
  127 + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({failure:'glass_of_water'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">),
  128 + form_remote_tag(:update => { :failure => "glass_of_water" }, :url => { :action => :fast })
  129 + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({success:'glass_of_beer',failure:'glass_of_water'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">),
  130 + form_remote_tag(:update => { :success => 'glass_of_beer', :failure => "glass_of_water" }, :url => { :action => :fast })
  131 + end
  132 +
  133 + def test_form_remote_tag_with_method
  134 + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\"><div style='margin:0;padding:0;display:inline'><input name='_method' type='hidden' value='put' /></div>),
  135 + form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, :html => { :method => :put })
  136 + end
  137 +
  138 + def test_form_remote_tag_with_block_in_erb
  139 + __in_erb_template = ''
  140 + form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }) { concat "Hello world!" }
  141 + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">Hello world!</form>), output_buffer
  142 + end
  143 +
  144 + def test_on_callbacks
  145 + callbacks = [:uninitialized, :loading, :loaded, :interactive, :complete, :success, :failure]
  146 + callbacks.each do |callback|
  147 + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">),
  148 + form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, callback=>"monkeys();")
  149 + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({success:'glass_of_beer'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">),
  150 + form_remote_tag(:update => { :success => "glass_of_beer" }, :url => { :action => :fast }, callback=>"monkeys();")
  151 + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({failure:'glass_of_beer'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">),
  152 + form_remote_tag(:update => { :failure => "glass_of_beer" }, :url => { :action => :fast }, callback=>"monkeys();")
  153 + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({success:'glass_of_beer',failure:'glass_of_water'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">),
  154 + form_remote_tag(:update => { :success => "glass_of_beer", :failure => "glass_of_water" }, :url => { :action => :fast }, callback=>"monkeys();")
  155 + end
  156 +
  157 + #HTTP status codes 200 up to 599 have callbacks
  158 + #these should work
  159 + 100.upto(599) do |callback|
  160 + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">),
  161 + form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, callback=>"monkeys();")
  162 + end
  163 +
  164 + #test 200 and 404
  165 + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on200:function(request){monkeys();}, on404:function(request){bananas();}, parameters:Form.serialize(this)}); return false;">),
  166 + form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, 200=>"monkeys();", 404=>"bananas();")
  167 +
  168 + #these shouldn't
  169 + 1.upto(99) do |callback|
  170 + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">),
  171 + form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, callback=>"monkeys();")
  172 + end
  173 + 600.upto(999) do |callback|
  174 + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">),
  175 + form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, callback=>"monkeys();")
  176 + end
  177 +
  178 + #test ultimate combo
  179 + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on200:function(request){monkeys();}, on404:function(request){bananas();}, onComplete:function(request){c();}, onFailure:function(request){f();}, onLoading:function(request){c1()}, onSuccess:function(request){s()}, parameters:Form.serialize(this)}); return false;\">),
  180 + form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, :loading => "c1()", :success => "s()", :failure => "f();", :complete => "c();", 200=>"monkeys();", 404=>"bananas();")
  181 + end
  182 +
  183 + def test_remote_form_for_with_record_identification_with_new_record
  184 + remote_form_for(@record, {:html => { :id => 'create-author' }}) {}
  185 +
  186 + expected = %(<form action='#{authors_path}' onsubmit="new Ajax.Request('#{authors_path}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='new_author' id='create-author' method='post'></form>)
  187 + assert_dom_equal expected, output_buffer
  188 + end
  189 +
  190 + def test_remote_form_for_with_record_identification_without_html_options
  191 + remote_form_for(@record) {}
  192 +
  193 + expected = %(<form action='#{authors_path}' onsubmit="new Ajax.Request('#{authors_path}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='new_author' method='post' id='new_author'></form>)
  194 + assert_dom_equal expected, output_buffer
  195 + end
  196 +
  197 + def test_remote_form_for_with_record_identification_with_existing_record
  198 + @record.save
  199 + remote_form_for(@record) {}
  200 +
  201 + expected = %(<form action='#{author_path(@record)}' id='edit_author_1' method='post' onsubmit="new Ajax.Request('#{author_path(@record)}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='edit_author'><div style='margin:0;padding:0;display:inline'><input name='_method' type='hidden' value='put' /></div></form>)
  202 + assert_dom_equal expected, output_buffer
  203 + end
  204 +
  205 + def test_remote_form_for_with_new_object_in_list
  206 + remote_form_for([@author, @article]) {}
  207 +
  208 + expected = %(<form action='#{author_articles_path(@author)}' onsubmit="new Ajax.Request('#{author_articles_path(@author)}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='new_article' method='post' id='new_article'></form>)
  209 + assert_dom_equal expected, output_buffer
  210 + end
  211 +
  212 + def test_remote_form_for_with_existing_object_in_list
  213 + @author.save
  214 + @article.save
  215 + remote_form_for([@author, @article]) {}
  216 +
  217 + expected = %(<form action='#{author_article_path(@author, @article)}' id='edit_article_1' method='post' onsubmit="new Ajax.Request('#{author_article_path(@author, @article)}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='edit_article'><div style='margin:0;padding:0;display:inline'><input name='_method' type='hidden' value='put' /></div></form>)
  218 + assert_dom_equal expected, output_buffer
  219 + end
  220 +
  221 +
  222 + def test_button_to_remote
  223 + assert_dom_equal %(<input class=\"fine\" type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true});\" />),
  224 + button_to_remote("Remote outpost", { :url => { :action => "whatnot" }}, { :class => "fine" })
  225 + assert_dom_equal %(<input type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onComplete:function(request){alert(request.reponseText)}});\" />),
  226 + button_to_remote("Remote outpost", :complete => "alert(request.reponseText)", :url => { :action => "whatnot" })
  227 + assert_dom_equal %(<input type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onSuccess:function(request){alert(request.reponseText)}});\" />),
  228 + button_to_remote("Remote outpost", :success => "alert(request.reponseText)", :url => { :action => "whatnot" })
  229 + assert_dom_equal %(<input type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onFailure:function(request){alert(request.reponseText)}});\" />),
  230 + button_to_remote("Remote outpost", :failure => "alert(request.reponseText)", :url => { :action => "whatnot" })
  231 + assert_dom_equal %(<input type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot?a=10&amp;b=20', {asynchronous:true, evalScripts:true, onFailure:function(request){alert(request.reponseText)}});\" />),
  232 + button_to_remote("Remote outpost", :failure => "alert(request.reponseText)", :url => { :action => "whatnot", :a => '10', :b => '20' })
  233 + end
  234 +
  235 + def test_submit_to_remote
  236 + assert_dom_equal %(<input name=\"More beer!\" onclick=\"new Ajax.Updater('empty_bottle', 'http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)});\" type=\"button\" value=\"1000000\" />),
  237 + submit_to_remote("More beer!", 1_000_000, :update => "empty_bottle")
  238 + end
  239 +
  240 +
  241 + def test_link_to_remote
  242 + assert_dom_equal %(<a class=\"fine\" href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true}); return false;\">Remote outauthor</a>),
  243 + link_to_remote("Remote outauthor", { :url => { :action => "whatnot" }}, { :class => "fine" })
  244 + assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onComplete:function(request){alert(request.responseText)}}); return false;\">Remote outauthor</a>),
  245 + link_to_remote("Remote outauthor", :complete => "alert(request.responseText)", :url => { :action => "whatnot" })
  246 + assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onSuccess:function(request){alert(request.responseText)}}); return false;\">Remote outauthor</a>),
  247 + link_to_remote("Remote outauthor", :success => "alert(request.responseText)", :url => { :action => "whatnot" })
  248 + assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onFailure:function(request){alert(request.responseText)}}); return false;\">Remote outauthor</a>),
  249 + link_to_remote("Remote outauthor", :failure => "alert(request.responseText)", :url => { :action => "whatnot" })
  250 + assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot?a=10&amp;b=20', {asynchronous:true, evalScripts:true, onFailure:function(request){alert(request.responseText)}}); return false;\">Remote outauthor</a>),
  251 + link_to_remote("Remote outauthor", :failure => "alert(request.responseText)", :url => { :action => "whatnot", :a => '10', :b => '20' })
  252 + assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:false, evalScripts:true}); return false;\">Remote outauthor</a>),
  253 + link_to_remote("Remote outauthor", :url => { :action => "whatnot" }, :type => :synchronous)
  254 + assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, insertion:'bottom'}); return false;\">Remote outauthor</a>),
  255 + link_to_remote("Remote outauthor", :url => { :action => "whatnot" }, :position => :bottom)
  256 + end
  257 +
  258 + def test_link_to_remote_html_options
  259 + assert_dom_equal %(<a class=\"fine\" href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true}); return false;\">Remote outauthor</a>),
  260 + link_to_remote("Remote outauthor", { :url => { :action => "whatnot" }, :html => { :class => "fine" } })
  261 + end
  262 +
  263 + def test_link_to_remote_url_quote_escaping
  264 + assert_dom_equal %(<a href="#" onclick="new Ajax.Request('http://www.example.com/whatnot\\\'s', {asynchronous:true, evalScripts:true}); return false;">Remote</a>),
  265 + link_to_remote("Remote", { :url => { :action => "whatnot's" } })
  266 + end
  267 +
  268 + protected
  269 + def request_forgery_protection_token
  270 + nil
  271 + end
  272 +
  273 + def protect_against_forgery?
  274 + false
  275 + end
  276 +
  277 + def create_generator
  278 + block = Proc.new { |*args| yield *args if block_given? }
  279 + JavaScriptGenerator.new self, &block
  280 + end
  281 +
  282 + def author_path(record)
  283 + "/authors/#{record.id}"
  284 + end
  285 +
  286 + def authors_path
  287 + "/authors"
  288 + end
  289 +
  290 + def author_articles_path(author)
  291 + "/authors/#{author.id}/articles"
  292 + end
  293 +
  294 + def author_article_path(author, article)
  295 + "/authors/#{author.id}/articles/#{article.id}"
  296 + end
  297 +end