aeonscope-btech_rest 0.4.4 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc CHANGED
@@ -21,12 +21,19 @@
21
21
  * Shortened the gem summary and added a more detailed description.
22
22
  * Updated the README file with minor setup and usage clarifications.
23
23
 
24
- = v0.4.x
24
+ = v0.5.0
25
25
 
26
26
  * Synchronized the summary and descriptions for the gem, README, and GitHub data.
27
27
  * Added UJS support for nested new/edit actions.
28
28
  * Added UJS support for nested delete actions.
29
29
  * Changed the show_destroy_link helper so that the default link ID is suffixed with "_destroy" instead of "_link".
30
- * Added a build_dom_id helper. Works the same as the dom_id found in Rails except that new records return a '_0' suffix instead of a "new_" prefix.
30
+ * Added a build_dom_id helper. Works the same as the dom_id found in Rails except that new records return a '_0' suffix instead of a "new_" prefix easier JavaScript manipulation.
31
31
  * Updated the show_destroy_link helper so that when a url option is not supplied an anchor link is used instead (derived from the record ID).
32
32
  * Updated all edit and destroy resource helpers so that they accept the parent DOM ID for which to apply UJS manipulation too.
33
+ * Renamed the rest_setup generator to ujs_setup since this is more specific.
34
+ * Changed all JavaScript code to JavaScript coding standards instead of Ruby standards (sorry, always thinking about Ruby instead ;-)
35
+ * Fixed a bug where an error would be thrown when attempting to increment null text.
36
+ * Renamed the build_action_label helper to show_action_label and removed the singularization the label passed in.
37
+ * Deleted the build_resource_form_submit helper since Rails 2.3 makes it so much easier to parse nested resource forms.
38
+ * Improved the README documentation including examples for how you might write your view code.
39
+
data/README.rdoc CHANGED
@@ -44,9 +44,9 @@ Update your environment.rb file to include the new gem:
44
44
 
45
45
  * config.gem "btech_rest"
46
46
 
47
- Type the following from the command line to setup:
47
+ To apply unobtrusive jQuery support, run the following generator (TIP: suffix the command line with -h option for usage):
48
48
 
49
- * script/generate rest_setup
49
+ * script/generate ujs_setup
50
50
 
51
51
  = Usage
52
52
 
@@ -60,6 +60,61 @@ Example:
60
60
  include BTech::Rest
61
61
  end
62
62
 
63
+ This will automatically create the seven REST actions (index, show, new, create, edit, update, and destroy) for your controller. The model (i.e. Post) and model instance (i.e. @posts or @post depending on the action) are automatically determined from the controller name and created for you as well which means you can immediately write the following code in your views:
64
+
65
+ *index.html.erb*
66
+
67
+ <h2>Posts</h2>
68
+ <div>
69
+ <table>
70
+ <thead>
71
+ <tr>
72
+ <th>Label</th>
73
+ <th>Created At</th>
74
+ <th>Updated At</th>
75
+ <th>Actions</th>
76
+ </tr>
77
+ </thead>
78
+ <tbody>
79
+ <%= render @posts %>
80
+ </tbody>
81
+ </table>
82
+ </div>
83
+
84
+ *show.html.erb*
85
+
86
+ <h2>Label</h2>
87
+ <p><%= @post.label %></p>
88
+
89
+ <h2>Content</h2>
90
+ <p><%= @post.content %></p>
91
+
92
+ <p><%= link_to "Back", :back %></p>
93
+
94
+ *new.html.erb*
95
+
96
+ <% form_for @post do |form| %>
97
+ <%= form.error_messages :header_data => :strong, :header_message => "Error" %>
98
+
99
+ <div>
100
+ <%= form.label :label %><br/>
101
+ <%= form.text_field :label %>
102
+ </div>
103
+
104
+ <div>
105
+ <%= form.label :content %><br/>
106
+ <%= form.text_area :content %>
107
+ </div>
108
+
109
+ <div><%= show_submit_and_cancel :cancel_options => posts_path %></div>
110
+ <% end %>
111
+
112
+ *edit.html.erb*
113
+
114
+ Use the same code as shown in the new.html.erb view above. ;-) The Rails form_for helper will automatically determine what action to take as shown in the following code:
115
+
116
+ <% form_for @post do |form| %>
117
+
63
118
  To customize the RESTful behavior of your controller, use any combination of these three macros:
