is_positionable 0.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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)
|