aeonscope-rest 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +25 -0
- data/README.rdoc +42 -30
- data/Rakefile +2 -2
- data/VERSION.yml +1 -1
- data/lib/class_methods.rb +17 -17
- data/lib/instance_methods.rb +261 -0
- data/lib/resource_helper.rb +133 -50
- data/lib/rest.rb +2 -2
- data/rails_generators/{ujs_setup → rest_setup}/USAGE +2 -2
- data/rails_generators/rest_setup/rest_setup_generator.rb +28 -0
- data/rails_generators/{ujs_setup → rest_setup}/templates/README +1 -1
- data/rails_generators/{ujs_setup → rest_setup}/templates/app/controllers/javascripts_controller.rb +0 -0
- data/rails_generators/{ujs_setup → rest_setup}/templates/app/views/javascripts/ujs.js.erb +3 -3
- data/rails_generators/rest_setup/templates/config/initializers/pagination.rb +10 -0
- data/rails_generators/rest_setup/templates/public/javascripts/jquery.rest.js +325 -0
- data/rails_generators/rest_setup/templates/public/themes/default/images/icons/rest/destroy.png +0 -0
- data/rails_generators/rest_setup/templates/public/themes/default/images/icons/rest/edit.png +0 -0
- data/rails_generators/rest_setup/templates/public/themes/default/images/icons/rest/new.png +0 -0
- data/rails_generators/rest_setup/templates/public/themes/default/images/icons/rest/show.png +0 -0
- metadata +17 -12
- data/lib/actions.rb +0 -230
- data/rails_generators/ujs_setup/templates/public/javascripts/rest.js +0 -119
- data/rails_generators/ujs_setup/ujs_setup_generator.rb +0 -18
data/rails_generators/rest_setup/templates/public/themes/default/images/icons/rest/destroy.png
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aeonscope-rest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.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-
|
12
|
+
date: 2009-08-26 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -30,7 +30,7 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 2.3.
|
33
|
+
version: 2.3.10
|
34
34
|
version:
|
35
35
|
description: "Ruby on Rails supports RESTful routing out-of-the-box. However, as you move along, you will often find yourself repeating the code for the seven REST actions: index, show, new, create, edit, update, destroy. This gem allows you to get all of the code for free by simply typing 'include Rest' at top of your controller code. That's it! Even better, you can have nested resources as well by adding a 'belongs_to' statement to your controllers much like you would for ActiveRecord models. This is just the tip of the iceburg so make sure to read the RDoc for more info."
|
36
36
|
email: aeonscope@gmail.com
|
@@ -47,19 +47,24 @@ files:
|
|
47
47
|
- README.rdoc
|
48
48
|
- Rakefile
|
49
49
|
- VERSION.yml
|
50
|
-
- lib/actions.rb
|
51
50
|
- lib/class_methods.rb
|
51
|
+
- lib/instance_methods.rb
|
52
52
|
- lib/resource_helper.rb
|
53
53
|
- lib/rest.rb
|
54
|
-
- rails_generators/
|
55
|
-
- rails_generators/
|
56
|
-
- rails_generators/
|
57
|
-
- rails_generators/
|
58
|
-
- rails_generators/
|
59
|
-
- rails_generators/
|
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/config/initializers/pagination.rb
|
60
|
+
- rails_generators/rest_setup/templates/public/javascripts/jquery.rest.js
|
61
|
+
- rails_generators/rest_setup/templates/public/themes/default/images/icons/rest/destroy.png
|
62
|
+
- rails_generators/rest_setup/templates/public/themes/default/images/icons/rest/edit.png
|
63
|
+
- rails_generators/rest_setup/templates/public/themes/default/images/icons/rest/new.png
|
64
|
+
- rails_generators/rest_setup/templates/public/themes/default/images/icons/rest/show.png
|
60
65
|
- spec/rest_spec.rb
|
61
66
|
- spec/spec_helper.rb
|
62
|
-
has_rdoc:
|
67
|
+
has_rdoc: false
|
63
68
|
homepage: http://github.com/aeonscope/rest
|
64
69
|
post_install_message:
|
65
70
|
rdoc_options:
|
@@ -85,7 +90,7 @@ rubyforge_project:
|
|
85
90
|
rubygems_version: 1.2.0
|
86
91
|
signing_key:
|
87
92
|
specification_version: 3
|
88
|
-
summary: Enables default REST functionality,
|
93
|
+
summary: Enables default REST functionality, UJS support (jQuery), and keeps your code DRY.
|
89
94
|
test_files:
|
90
95
|
- spec/rest_spec.rb
|
91
96
|
- spec/spec_helper.rb
|
data/lib/actions.rb
DELETED
@@ -1,230 +0,0 @@
|
|
1
|
-
module Rest
|
2
|
-
module Actions
|
3
|
-
# Default index action. Feel free to override.
|
4
|
-
def index
|
5
|
-
build_resources
|
6
|
-
if @resources.size > 1
|
7
|
-
# Records for a nested resource (act on the second-to-last parent).
|
8
|
-
parent = @resources[@resources.size - 2][:record]
|
9
|
-
records_name = parent.class.name.underscore.pluralize
|
10
|
-
records = parent.instance_eval("#{@resources.last[:parent_resource_method] || @resources.last[:name]}").paginate :page => params[:page], :per_page => 10
|
11
|
-
else
|
12
|
-
# Records for single resource.
|
13
|
-
records_name = get_model_name
|
14
|
-
if records_name
|
15
|
-
records_name = records_name.pluralize
|
16
|
-
records = @resources.last[:model].all.paginate(:page => params[:page], :per_page => 10)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
instance_variable_set "@#{records_name}", records if records_name
|
20
|
-
end
|
21
|
-
|
22
|
-
# Default show action. Feel free to override.
|
23
|
-
def show
|
24
|
-
build_resources
|
25
|
-
render_action_partial @resources.last[:show_partial]
|
26
|
-
end
|
27
|
-
|
28
|
-
# Default new action. Feel free to override.
|
29
|
-
def new
|
30
|
-
build_resources
|
31
|
-
render_new_or_edit_partial
|
32
|
-
end
|
33
|
-
|
34
|
-
# Default edit action. Feel free to override.
|
35
|
-
def edit
|
36
|
-
build_resources
|
37
|
-
render_new_or_edit_partial
|
38
|
-
end
|
39
|
-
|
40
|
-
# Default create action. Feel free to override.
|
41
|
-
def create
|
42
|
-
build_resources
|
43
|
-
if get_record.update_attributes params[get_model_symbol]
|
44
|
-
redirect_to build_resource_url(@resources)
|
45
|
-
else
|
46
|
-
render_new_or_edit_partial
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
# Default update action. Feel free to override.
|
51
|
-
def update
|
52
|
-
build_resources
|
53
|
-
if get_record.update_attributes params[get_model_symbol]
|
54
|
-
redirect_to build_resource_url(@resources)
|
55
|
-
else
|
56
|
-
render_new_or_edit_partial
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
# Default destroy action. Feel free to override.
|
61
|
-
def destroy
|
62
|
-
build_resources
|
63
|
-
get_record.destroy
|
64
|
-
@resources.last.delete :record
|
65
|
-
redirect_to build_resource_url(@resources)
|
66
|
-
end
|
67
|
-
|
68
|
-
protected
|
69
|
-
|
70
|
-
# Convenience method for rendering the action partials.
|
71
|
-
def render_action_partial partial
|
72
|
-
symbol = get_model_symbol
|
73
|
-
record = get_record
|
74
|
-
if symbol && record
|
75
|
-
render :partial => partial, :layout => true, :locals => {symbol => record, :resources => @resources}
|
76
|
-
else
|
77
|
-
render :partial => partial, :layout => true, :locals => {:resources => @resources}
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
# Convenience method for rendering the new or edit partial.
|
82
|
-
def render_new_or_edit_partial
|
83
|
-
render_action_partial @resources.last[:new_or_edit_partial]
|
84
|
-
end
|
85
|
-
|
86
|
-
# Builds the RESTful parent URL based on an array of resources.
|
87
|
-
def build_parent_url resources = []
|
88
|
-
namespaces = resources.last[:namespaces]
|
89
|
-
url = namespaces && !namespaces.empty? ? '/' + resources.last[:namespaces].join('/') : nil
|
90
|
-
if resources.size > 1
|
91
|
-
resources.slice(0...resources.size - 1).each do |resource|
|
92
|
-
url = [url, resource[:name], resource[:parent_id]].join('/')
|
93
|
-
end
|
94
|
-
end
|
95
|
-
url
|
96
|
-
end
|
97
|
-
|
98
|
-
# A convenience method for builing RESTful URLs based on an array of resources with the
|
99
|
-
# option to override the default action. This is also defined as a helper method (see base.rb).
|
100
|
-
def build_resource_url resources = [], action = :index
|
101
|
-
name = resources.last[:name]
|
102
|
-
id = resources.last[:record].id if resources.last[:record]
|
103
|
-
parent_url = build_parent_url(resources)
|
104
|
-
url = parent_url ? [parent_url, name].join('/') : '/' + name
|
105
|
-
case action
|
106
|
-
when :show then url = [url, id].compact.join('/')
|
107
|
-
when :new then url = [url, "new"].compact.join('/')
|
108
|
-
when :edit then url = [url, id, "edit"].compact.join('/')
|
109
|
-
when :update then url = [url, id].compact.join('/') if name == name.pluralize
|
110
|
-
when :destroy then url = [url, id].compact.join('/') if name == name.pluralize
|
111
|
-
end
|
112
|
-
logger.debug "Resource URL: #{url}"
|
113
|
-
url
|
114
|
-
end
|
115
|
-
|
116
|
-
private
|
117
|
-
|
118
|
-
# Answers the name of the current model.
|
119
|
-
def get_model_name
|
120
|
-
model = @resources.last[:model]
|
121
|
-
model ? model.name.underscore : nil
|
122
|
-
end
|
123
|
-
|
124
|
-
# Answers the symbol of the current model.
|
125
|
-
def get_model_symbol
|
126
|
-
name = get_model_name
|
127
|
-
name ? name.to_sym : nil
|
128
|
-
end
|
129
|
-
|
130
|
-
# Answers the current record (a.k.a. the record of the last resource).
|
131
|
-
def get_record
|
132
|
-
name = get_model_name
|
133
|
-
name ? instance_variable_get("@#{name}") : nil
|
134
|
-
end
|
135
|
-
|
136
|
-
# Builds all resources for the controller(s).
|
137
|
-
def build_resources
|
138
|
-
@resources ||= []
|
139
|
-
if @resources.empty?
|
140
|
-
controller_name = self.class.name
|
141
|
-
add_resource controller_name, @resources
|
142
|
-
@resources.reverse!
|
143
|
-
end
|
144
|
-
# Convenience for accessing the current record.
|
145
|
-
name = get_model_name
|
146
|
-
instance_variable_set "@#{name}", @resources.last[:record] if name
|
147
|
-
end
|
148
|
-
|
149
|
-
# Convenience method for answering back a properly camelized controller name.
|
150
|
-
def camelize_controller_name name
|
151
|
-
name = name.gsub(/^(\w)/) {|c| c.capitalize}
|
152
|
-
name += "Controller" unless name.include? "Controller"
|
153
|
-
name
|
154
|
-
end
|
155
|
-
|
156
|
-
# Answers the child or parent controller namespaces (array) and name (string).
|
157
|
-
# Accepts the following argruments:
|
158
|
-
# * *full_name* - The fully namespaced controller (i.e. PostsController) or parent name (i.e. protected_pages).
|
159
|
-
# Usage:
|
160
|
-
# * Input: Public::PostsController, Output: [Public], "PostsController"
|
161
|
-
# * Input: member_manage_posts, Output: [Member, Manage], "PostsController"
|
162
|
-
# * Input: posts, Output: nil, "PostsController"
|
163
|
-
def get_controller_namespaces_and_name full_name
|
164
|
-
if full_name
|
165
|
-
delimiter = full_name.include?("Controller") ? "::" : '_'
|
166
|
-
if full_name.include? delimiter
|
167
|
-
namespaces = full_name.split delimiter
|
168
|
-
name = camelize_controller_name namespaces.pop
|
169
|
-
return namespaces.collect(&:capitalize), name
|
170
|
-
else
|
171
|
-
return nil, camelize_controller_name(full_name)
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
# Recursively walks the controller belongs_to hierarchy (if any) adding new resources along the way.
|
177
|
-
def add_resource controller_name, resources
|
178
|
-
logger.debug "Adding resource '#{controller_name}' to resources (size = #{resources.size})."
|
179
|
-
resource = configure_resource controller_name
|
180
|
-
if resource
|
181
|
-
resources << resource
|
182
|
-
# Recursively add parents (if any).
|
183
|
-
if resource[:controller].methods.include? "parent_resource"
|
184
|
-
add_resource resource[:controller].parent_resource, resources
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
# Configures a resource via belongs_to name refrence in controller. By default the controller and model
|
190
|
-
# are assumed to use the same root name regardless of singular or plural context.
|
191
|
-
def configure_resource controller_name
|
192
|
-
namespaces, name = get_controller_namespaces_and_name controller_name
|
193
|
-
controller = [namespaces, name].compact.join("::").constantize
|
194
|
-
name = name.chomp("Controller").underscore
|
195
|
-
parent_key = name.singularize + "_id"
|
196
|
-
resource = controller.resource_options || {}
|
197
|
-
resource.reverse_merge! :parent_key => parent_key,
|
198
|
-
:parent_id => params[parent_key],
|
199
|
-
:name => name,
|
200
|
-
:controller => controller,
|
201
|
-
:label => name.capitalize,
|
202
|
-
:namespaces => (namespaces.collect(&:downcase) if namespaces),
|
203
|
-
:show_partial => '/' + [namespaces, name, "show"].compact.join('/').downcase,
|
204
|
-
:new_or_edit_partial => '/' + [namespaces, name, "new_or_edit"].compact.join('/').downcase
|
205
|
-
begin
|
206
|
-
resource.reverse_merge! :model => name.singularize.camelize.constantize
|
207
|
-
rescue NameError
|
208
|
-
logger.warn "Unable to constantize: " + name
|
209
|
-
end
|
210
|
-
add_record resource
|
211
|
-
end
|
212
|
-
|
213
|
-
# Adds the current record to the resource based on position in chain.
|
214
|
-
def add_record resource
|
215
|
-
if resource[:model]
|
216
|
-
if params.include? resource[:parent_key]
|
217
|
-
# Nested parent.
|
218
|
-
resource[:record] = resource[:model].find resource[:parent_id] if resource[:parent_id]
|
219
|
-
else
|
220
|
-
# Single resource and/or end of nested chain.
|
221
|
-
resource[:record] = params[:id] ? resource[:model].find(params[:id]) : resource[:model].new
|
222
|
-
end
|
223
|
-
else
|
224
|
-
logger.error "Invalid model. Check that your controller and model are of the same name, otherwise specify the model as a resource option."
|
225
|
-
end
|
226
|
-
resource
|
227
|
-
end
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
@@ -1,119 +0,0 @@
|
|
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,18 +0,0 @@
|
|
1
|
-
class UjsSetupGenerator < Rails::Generator::Base
|
2
|
-
def manifest
|
3
|
-
record do |m|
|
4
|
-
# Controllers
|
5
|
-
m.file "app/controllers/javascripts_controller.rb", "app/controllers/javascripts_controller.rb"
|
6
|
-
|
7
|
-
# Views
|
8
|
-
m.directory "app/views/javascripts"
|
9
|
-
m.file "app/views/javascripts/ujs.js.erb", "app/views/javascripts/ujs.js.erb"
|
10
|
-
|
11
|
-
# JavaScript
|
12
|
-
m.file "public/javascripts/rest.js", "public/javascripts/rest.js"
|
13
|
-
|
14
|
-
# Instructions
|
15
|
-
m.readme "README"
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|