64
119
 
65
120
  * *belongs_to* - Enables resource nesting where a controller can belong to a parent controller. This behavior is similar to the ActiveRecord {belongs_to}[http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/belongs_to] macro.
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
- :minor: 4
3
- :patch: 4
2
+ :minor: 5
3
+ :patch: 0
4
4
  :major: 0
data/lib/actions.rb CHANGED
@@ -140,9 +140,9 @@ module BTech
140
140
  # Accepts the following argruments:
141
141
  # * *full_name* - The fully namespaced controller (i.e. PostsController) or parent name (i.e. protected_pages).
142
142
  # Usage:
143
- # * Input: Public::PostsController, Output: [Public], "PostsController"
144
- # * Input: member_manage_posts, Output: [Member, Manage], "PostsController"
145
- # * Input: posts, Output: nil, "PostsController"
143
+ # * Input: Public::PostsController, Output: [Public], "PostsController"
144
+ # * Input: member_manage_posts, Output: [Member, Manage], "PostsController"
145
+ # * Input: posts, Output: nil, "PostsController"
146
146
  def get_controller_namespaces_and_name full_name
147
147
  if full_name
148
148
  delimiter = full_name.include?("Controller") ? "::" : '_'
data/lib/class_methods.rb CHANGED
@@ -29,8 +29,7 @@ module BTech
29
29
  # Allows one to disable any number of default actions. Accepts the following parameters:
30
30
  # * *actions* - A variable list of REST action symbols you wish to disable. You may use any of the following: index, show, new, create, edit, update, and/or destroy.
31
31
  def disabled_actions *actions
32
- actions.uniq!
33
- actions.each {|action| undef_method(action)}
32
+ actions.uniq!.each {|action| undef_method action}
34
33
  end
35
34
  end
36
35
  end
@@ -24,33 +24,16 @@ module ResourceHelper
24
24
  end
25
25
 
26
26
  # Builds a DOM ID for a given record. Works the same as the dom_id helper found in Rails except that it returns a record ID with
27
- # a "_0" suffix for new records instead of a "new_" prefix.
27
+ # a "_0" suffix for new records instead of a "new_" prefix. This makes attaching JavaScript events easier since all DOM IDs are numbers.
28
28
  def build_dom_id record
29
29
  name = record.class.name.underscore
30
30
  record.new_record? ? name + "_0" : name + '_' + record.id.to_s
31
31
  end
32
32
 
33
- # Builds the submit path for a new or edit form based on current controller action. This assumes
34
- # that the new/create and edit/update forms are always submitted to the same URL. Accepts the following parameters:
35
- # * *resources* - The array of resource hashes.
36
- # * *html_options* - The html options for a form (same as form_for[http://apidock.com/rails/ActionView/Helpers/FormHelper/form_for] html options).
37
- def build_resource_form_submit resources = [], html_options = {}
38
- case params[:action]
39
- # New/create flow.
40
- when "new" then return :url => build_resource_url(resources, :create), :html => html_options
41
- # Validate/create flow.
42
- when "create" then return :url => build_resource_url(resources, :create), :html => html_options
43
- # Edit/update flow.
44
- when "edit" then return :url => build_resource_url(resources, :update), :html => html_options.merge({:method => :put})
45
- # Validate/update flow.
46
- when "update" then return :url => build_resource_url(resources, :update), :html => html_options.merge({:method => :put})
47
- end
48
- end
49
-
50
- # Builds a more descriptive label based on the current controller action. Accepts the following parameters:
33
+ # Show a descriptive label based on the current controller action. Useful for new/edit actions. Accepts the following parameters:
51
34
  # * *label* - The action label.
