delayed_form_observer 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.specification +9 -9
- data/README.rdoc +110 -0
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/delayed_form_observer.gemspec +6 -5
- data/lib/generators/delayed_form_observer/delayed_form_observer_generator.rb +20 -0
- data/lib/generators/delayed_form_observer/templates/prototype_extension.js +20 -0
- metadata +9 -7
- data/README +0 -13
data/.specification
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: delayed_form_observer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Coroutine
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2010-07-
|
20
|
+
date: 2010-07-30 00:00:00 -05:00
|
21
21
|
default_executable:
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|
@@ -52,19 +52,18 @@ dependencies:
|
|
52
52
|
version: 2.3.4
|
53
53
|
type: :development
|
54
54
|
version_requirements: *id002
|
55
|
-
description: Delayed Form Observer provides Rails with timed form observers that do not create race conditions.
|
55
|
+
description: Delayed Form Observer provides Rails with timed form observers that do not create race conditions. The gem extends Prototype and adds a Rails PrototypeHelper to use this new object.
|
56
56
|
email: gems@coroutine.com
|
57
57
|
executables: []
|
58
58
|
|
59
59
|
extensions: []
|
60
60
|
|
61
61
|
extra_rdoc_files:
|
62
|
-
- README
|
62
|
+
- README.rdoc
|
63
63
|
files:
|
64
64
|
- .gitignore
|
65
65
|
- .specification
|
66
66
|
- MIT-LICENSE
|
67
|
-
- README
|
68
67
|
- Rakefile
|
69
68
|
- VERSION
|
70
69
|
- delayed_form_observer.gemspec
|
@@ -76,8 +75,9 @@ files:
|
|
76
75
|
- lib/generators/delayed_form_observer/delayed_form_observer_generator.rb
|
77
76
|
- lib/generators/delayed_form_observer/templates/prototype_extension.js
|
78
77
|
- rails/init.rb
|
79
|
-
- test/
|
78
|
+
- test/delayed_form_observer/helpers_test.rb
|
80
79
|
- test/test_helper.rb
|
80
|
+
- README.rdoc
|
81
81
|
has_rdoc: true
|
82
82
|
homepage: http://github.com/coroutine/delayed_form_observer
|
83
83
|
licenses: []
|
@@ -113,6 +113,6 @@ signing_key:
|
|
113
113
|
specification_version: 3
|
114
114
|
summary: Delayed Form Observer provides Rails with timed form observers that do not create race conditions.
|
115
115
|
test_files:
|
116
|
-
- test/
|
116
|
+
- test/delayed_form_observer/helpers_test.rb
|
117
117
|
- test/test_helper.rb
|
118
118
|
|
data/README.rdoc
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
= Delayed Form Observer
|
2
|
+
|
3
|
+
Delayed Form Observer eliminates a race condition in a common Rails search implementation.
|
4
|
+
|
5
|
+
Large lists are often made more manageable by positioning a search textbox above the list
|
6
|
+
and attaching a Prototype timed observer to the textbox. A javascript object is checking
|
7
|
+
the textbox for changes and remotely submitting the search form every so many milliseconds.
|
8
|
+
The user experiences this as a list whose items change with every keystroke.
|
9
|
+
|
10
|
+
The pattern works fine as long as the search query is working against a simple dataset. The
|
11
|
+
asynchronous requests come back in the same order they are sent.
|
12
|
+
|
13
|
+
But if the dataset is not simple, search #1 might return *after* search #2. A user who types
|
14
|
+
in "J" then "o" initiates two searches against a list of contacts. "J" matches both Jim and
|
15
|
+
John; "Jo" only matches John. But since it is easier for the database to return fewer records,
|
16
|
+
what if we get [John] before we get [Jim,John]? The textbox will show "Jo" but the list will
|
17
|
+
show Jim and John. Oops.
|
18
|
+
|
19
|
+
|
20
|
+
== A Gap in Prototype
|
21
|
+
|
22
|
+
The problem exists primarily because Prototype only offers two basic kinds of observers: timed
|
23
|
+
observers and event-driven observers.
|
24
|
+
|
25
|
+
We've already explained the issue with the timed observer.
|
26
|
+
|
27
|
+
Event-driven observers don't result in race conditions but they cause far too many search
|
28
|
+
requests. Every keystroke would result in a query.
|
29
|
+
|
30
|
+
What we want is an event-driven observer with a delay before the request is made. If a new
|
31
|
+
event arrives during the delay window, the previous event is abandoned and delay counter is
|
32
|
+
reset.
|
33
|
+
|
34
|
+
Allow me to introduce you to Delayed Form Observer.
|
35
|
+
|
36
|
+
|
37
|
+
== Usage
|
38
|
+
|
39
|
+
The generator that comes with this gem adds the required Prototype extension to your application's
|
40
|
+
public javascripts directory. It also adds an ActionView Prototype helper for creating a form
|
41
|
+
observer that uses this new Prototype object.
|
42
|
+
|
43
|
+
The helper uses the same arguments as <tt>observe_form</tt>.
|
44
|
+
|
45
|
+
# Observe changes to the search form
|
46
|
+
<%= delayed_observe_form "MySearchForm", :url => { :action => :index }, :method => :get, :frequency => 0.5
|
47
|
+
|
48
|
+
|
49
|
+
If you need more help than that, maybe you should just look at the source code. There are a ton of comments
|
50
|
+
in there.
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
== Helpful Links
|
55
|
+
|
56
|
+
* <b>Repository:</b> http://github.com/coroutine/delayed_form_observer
|
57
|
+
* <b>Gem:</b> http://rubygems.org/gems/delayed_form_observer
|
58
|
+
* <b>Authors:</b> http://coroutine.com
|
59
|
+
|
60
|
+
|
61
|
+
|
62
|
+
== Prerequisites
|
63
|
+
|
64
|
+
As you might have guessed, a gem that extends Prototype requires Prototype.
|
65
|
+
|
66
|
+
But since the gem was designed as a Rails extension, chances are Prototype
|
67
|
+
is already included.
|
68
|
+
|
69
|
+
* <b>Prototype:</b> http://prototypejs.org
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
== Installation & Generators
|
74
|
+
|
75
|
+
Install as a gem from RubyGems.org and add a gem dependency in the appropriate file.
|
76
|
+
|
77
|
+
$ gem install delayed_form_observer
|
78
|
+
|
79
|
+
Or install as a plugin.
|
80
|
+
|
81
|
+
$ script/plugin install git://github.com/coroutine/delayed_form_observer.git
|
82
|
+
|
83
|
+
Either way, then generate the required javascript file.
|
84
|
+
|
85
|
+
$ script/generate delayed_form_observer
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
== License
|
90
|
+
|
91
|
+
Copyright (c) 2010 {Coroutine LLC}[http://coroutine.com].
|
92
|
+
|
93
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
94
|
+
a copy of this software and associated documentation files (the
|
95
|
+
"Software"), to deal in the Software without restriction, including
|
96
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
97
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
98
|
+
permit persons to whom the Software is furnished to do so, subject to
|
99
|
+
the following conditions:
|
100
|
+
|
101
|
+
The above copyright notice and this permission notice shall be
|
102
|
+
included in all copies or substantial portions of the Software.
|
103
|
+
|
104
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
105
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
106
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
107
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
108
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
109
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
110
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
CHANGED
@@ -29,7 +29,7 @@ end
|
|
29
29
|
begin
|
30
30
|
Jeweler::Tasks.new do |gemspec|
|
31
31
|
gemspec.authors = ["Coroutine", "Tim Lowrimore", "John Dugan"]
|
32
|
-
gemspec.description = "Delayed Form Observer provides Rails with timed form observers that do not create race conditions."
|
32
|
+
gemspec.description = "Delayed Form Observer provides Rails with timed form observers that do not create race conditions. The gem extends Prototype and adds a Rails PrototypeHelper to use this new object."
|
33
33
|
gemspec.email = "gems@coroutine.com"
|
34
34
|
gemspec.homepage = "http://github.com/coroutine/delayed_form_observer"
|
35
35
|
gemspec.name = "delayed_form_observer"
|
@@ -39,7 +39,7 @@ begin
|
|
39
39
|
gemspec.add_development_dependency("activesupport", ">=2.3.4")
|
40
40
|
|
41
41
|
gemspec.files.include("generators/**/*", "lib/**/*")
|
42
|
-
gemspec.files.include("test
|
42
|
+
gemspec.files.include("test/**/*")
|
43
43
|
end
|
44
44
|
Jeweler::GemcutterTasks.new
|
45
45
|
rescue LoadError
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
@@ -5,21 +5,20 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{delayed_form_observer}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Coroutine", "Tim Lowrimore", "John Dugan"]
|
12
|
-
s.date = %q{2010-07-
|
13
|
-
s.description = %q{Delayed Form Observer provides Rails with timed form observers that do not create race conditions.}
|
12
|
+
s.date = %q{2010-07-30}
|
13
|
+
s.description = %q{Delayed Form Observer provides Rails with timed form observers that do not create race conditions. The gem extends Prototype and adds a Rails PrototypeHelper to use this new object.}
|
14
14
|
s.email = %q{gems@coroutine.com}
|
15
15
|
s.extra_rdoc_files = [
|
16
|
-
"README"
|
16
|
+
"README.rdoc"
|
17
17
|
]
|
18
18
|
s.files = [
|
19
19
|
".gitignore",
|
20
20
|
".specification",
|
21
21
|
"MIT-LICENSE",
|
22
|
-
"README",
|
23
22
|
"Rakefile",
|
24
23
|
"VERSION",
|
25
24
|
"delayed_form_observer.gemspec",
|
@@ -28,6 +27,8 @@ Gem::Specification.new do |s|
|
|
28
27
|
"init.rb",
|
29
28
|
"lib/delayed_form_observer.rb",
|
30
29
|
"lib/delayed_form_observer/helpers.rb",
|
30
|
+
"lib/generators/delayed_form_observer/delayed_form_observer_generator.rb",
|
31
|
+
"lib/generators/delayed_form_observer/templates/prototype_extension.js",
|
31
32
|
"rails/init.rb",
|
32
33
|
"test/delayed_form_observer/helpers_test.rb",
|
33
34
|
"test/test_helper.rb"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "rails/generators"
|
2
|
+
|
3
|
+
|
4
|
+
class DelayedFormObserverGenerator < Rails::Generators::Base
|
5
|
+
|
6
|
+
# This call establishes the path to the templates directory.
|
7
|
+
#
|
8
|
+
def self.source_root
|
9
|
+
File.join(File.dirname(__FILE__), "templates")
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
# This method copies javascript files to the corresponding
|
14
|
+
# public directories.
|
15
|
+
#
|
16
|
+
def generate_assets
|
17
|
+
copy_file "prototype_extension.js", "public/javascripts/prototype_delayed_form_observer.js"
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Form.DelayedObserver = Class.create(Form.Observer, {
|
2
|
+
initialize: function($super, element, frequency, callback) {
|
3
|
+
$super(element, frequency, callback);
|
4
|
+
this.invocationPending = false;
|
5
|
+
},
|
6
|
+
|
7
|
+
// Overrides Abstract.TimedObserver.execute
|
8
|
+
execute: function() {
|
9
|
+
var value = this.getValue();
|
10
|
+
if (Object.isString(this.lastValue) && Object.isString(value) ?
|
11
|
+
this.lastValue != value : String(this.lastValue) != String(value)) {
|
12
|
+
this.lastValue = value;
|
13
|
+
this.invocationPending = true;
|
14
|
+
} else if(this.invocationPending) {
|
15
|
+
this.invocationPending = false;
|
16
|
+
this.callback(this.element, value);
|
17
|
+
this.lastValue = value;
|
18
|
+
}
|
19
|
+
}
|
20
|
+
});
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: delayed_form_observer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 2
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Coroutine
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2010-07-
|
20
|
+
date: 2010-07-30 00:00:00 -05:00
|
21
21
|
default_executable:
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|
@@ -52,19 +52,18 @@ dependencies:
|
|
52
52
|
version: 2.3.4
|
53
53
|
type: :development
|
54
54
|
version_requirements: *id002
|
55
|
-
description: Delayed Form Observer provides Rails with timed form observers that do not create race conditions.
|
55
|
+
description: Delayed Form Observer provides Rails with timed form observers that do not create race conditions. The gem extends Prototype and adds a Rails PrototypeHelper to use this new object.
|
56
56
|
email: gems@coroutine.com
|
57
57
|
executables: []
|
58
58
|
|
59
59
|
extensions: []
|
60
60
|
|
61
61
|
extra_rdoc_files:
|
62
|
-
- README
|
62
|
+
- README.rdoc
|
63
63
|
files:
|
64
64
|
- .gitignore
|
65
65
|
- .specification
|
66
66
|
- MIT-LICENSE
|
67
|
-
- README
|
68
67
|
- Rakefile
|
69
68
|
- VERSION
|
70
69
|
- delayed_form_observer.gemspec
|
@@ -73,9 +72,12 @@ files:
|
|
73
72
|
- init.rb
|
74
73
|
- lib/delayed_form_observer.rb
|
75
74
|
- lib/delayed_form_observer/helpers.rb
|
75
|
+
- lib/generators/delayed_form_observer/delayed_form_observer_generator.rb
|
76
|
+
- lib/generators/delayed_form_observer/templates/prototype_extension.js
|
76
77
|
- rails/init.rb
|
77
78
|
- test/delayed_form_observer/helpers_test.rb
|
78
79
|
- test/test_helper.rb
|
80
|
+
- README.rdoc
|
79
81
|
has_rdoc: true
|
80
82
|
homepage: http://github.com/coroutine/delayed_form_observer
|
81
83
|
licenses: []
|