railties 3.2.12 → 3.2.13.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ca27009202f0c4e3370e35eabb7f92cddd1068c8
4
- data.tar.gz: 4ceb7b9367ab6228983d3332ab25f6a11fdf639d
3
+ metadata.gz: bde618835c8daa65c4ec0af2b94404b6225b636c
4
+ data.tar.gz: 2cf3ce364b6a624f1be913c1fc634e3bfec56200
5
5
  SHA512:
6
- metadata.gz: d7de75d5641ebe1280964b8103325649ef1498e88d601120374ba3b336c731b439d94ae9c35d43cc19825b6fdd91a3696767d3913b69314f4e875e2953658a8d
7
- data.tar.gz: b69a7a7a3b1488a6cfb8a6b7a75f60e9549ca1b86d077c801061234a52fe35683d115b4ae31376782dd3319b31abe7bb5af134554d342fd9def78af778cb3c71
6
+ metadata.gz: 0c33c6eec3542a7fb96a272189738da063f0b828f1bda1d415baad3c0fc26d38baeb9109a5c94710cd88e20ebd94f3ffb0b425cbd5ee1fef4c9abefdffb7ed78
7
+ data.tar.gz: 4cc44097795857097012a1e812eadb78b71966f1698a2e01ff6ec7fc01cf2b73ffeab8324b8242e6ecd27c2f99801c3abf899db8dcbfe2f2532d1a2de8d9ad3e
@@ -1,9 +1,50 @@
1
- ## Rails 3.2.10 ##
1
+ ## unreleased ##
2
+
3
+ * No changes.
4
+
5
+
6
+ ## Rails 3.2.13 (Feb 17, 2013) ##
7
+
8
+ * No changes.
9
+
10
+
11
+ ## Rails 3.2.12 (Feb 11, 2013) ##
12
+
13
+ * No changes.
14
+
15
+
16
+ ## Rails 3.2.11 (Jan 8, 2013) ##
17
+
18
+ * No changes.
19
+
20
+
21
+ ## Rails 3.2.10 (Jan 2, 2013) ##
22
+
23
+ * No changes.
24
+
2
25
 
3
26
  ## Rails 3.2.9 (Nov 12, 2012) ##
4
27
 