52
- def build_action_label label
53
- [params[:action].capitalize, label.singularize].compact.join ' '
35
+ def show_action_label label
36
+ [params[:action].capitalize, label].compact.join ' '
54
37
  end
55
38
 
56
39
  # Shows an unobtrusive jQuery link where the UJS event is attached to the link via the "destroy" class.
@@ -76,8 +59,8 @@ module ResourceHelper
76
59
  # Shows an unobtrusive jQuery link based on an array of resource hashes. See the show_destroy_link above
77
60
  # for further details. Accepts the following arguments:
78
61
  # * *resources* - The array of resource hashes.
79
- def show_nested_destroy_resource_link resources, parent_dom_id
80
- show_destroy_link(:id => parent_dom_id.to_s + "_nested-destroy", :class => "nested-destroy") unless resources.last[:record].new_record?
62
+ def show_destroy_nested_resource_link resources, parent_dom_id
63
+ show_destroy_link(:id => parent_dom_id.to_s + "_destroy-nested", :class => "destroy-nested") unless resources.last[:record].new_record?
81
64
  end
82
65
 
83
66
  # Shows edit and delete links for resources. Accepts the following parameters:
@@ -0,0 +1,11 @@
1
+ Berserk Technologies UJS Setup Generator
2
+
3
+ Description:
4
+ Applies unobtrusive jQuery support to your Ruby on Rails application.
5
+
6
+ Requirements
7
+ 1. jQuery 1.3 or higher.
8
+ 2. jQuery UI 1.7 or higher.
9
+
10
+ Usage:
11
+ script/generate ujs_setup
@@ -1,7 +1,4 @@
1
1
 
2
- Overview
3
- REST setup is complete.
4
-
5
2
  Tasks You Need to Complete:
6
3
  1. Update your layouts/application.html.erb as follows:
7
4
 
