is_positionable 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +85 -14
- data/is_positionable.gemspec +1 -1
- data/lib/is_positionable.rb +11 -31
- data/lib/is_positionable/interface.rb +14 -20
- metadata +1 -1
data/README.rdoc
CHANGED
@@ -1,17 +1,88 @@
|
|
1
|
-
=
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
1
|
+
= Is Positionable
|
2
|
+
|
3
|
+
== What is "Is Positionable"?
|
4
|
+
|
5
|
+
Is Positionable handles the positioning (ordering) your ActiveRecord Objects. It makes use of the "Acts As List" gem to do it the most efficient way. Is Positionable basically creates a front-end (dynamically generates buttons and actions) for moving ActiveRecord Objects "up", "down", to the "top" and to the "bottom". Doing the simplest set up takes just 1 word: "is_positionable".
|
6
|
+
|
7
|
+
=== Quick and Simple Example
|
8
|
+
|
9
|
+
==== config/environment.rb
|
10
|
+
|
11
|
+
config.gem "is_positionable", :source => "http://gemcutter.org/"
|
12
|
+
|
13
|
+
==== app/controllers/posts_controller.rb
|
14
|
+
|
15
|
+
PostsController < ApplicationController
|
16
|
+
is_positionable
|
17
|
+
|
18
|
+
def index
|
19
|
+
@posts = Post.all
|
20
|
+
end
|
21
|
+
...
|
22
|
+
end
|
23
|
+
|
24
|
+
==== app/models/post.rb
|
25
|
+
|
26
|
+
class Post < ActiveRecord::Base
|
27
|
+
default_scope :order => :position
|
28
|
+
end
|
29
|
+
|
30
|
+
==== app/views/posts/index.html.erb
|
31
|
+
|
32
|
+
for post in @posts
|
33
|
+
<%= up_button_for_posts(@posts, post) %>
|
34
|
+
<%= down_button_for_posts(@posts, post) %>
|
35
|
+
<%= top_button_for_posts(@posts, post) %>
|
36
|
+
<%= bottom_button_for_posts(@posts, post) %>
|
37
|
+
...
|
38
|
+
# Other Stuff like post.name post.user.name etc.
|
39
|
+
end
|
40
|
+
|
41
|
+
With just this bit of code, you now enabled positioning with "posts".
|
42
|
+
This might already be obvious, but the following 4 buttons are generated per post:
|
43
|
+
- Up Button
|
44
|
+
- Down Button
|
45
|
+
- To Top Button
|
46
|
+
- To Bottom Button
|
47
|
+
|
48
|
+
Now, this is the most basic setup. You might have "users" manage posts. So that'd mean "User has_many :posts".
|
49
|
+
In this case you can add a "scope" and "scope_object" so that one user cannot conflict with another user's post positions.
|
50
|
+
|
51
|
+
This would look something like this
|
52
|
+
|
53
|
+
is_listable :scope => :user_id,
|
54
|
+
:scope_object => current_user
|
55
|
+
|
56
|
+
# Assuming that "current_user" is the currently logged in use
|
57
|
+
|
58
|
+
The above will ensure that, not only will one users' post NOT conflict with another users' post,
|
59
|
+
but if one user tries to be hack-ish and try to attempt to change post position of a different user through cURL or the AddressBar
|
60
|
+
it will be out of scope cause of the :scope_object attribute, restricting access to any other user, but the owner of the post.
|
61
|
+
|
62
|
+
==== Of course, these are not the only options you can set, for more information, see the Wiki pages!
|
63
|
+
|
64
|
+
==== Setting all this up takes me about 1-2 minutes
|
65
|
+
|
66
|
+
|
67
|
+
== Interested in trying out "Is Positionable"?
|
68
|
+
|
69
|
+
=== Check out the following Wiki pages:
|
70
|
+
|
71
|
+
=== Installation
|
72
|
+
|
73
|
+
http://wiki.github.com/meskyanichi/is_positionable/installation
|
74
|
+
|
75
|
+
|
76
|
+
=== Getting Started
|
77
|
+
|
78
|
+
http://wiki.github.com/meskyanichi/is_positionable/getting-started
|
79
|
+
|
80
|
+
|
81
|
+
=== Options
|
82
|
+
|
83
|
+
http://wiki.github.com/meskyanichi/is_positionable/options
|
84
|
+
|
85
|
+
|
15
86
|
|
16
87
|
== Copyright
|
17
88
|
|
data/is_positionable.gemspec
CHANGED
data/lib/is_positionable.rb
CHANGED
@@ -43,7 +43,7 @@ module IsPositionable
|
|
43
43
|
end
|
44
44
|
|
45
45
|
# Sets the default scope to order by the specified column
|
46
|
-
default_scope :order => interface.column if interface.set_default_scope?
|
46
|
+
# default_scope :order => interface.column if interface.set_default_scope?
|
47
47
|
|
48
48
|
end
|
49
49
|
|
@@ -112,7 +112,7 @@ module IsPositionable
|
|
112
112
|
|
113
113
|
# Injects the "UP" button for the view helpers into the controller
|
114
114
|
# This will be available to all views within the specified controller
|
115
|
-
define_method "up_button_for_#{interface.controller_name}" do |object, *options|
|
115
|
+
define_method "up_button_for_#{interface.controller_name}" do |objects, object, *options|
|
116
116
|
|
117
117
|
# Set default options and overwrite the existing ones with
|
118
118
|
# possible user input
|
@@ -128,13 +128,13 @@ module IsPositionable
|
|
128
128
|
:id => "up_button_for_#{interface.controller_name.singularize}_#{object.id}",
|
129
129
|
:class => "up_button_for_#{interface.controller_name}" }
|
130
130
|
}.update(options.empty? ? {} : options.first)
|
131
|
-
|
132
|
-
button_to(options[:name], options[:url], options[:html]) unless
|
131
|
+
|
132
|
+
button_to(options[:name], options[:url], options[:html]) unless objects.first.eql?(object)
|
133
133
|
end
|
134
134
|
|
135
135
|
# Injects the "DOWN" button for the view helpers into the controller
|
136
136
|
# This will be available to all views within the specified controller
|
137
|
-
define_method "down_button_for_#{interface.controller_name}" do |object, *options|
|
137
|
+
define_method "down_button_for_#{interface.controller_name}" do |objects, object, *options|
|
138
138
|
|
139
139
|
# Set default options and overwrite the existing ones with
|
140
140
|
# possible user input
|
@@ -151,22 +151,12 @@ module IsPositionable
|
|
151
151
|
:class => "down_button_for_#{interface.controller_name}" }
|
152
152
|
}.update(options.empty? ? {} : options.first)
|
153
153
|
|
154
|
-
|
155
|
-
# and not for each object that comes through the loop
|
156
|
-
unless defined?(@ip_last)
|
157
|
-
@ip_last = interface.find_last_id
|
158
|
-
end
|
159
|
-
|
160
|
-
# Ensures that the last "Down" button will not be displayed
|
161
|
-
# since you can't go lower than the lowest position
|
162
|
-
unless @ip_last.eql?(object.id)
|
163
|
-
button_to(options[:name], options[:url], options[:html])
|
164
|
-
end
|
154
|
+
button_to(options[:name], options[:url], options[:html]) unless objects.last.eql?(object)
|
165
155
|
end
|
166
156
|
|
167
157
|
# Injects the "TOP" button for the view helpers into the controller
|
168
158
|
# This will be available to all views within the specified controller
|
169
|
-
define_method "top_button_for_#{interface.controller_name}" do |object, *options|
|
159
|
+
define_method "top_button_for_#{interface.controller_name}" do |objects, object, *options|
|
170
160
|
|
171
161
|
# Set default options and overwrite the existing ones with
|
172
162
|
# possible user input
|
@@ -183,12 +173,12 @@ module IsPositionable
|
|
183
173
|
:class => "top_button_for_#{interface.controller_name}" }
|
184
174
|
}.update(options.empty? ? {} : options.first)
|
185
175
|
|
186
|
-
button_to(options[:name], options[:url], options[:html]) unless
|
176
|
+
button_to(options[:name], options[:url], options[:html]) unless objects.first.eql?(object)
|
187
177
|
end
|
188
178
|
|
189
179
|
# Injects the "BOTTOM" button for the view helpers into the controller
|
190
180
|
# This will be available to all views within the specified controller
|
191
|
-
define_method "bottom_button_for_#{interface.controller_name}" do |object, *options|
|
181
|
+
define_method "bottom_button_for_#{interface.controller_name}" do |objects, object, *options|
|
192
182
|
|
193
183
|
# Set default options and overwrite the existing ones with
|
194
184
|
# possible user input
|
@@ -204,18 +194,8 @@ module IsPositionable
|
|
204
194
|
:id => "bottom_button_for_#{interface.controller_name.singularize}_#{object.id}",
|
205
195
|
:class => "bottom_button_for_#{interface.controller_name}" }
|
206
196
|
}.update(options.empty? ? {} : options.first)
|
207
|
-
|
208
|
-
|
209
|
-
# and not for each object that comes through the loop
|
210
|
-
unless defined?(@ip_last)
|
211
|
-
@ip_last = interface.find_last_id
|
212
|
-
end
|
213
|
-
|
214
|
-
# Ensures that the last "Down" button will not be displayed
|
215
|
-
# since you can't go lower than the lowest position
|
216
|
-
unless @ip_last.eql?(object.id)
|
217
|
-
button_to(options[:name], options[:url], options[:html])
|
218
|
-
end
|
197
|
+
|
198
|
+
button_to(options[:name], options[:url], options[:html]) unless objects.last.eql?(object)
|
219
199
|
end
|
220
200
|
|
221
201
|
# Makes the buttons available to the views that belong to the
|
@@ -8,9 +8,10 @@ module IsPositionable
|
|
8
8
|
:model => options[:controller] || controller_name,
|
9
9
|
:action => :positionable,
|
10
10
|
:scope => nil,
|
11
|
+
:scope_object => nil,
|
11
12
|
:redirect_to => :back,
|
12
|
-
:param => :move
|
13
|
-
|
13
|
+
:param => :move
|
14
|
+
# :set_default_scope => true
|
14
15
|
}.update(options))
|
15
16
|
end
|
16
17
|
|
@@ -22,34 +23,27 @@ module IsPositionable
|
|
22
23
|
# It will determine whether to use a plain find
|
23
24
|
# or whether to use a find through an association
|
24
25
|
def find(id)
|
25
|
-
if
|
26
|
+
if scope_object.nil?
|
26
27
|
model.find(id)
|
27
28
|
else
|
28
|
-
|
29
|
+
scope_object.send(model_association_name).find(id)
|
29
30
|
end
|
30
31
|
end
|
31
|
-
|
32
|
-
# Finds the last id of a list of records
|
33
|
-
# It will determine whether to use a plain find
|
34
|
-
# or whether to use a find through an association
|
35
|
-
def find_last_id
|
36
|
-
if scope.nil?
|
37
|
-
model.all.last.id
|
38
|
-
else
|
39
|
-
scope.send(model_association_name).last.id
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
32
|
+
|
43
33
|
# Returns the value of the :redirect_to attribute
|
44
34
|
def redirect
|
45
35
|
options[:redirect_to]
|
46
36
|
end
|
47
|
-
|
37
|
+
|
48
38
|
# Returns the value of the :scope attribute
|
49
39
|
def scope
|
50
40
|
options[:scope]
|
51
41
|
end
|
52
42
|
|
43
|
+
def scope_object
|
44
|
+
options[:scope_object]
|
45
|
+
end
|
46
|
+
|
53
47
|
# Returns the model Class which can be invoked using class methods
|
54
48
|
def model
|
55
49
|
Kernel.const_get(options[:model].singularize.camelize)
|
@@ -95,9 +89,9 @@ module IsPositionable
|
|
95
89
|
|
96
90
|
# Returns a boolean
|
97
91
|
# Determines whether the :set_default_scope attribute was set
|
98
|
-
def set_default_scope?
|
99
|
-
|
100
|
-
end
|
92
|
+
#def set_default_scope?
|
93
|
+
# true if options[:set_default_scope].eql?(true)
|
94
|
+
#end
|
101
95
|
|
102
96
|
# Require additional gems
|
103
97
|
# When the "ignore_error" argument is set to "true" (default)
|