28
+ * Quote column names in generates fixture files. This prevents
29
+ conflicts with reserved YAML keywords such as 'yes' and 'no'
30
+ Fix #8612.
31
+ Backport #8616.
32
+
33
+ *Yves Senn*
34
+
35
+ * Engines with a dummy app include the rake tasks of dependencies in the app namespace. [Backport: #8262]
36
+ Fix #8229
37
+
38
+ *Yves Senn*
39
+
40
+ * Add dummy app Rake tasks when --skip-test-unit and --dummy-path is passed to the plugin generator. [Backport #8139]
41
+ Fix #8121
42
+
43
+ *Yves Senn*
44
+
5
45
  * Update supported ruby versions error message in ruby_version_check.rb *Lihan Li*
6
46
 
47
+
7
48
  ## Rails 3.2.8 (Aug 9, 2012) ##
8
49
 
9
50
  * ERB scaffold generator use the `:data => { :confirm => "Text" }` syntax instead of `:confirm`.
@@ -901,8 +901,12 @@ Below is a simple example where we change the Rails behavior to always display t
901
901
 
902
902
  <ruby>
903
903
  ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
904
- errors = Array(instance.error_message).join(',')
905
- %(#{html_tag}<span class="validation-error">&nbsp;#{errors}</span>).html_safe
904
+ if html_tag =~ /\<label/
905
+ html_tag
906
+ else
907
+ errors = Array(instance.error_message).join(',')
908
+ %(#{html_tag}<span class="validation-error">&nbsp;#{errors}</span>).html_safe
909
+ end
906
910
  end
907
911
  </ruby>
908
912
 
@@ -3615,7 +3615,9 @@ File.atomic_write(joined_asset_path) do |cache|
3615
3615
  end
3616
3616
  </ruby>
3617
3617
 
3618
- To accomplish this +atomic_write+ creates a temporary file. That's the file the code in the block actually writes to. On completion, the temporary file is renamed, which is an atomic operation on POSIX systems. If the target file exists +atomic_write+ overwrites it and keeps owners and permissions.
3618
+ To accomplish this `atomic_write` creates a temporary file. That's the file the code in the block actually writes to. On completion, the temporary file is renamed, which is an atomic operation on POSIX systems. If the target file exists `atomic_write` overwrites it and keeps owners and permissions. However there are a few cases where `atomic_write` cannot change the file ownership or permissions, this error is caught and skipped over trusting in the user/filesystem to ensure the file is accessible to the processes that need it.
3619
+
3620
+ NOTE. Due to the chmod operation `atomic_write` performs, if the target file has an ACL set on it this ACL will be recalculated/modified.
3619
3621
 
3620
3622
  WARNING. Note you can't append with +atomic_write+.
3621
3623
 
@@ -277,6 +277,8 @@ h4. Configuring Active Record
277
277
 
278
278
  * +config.active_record.auto_explain_threshold_in_seconds+ configures the threshold for automatic EXPLAINs (+nil+ disables this feature). Queries exceeding the threshold get their query plan logged. Default is 0.5 in development mode.
279
279
 
280
+ * +config.active_record.cache_timestamp_format+ controls the format of the timestamp value in the cache key. Default is +:number+.
281
+
280
282
  The MySQL adapter adds one additional configuration option:
281
283
 
282
284
  * +ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans+ controls whether Active Record will consider all +tinyint(1)+ columns in a MySQL database to be booleans and is true by default.
@@ -447,7 +447,7 @@ h4. Using Ruby-Prof on MRI and REE
447
447
  Add Ruby-Prof to your applications' Gemfile if you want to benchmark/profile under MRI or REE:
448
448
 
449
449
  <ruby>
450
- gem 'ruby-prof', :git => 'git://github.com/wycats/ruby-prof.git'
450
+ gem 'ruby-prof'
451
451
  </ruby>
452
452
 
453
453
  Now run +bundle install+ and you're ready to go.
@@ -157,9 +157,9 @@ The default directory structure of a generated Ruby on Rails application:
157
157
 
158
158
  |-- app
159
159
  | |-- assets
160
- | |-- images
161
- | |-- javascripts
162
- | `-- stylesheets
160
+ | | |-- images
161
+ | | |-- javascripts
162
+ | | `-- stylesheets
163
163
  | |-- controllers
164
164
  | |-- helpers
165
165
  | |-- mailers
@@ -173,6 +173,7 @@ The default directory structure of a generated Ruby on Rails application:
173
173
  |-- db
174
174
  |-- doc
175
175
  |-- lib
176
+ | |-- assets
176
177
  | `-- tasks
177
178
  |-- log
178
179
  |-- public
@@ -184,13 +185,12 @@ The default directory structure of a generated Ruby on Rails application:
184
185
  | |-- performance
185
186
  | `-- unit
186
187
  |-- tmp
187
- | |-- cache
188
- | |-- pids
189
- | |-- sessions
190
- | `-- sockets
188
+ | `-- cache
189
+ | `-- assets
191
190
  `-- vendor
192
191
  |-- assets
193
- `-- stylesheets
192
+ | |-- javascripts
193
+ | `-- stylesheets
194
194
  `-- plugins
195
195
 
196
196
  app
@@ -204,7 +204,7 @@ task :default => :test
204
204
  end
205
205
 
206
206
  def create_test_dummy_files
207
- return if options[:skip_test_unit] && options[:dummy_path] == 'test/dummy'
207
+ return unless with_dummy_app?
208
208
  create_dummy_app
209
209
  end
210
210
 
@@ -214,6 +214,18 @@ task :default => :test
214
214
 
215
215
  public_task :apply_rails_template, :run_bundle
216
216
 
217
+ def name
218
+ @name ||= begin
219
+ # same as ActiveSupport::Inflector#underscore except not replacing '-'
220
+ underscored = original_name.dup
221
+ underscored.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
222
+ underscored.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
223
+ underscored.downcase!
224
+
225
+ underscored
226
+ end
227
+ end
228
+
217
229
  protected
218
230
 
219
231
  def app_templates_dir
@@ -242,6 +254,10 @@ task :default => :test
242
254
  options[:mountable]
243
255
  end
244
256
 
257
+ def with_dummy_app?
258
+ options[:skip_test_unit].blank? || options[:dummy_path] != 'test/dummy'
259
+ end
260
+
245
261
  def self.banner
246
262
  "rails plugin new #{self.arguments.map(&:usage).join(' ')} [options]"
247
263
  end
@@ -250,18 +266,6 @@ task :default => :test
250
266
  @original_name ||= File.basename(destination_root)
251
267
  end
252
268
 
253
- def name
254
- @name ||= begin
255
- # same as ActiveSupport::Inflector#underscore except not replacing '-'
256
- underscored = original_name.dup
257
- underscored.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
258
- underscored.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
259
- underscored.downcase!
260
-
261
- underscored
262
- end
263
- end
264
-
265
269
  def camelized
266
270
  @camelized ||= name.gsub(/\W/, '_').squeeze('_').camelize
267
271
  end
@@ -282,7 +286,7 @@ task :default => :test
282
286
  dummy_application_path = File.expand_path("#{dummy_path}/config/application.rb", destination_root)
283
287
  unless options[:pretend] || !File.exists?(dummy_application_path)
284
288
  contents = File.read(dummy_application_path)
285
- contents[(contents.index("module Dummy"))..-1]
289
+ contents[(contents.index(/module ([\w]+)\n(.*)class Application/m))..-1]
286
290
  end
287
291
  end
288
292
  end
@@ -20,7 +20,7 @@ RDoc::Task.new(:rdoc) do |rdoc|
20
20
  rdoc.rdoc_files.include('lib/**/*.rb')
21
21
  end
22
22
 
23
- <% if full? && !options[:skip_active_record] && !options[:skip_test_unit] -%>
23
+ <% if full? && !options[:skip_active_record] && with_dummy_app? -%>
24
24
  APP_RAKEFILE = File.expand_path("../<%= dummy_path -%>/Rakefile", __FILE__)
25
25
  load 'rails/tasks/engine.rake'
26
26
  <% end %>
@@ -12,7 +12,7 @@ require "active_resource/railtie"
12
12
  <%= comment_if :skip_test_unit %>require "rails/test_unit/railtie"
13
13
  <% end -%>
14
14
 
15
- Bundler.require
15
+ Bundler.require(*Rails.groups)
16
16
  require "<%= name %>"
17
17
 
18
18
  <%= application_definition %>
@@ -3,6 +3,9 @@ require 'rails/generators/test_unit'
3
3
  module TestUnit
4
4
  module Generators
5
5
  class ModelGenerator < Base
6
+
7
+ RESERVED_YAML_KEYWORDS = %w(y yes n no true false on off null)
8
+
6
9
  argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
7
10
  class_option :fixture, :type => :boolean
8
11
 
@@ -19,6 +22,15 @@ module TestUnit
19
22
  template 'fixtures.yml', File.join('test/fixtures', class_path, "#{plural_file_name}.yml")
20
23
  end
21
24
  end
25
+
26
+ private
27
+ def yaml_key_value(key, value)
28
+ if RESERVED_YAML_KEYWORDS.include?(key.downcase)
29
+ "'#{key}': #{value}"
30
+ else
31
+ "#{key}: #{value}"
32
+ end
33
+ end
22
34
  end
23
35
  end
24
36
  end
@@ -3,12 +3,12 @@
3
3
  <% unless attributes.empty? -%>
4
4
  one:
5
5
  <% attributes.each do |attribute| -%>
6
- <%= attribute.name %>: <%= attribute.default %>
6
+ <%= yaml_key_value(attribute.name, attribute.default) %>
7
7
  <% end -%>
8
8
 
9
9
  two:
10
10
  <% attributes.each do |attribute| -%>
11
- <%= attribute.name %>: <%= attribute.default %>
11
+ <%= yaml_key_value(attribute.name, attribute.default) %>
12
12
  <% end -%>
13
13
  <% else -%>
14
14
  # This model initially had no columns defined. If you add columns to the
@@ -2,8 +2,8 @@ module Rails
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 3
4
4
  MINOR = 2
5
- TINY = 12
6
- PRE = nil
5
+ TINY = 13
6
+ PRE = "rc1"
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
9
9
  end
metadata CHANGED
@@ -1,75 +1,75 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: railties
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.12
4
+ version: 3.2.13.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-02-11 00:00:00.000000000 Z
11
+ date: 2013-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: 0.8.7
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.8.7
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rack-ssl
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
33
  version: 1.3.2
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
40
  version: 1.3.2
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: thor
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - '>='
46
46
  - !ruby/object:Gem::Version
47
47
  version: 0.14.6
48
- - - "<"
48
+ - - <
49
49
  - !ruby/object:Gem::Version
50
50
  version: '2.0'
51
51
  type: :runtime
52
52
  prerelease: false
53
53
  version_requirements: !ruby/object:Gem::Requirement
54
54
  requirements:
55
- - - ">="
55
+ - - '>='
56
56
  - !ruby/object:Gem::Version
57
57
  version: 0.14.6
58
- - - "<"
58
+ - - <
59
59
  - !ruby/object:Gem::Version
60
60
  version: '2.0'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: rdoc
63
63
  requirement: !ruby/object:Gem::Requirement
64
64
  requirements:
65
- - - "~>"
65
+ - - ~>
66
66
  - !ruby/object:Gem::Version
67
67
  version: '3.4'
68
68
  type: :runtime
69
69
  prerelease: false
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
- - - "~>"
72
+ - - ~>
73
73
  - !ruby/object:Gem::Version
74
74
  version: '3.4'
75
75
  - !ruby/object:Gem::Dependency
@@ -78,30 +78,29 @@ dependencies:
78
78
  requirements:
79
79
  - - '='
80
80
  - !ruby/object:Gem::Version
81
- version: 3.2.12
81
+ version: 3.2.13.rc1
82
82
  type: :runtime
83
83
  prerelease: false
84
84
  version_requirements: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - '='
87
87
  - !ruby/object:Gem::Version
88
- version: 3.2.12
88
+ version: 3.2.13.rc1
89
89
  - !ruby/object:Gem::Dependency
90
90
  name: actionpack
91
91
  requirement: !ruby/object:Gem::Requirement
92
92
  requirements:
93
93
  - - '='
94
94
  - !ruby/object:Gem::Version
95
- version: 3.2.12
95
+ version: 3.2.13.rc1
96
96
  type: :runtime
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - '='
101
101
  - !ruby/object:Gem::Version
102
- version: 3.2.12
103
- description: ! 'Rails internals: application bootup, plugins, generators, and rake
104
- tasks.'
102
+ version: 3.2.13.rc1
103
+ description: 'Rails internals: application bootup, plugins, generators, and rake tasks.'
105
104
  email: david@loudthinking.com
106
105
  executables:
107
106
  - rails
@@ -332,7 +331,6 @@ files:
332
331
  - guides/source/active_record_validations_callbacks.textile
333
332
  - guides/source/active_resource_basics.textile
334
333
  - guides/source/active_support_core_extensions.textile
335
- - guides/source/ajax_on_rails.textile
336
334
  - guides/source/api_documentation_guidelines.textile
337
335
  - guides/source/asset_pipeline.textile
338
336
  - guides/source/association_basics.textile
@@ -596,23 +594,23 @@ licenses: []
596
594
  metadata: {}
597
595
  post_install_message:
598
596
  rdoc_options:
599
- - "--exclude"
600
- - "."
597
+ - --exclude
598
+ - .
601
599
  require_paths:
602
600
  - lib
603
601
  required_ruby_version: !ruby/object:Gem::Requirement
604
602
  requirements:
605
- - - ">="
603
+ - - '>='
606
604
  - !ruby/object:Gem::Version
607
605
  version: 1.8.7
608
606
  required_rubygems_version: !ruby/object:Gem::Requirement
609
607
  requirements:
610
- - - ">="
608
+ - - '>'
611
609
  - !ruby/object:Gem::Version
612
- version: '0'
610
+ version: 1.3.1
613
611
  requirements: []
614
612
  rubyforge_project:
615
- rubygems_version: 2.0.0.rc.2
613
+ rubygems_version: 2.0.0
616
614
  signing_key:
617
615
  specification_version: 4
618
616
  summary: Tools for creating, working with, and running Rails applications.
@@ -1,267 +0,0 @@
1
- h2. AJAX on Rails
2
-
3
- This guide covers the built-in Ajax/JavaScript functionality of Rails (and more); it will enable you to create rich and dynamic AJAX applications with ease! We will cover the following topics:
4
-
5
- * Quick introduction to AJAX and related technologies
6
- * Unobtrusive JavaScript helpers with drivers for Prototype, jQuery etc
7
- * Testing JavaScript functionality
8
-
9
- endprologue.
10
-
11
- h3. Hello AJAX - a Quick Intro
12
-
13
- You'll need the basics of DOM, HTTP requests and other topics discussed here to really understand Ajax on Rails.
14
-
15
- h4. Asynchronous JavaScript + XML
16
-
17
- Basic terminology, new style of creating web apps
18
-
19
- h4. The DOM
20
-
21
- basics of the DOM, how is it built, properties, features, why is it central to AJAX
22
-
23
- h4. Standard HTML communication vs AJAX
24
-
25
- How do 'standard' and AJAX requests differ, why does this matter for understanding AJAX on Rails (tie in for *_remote helpers, the next section)
26
-
27
- h3. Built-in Rails Helpers
28
-
29
- Rails 3.1 ships with "jQuery":http://jquery.com as the default JavaScript library. The Gemfile contains <tt>gem 'jquery-rails'</tt> which makes the jQuery files available to the application automatically. This can be accessed as:
30
-
31
- <ruby>
32
- javascript_include_tag :defaults
33
- </ruby>
34
-
35
- h4. Examples
36
-
37
- All the remote_method helpers has been removed. To make them working with AJAX, simply pass the <tt>:remote => true</tt> option to the original non-remote method.
38
-
39
- <ruby>
40
- button_to "New", :action => "new", :form_class => "new-thing"
41
- </ruby>
42
-
43
- will produce
44
-
45
- <html>
46
- <form method="post" action="/controller/new" class="new-thing">
47
- <div><input value="New" type="submit" /></div>
48
- </form>
49
- </html>
50
-
51
- <ruby>
52
- button_to "Create", :action => "create", :remote => true, :form => { "data-type" => "json" }
53
- </ruby>
54
-
55
- will produce
56
-
57
- <html>
58
- <form method="post" action="/images/create" class="button_to" data-remote="true" data-type="json">
59
- <div><input value="Create" type="submit" /></div>
60
- </form>
61
- </html>
62
-
63
- <ruby>
64
- button_to "Delete Image", { :action => "delete", :id => @image.id },
65
- :confirm => "Are you sure?", :method => :delete
66
- </ruby>
67
-
68
- will produce
69
-
70
- <html>
71
- <form method="post" action="/images/delete/1" class="button_to">
72
- <div>
73
- <input type="hidden" name="_method" value="delete" />
74
- <input data-confirm='Are you sure?' value="Delete" type="submit" />
75
- </div>
76
- </form>
77
- </html>
78
-
79
- <ruby>
80
- button_to('Destroy', 'http://www.example.com', :confirm => 'Are you sure?',
81
- :method => "delete", :remote => true, :disable_with => 'loading...')
82
- </ruby>
83
-
84
- will produce
85
-
86
- <html>
87
- <form class='button_to' method='post' action='http://www.example.com' data-remote='true'>
88
- <div>
89
- <input name='_method' value='delete' type='hidden' />
90
- <input value='Destroy' type='submit' disable_with='loading...' data-confirm='Are you sure?' />
91
- </div>
92
- </form>
93
- </html>
94
-
95
- You can also choose to use Prototype instead of jQuery and specify the option using +-j+ switch while generating the application.
96
-
97
- <shell>
98
- rails new app_name -j prototype
99
- </shell>
100
-
101
- You are ready to add some AJAX love to your Rails app!
102
-
103
- h4. The Quintessential AJAX Rails Helper: link_to_remote
104
-
105
- Let's start with what is probably the most often used helper: +link_to_remote+. It has an interesting feature from the documentation point of view: the options supplied to +link_to_remote+ are shared by all other AJAX helpers, so learning the mechanics and options of +link_to_remote+ is a great help when using other helpers.
106
-
107
- The signature of +link_to_remote+ function is the same as that of the standard +link_to+ helper:
108
-
109
- <ruby>
110
- def link_to_remote(name, options = {}, html_options = nil)
111
- </ruby>
112
-
113
- And here is a simple example of link_to_remote in action:
114
-
115
- <ruby>
116
- link_to_remote "Add to cart",
117
- :url => add_to_cart_url(product.id),
118
- :update => "cart"
119
- </ruby>
120
-
121
- * The very first parameter, a string, is the text of the link which appears on the page.
122
- * The second parameter, the +options+ hash is the most interesting part as it has the AJAX specific stuff:
123
- ** *:url* This is the only parameter that is always required to generate the simplest remote link (technically speaking, it is not required, you can pass an empty +options+ hash to +link_to_remote+ - but in this case the URL used for the POST request will be equal to your current URL which is probably not your intention). This URL points to your AJAX action handler. The URL is typically specified by Rails REST view helpers, but you can use the +url_for+ format too.
124
- ** *:update* Specifying a DOM id of the element we would like to update. The above example demonstrates the simplest way of accomplishing this - however, we are in trouble if the server responds with an error message because that will be injected into the page too! However, Rails has a solution for this situation:
125
-
126
- <ruby>
127
- link_to_remote "Add to cart",
128
- :url => add_to_cart_url(product),
129
- :update => { :success => "cart", :failure => "error" }
130
- </ruby>
131
-
132
- If the server returns 200, the output of the above example is equivalent to our first, simple one. However, in case of error, the element with the DOM id +error+ is updated rather than the +cart+ element.
133
-
134
- ** *position* By default (i.e. when not specifying this option, like in the examples before) the response is injected into the element with the specified DOM id, replacing the original content of the element (if there was any). You might want to alter this behavior by keeping the original content - the only question is where to place the new content? This can specified by the +position+ parameter, with four possibilities:
135
- *** +:before+ Inserts the response text just before the target element. More precisely, it creates a text node from the response and inserts it as the left sibling of the target element.
136
- *** +:after+ Similar behavior to +:before+, but in this case the response is inserted after the target element.
137
- *** +:top+ Inserts the text into the target element, before it's original content. If the target element was empty, this is equivalent with not specifying +:position+ at all.
138
- *** +:bottom+ The counterpart of +:top+: the response is inserted after the target element's original content.
139
-
140
- A typical example of using +:bottom+ is inserting a new &lt;li&gt; element into an existing list:
141
-
142
- <ruby>
143
- link_to_remote "Add new item",
144
- :url => items_url,
145
- :update => 'item_list',
146
- :position => :bottom
147
- </ruby>
148
-
149
- ** *:method* Most typically you want to use a POST request when adding a remote link to your view so this is the default behavior. However, sometimes you'll want to update (PUT) or delete/destroy (DELETE) something and you can specify this with the +:method+ option. Let's see an example for a typical AJAX link for deleting an item from a list:
150
-
151
- <ruby>
152
- link_to_remote "Delete the item",
153
- :url => item_url(item),
154
- :method => :delete
155
- </ruby>
156
-
157
- Note that if we wouldn't override the default behavior (POST), the above snippet would route to the create action rather than destroy.
158
-
159
- ** *JavaScript filters* You can customize the remote call further by wrapping it with some JavaScript code. Let's say in the previous example, when deleting a link, you'd like to ask for a confirmation by showing a simple modal text box to the user. This is a typical example what you can accomplish with these options - let's see them one by one:
160
- *** +:confirm+ =&gt; +msg+ Pops up a JavaScript confirmation dialog, displaying +msg+. If the user chooses 'OK', the request is launched, otherwise canceled.
161
- *** +:condition+ =&gt; +code+ Evaluates +code+ (which should evaluate to a boolean) and proceeds if it's true, cancels the request otherwise.
162
- *** +:before+ =&gt; +code+ Evaluates the +code+ just before launching the request. The output of the code has no influence on the execution. Typically used show a progress indicator (see this in action in the next example).
163
- *** +:after+ =&gt; +code+ Evaluates the +code+ after launching the request. Note that this is different from the +:success+ or +:complete+ callback (covered in the next section) since those are triggered after the request is completed, while the code snippet passed to +:after+ is evaluated after the remote call is made. A common example is to disable elements on the page or otherwise prevent further action while the request is completed.
164
- *** +:submit+ =&gt; +dom_id+ This option does not make sense for +link_to_remote+, but we'll cover it for the sake of completeness. By default, the parent element of the form elements the user is going to submit is the current form - use this option if you want to change the default behavior. By specifying this option you can change the parent element to the element specified by the DOM id +dom_id+.
165
- *** +:with+ &gt; +code+ The JavaScript code snippet in +code+ is evaluated and added to the request URL as a parameter (or set of parameters). Therefore, +code+ should return a valid URL query string (like "item_type=8" or "item_type=8&sort=true"). Usually you want to obtain some value(s) from the page - let's see an example:
166
-
167
- <ruby>
168
- link_to_remote "Update record",
169
- :url => record_url(record),
170
- :method => :put,
171
- :with => "'status=' <plus> 'encodeURIComponent($('status').value) <plus> '&completed=' <plus> $('completed')"
172
- </ruby>
173
-
174
- This generates a remote link which adds 2 parameters to the standard URL generated by Rails, taken from the page (contained in the elements matched by the 'status' and 'completed' DOM id).
175
-
176
- ** *Callbacks* Since an AJAX call is typically asynchronous, as it's name suggests (this is not a rule, and you can fire a synchronous request - see the last option, +:type+) your only way of communicating with a request once it is fired is via specifying callbacks. There are six options at your disposal (in fact 508, counting all possible response types, but these six are the most frequent and therefore specified by a constant):
177
- *** +:loading:+ =&gt; +code+ The request is in the process of receiving the data, but the transfer is not completed yet.
178
- *** +:loaded:+ =&gt; +code+ The transfer is completed, but the data is not processed and returned yet
179
- *** +:interactive:+ =&gt; +code+ One step after +:loaded+: The data is fully received and being processed
180
- *** +:success:+ =&gt; +code+ The data is fully received, parsed and the server responded with "200 OK"
181
- *** +:failure:+ =&gt; +code+ The data is fully received, parsed and the server responded with *anything* but "200 OK" (typically 404 or 500, but in general with any status code ranging from 100 to 509)
182
- *** +:complete:+ =&gt; +code+ The combination of the previous two: The request has finished receiving and parsing the data, and returned a status code (which can be anything).
183
- *** Any other status code ranging from 100 to 509: Additionally you might want to check for other HTTP status codes, such as 404. In this case simply use the status code as a number:
184
- <ruby>
185
- link_to_remote "Add new item",
186
- :url => items_url,
187
- :update => "item_list",
188
- 404 => "alert('Item not found!')"
189
- </ruby>
190
- Let's see a typical example for the most frequent callbacks, +:success+, +:failure+ and +:complete+ in action:
191
-
192
- <ruby>
193
- link_to_remote "Add new item",
194
- :url => items_url,
195
- :update => "item_list",
196
- :before => "$('progress').show()",
197
- :complete => "$('progress').hide()",
198
- :success => "display_item_added(request)",
199
- :failure => "display_error(request)"
200
- </ruby>
201
-
202
- ** *:type* If you want to fire a synchronous request for some obscure reason (blocking the browser while the request is processed and doesn't return a status code), you can use the +:type+ option with the value of +:synchronous+.
203
- * Finally, using the +html_options+ parameter you can add HTML attributes to the generated tag. It works like the same parameter of the +link_to+ helper. There are interesting side effects for the +href+ and +onclick+ parameters though:
204
- ** If you specify the +href+ parameter, the AJAX link will degrade gracefully, i.e. the link will point to the URL even if JavaScript is disabled in the client browser
205
- ** +link_to_remote+ gains it's AJAX behavior by specifying the remote call in the onclick handler of the link. If you supply +html_options[:onclick]+ you override the default behavior, so use this with care!
206
-
207
- We are finished with +link_to_remote+. I know this is quite a lot to digest for one helper function, but remember, these options are common for all the rest of the Rails view helpers, so we will take a look at the differences / additional parameters in the next sections.
208
-
209
- h4. AJAX Forms
210
-
211
- There are three different ways of adding AJAX forms to your view using Rails Prototype helpers. They are slightly different, but striving for the same goal: instead of submitting the form using the standard HTTP request/response cycle, it is submitted asynchronously, thus not reloading the page. These methods are the following:
212
-
213
- * +remote_form_for+ (and it's alias +form_remote_for+) is tied to Rails most tightly of the three since it takes a resource, model or array of resources (in case of a nested resource) as a parameter.
214
- * +form_remote_tag+ AJAXifies the form by serializing and sending it's data in the background
215
- * +submit_to_remote+ and +button_to_remote+ is more rarely used than the previous two. Rather than creating an AJAX form, you add a button/input
216
-
217
- Let's see them in action one by one!
218
-
219
- h5. +remote_form_for+
220
-
221
- h5. +form_remote_tag+
222
-
223
- h5. +submit_to_remote+
224
-
225
- h4. Observing Elements
226
-
227
- h5. +observe_field+
228
-
229
- h5. +observe_form+
230
-
231
- h4. Calling a Function Periodically
232
-
233
- h5. +periodically_call_remote+
234
-
235
-
236
- h4. Miscellaneous Functionality
237
-
238
- h5. +remote_function+
239
-
240
- h5. +update_page+
241
-
242
- h4. Serving JavaScript
243
-
244
- First we'll check out how to send JavaScript to the server manually. You are practically never going to need this, but it's interesting to understand what's going on under the hood.
245
-
246
- <ruby>
247
- def javascript_test
248
- render :text => "alert('Hello, world!')",
249
- :content_type => "text/javascript"
250
- end
251
- </ruby>
252
-
253
- (Note: if you want to test the above method, create a +link_to_remote+ with a single parameter - +:url+, pointing to the +javascript_test+ action)
254
-
255
- What happens here is that by specifying the Content-Type header variable, we instruct the browser to evaluate the text we are sending over (rather than displaying it as plain text, which is the default behavior).
256
-
257
- h3. Testing JavaScript
258
-
259
- JavaScript testing reminds me the definition of the world 'classic' by Mark Twain: "A classic is something that everybody wants to have read and nobody wants to read." It's similar with JavaScript testing: everyone would like to have it, yet it's not done by too much developers as it is tedious, complicated, there is a proliferation of tools and no consensus/accepted best practices, but we will nevertheless take a stab at it:
260
-
261
- * (Fire)Watir
262
- * Selenium
263
- * Celerity/Culerity
264
- * Cucumber+Webrat
265
- * Mention stuff like screw.unit/jsSpec
266
-
267
- Note to self: check out the RailsConf JS testing video