@@ -0,0 +1,6 @@
1
+ # Enables dynamic javascript, namely Unobtrusive JavaScript (UJS) support for jQuery.
2
+ class JavascriptsController < ApplicationController
3
+ # Serves global jQuery UJS settings. See the /views/layouts/application.html.erb for usage.
4
+ def ujs
5
+ end
6
+ end
@@ -0,0 +1,119 @@
1
+ // Chops off the last string segment designated by delimiter. If no delimiter is found then the original string is
2
+ // returned instead. The following attributes are accepted:
3
+ // string = Required. The string to chop.
4
+ // delimiter = Optional. The delimiter used to chop up the string. Defaults to '_'.
5
+ function stringChop(string, delimiter) {
6
+ var chopped = string;
7
+ if (delimiter == undefined) {delimiter = '_';}
8
+ var endIndex = string.lastIndexOf(delimiter);
9
+ if (endIndex > 1) {chopped = string.slice(0, endIndex);}
10
+ return chopped;
11
+ };
12
+
13
+ // Increments a number embedded in the text by one. If no number is found then the original text is returned.
14
+ function incrementText(text) {
15
+ if (text != undefined) {
16
+ var match = text.match(/\d+/);
17
+ if (match != null) {
18
+ var number = new Number(match);
19
+ var newNumber = number + 1;
20
+ text = text.replace(number, newNumber);
21
+ }
22
+ }
23
+ return text;
24
+ };
25
+
26
+ // Increments the input field ID number by one so ActiveRecord can save new record attributes.
27
+ function incrementInputId(input) {
28
+ id = $(input).attr("id");
29
+ id = incrementText(id);
30
+ $(input).attr("id", id);
31
+ };
32
+
33
+ // Increments the input field name number by one so ActiveRecord can save new record attributes.
34
+ function incrementInputName(input) {
35
+ name = $(input).attr("name");
36
+ name = incrementText(name);
37
+ $(input).attr("name", name);
38
+ };
39
+
40
+ // Generates a hidden input field based off original input field data that instructs ActiveRecord to delete
41
+ // a record based on the ID of the input field.
42
+ function generateDestroyInput(input) {
43
+ $(input).attr("id", stringChop($(input).attr("id")) + "__delete");
44
+ $(input).attr("name", stringChop($(input).attr("name"), '[') + "[_delete]");
45
+ $(input).attr("type", "hidden");
46
+ $(input).attr("value", 1);
47
+ return input;
48
+ };
49
+
50
+ // Animates the removal of a DOM element.
51
+ function animateDestroy(id) {
52
+ $(id).animate({backgroundColor: "#FF0000", border: "0.2em solid #FF0000"}, 500);
53
+ $(id).fadeOut(500);
54
+ };
55
+
56
+ // UJS
57
+ $(document).ready(function(){
58
+ // Nested New
59
+ $("a.new-nested").click(function(){
60
+ var parentId = '#' + stringChop($(this).attr("id"));
61
+ var child = $(parentId).children(":last").clone(true);
62
+ var childId = child.attr("id");
63
+ child.attr("id", incrementText(childId));
64
+ $(parentId).append(child);
65
+ // Ensure the cloned input fields are unique.
66
+ $('#' + child.attr("id") + " :input").each(function(){
67
+ incrementInputId(this);
68
+ incrementInputName(this);
69
+ $(this).attr("value", '');
70
+ return this;
71
+ });
72
+ // Ensure the cloned destroy link is unique.
73
+ destroyLink = $("a.destroy-nested:last");
74
+ destroyLink.attr("id", incrementText(destroyLink.attr("id")));
75
+ // Ensure that the default event does not fire.
76
+ return false;
77
+ });
78
+
79
+ // Nested Destroy
80
+ $("a.destroy-nested").click(function(){
81
+ try {
82
+ var id = $(this).attr("id");
83
+ var parentId = stringChop(id);
84
+ if (parentId != id) {
85
+ parentId = '#' + parentId;
86
+ $(parentId).prepend(generateDestroyInput($(parentId + " input:first").clone()));
87
+ animateDestroy(parentId);
88
+ } else {
89
+ throw "Invalid ID";
90
+ }
91
+ } catch (e) {
92
+ alert("Error: " + e + ". Check that parent ID is defined and/or the link ID includes parent ID as part of the link ID.");
93
+ }
94
+ // Ensure that the default event does not fire.
95
+ return false;
96
+ });
97
+
98
+ // Destroy
99
+ $("a.destroy").click(function(){
100
+ var result = confirm("Are you sure you want to delete this?");
101
+ if (result) {
102
+ try {
103
+ var id = $(this).attr("id");
104
+ var parentId = stringChop(id);
105
+ if (parentId != id) {
106
+ animateDestroy('#' + parentId);
107
+ } else {
108
+ throw "Invalid ID";
109
+ }
110
+ // Finally, call the destroy action.
111
+ $.post($(this).attr("href"), "_method=delete");
112
+ } catch (e) {
113
+ alert("Error: " + e + ". Check that parent ID is defined and/or the link ID includes parent ID as part of the link ID.");
114
+ }
115
+ }
116
+ // Ensure that the default event does not fire.
117
+ return false;
118
+ });
119
+ });
@@ -1,4 +1,4 @@
1
- class RestSetupGenerator < Rails::Generator::Base
1
+ class UjsSetupGenerator < Rails::Generator::Base
2
2
  def manifest
3
3
  record do |m|
4
4
  # Controllers
@@ -8,7 +8,7 @@ class RestSetupGenerator < Rails::Generator::Base
8
8
  m.directory "app/views/javascripts"
9
9
  m.file "app/views/javascripts/ujs.js.erb", "app/views/javascripts/ujs.js.erb"
10
10
 
11
- # JavaScripts
11
+ # JavaScript
12
12
  m.file "public/javascripts/rest.js", "public/javascripts/rest.js"
