margrid 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 83c794d5429839e68bb60d5d011985d7acff150a
4
+ data.tar.gz: 6f127550111511be4d2526f6dce44c06acc8166c
5
+ SHA512:
6
+ metadata.gz: 0ecc919ddac29945a2074bce80bababd284b1af65defbcac8f5bcec7dd84372d25fb2a8821ce9abf3293a3182510b49ec1cb30ed730d123e7e0a83929ccb46ad
7
+ data.tar.gz: dc936ac2a2ccf3a572a41e44290ea725b18b4fa6d90c4223bb04f531321117ef654d28fc896955b0ea398c29b259510e4c510998c177d9d5636b6facd10509eb
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in margrid.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Yves Senn
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Margrid
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'margrid'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install margrid
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://github.com/[my-github-username]/margrid/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.test_files = FileList['test/margrid/*_test.rb']
6
+ t.verbose = true
7
+ end
8
+
9
+ task :default => :test
@@ -0,0 +1,46 @@
1
+ module Margrid
2
+ # Utility class to ease the creation of Margrid::Grid instances.
3
+ # It can be subclassed to provide more specialized behavior for your applications.
4
+ #
5
+ # class MyBuilder < Margrid::Builder
6
+ # def self.articles(id: "articles", relation: Articles.all)
7
+ # builder = new Margrid::Grid.new(id, relation)
8
+ # builder.sort_by "published_at", "desc"
9
+ # builder
10
+ # end
11
+ # end
12
+ class Builder
13
+ attr_reader :grid
14
+
15
+ def initialize(grid)
16
+ @grid = grid
17
+ end
18
+
19
+ # Configure the grid to use pagination.
20
+ def paginated(current_page: 1)
21
+ prepend paginator: Margrid::Paginator.new(current_page)
22
+ end
23
+
24
+ # Sort the grid by +column+ in +direction+.
25
+ # Direction can be +:asc+ or +:desc+
26
+ def sort_by(column, direction)
27
+ prepend sorter: Margrid::Sorter.new(column, direction)
28
+ end
29
+
30
+ # Deserialize Margrid components from a hash. This is usually the case
31
+ # when the state using the query string.
32
+ #
33
+ # NOTE: this method should be the last call when chaining Builder methods.
34
+ # It will return the Margrid::Grid instance and not the builder itself.
35
+ def load(params)
36
+ @grid.load(params)
37
+ end
38
+
39
+ def method_missing(sym, *args)
40
+ if @grid.respond_to?(sym)
41
+ @grid = @grid.send(sym, *args)
42
+ self
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,53 @@
1
+ module Margrid
2
+ class Sorter < Struct.new(:column, :direction)
3
+ def initialize(column, direction)
4
+ super column.to_s, direction.to_s
5
+ end
6
+
7
+ def apply(relation)
8
+ relation.reorder(sorting)
9
+ end
10
+
11
+ def inverted
12
+ self.class.new(column, asc? ? :desc : :asc)
13
+ end
14
+
15
+ def desc?
16
+ direction == "desc"
17
+ end
18
+
19
+ def asc?
20
+ !desc?
21
+ end
22
+
23
+ def self.load(data)
24
+ new data[:sort], data[:direction] if data.key? :sort
25
+ end
26
+
27
+ def dump
28
+ {sort: column, direction: direction}
29
+ end
30
+
31
+ private
32
+ def sorting
33
+ # FIXME: (Rails 4.2) Replace with
34
+ # relation.reorder(column => direction)
35
+ # when order accepts the direction as strings.
36
+ {column => asc? ? :asc : :desc}
37
+ end
38
+ end
39
+
40
+ class Paginator < Struct.new(:current_page)
41
+ def apply(relation)
42
+ relation.page current_page
43
+ end
44
+
45
+ def self.load(data)
46
+ new data[:page] if data.key? :page
47
+ end
48
+
49
+ def dump
50
+ {page: current_page}
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,15 @@
1
+ module Margrid
2
+ module FactoryMethods
3
+ def grid(*args)
4
+ Margrid::Grid.new(*args)
5
+ end
6
+
7
+ def sorter(*args)
8
+ Margrid::Sorter.new(*args)
9
+ end
10
+
11
+ def paginator(*args)
12
+ Margrid::Paginator.new(*args)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,70 @@
1
+ module Margrid
2
+ class Grid
3
+ def initialize(id, relation)
4
+ @id = id
5
+ @relation = relation
6
+ @components = {}
7
+ end
8
+
9
+ # Check wether a component is registered or not.
10
+ def component?(comp_sym)
11
+ @components.key? comp_sym
12
+ end
13
+
14
+ # Get the component for a given +comp_sym+.
15
+ def component(comp_sym)
16
+ @components[comp_sym]
17
+ end
18
+
19
+ # Attach components to the grid. This method can be called multiple times.
20
+ # Prepending a component will overwrite existing components.
21
+ #
22
+ # +comp_hash+ uses a +comp_sym+ as key and a component instance as value.
23
+ def prepend(comp_hash)
24
+ @components.update comp_hash
25
+ self
26
+ end
27
+
28
+ # Load components from a Hash.
29
+ def load(params)
30
+ grid_params = params.fetch("margrid", {}).fetch(@id, {})
31
+ if sorter = Sorter.load(grid_params)
32
+ prepend sorter: sorter
33
+ end
34
+ if paginator = Paginator.load(grid_params)
35
+ prepend paginator: paginator
36
+ end
37
+ self
38
+ end
39
+
40
+ # Dump components to a nested Hash.
41
+ def dump(comps = nil)
42
+ comps ||= @components.values
43
+ grid_params = comps.inject({}) do |params, comp|
44
+ params.merge(comp.dump)
45
+ end
46
+ {"margrid" => {@id => grid_params}}
47
+ end
48
+
49
+ # Dump components to a Hash. The key of the Hash is the rack param name.
50
+ def to_query(comps = nil)
51
+ comps ||= @components.values
52
+ prefix = "margrid[#{@id}]"
53
+ comps.inject({}) do |params, comp|
54
+ comp.dump.each do |k, v|
55
+ params[prefix + "[#{k}]"] = v
56
+ end
57
+ params
58
+ end
59
+ end
60
+
61
+ # Rows to display in the grid. This will apply every registered component
62
+ # to the +ActiveRecord::Relation+ passed upon grid initialization.
63
+ # This method returns a new +ActiveRecord::Relation+ representing the grid rows.
64
+ def rows
65
+ @rows ||= @components.values.inject(@relation) do |relation, comp|
66
+ comp.apply(relation)
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,3 @@
1
+ module Margrid
2
+ VERSION = "0.0.1"
3
+ end
data/lib/margrid.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "margrid/components"
2
+ require "margrid/grid"
3
+ require "margrid/builder"
4
+ require "margrid/factory_methods"
5
+
6
+ module Margrid
7
+ extend FactoryMethods
8
+ end
data/margrid.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'margrid/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "margrid"
8
+ spec.version = Margrid::VERSION
9
+ spec.authors = ["Yves Senn", "Jonas Baumann"]
10
+ spec.email = ["yves.senn@gmail.com"]
11
+ spec.summary = %q{Grid library to build paginated and sortable tables.}
12
+ spec.description = %q{Margrid makes it easy to add sortable and paginated tables to your web pages. Since state is passed through the query string, browser bookmarks can be used to save different views.}
13
+ spec.homepage = "https://www.github.com/4teamwork/margrid"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "minitest", "~> 5.4"
24
+ end
@@ -0,0 +1,27 @@
1
+ require_relative "../test_helper"
2
+
3
+ class BuilderTest < Margrid::TestCase
4
+ def setup
5
+ @builder = Margrid::Builder.new(Margrid.grid("built", Minitest::Mock.new))
6
+ end
7
+
8
+ def test_add_paginator_to_grid
9
+ grid = @builder.paginated.grid
10
+ assert_equal Margrid.paginator(1), grid.component(:paginator)
11
+ end
12
+
13
+ def test_add_default_sort_to_grid
14
+ grid = @builder.sort_by("size", "desc").grid
15
+ assert_equal Margrid.sorter("size", "desc"), grid.component(:sorter)
16
+ end
17
+
18
+ def test_load_components_from_params
19
+ grid = @builder.load({"margrid" => {"built" => {page: 4}}})
20
+ assert_equal Margrid.paginator(4), grid.component(:paginator)
21
+ end
22
+
23
+ def test_use_grid_methods_on_builder
24
+ grid = @builder.prepend(custom: "CUSTOM COMPONENT").grid
25
+ assert_equal "CUSTOM COMPONENT", grid.component(:custom)
26
+ end
27
+ end
@@ -0,0 +1,90 @@
1
+ require_relative "../test_helper"
2
+
3
+ class GridTest < Margrid::TestCase
4
+ class CustomComponent < Struct.new(:prefix)
5
+ def apply(relation)
6
+ relation.do_stuff
7
+ end
8
+
9
+ def dump
10
+ {prefix => "state"}
11
+ end
12
+ end
13
+
14
+ def setup
15
+ @relation = Minitest::Mock.new
16
+ @grid = Margrid::Grid.new("test", @relation)
17
+ end
18
+
19
+ def test_prepending_components_overwrites_existing_ones
20
+ @grid.prepend custom: (first = CustomComponent.new)
21
+ @grid.prepend custom: (second = CustomComponent.new)
22
+
23
+ assert_equal second, @grid.component(:custom)
24
+ end
25
+
26
+ def test_rows_applies_every_component_to_the_relation
27
+ @grid.prepend custom: CustomComponent.new
28
+
29
+ @relation.expect :do_stuff, "APPLIED RELATION", []
30
+ assert_equal "APPLIED RELATION", @grid.rows
31
+ end
32
+
33
+ def test_knows_registered_components
34
+ @grid.prepend first: CustomComponent.new
35
+ @grid.prepend second: CustomComponent.new
36
+
37
+ assert @grid.component?(:first)
38
+ assert @grid.component?(:second)
39
+ refute @grid.component?(:third)
40
+ end
41
+
42
+ def test_access_registerd_components
43
+ @grid.prepend first: (first_comp = CustomComponent.new)
44
+
45
+ assert_equal first_comp, @grid.component(:first)
46
+ end
47
+
48
+ def test_access_non_registerd_components
49
+ assert_equal nil, @grid.component(:does_not_exist)
50
+ end
51
+
52
+ def test_dumping_a_grid_dumps_every_component
53
+ @grid.prepend first: CustomComponent.new("some")
54
+ @grid.prepend second: CustomComponent.new("more")
55
+
56
+ assert_equal({"margrid"=>{"test"=>{"some"=>"state", "more"=>"state"}}}, @grid.dump)
57
+ end
58
+
59
+ def test_dumping_a_specific_component
60
+ assert_equal({"margrid"=>{"test"=>{"not_much"=>"state"}}},
61
+ @grid.dump([CustomComponent.new("not_much")]))
62
+ end
63
+
64
+ def test_represent_the_grid_as_a_query
65
+ @grid.prepend first: CustomComponent.new("first")
66
+ @grid.prepend second: CustomComponent.new("second")
67
+
68
+ assert_equal({"margrid[test][first]"=>"state", "margrid[test][second]"=>"state"},
69
+ @grid.to_query)
70
+ end
71
+
72
+ def test_representing_a_component_as_query
73
+ assert_equal({"margrid[test][stuff]"=>"state"},
74
+ @grid.to_query([CustomComponent.new("stuff")]))
75
+ end
76
+
77
+ def test_load_components_form_a_hash
78
+ @grid.load({"margrid" => {"test" => {sort: "name", direction: "asc", page: 3}}})
79
+ assert_equal Margrid.sorter("name", "asc"), @grid.component(:sorter)
80
+ assert_equal Margrid.paginator(3), @grid.component(:paginator)
81
+ end
82
+
83
+ def test_load_and_prepend_overwrite_eachother
84
+ @grid.prepend(paginator: CustomComponent.new("fluffy"))
85
+ @grid.load({"margrid" => {"test" => {sort: "name", direction: "asc", page: 8}}})
86
+ @grid.prepend(sorter: CustomComponent.new("cat"))
87
+ assert_equal CustomComponent.new("cat"), @grid.component(:sorter)
88
+ assert_equal Margrid.paginator(8), @grid.component(:paginator)
89
+ end
90
+ end
@@ -0,0 +1,26 @@
1
+ require_relative "../test_helper"
2
+
3
+ class PaginatorTest < Margrid::TestCase
4
+ def test_applying_a_paginator_delegates_to_page
5
+ relation = Minitest::Mock.new
6
+ paginator = Margrid.paginator(11)
7
+
8
+ relation.expect :page, "PAGINATED", [11]
9
+ assert_equal "PAGINATED", paginator.apply(relation)
10
+ end
11
+
12
+ def test_load_from_hash_with_existing_param
13
+ paginator = Margrid::Paginator.load({page: 23})
14
+ assert_equal Margrid.paginator(23), paginator
15
+ end
16
+
17
+ def test_load_from_hash_without_existing_param
18
+ paginator = Margrid::Paginator.load({})
19
+ assert_equal nil, paginator
20
+ end
21
+
22
+ def test_dumping_to_a_hash
23
+ paginator = Margrid.paginator(7)
24
+ assert_equal({page: 7}, paginator.dump)
25
+ end
26
+ end
@@ -0,0 +1,35 @@
1
+ require_relative "../test_helper"
2
+
3
+ class SorterTest < Margrid::TestCase
4
+ def test_applying_a_sorter_delegates_to_reorder
5
+ relation = Minitest::Mock.new
6
+ sorter = Margrid.sorter("age", "desc")
7
+
8
+ relation.expect :reorder, "SORTED", ["age" => :desc]
9
+ assert_equal "SORTED", sorter.apply(relation)
10
+ end
11
+
12
+ def test_load_from_hash_with_existing_param
13
+ sorter = Margrid::Sorter.load({sort: "name", direction: "asc"})
14
+ assert_equal Margrid.sorter("name", "asc"), sorter
15
+ end
16
+
17
+ def test_load_from_hash_without_existing_param
18
+ sorter = Margrid::Sorter.load({})
19
+ assert_equal nil, sorter
20
+ end
21
+
22
+ def test_dumping_to_a_hash
23
+ sorter = Margrid.sorter("author", "desc")
24
+ assert_equal({sort: "author", direction: "desc"}, sorter.dump)
25
+ end
26
+
27
+ def test_works_with_symbols_and_strings
28
+ assert_equal Margrid.sorter(:name, :desc), Margrid.sorter("name", "desc")
29
+ end
30
+
31
+ def test_inverting_flips_direction
32
+ assert Margrid.sorter("name", "asc").inverted.desc?
33
+ assert Margrid.sorter("name", "desc").inverted.asc?
34
+ end
35
+ end
@@ -0,0 +1,9 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/pride'
3
+ require 'minitest/mock'
4
+
5
+ $: << File.expand_path('../../lib', __FILE__)
6
+ require "margrid"
7
+
8
+ class Margrid::TestCase < MiniTest::Unit::TestCase
9
+ end
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: margrid
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Yves Senn
8
+ - Jonas Baumann
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-08-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: '1.6'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: '1.6'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: '10.0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ version: '10.0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: minitest
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ~>
47
+ - !ruby/object:Gem::Version
48
+ version: '5.4'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ version: '5.4'
56
+ description: Margrid makes it easy to add sortable and paginated tables to your web
57
+ pages. Since state is passed through the query string, browser bookmarks can be
58
+ used to save different views.
59
+ email:
60
+ - yves.senn@gmail.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - .gitignore
66
+ - Gemfile
67
+ - LICENSE.txt
68
+ - README.md
69
+ - Rakefile
70
+ - lib/margrid.rb
71
+ - lib/margrid/builder.rb
72
+ - lib/margrid/components.rb
73
+ - lib/margrid/factory_methods.rb
74
+ - lib/margrid/grid.rb
75
+ - lib/margrid/version.rb
76
+ - margrid.gemspec
77
+ - test/margrid/builder_test.rb
78
+ - test/margrid/grid_test.rb
79
+ - test/margrid/paginator_test.rb
80
+ - test/margrid/sorter_test.rb
81
+ - test/test_helper.rb
82
+ homepage: https://www.github.com/4teamwork/margrid
83
+ licenses:
84
+ - MIT
85
+ metadata: {}
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubyforge_project:
102
+ rubygems_version: 2.1.11
103
+ signing_key:
104
+ specification_version: 4
105
+ summary: Grid library to build paginated and sortable tables.
106
+ test_files:
107
+ - test/margrid/builder_test.rb
108
+ - test/margrid/grid_test.rb
109
+ - test/margrid/paginator_test.rb
110
+ - test/margrid/sorter_test.rb
111
+ - test/test_helper.rb