the_grid 1.0.10 → 1.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.
- checksums.yaml +8 -8
- data/README.md +36 -2
- data/lib/generators/the_grid/install/templates/the_grid.rb +2 -2
- data/lib/the_grid/builder/csv.rb +45 -0
- data/lib/the_grid/builder.rb +11 -13
- data/lib/the_grid/version.rb +1 -1
- data/spec/builder/csv_spec.rb +47 -0
- data/spec/builder/json_spec.rb +14 -16
- data/spec/builder/view_builder_helper.rb +10 -0
- data/the_grid.gemspec +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
Y2YyOTU4N2Y4MWQ1NDcxZTZmNmZiZTIxOTE4M2JkNGUwMTNjZDUyNA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZDJkZThhYjEzYjBjYTc0YmM4NjU3NzkxZWM2NTgwMDFiZGM4ZWMzNQ==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NGFhZjQ2NTJjMzhkYTFmMzJkNGY4ZTA5NzQ0MWU5YzMwMGRiYzA4ODMwY2U0
|
10
|
+
YzAxZWM2ZDgwMDBiMTE3OTRkOGUxYTg5YzBhMTQ5MGE1MDg5NTM4YWUwMDk3
|
11
|
+
ODQwOTJlZWM1MmQ1NmJhYzViOWQ2OWFiZWFmMTI1NGFhMTNhYmI=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YjViYzJjMWZhZmMzMTY4YmE2YzVlOTQ3YzU3YTBiOWZiY2I3NDU0MDU4MTY0
|
14
|
+
ZDJlYjY4MzkyYmUwNzhhYmE2MjllMWZlODJhYWY1NTExNjFjMzE4YmE4MjNi
|
15
|
+
MDAyN2FjNTA1YTQ4NmUzZThjY2FmNjkwZTU2YzZmMWQzOWUwNTQ=
|
data/README.md
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
Yet Another Grid
|
2
2
|
=========
|
3
3
|
|
4
|
-
This plugin is designed to provide API for building
|
4
|
+
This plugin is designed to provide API for building response based on `ActiveRecord::Relation` objects (json, csv, even using custom view builder).
|
5
5
|
It makes much easier to fetch information from database for displaying it using JavaScript MV* based frameworks such as Knockout, Backbone, Angular, etc.
|
6
6
|
|
7
7
|
## Getting started
|
8
8
|
|
9
9
|
First of all specify grid in your Gemfile and run `bundle install`.
|
10
|
-
After gem is installed you need to run `rails generate
|
10
|
+
After gem is installed you need to run `rails generate the_grid:install`. This will generate grid initializer file with basic configuration.
|
11
11
|
|
12
12
|
## Usage
|
13
13
|
|
@@ -37,6 +37,8 @@ grid_for @articles, :per_page => 25 do
|
|
37
37
|
end
|
38
38
|
```
|
39
39
|
|
40
|
+
The same grid defenition can be used with different formats.
|
41
|
+
|
40
42
|
## API
|
41
43
|
|
42
44
|
The API is based on commands. Term *command* describes client's action which can be simple or complicated as well.
|
@@ -422,6 +424,38 @@ grid_for @groups, :per_page => 2 do
|
|
422
424
|
end
|
423
425
|
end
|
424
426
|
```
|
427
|
+
#### CSV builder
|
428
|
+
|
429
|
+
It's possible to generate csv using grid views.
|
430
|
+
The main power is that this view builder also responds to also the api request parameters except pagination.
|
431
|
+
So, it's possible to filter records for output csv. All what you need is just create a simple view:
|
432
|
+
```ruby
|
433
|
+
# app/views/products/index.csv.grid_builder
|
434
|
+
grid_for @products do
|
435
|
+
column :title
|
436
|
+
column :qty
|
437
|
+
column :created_at
|
438
|
+
end
|
439
|
+
```
|
440
|
+
And in your controller
|
441
|
+
```ruby
|
442
|
+
# app/controllers/products_controller.rb
|
443
|
+
class ProductsController < ApplicationController
|
444
|
+
respond_to :csv, :html
|
445
|
+
|
446
|
+
def index
|
447
|
+
@products = Product.active
|
448
|
+
respond_with @products
|
449
|
+
end
|
450
|
+
end
|
451
|
+
```
|
452
|
+
|
453
|
+
Then you can send requests like:
|
454
|
+
```
|
455
|
+
http://your.domain.com/route.csv?cmd[]=filter&filters[is_active]=1
|
456
|
+
```
|
457
|
+
and will get csv file which contains only filtered active products.
|
458
|
+
|
425
459
|
## License
|
426
460
|
|
427
461
|
Released under the [MIT License](http://www.opensource.org/licenses/MIT)
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
module TheGrid
|
4
|
+
class Builder::Csv
|
5
|
+
attr_reader :api, :context
|
6
|
+
|
7
|
+
BATCH_SIZE = 1000
|
8
|
+
|
9
|
+
def initialize(relation, context)
|
10
|
+
@api = TheGrid::Api.new(relation)
|
11
|
+
@context = context
|
12
|
+
end
|
13
|
+
|
14
|
+
def assemble_with(params)
|
15
|
+
options = params.merge context.params
|
16
|
+
api.compose!(options.merge :per_page => BATCH_SIZE)
|
17
|
+
generate_csv_with(options)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def generate_csv_with(options)
|
23
|
+
CSV.generate do |csv|
|
24
|
+
csv << headers
|
25
|
+
put_relation_to(csv)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def put_relation_to(csv)
|
30
|
+
(1..api.options[:max_page]).each do |page|
|
31
|
+
relation = api.run_command!(:paginate, :page => page, :per_page => BATCH_SIZE)
|
32
|
+
put_records_to(csv, relation)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def put_records_to(csv, records)
|
37
|
+
context.assemble(records).each{ |row| csv << row.values }
|
38
|
+
end
|
39
|
+
|
40
|
+
def headers
|
41
|
+
context.options[:headers] || context.columns.keys.map { |col| col.to_s.titleize }
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
data/lib/the_grid/builder.rb
CHANGED
@@ -10,21 +10,26 @@ module TheGrid
|
|
10
10
|
end
|
11
11
|
|
12
12
|
%{
|
13
|
-
::TheGrid::Builder.assemble(:
|
13
|
+
::TheGrid::Builder.assemble(:format => #{template.formats.first.inspect}, :scope => self) {
|
14
14
|
#{source}
|
15
15
|
}
|
16
16
|
}
|
17
17
|
end
|
18
18
|
|
19
|
+
def self.detect_view(format)
|
20
|
+
@@view_types ||= {}
|
21
|
+
@@view_types[format] ||= "the_grid/builder/#{format}".camelize.constantize
|
22
|
+
end
|
23
|
+
|
19
24
|
def self.assemble(options, &block)
|
20
|
-
new(options, &block)
|
25
|
+
new(options, &block).instance_eval(&block)
|
21
26
|
end
|
22
27
|
|
23
28
|
def initialize(options, &block)
|
24
|
-
options.assert_valid_keys(:scope, :
|
29
|
+
options.assert_valid_keys(:scope, :format)
|
25
30
|
|
26
31
|
@_scope = options.delete(:scope)
|
27
|
-
@_view_type = options.delete(:
|
32
|
+
@_view_type = self.class.detect_view(options.delete(:format))
|
28
33
|
|
29
34
|
copy_instance_variables_from(@_scope) if @_scope
|
30
35
|
self.instance_eval(&block)
|
@@ -32,11 +37,7 @@ module TheGrid
|
|
32
37
|
|
33
38
|
def grid_for(relation, options = {}, &block)
|
34
39
|
context = Context.new(options.merge(:scope => @_scope), &block)
|
35
|
-
@
|
36
|
-
end
|
37
|
-
|
38
|
-
def assemble(&block)
|
39
|
-
@_view_handler.assemble_with(@_scope.params, &block)
|
40
|
+
@_view_type.new(relation, context)
|
40
41
|
end
|
41
42
|
|
42
43
|
def method_missing(name, *args, &block)
|
@@ -47,14 +48,11 @@ module TheGrid
|
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
50
|
-
def to_s; assemble;end
|
51
|
-
def to_str; assemble;end
|
52
|
-
|
53
51
|
private
|
54
52
|
|
55
53
|
def copy_instance_variables_from(object)
|
56
54
|
vars = object.instance_variables.map(&:to_s)
|
57
|
-
vars.each
|
55
|
+
vars.each{ |name| instance_variable_set(name.to_sym, object.instance_variable_get(name)) }
|
58
56
|
end
|
59
57
|
|
60
58
|
end
|
data/lib/the_grid/version.rb
CHANGED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require_relative 'view_builder_helper'
|
3
|
+
|
4
|
+
describe TheGrid::Builder::Csv do
|
5
|
+
subject{ TheGrid::Builder::Csv.new(relation, build_context) }
|
6
|
+
|
7
|
+
include_examples "for Grid View Builder"
|
8
|
+
before(:each) { subject.api.stub(:compose!){ subject.api.options[:max_page] = 1 } }
|
9
|
+
|
10
|
+
let(:relation) { double.as_null_object }
|
11
|
+
let(:record) {{ :id => 1, :name => "Name", :status => "Active", :text => "Text" }}
|
12
|
+
let(:records) {[ record, record, record ]}
|
13
|
+
let(:params) {{ :cmd => [:sort], :field => :name, :order => :desc, :per_page => subject.class.const_get("BATCH_SIZE") }}
|
14
|
+
|
15
|
+
it "generates expected csv string" do
|
16
|
+
subject.assemble_with(params).should eql generate_csv(records, subject.context.options[:headers])
|
17
|
+
end
|
18
|
+
|
19
|
+
it "uses titleized column names if headers are not specified" do
|
20
|
+
subject.context.stub(:options => {})
|
21
|
+
headers = record.keys.map{|c| c.to_s.titleize }
|
22
|
+
subject.assemble_with(params).should eql generate_csv(records, headers)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "generates csv records in batches" do
|
26
|
+
subject.api.should_receive(:run_command!).with(:paginate, :page => 1, :per_page => params[:per_page])
|
27
|
+
subject.assemble_with(params);
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def generate_csv(records, headers)
|
32
|
+
CSV.generate do |csv|
|
33
|
+
csv << headers
|
34
|
+
records.each{ |item| csv << item.values }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def build_context
|
39
|
+
TheGrid::Builder::Context.new do
|
40
|
+
headers "Id", "Title", "Status", "Description"
|
41
|
+
column :name
|
42
|
+
column :status
|
43
|
+
column :text
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
data/spec/builder/json_spec.rb
CHANGED
@@ -1,21 +1,22 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require_relative 'view_builder_helper'
|
2
3
|
|
3
4
|
describe TheGrid::Builder::Json do
|
4
|
-
subject
|
5
|
+
subject{ TheGrid::Builder::Json.new(Object.new, build_context) }
|
5
6
|
|
6
|
-
|
7
|
+
include_examples "for Grid View Builder"
|
8
|
+
before(:each) { subject.api.stub(:compose!){ subject.api.options[:max_page] = 25 } }
|
7
9
|
|
8
|
-
let(:
|
9
|
-
let(:
|
10
|
-
let(:params) {{ :cmd => [:sort], :field => :name, :order => :desc }}
|
10
|
+
let(:records) {[ 1, 2, 3, 4 ]}
|
11
|
+
let(:params) {{ :cmd => [:sort], :field => :name, :order => :desc }}
|
11
12
|
|
12
|
-
let(:meta) {{ "meta" => {"api_key" => context.options[:api_key]}, "columns" => columns }}
|
13
|
-
let(:columns) { context.visible_columns.stringify_keys.map{ |n, o| o.merge "name" => n } }
|
14
|
-
let(:json_schema) {{ "max_page" => 25, "items" => context.assemble }}
|
13
|
+
let(:meta) {{ "meta" => {"api_key" => subject.context.options[:api_key]}, "columns" => columns }}
|
14
|
+
let(:columns) { subject.context.visible_columns.stringify_keys.map{ |n, o| o.merge "name" => n } }
|
15
|
+
let(:json_schema) {{ "max_page" => 25, "items" => subject.context.assemble }}
|
15
16
|
let(:assembled_result) { JSON.parse(subject.assemble_with(params)) }
|
16
17
|
|
17
18
|
it "merges params with context options" do
|
18
|
-
subject.api.should_receive(:compose!).with(params.merge context.options)
|
19
|
+
subject.api.should_receive(:compose!).with(params.merge subject.context.options)
|
19
20
|
subject.assemble_with params
|
20
21
|
end
|
21
22
|
|
@@ -29,16 +30,13 @@ describe TheGrid::Builder::Json do
|
|
29
30
|
end
|
30
31
|
|
31
32
|
it "generates json notification when get wrong argument" do
|
32
|
-
subject.api.stub(:compose!) { raise ArgumentError, "
|
33
|
-
assembled_result.should eql
|
33
|
+
subject.api.stub(:compose!) { raise ArgumentError, "my message" }
|
34
|
+
assembled_result.should eql "status" => "error", "message" => "my message"
|
34
35
|
end
|
35
36
|
|
36
|
-
|
37
|
-
def create_context
|
37
|
+
def build_context
|
38
38
|
TheGrid::Builder::Context.new do
|
39
|
-
api_key
|
40
|
-
delegate :sort => :articles, :filter => :articles
|
41
|
-
|
39
|
+
api_key 1234567
|
42
40
|
column :name
|
43
41
|
column :is_active
|
44
42
|
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
shared_examples "for Grid View Builder" do
|
2
|
+
before(:each) { subject.context.stub(:assemble => records) }
|
3
|
+
|
4
|
+
it { should respond_to(:assemble_with) }
|
5
|
+
|
6
|
+
it "merges context with params" do
|
7
|
+
subject.api.should_receive(:compose!).with(params.merge subject.context.options)
|
8
|
+
subject.assemble_with(params)
|
9
|
+
end
|
10
|
+
end
|
data/the_grid.gemspec
CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.description = <<-EOF
|
16
16
|
Provides json API for building ActiveRecord::Relation's. It makes much easier to fetch information from database for displaying it using JavaScript MV* based frameworks such as Knockout, Backbone, Angular, etc.
|
17
17
|
|
18
|
-
Tags: json, grid, api, grid builder, activerecord relation builder, relation
|
18
|
+
Tags: json, csv, grid, api, grid builder, activerecord relation builder, relation
|
19
19
|
EOF
|
20
20
|
|
21
21
|
s.post_install_message = <<-_MSG_
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: the_grid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergiy Stotskiy
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-04-
|
12
|
+
date: 2013-04-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -72,7 +72,7 @@ description: ! 'Provides json API for building ActiveRecord::Relation''s. It ma
|
|
72
72
|
MV* based frameworks such as Knockout, Backbone, Angular, etc.
|
73
73
|
|
74
74
|
|
75
|
-
Tags: json, grid, api, grid builder, activerecord relation builder, relation
|
75
|
+
Tags: json, csv, grid, api, grid builder, activerecord relation builder, relation
|
76
76
|
|
77
77
|
'
|
78
78
|
email: sergiy.stotskiy@gmail.com
|
@@ -97,6 +97,7 @@ files:
|
|
97
97
|
- lib/the_grid/api/command/sort.rb
|
98
98
|
- lib/the_grid/builder.rb
|
99
99
|
- lib/the_grid/builder/context.rb
|
100
|
+
- lib/the_grid/builder/csv.rb
|
100
101
|
- lib/the_grid/builder/json.rb
|
101
102
|
- lib/the_grid/config.rb
|
102
103
|
- lib/the_grid/version.rb
|
@@ -109,7 +110,9 @@ files:
|
|
109
110
|
- spec/api/command_spec.rb
|
110
111
|
- spec/api_spec.rb
|
111
112
|
- spec/builder/context_spec.rb
|
113
|
+
- spec/builder/csv_spec.rb
|
112
114
|
- spec/builder/json_spec.rb
|
115
|
+
- spec/builder/view_builder_helper.rb
|
113
116
|
- spec/config_spec.rb
|
114
117
|
- spec/spec_helper.rb
|
115
118
|
- the_grid.gemspec
|