13
13
 
14
14
  # Instructions
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aeonscope-btech_rest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.4
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brooke Kuhlmann
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-04-15 00:00:00 -07:00
12
+ date: 2009-04-18 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -51,12 +51,12 @@ files:
51
51
  - lib/btech_rest.rb
52
52
  - lib/class_methods.rb
53
53
  - lib/resource_helper.rb
54
- - rails_generators/rest_setup/USAGE
55
- - rails_generators/rest_setup/rest_setup_generator.rb
56
- - rails_generators/rest_setup/templates/README
57
- - rails_generators/rest_setup/templates/app/controllers/javascripts_controller.rb
58
- - rails_generators/rest_setup/templates/app/views/javascripts/ujs.js.erb
59
- - rails_generators/rest_setup/templates/public/javascripts/rest.js
54
+ - rails_generators/ujs_setup/USAGE
55
+ - rails_generators/ujs_setup/templates/README
56
+ - rails_generators/ujs_setup/templates/app/controllers/javascripts_controller.rb
57
+ - rails_generators/ujs_setup/templates/app/views/javascripts/ujs.js.erb
58
+ - rails_generators/ujs_setup/templates/public/javascripts/rest.js
59
+ - rails_generators/ujs_setup/ujs_setup_generator.rb
60
60
  - test/btech_rest_test.rb
61
61
  - test/test_helper.rb
62
62
  has_rdoc: true
@@ -84,7 +84,7 @@ requirements: []
84
84
  rubyforge_project:
85
85
  rubygems_version: 1.2.0
86
86
  signing_key:
87
- specification_version: 2
87
+ specification_version: 3
88
88
  summary: Enables default REST functionality, more than what you get with Rails out-of-the-box, and keeps your code DRY.
89
89
  test_files:
90
90
  - test/btech_rest_test.rb
