dm-is-list 0.9.11 → 0.10.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/History.rdoc +46 -0
- data/Manifest.txt +2 -2
- data/README.rdoc +220 -0
- data/Rakefile +2 -3
- data/lib/dm-is-list/is/list.rb +493 -78
- data/lib/dm-is-list/is/version.rb +1 -1
- data/lib/dm-is-list.rb +1 -9
- data/spec/integration/list_spec.rb +981 -140
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +11 -8
- data/tasks/install.rb +1 -1
- data/tasks/spec.rb +4 -4
- metadata +14 -31
- data/History.txt +0 -17
- data/README.txt +0 -57
data/History.rdoc
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
=== 0.10.0 / 2009-10-15
|
2
|
+
|
3
|
+
* Major changes:
|
4
|
+
|
5
|
+
* Rewrote the README for better clarity and usage information.
|
6
|
+
|
7
|
+
* Made :move accept more vectors (:top, :bottom)
|
8
|
+
|
9
|
+
* Aliased #left_sibling & :right_sibling methods to more obvious => :higher_item, :lower_item, :previous_item, :next_item
|
10
|
+
|
11
|
+
* Improved the Specs and made them more comprehensive. ( Too comprehensive? )
|
12
|
+
|
13
|
+
* Improved the documentation for each of the methods.
|
14
|
+
|
15
|
+
* Issue fixes:
|
16
|
+
|
17
|
+
* [:735] Fixed. Incorporated patch from Brian Terlson. NB! see point below.
|
18
|
+
|
19
|
+
* [:737] Fixed. Incorporated specs from Brian Terlson [ http://github.com/bterlson/dm-more/commit/6eb521636e945f396723a53fa5a8cba1c9ef1350 ]
|
20
|
+
|
21
|
+
* [:738] Semi-fixed. Fixes item.move(-1) cases, but NOT item.position = -1 cases, due to a wish to reduce the number of SQL queries.
|
22
|
+
|
23
|
+
* [:739] Fixed. Fixes item.move(:to => 2) should retain correct list order.
|
24
|
+
|
25
|
+
* [:740] Fixed. Fixes item.reorder_list(\[:title.asc\]) with correct list positions and order.
|
26
|
+
|
27
|
+
* [:818] Addressed / Fixed. Same issue as [:738]. Use item.move(1) instead of item.position = 1.
|
28
|
+
|
29
|
+
|
30
|
+
=== 0.9.11 / 2009-03-29
|
31
|
+
|
32
|
+
* No changes this version
|
33
|
+
|
34
|
+
=== 0.9.10 / 2009-01-19
|
35
|
+
|
36
|
+
* No changes this version
|
37
|
+
|
38
|
+
=== 0.9.9 / 2009-01-04
|
39
|
+
|
40
|
+
* No changes this version
|
41
|
+
|
42
|
+
=== 0.9.8 / 2008-12-07
|
43
|
+
|
44
|
+
* 1 bug fix:
|
45
|
+
|
46
|
+
* Applied patch to fix bug with manual positioning [#672 state:resolved]
|
data/Manifest.txt
CHANGED
data/README.rdoc
ADDED
@@ -0,0 +1,220 @@
|
|
1
|
+
= dm-is-list
|
2
|
+
|
3
|
+
DataMapper plugin for creating and organizing lists.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
=== Stable
|
8
|
+
|
9
|
+
Install the +dm-more+ gem, which will by default install +dm-is-list+ and other required gems.
|
10
|
+
|
11
|
+
$ (sudo)? gem install dm-more
|
12
|
+
|
13
|
+
=== Edge
|
14
|
+
|
15
|
+
Download or clone +dm-more+ from Github[http://github.com/datamapper/dm-more/].
|
16
|
+
|
17
|
+
$ cd /path/to/dm-more
|
18
|
+
|
19
|
+
$ rake install # will install all the dm-more gems (some of which are required by dm-is-list)
|
20
|
+
|
21
|
+
# enter your password at the prompt, if required
|
22
|
+
$ password ...
|
23
|
+
|
24
|
+
|
25
|
+
== Getting started
|
26
|
+
|
27
|
+
First of all, for a better understanding of this gem, make sure you study the '<tt>dm-is-list/spec/integration/list_spec.rb</tt>' file.
|
28
|
+
|
29
|
+
----
|
30
|
+
|
31
|
+
Require +dm-is-list+ in your app.
|
32
|
+
|
33
|
+
require 'dm-core' # must be required first
|
34
|
+
require 'dm-is-list'
|
35
|
+
|
36
|
+
|
37
|
+
Lets say we have a User class, and we want to give users the possibility of
|
38
|
+
having their own todo-lists.
|
39
|
+
|
40
|
+
|
41
|
+
class User
|
42
|
+
include DataMapper::Resource
|
43
|
+
|
44
|
+
property :id, Serial
|
45
|
+
property :name, String
|
46
|
+
|
47
|
+
has n, :todos
|
48
|
+
end
|
49
|
+
|
50
|
+
class Todo
|
51
|
+
include DataMapper::Resource
|
52
|
+
|
53
|
+
property :id, Serial
|
54
|
+
property :title, String
|
55
|
+
property :done, DateTime
|
56
|
+
|
57
|
+
belongs_to :user
|
58
|
+
|
59
|
+
# here we define that this should be a list, scoped on :user_id
|
60
|
+
is :list, :scope => [:user_id]
|
61
|
+
end
|
62
|
+
|
63
|
+
Once we have our Users and Lists, we might want to work with...
|
64
|
+
|
65
|
+
== Movements of list items
|
66
|
+
|
67
|
+
Any list item can be moved around <b>within the same list</b> easily through the <tt>\#move</tt> method.
|
68
|
+
|
69
|
+
|
70
|
+
=== :move( vector )
|
71
|
+
|
72
|
+
There are number of convenient vectors that help you move items around within the list.
|
73
|
+
|
74
|
+
item = Todo.get(1)
|
75
|
+
other = Todo.get(2)
|
76
|
+
|
77
|
+
item.move(:highest) # moves to top of list.
|
78
|
+
item.move(:lowest) # moves to bottom of list.
|
79
|
+
item.move(:top) # moves to top of list.
|
80
|
+
item.move(:bottom) # moves to bottom of list.
|
81
|
+
item.move(:up) # moves one up (:higher and :up is the same) within the scope.
|
82
|
+
item.move(:down) # moves one up (:lower and :down is the same) within the scope.
|
83
|
+
item.move(:to => position) # moves item to a specific position.
|
84
|
+
item.move(:above => other) # moves item above the other item.*
|
85
|
+
item.move(:below => other) # moves item above the other item.*
|
86
|
+
|
87
|
+
# * won't move if the other item is in another scope. (should this be enabled?)
|
88
|
+
|
89
|
+
The list will act as intelligently as possible and keep positions in a logical running order.
|
90
|
+
|
91
|
+
|
92
|
+
=== :move( Integer )
|
93
|
+
|
94
|
+
<b>NOTE! VERY IMPORTANT!</b>
|
95
|
+
|
96
|
+
If you set the position manually, and then save, <b>the list will NOT reorganize itself</b>.
|
97
|
+
|
98
|
+
item.position = 3 # setting position manually
|
99
|
+
item.save # the item will now have position 3, but the list may have two items with the same position.
|
100
|
+
|
101
|
+
# alternatively
|
102
|
+
item.update(:position => 3) # sets the position manually, but does not reorganize the list positions.
|
103
|
+
|
104
|
+
|
105
|
+
You should therefore <b>always use</b> the <tt>item.move(N)</tt> syntax instead.
|
106
|
+
|
107
|
+
item.move(3) # does the same as above, but in one call AND *reorganizes* the list.
|
108
|
+
|
109
|
+
<hr>
|
110
|
+
|
111
|
+
<b>Hold On!</b>
|
112
|
+
|
113
|
+
<tt>dm-is-list</tt> used to work with <tt>item.position = 1</tt> type syntax. Why this change?
|
114
|
+
|
115
|
+
The main reason behind this change was that the previous version of <tt>dm-is-list</tt> created a LOT of
|
116
|
+
extra SQL queries in order to support the manual updating of position, and as a result had a quite a few bugs/issues,
|
117
|
+
which have been fixed in this version.
|
118
|
+
|
119
|
+
The other reason is that I couldn't work out how to keep the functionality without adding the extra queries. But perhaps you can ?
|
120
|
+
|
121
|
+
<hr>
|
122
|
+
|
123
|
+
See "<b>Batch Changing Positions</b>" below for information on how to change the positions on a whole list.
|
124
|
+
|
125
|
+
== Movements between scopes
|
126
|
+
|
127
|
+
When you move items between scopes, the list will try to work with your intentions.
|
128
|
+
|
129
|
+
|
130
|
+
Move the item from list to new list and add the item to the bottom of that list.
|
131
|
+
|
132
|
+
item.user_id # => 1
|
133
|
+
item.move_to_list(10) # => the scope id ie User.get(10).id
|
134
|
+
|
135
|
+
# results in...
|
136
|
+
item.user_id # => 10
|
137
|
+
item.position # => < bottom of the list >
|
138
|
+
|
139
|
+
|
140
|
+
Move the item from list to new list and add at the position given.
|
141
|
+
|
142
|
+
item.user_id # => 1
|
143
|
+
item.move_to_list(10, 2) # => the scope id ie User.get(10).id, position => 2
|
144
|
+
|
145
|
+
# results in...
|
146
|
+
item.user_id # => 10
|
147
|
+
item.position # => 2
|
148
|
+
|
149
|
+
|
150
|
+
== Batch Changing Positions
|
151
|
+
|
152
|
+
A common scenario when working with lists is the sorting of a whole list via something like JQuery's sortable() functionality.
|
153
|
+
<br>
|
154
|
+
(Think re-arranging the order of Todo's according to priority or something similar)
|
155
|
+
|
156
|
+
|
157
|
+
=== Optimum scenario
|
158
|
+
|
159
|
+
The most SQL query efficient way of changing the positions is:
|
160
|
+
|
161
|
+
|
162
|
+
sort_order = [5,4,3,2,1] # list from AJAX request..
|
163
|
+
|
164
|
+
items = Todo.all(:user => @u1) # loads all 5 items in the list
|
165
|
+
|
166
|
+
items.each{ |item| item.update(:position => sort_order.index(item.id) + 1) } # remember the +1 since array's are indexed from 0
|
167
|
+
|
168
|
+
|
169
|
+
The above code will result in something like these queries.
|
170
|
+
|
171
|
+
# SELECT "id", "title", "position", "user_id" FROM "todos" WHERE "user_id" = 1 ORDER BY "position"
|
172
|
+
# UPDATE "todos" SET "position" = 5 WHERE "id" = 1
|
173
|
+
# UPDATE "todos" SET "position" = 4 WHERE "id" = 2
|
174
|
+
# UPDATE "todos" SET "position" = 2 WHERE "id" = 4
|
175
|
+
# UPDATE "todos" SET "position" = 1 WHERE "id" = 5
|
176
|
+
|
177
|
+
<b>Remember!</b> Your sort order list has to be the same length as the found items in the list, or your loop will fail.
|
178
|
+
|
179
|
+
|
180
|
+
=== Wasteful scenario
|
181
|
+
|
182
|
+
You can also use this version, but it will create upto <b>5 times as many SQL queries</b>. :(
|
183
|
+
|
184
|
+
|
185
|
+
sort_order = ['5','4','3','2','1'] # list from AJAX request..
|
186
|
+
|
187
|
+
items = Todo.all(:user => @u1) # loads all 5 items in the list
|
188
|
+
|
189
|
+
items.each{ |item| item.move(sort_order.index(item.id).to_i + 1) } # remember the +1 since array's are indexed from 0
|
190
|
+
|
191
|
+
The above code will result in something like these queries:
|
192
|
+
|
193
|
+
# SELECT "id", "title", "position", "user_id" FROM "todos" WHERE "user_id" = 1 ORDER BY "position"
|
194
|
+
|
195
|
+
# SELECT "id", "title", "position", "user_id" FROM "todos" WHERE "user_id" = 1 ORDER BY "position" DESC LIMIT 1
|
196
|
+
# SELECT "id" FROM "todos" WHERE "user_id" = 1 AND "id" IN (1, 2, 3, 4, 5) AND "position" BETWEEN 1 AND 5 ORDER BY "position"
|
197
|
+
# UPDATE "todos" SET "position" = "position" + -1 WHERE "user_id" = 1 AND "position" BETWEEN 1 AND 5
|
198
|
+
# SELECT "id", "position" FROM "todos" WHERE "id" IN (1, 2, 3, 4, 5) ORDER BY "id"
|
199
|
+
# UPDATE "todos" SET "position" = 5 WHERE "id" = 1
|
200
|
+
|
201
|
+
# SELECT "id", "title", "position", "user_id" FROM "todos" WHERE "user_id" = 1 ORDER BY "position" DESC LIMIT 1
|
202
|
+
# SELECT "id" FROM "todos" WHERE "user_id" = 1 AND "id" IN (1, 2, 3, 4, 5) AND "position" BETWEEN 1 AND 4 ORDER BY "position"
|
203
|
+
# UPDATE "todos" SET "position" = "position" + -1 WHERE "user_id" = 1 AND "position" BETWEEN 1 AND 4
|
204
|
+
# SELECT "id", "position" FROM "todos" WHERE "id" IN (2, 3, 4, 5) ORDER BY "id"
|
205
|
+
# UPDATE "todos" SET "position" = 4 WHERE "id" = 2
|
206
|
+
|
207
|
+
# ...
|
208
|
+
|
209
|
+
As you can see it will also do the job, but will be more expensive.
|
210
|
+
|
211
|
+
|
212
|
+
== RTFM
|
213
|
+
|
214
|
+
As I said above, for a better understanding of this gem/plugin, make sure you study the '<tt>dm-is-list/spec/integration/list_spec.rb</tt>' tests.
|
215
|
+
|
216
|
+
|
217
|
+
== Errors / Bugs
|
218
|
+
|
219
|
+
If something is not behaving intuitively, it is a bug, and should be reported.
|
220
|
+
Report it here: http://datamapper.lighthouseapp.com/
|
data/Rakefile
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'pathname'
|
2
|
-
require 'rubygems'
|
3
2
|
|
4
3
|
ROOT = Pathname(__FILE__).dirname.expand_path
|
5
4
|
JRUBY = RUBY_PLATFORM =~ /java/
|
@@ -14,10 +13,10 @@ GEM_NAME = 'dm-is-list'
|
|
14
13
|
GEM_VERSION = DataMapper::Is::List::VERSION
|
15
14
|
GEM_DEPENDENCIES = [['dm-core', GEM_VERSION], ['dm-adjust', GEM_VERSION]]
|
16
15
|
GEM_CLEAN = %w[ log pkg coverage ]
|
17
|
-
GEM_EXTRAS = { :has_rdoc => true, :extra_rdoc_files => %w[ README.
|
16
|
+
GEM_EXTRAS = { :has_rdoc => true, :extra_rdoc_files => %w[ README.rdoc LICENSE TODO History.rdoc ] }
|
18
17
|
|
19
18
|
PROJECT_NAME = 'datamapper'
|
20
|
-
PROJECT_URL = "http://github.com/
|
19
|
+
PROJECT_URL = "http://github.com/datamapper/dm-more/tree/master/#{GEM_NAME}"
|
21
20
|
PROJECT_DESCRIPTION = PROJECT_SUMMARY = 'DataMapper plugin for creating and organizing lists'
|
22
21
|
|
23
22
|
[ ROOT, ROOT.parent ].each do |dir|
|