active_record_florder 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +39 -23
- data/active_record_florder.gemspec +2 -2
- data/lib/active_record_florder.rb +15 -32
- data/lib/active_record_florder/base.rb +9 -2
- data/lib/active_record_florder/configurable.rb +12 -4
- data/lib/active_record_florder/version.rb +1 -1
- metadata +11 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a6f1f17396e98217c975819a304d7ab834b2264c
|
4
|
+
data.tar.gz: 8a6fce2c3b548e92977bf7418e013ffb12d3bc3b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b7680e829c88ad497d0ad0dc5067d0c047acebb7cd7d5d27bbbfca80e68b1ff8b65bec8c133cb626e63a800232ba3559e3dd625f123a98ff2549d7da76a184ac
|
7
|
+
data.tar.gz: b39ffefa65a8c0112044dd4b06f15d21a5bc2a04ec409954053693a53a2290be6341cc4ef80a23e044bc89377d622ecb920dd270f36cb3cae6d410f8e6b112a4
|
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -3,52 +3,65 @@
|
|
3
3
|
[![Build Status](https://travis-ci.org/turboMaCk/active-record-florder.svg)](https://travis-ci.org/turboMaCk/active-record-florder)
|
4
4
|
[![Code Climate](https://codeclimate.com/github/turboMaCk/active-record-florder/badges/gpa.svg)](https://codeclimate.com/github/turboMaCk/active-record-florder)
|
5
5
|
[![Test Coverage](https://codeclimate.com/github/turboMaCk/active-record-florder/badges/coverage.svg)](https://codeclimate.com/github/turboMaCk/active-record-florder/coverage)
|
6
|
+
[![Inline docs](http://inch-ci.org/github/turboMaCk/active-record-florder.svg?branch=master)](http://inch-ci.org/github/turboMaCk/active-record-florder)
|
7
|
+
[![Gem Version](https://badge.fury.io/rb/active_record_florder.svg)](https://badge.fury.io/rb/active_record_florder)
|
6
8
|
|
7
|
-
Floating point ActiveRecord
|
8
|
-
ActiveRecordFlorder let client decide position
|
9
|
-
to keep your data clean. It's highly optimalized and generate as small SQL queries
|
9
|
+
Floating point ActiveRecord Models ordering for rich client apps heavily inspirated by Trello's ordering alorithm.
|
10
|
+
ActiveRecordFlorder let client decide model's position in collection, normalize given value and resolve conflicts
|
11
|
+
to keep your data clean. It's highly optimalized and generate as small SQL queries.
|
10
12
|
The whole philosophy is to load and update as little records as possible so in 99% it runs just one SELECT and one UPDATE.
|
11
|
-
In edge cases sanitization of all records happens and bring records back to the Garden of Eden.
|
13
|
+
In edge cases sanitization of all records happens and bring records back to the "Garden of Eden" state.
|
12
14
|
It's implemented with both Rails and non-Rails apps in mind and highly configurable.
|
13
15
|
|
14
|
-
THIS SOFTWARE IS STILL IN BETA!
|
15
|
-
|
16
16
|
## Installation
|
17
17
|
|
18
18
|
add to your Gemfile if you're using Bundler
|
19
19
|
|
20
20
|
```ruby
|
21
|
-
gem 'active_record_florder',
|
21
|
+
gem 'active_record_florder', '~> 0.0.1'
|
22
22
|
```
|
23
23
|
|
24
|
-
|
24
|
+
or simply install via Ruby Gems
|
25
|
+
|
26
|
+
```shell
|
27
|
+
gem install active_record_florder
|
28
|
+
```
|
25
29
|
|
26
30
|
## Api
|
27
31
|
|
28
|
-
This gem defines new method for ActiveRecord::Base named `florder`.
|
32
|
+
This gem defines new method for `ActiveRecord::Base` named `florder`.
|
29
33
|
|
30
34
|
### Parameters
|
31
35
|
|
32
|
-
* direction {Symbol} values: `:asc` `:desc`, **required**
|
33
|
-
* options {Hash}
|
36
|
+
* `direction {Symbol}` values: `:asc` `:desc`, **required**
|
37
|
+
* `options {Hash}`, optional
|
34
38
|
|
35
39
|
### Options
|
36
40
|
|
37
|
-
* scope {Symbol} - ordering scope (should be relationship or any other model property)
|
38
|
-
* attribute {Sumbol} - position column name, **default:** position
|
39
|
-
* min_delta {Number} - Minimal allowed position delata, affect position normalization *
|
40
|
-
* step
|
41
|
+
* `scope {Symbol}` - ordering scope (should be relationship or any other model property)
|
42
|
+
* `attribute {Sumbol}` - position column name, **default:** position
|
43
|
+
* `min_delta {Number}` - Minimal allowed position delata, affect position normalization *
|
44
|
+
* `step {Number}` - Optimal (init) delta between positions *
|
45
|
+
* `return_all_affected {Boolean}` - If true `move` method will return array of all affected records instead of just `self`
|
41
46
|
|
42
47
|
* *Setting this should affect performance. We recommend using default values*
|
43
48
|
|
49
|
+
### Example
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
class Post < ActiveRecord::Base
|
53
|
+
florder :desc, scope: :user, attribute: :order_position, min_delta: 0.001, step: 2**8, return_all_affected: true
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
44
57
|
## Usage
|
45
58
|
|
46
|
-
If you're using Rails or ActiveRecordMigrations create migration
|
59
|
+
If you're using Rails or `ActiveRecordMigrations` create new migration:
|
47
60
|
|
48
61
|
```ruby
|
49
62
|
class AddPositionToPosts < ActiveRecord::Migration
|
50
63
|
def change
|
51
|
-
add_column :posts, :position, default: 0
|
64
|
+
add_column :posts, :position, :float, default: 0
|
52
65
|
end
|
53
66
|
end
|
54
67
|
```
|
@@ -59,7 +72,7 @@ With rails you can use generator for this:
|
|
59
72
|
rails g migration add_position_to_posts position:float
|
60
73
|
```
|
61
74
|
|
62
|
-
Now migrate your
|
75
|
+
Now migrate your database:
|
63
76
|
|
64
77
|
```shell
|
65
78
|
rake db:migrate
|
@@ -113,7 +126,7 @@ Client itself request position for given Model. This Gem is build with drag and
|
|
113
126
|
Calculation on is simple - you just need to now position of two sibling to place model in middle of them.
|
114
127
|
For first and last position simply use hiher/lower value than first / last.
|
115
128
|
|
116
|
-
Here is
|
129
|
+
Here is hypotetical implementation in JavaScript:
|
117
130
|
|
118
131
|
```js
|
119
132
|
/*
|
@@ -139,13 +152,16 @@ You can use initializer to overwrite default settings like this:
|
|
139
152
|
|
140
153
|
```Ruby
|
141
154
|
ActiveRecordFlorder.configure do |config|
|
142
|
-
config.scope :owner
|
143
|
-
config.attribute :position_2
|
144
|
-
config.step 3
|
145
|
-
config.min_delta 0.1
|
155
|
+
config.scope = :owner
|
156
|
+
config.attribute = :position_2
|
157
|
+
config.step = 3
|
158
|
+
config.min_delta = 0.1
|
146
159
|
end
|
147
160
|
```
|
148
161
|
|
162
|
+
## Upgrading
|
163
|
+
Please see summary of changes for each version in [changelog](CHANGELOG.md)
|
164
|
+
|
149
165
|
## Developing
|
150
166
|
|
151
167
|
Git clone repository and cd in it:
|
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Marek Fajkus"]
|
10
10
|
spec.email = ["marek.faj@gmail.com"]
|
11
11
|
|
12
|
-
spec.summary = "Floating point ActiveRecord ordering for rich client apps"
|
13
|
-
spec.description = "Floating point ActiveRecord
|
12
|
+
spec.summary = "Floating point ActiveRecord Models ordering for rich client apps"
|
13
|
+
spec.description = "Floating point ActiveRecord Models ordering for rich client apps heavily inspirated by Trello's ordering alorithm. ActiveRecordFlorder let client decide model's position in collection, normalize given value and resolve conflicts to keep your data clean. It's highly optimalized and generate as small SQL queries. The whole philosophy is to load and update as little records as possible so in 99% it runs just one SELECT and one UPDATE. In edge cases sanitization of all records happens and bring records back to the Garden of Eden state. It's implemented with both Rails and non-Rails apps in mind and highly configurable."
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
@@ -12,48 +12,31 @@ require 'active_record_florder/version'
|
|
12
12
|
module ActiveRecordFlorder
|
13
13
|
class << self
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
# config.{attribute} {value}
|
18
|
-
# end
|
19
|
-
def configure
|
20
|
-
yield self if block_given?
|
21
|
-
end
|
22
|
-
|
23
|
-
# DB column name
|
24
|
-
def attribute(value)
|
25
|
-
@attribute = value
|
26
|
-
end
|
15
|
+
attr_writer(:attribute, :min_delta, :step, :return_all_affected)
|
16
|
+
attr_accessor(:scope)
|
27
17
|
|
28
|
-
def
|
18
|
+
def attribute
|
29
19
|
@attribute || :position
|
30
20
|
end
|
31
21
|
|
32
|
-
|
33
|
-
|
34
|
-
@scope = value
|
35
|
-
end
|
36
|
-
|
37
|
-
def get_scope
|
38
|
-
@scope || nil
|
39
|
-
end
|
40
|
-
|
41
|
-
# Minimal allowed delata between positions
|
42
|
-
def min_delta(value)
|
43
|
-
@min_delta = value
|
22
|
+
def min_delta
|
23
|
+
@min_delta || 0.0005
|
44
24
|
end
|
45
25
|
|
46
|
-
def
|
47
|
-
@
|
26
|
+
def step
|
27
|
+
@step || 2**16
|
48
28
|
end
|
49
29
|
|
50
|
-
|
51
|
-
|
52
|
-
@step = value
|
30
|
+
def return_all_affected
|
31
|
+
@return_all_affected || false
|
53
32
|
end
|
54
33
|
|
55
|
-
|
56
|
-
|
34
|
+
# Configure method can be used from initializer
|
35
|
+
# ActiveRecordFlorder.confige do |config|
|
36
|
+
# config.{attribute} {value}
|
37
|
+
# end
|
38
|
+
def configure
|
39
|
+
yield self if block_given?
|
57
40
|
end
|
58
41
|
end
|
59
42
|
end
|
@@ -44,13 +44,13 @@ module ActiveRecordFlorder
|
|
44
44
|
# @returns self {ModelInstance}
|
45
45
|
# @api public
|
46
46
|
def move(position)
|
47
|
-
position.to_f
|
47
|
+
position = position.to_f
|
48
48
|
|
49
49
|
fail ActiveRecordFlorder::Error, 'Position param is required' unless position
|
50
50
|
fail ActiveRecordFlorder::Error, 'Position should be > 0' unless (normalized_position = normalize_position(position)) > 0
|
51
51
|
normalized_position = normalize_position(position)
|
52
52
|
|
53
|
-
ensure_position_solving(position, normalized_position)
|
53
|
+
affected = ensure_position_solving(position, normalized_position)
|
54
54
|
|
55
55
|
if new_record?
|
56
56
|
self[position_attr_name.to_sym] = normalized_position
|
@@ -58,6 +58,13 @@ module ActiveRecordFlorder
|
|
58
58
|
update_attribute(position_attr_name.to_sym, normalized_position)
|
59
59
|
end
|
60
60
|
|
61
|
+
# populating all affected records
|
62
|
+
# only if return_all_affected_by_move option is true
|
63
|
+
if return_all_affected_by_move
|
64
|
+
affected ||= []
|
65
|
+
return affected << self
|
66
|
+
end
|
67
|
+
|
61
68
|
self
|
62
69
|
end
|
63
70
|
|
@@ -11,19 +11,23 @@ module ActiveRecordFlorder
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def position_attr_name
|
14
|
-
@florder_config[:attribute] || ActiveRecordFlorder.
|
14
|
+
@florder_config[:attribute] || ActiveRecordFlorder.attribute
|
15
15
|
end
|
16
16
|
|
17
17
|
def position_scope_attr
|
18
|
-
@florder_config[:scope] || ActiveRecordFlorder.
|
18
|
+
@florder_config[:scope] || ActiveRecordFlorder.scope
|
19
19
|
end
|
20
20
|
|
21
21
|
def min_position_delta
|
22
|
-
@florder_config[:min_delta] || ActiveRecordFlorder.
|
22
|
+
@florder_config[:min_delta] || ActiveRecordFlorder.min_delta
|
23
23
|
end
|
24
24
|
|
25
25
|
def next_position_step
|
26
|
-
@florder_config[:step] || ActiveRecordFlorder.
|
26
|
+
@florder_config[:step] || ActiveRecordFlorder.step
|
27
|
+
end
|
28
|
+
|
29
|
+
def return_all_affected_by_move
|
30
|
+
@florder_config[:return_all_affected] || ActiveRecordFlorder.return_all_affected
|
27
31
|
end
|
28
32
|
end
|
29
33
|
|
@@ -48,5 +52,9 @@ module ActiveRecordFlorder
|
|
48
52
|
def next_position_step
|
49
53
|
self.class.next_position_step
|
50
54
|
end
|
55
|
+
|
56
|
+
def return_all_affected_by_move
|
57
|
+
self.class.return_all_affected_by_move
|
58
|
+
end
|
51
59
|
end
|
52
60
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_record_florder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marek Fajkus
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-01
|
11
|
+
date: 2016-02-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,14 +52,14 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.0'
|
55
|
-
description: Floating point ActiveRecord
|
55
|
+
description: Floating point ActiveRecord Models ordering for rich client apps heavily
|
56
56
|
inspirated by Trello's ordering alorithm. ActiveRecordFlorder let client decide
|
57
|
-
position
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
57
|
+
model's position in collection, normalize given value and resolve conflicts to keep
|
58
|
+
your data clean. It's highly optimalized and generate as small SQL queries. The
|
59
|
+
whole philosophy is to load and update as little records as possible so in 99% it
|
60
|
+
runs just one SELECT and one UPDATE. In edge cases sanitization of all records happens
|
61
|
+
and bring records back to the Garden of Eden state. It's implemented with both Rails
|
62
|
+
and non-Rails apps in mind and highly configurable.
|
63
63
|
email:
|
64
64
|
- marek.faj@gmail.com
|
65
65
|
executables: []
|
@@ -71,6 +71,7 @@ files:
|
|
71
71
|
- ".rspec"
|
72
72
|
- ".ruby-version"
|
73
73
|
- ".travis.yml"
|
74
|
+
- CHANGELOG.md
|
74
75
|
- Gemfile
|
75
76
|
- Gemfile.lock
|
76
77
|
- LICENSE.txt
|
@@ -121,5 +122,5 @@ rubyforge_project:
|
|
121
122
|
rubygems_version: 2.4.5.1
|
122
123
|
signing_key:
|
123
124
|
specification_version: 4
|
124
|
-
summary: Floating point ActiveRecord ordering for rich client apps
|
125
|
+
summary: Floating point ActiveRecord Models ordering for rich client apps
|
125
126
|
test_files: []
|