@@ -1,11 +0,0 @@
1
- Berserk Technologies REST Setup Generator
2
-
3
- Description:
4
- Configures unobtrusive jQuery support.
5
-
6
- Requirements
7
- 1. jQuery 1.3 or higher.
8
- 2. jQuery UI 1.7 or higher.
9
-
10
- Usage:
11
- script/generate rest_setup
@@ -1,7 +0,0 @@
1
- # Enables the ability to serve up dynamic javascript, namely Unobtrusive JavaScript
2
- # support for jQuery.
3
- class JavascriptsController < ApplicationController
4
- # Serves global jQuery UJS settings. See the /views/layouts/application.html.erb for usage.
5
- def ujs
6
- end
7
- end
@@ -1,133 +0,0 @@
1
- // Chops off the last string segment per delimiter. If no delimiter is found in the string then the original string is
2
- // returned instead. The following attributes are accepted:
3
- // string = Required. The string to chop.
4
- // delimiter = Optional. The delimiter used to chop up the string. Defaults to '_'.
5
- function chop_last(string, delimiter) {
6
- var chopped = string;
7
- if (delimiter == undefined) {delimiter = '_';}
8
- var endIndex = string.lastIndexOf(delimiter);
9
- if (endIndex > 1) {chopped = string.slice(0, endIndex);}
10
- return chopped;
11
- }
12
-
13
- // Increments a number embedded in the text by one. If no number is found then the original text is returned.
14
- function increment_text(text) {
15
- var match = text.match(/\d+/);
16
- if (match != null) {
17
- var number = new Number(match);
18
- var new_number = number + 1;
19
- text = text.replace(number, new_number);
20
- }
21
- return text;
22
- };
23
-
24
- // Suffixes text with a number. Accepts the following arguments:
25
- // text = Required. The text to suffix.
26
- // number = Optional. The number to be suffixed to the text. Defaults to 1.
27
- // delimiter = Optional. The delimiter between the text and number. Defaults to '_'.
28
- function suffix_num_to_text(text, number, delimiter) {
29
- if (text != null) {
30
- if (number == undefined) { number = 1; };
31
- if (delimiter == undefined) { delimiter = '_'; };
32
- return text + delimiter + number;
33
- };
34
- };
35
-
36
- // Increments the input field ID number by one so ActiveRecord can save new record attributes.
37
- function increment_input_id(input) {
38
- id = $(input).attr("id");
39
- id = increment_text(id);
40
- $(input).attr("id", id);
41
- };
42
-
43
- // Increments the input field name number by one so ActiveRecord can save new record attributes.
44
- function increment_input_name(input) {
45
- name = $(input).attr("name");
46
- name = increment_text(name);
47
- $(input).attr("name", name);
48
- };
49
-
50
- // Generates a hidden input field based off original input field data that instructs ActiveRecord to delete
51
- // a record based on the ID of the input field.
52
- function generate_destroy_input(input) {
53
- $(input).attr("id", chop_last($(input).attr("id")) + "__delete");
54
- $(input).attr("name", chop_last($(input).attr("name"), '[') + "[_delete]");
55
- $(input).attr("type", "hidden");
56
- $(input).attr("value", 1);
57
- return input;
58
- }
59
-
60
- // UJS
61
- $(document).ready(function(){
62
- // Nested New
63
- $("a.nested-new").click(function(){
64
- var id = $(this).attr("id");
65
- var parent_id = '#' + chop_last(id);
66
- var clone = $(parent_id + " tr:last").clone(true);
67
- var clone_id = clone.attr("id");
68
- // Clone for new action.
69
- if (clone_id.length > 4 && clone_id.substr(0, 4) == "new_") {
70
- clone_id = clone_id.slice(4);
71
- clone_id = suffix_num_to_text(clone_id);
72
- clone.attr("id", clone_id);
73
- }
74
- // Clone for edit action.
75
- else {
76
- clone.attr("id", increment_text(clone_id));
77
- }
78
- $(parent_id).append(clone);
79
- // Ensure all cloned input fields are unique.
80
- $.each($('#' + clone.attr("id") + " :input"), function(){
81
- increment_input_id(this);
82
- increment_input_name(this);
83
- $(this).attr("value", '');
84
- return this;
85
- });
86
- // Ensure default event does not fire.
87
- return false;
88
- });
89
-
90
- // Nested Destroy
91
- $("a.nested-destroy").click(function(){
92
- try {
93
- var id = $(this).attr("id");
94
- var parent_id = chop_last(id);
95
- if (parent_id != id) {
96
- parent_id = '#' + parent_id;
97
- $(parent_id).prepend(generate_destroy_input($(parent_id + " input:first").clone()));
98
- $(parent_id).animate({backgroundColor: "#FF0000"}, 500);
99
- $(parent_id).fadeOut(500);
100
- } else {
101
- throw "Invalid ID";
102
- }
103
- } catch (e) {
104
- alert("Error: " + e + ". Check that parent ID is defined and/or the link ID includes parent ID as part of the link ID.");
105
- }
106
- // Ensure default event does not fire.
107
- return false;
108
- });
109
-
110
- // Destroy
111
- $("a.destroy").click(function(){
112
- var result = confirm("Are you sure you want to delete this?");
113
- if (result) {
114
- try {
115
- var id = $(this).attr("id");
116
- var parent_id = chop_last(id);
117
- if (parent_id != id) {
118
- parent_id = '#' + parent_id;
119
- $(parent_id).animate({backgroundColor: "#FF0000"}, 500);
120
- $(parent_id).fadeOut(500);
121
- } else {
122
- throw "Invalid ID";
123
- }
124
- // Finally, call the destroy action.
125
- $.post($(this).attr("href"), "_method=delete");
126
- } catch (e) {
127
- alert("Error: " + e + ". Check that parent ID is defined and/or the link ID includes parent ID as part of the link ID.");
128
- }
129
- }
130
- // Ensure default event does not fire.
131
- return false;
132
- });
133
- });