admino 0.0.10 → 0.0.11

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fe0d128c8350787165c4d23c7e9615df3475b4a9
4
- data.tar.gz: 7e5bf3ecf69f2f45152ac342d8effbbdff5bb41f
3
+ metadata.gz: b0d55f8a3f155b631729a250ce1ff8eafdf443aa
4
+ data.tar.gz: f02070346455841d8466fdb67cd3f40d65ffe96c
5
5
  SHA512:
6
- metadata.gz: 2ed53f3c1ad99454097045f3662f92db7766cdaf24cba9f78165fb3a784ec58c9a733f2d4ec62cbeb5303f7c5672c94fc30f7a70fa36c7ced3d99e1748246ded
7
- data.tar.gz: ae0e7e38ac6fa22b2e1ed394b2ccc2fd2ac198b204a5ec7362033716bf671408eb5d828e703a9bc26306fdda224f4b7901ab7cce2c135d8faad504a010325e54
6
+ metadata.gz: bf0d27b8b835de7f2e10fe16cadbc3301e9771f76a40ccee7ef4e4234259210a0d8589cdac9fa1783edc964cbe0d14aab6d30bb34a746b657bb3f9f3c7d84115
7
+ data.tar.gz: 85b3cab3ac2fd27d265ac11d547ae85383e273d66f59879d23e89e09c8fc66d068d99e36dea1d20601eafc44ad487666988d9f8eca6cbc12917bd867d4179d8f
data/README.md CHANGED
@@ -26,6 +26,10 @@ If a particular controller or view needs something different from the standard C
26
26
 
27
27
  So what about Admino? Well, it complements the above-mentioned gems, giving you the the missing ~10%: a fast way to generate administrative index views.
28
28
 
29
+ ## Demo
30
+
31
+ To better illustrate how to create a 100%-custom, super-DRY administrative interface using Admino and the aforementioned gems, we prepared a [repo with a sample Rails project](https://github.com/cantierecreativo/admino-example) you can take a look. The app is browsable at [http://admino-example.herokuapp.com](http://admino-example.herokuapp.com), and features a Bootstrap 3 theme.
32
+
29
33
  ## Installation
30
34
 
31
35
  Add this line to your application's Gemfile:
@@ -86,6 +90,7 @@ class TasksQuery < Admino::Query::Base
86
90
  search_field :title_matches
87
91
  end
88
92
  ```
93
+
89
94
  The `#scope` method will check the presence of the `params[:query][:title_matches]` key. If it finds it, it will augment the query with a named scope called `:title_matches`, expected to be found within the `Task` model. The scope needs to accept an argument.
90
95
 
91
96
  ```ruby
@@ -102,6 +107,15 @@ TaskQuery.new.scope.count # => 2
102
107
  TaskQuery.new(query: { title_matches: 'ASAP' }).scope.count # => 1
103
108
  ```
104
109
 
110
+ You can provide a default value with the `default` option:
111
+
112
+ ```ruby
113
+ class TasksQuery < Admino::Query::Base
114
+ # ...
115
+ search_field :title_matches, default: 'TODO'
116
+ end
117
+ ```
118
+
105
119
  #### `filter_by`
106
120
 
107
121
  ```ruby
@@ -129,6 +143,17 @@ TaskQuery.new(query: { status: 'pending' }).scope.count # => 1
129
143
  TaskQuery.new(query: { status: 'foobar' }).scope.count # => 3
130
144
  ```
131
145
 
146
+ You can include a "reset" scope with the `include_empty_scope` option, and provide a default scope with the `default` option:
147
+
148
+ ```ruby
149
+ class TasksQuery < Admino::Query::Base
150
+ # ...
151
+ filter_by :time, [:last_month, :last_week],
152
+ include_empty_scope: true,
153
+ default: :last_week
154
+ end
155
+ ```
156
+
132
157
  #### `sorting`
133
158
 
134
159
  ```ruby
@@ -485,7 +510,7 @@ class CustomTablePresenter < Admino::Table::Presenter
485
510
  { class: 'table-class' }
486
511
  end
487
512
 
488
- def tbody_tr_html_options(resource_index)
513
+ def tbody_tr_html_options(resource, index)
489
514
  { class: 'tr-class' }
490
515
  end
491
516
 
@@ -3,16 +3,26 @@ module Admino
3
3
  class Configuration
4
4
  class SearchField
5
5
  attr_reader :name
6
- attr_reader :coerce_to
6
+ attr_reader :options
7
7
 
8
8
  def initialize(name, options = {})
9
9
  options.symbolize_keys!
10
- options.assert_valid_keys(:coerce)
10
+ options.assert_valid_keys(
11
+ :coerce,
12
+ :default
13
+ )
11
14
 
12
15
  @name = name.to_sym
16
+ @options = options
17
+ end
18
+
19
+ def default_value
20
+ options[:default]
21
+ end
13
22
 
14
- if coerce_to = options[:coerce]
15
- @coerce_to = coerce_to.to_sym
23
+ def coerce_to
24
+ if options[:coerce]
25
+ options[:coerce].to_sym
16
26
  end
17
27
  end
18
28
  end
@@ -24,7 +34,10 @@ module Admino
24
34
 
25
35
  def initialize(name, scopes, options = {})
26
36
  options.symbolize_keys!
27
- options.assert_valid_keys(:include_empty_scope)
37
+ options.assert_valid_keys(
38
+ :include_empty_scope,
39
+ :default
40
+ )
28
41
 
29
42
  @name = name.to_sym
30
43
  @scopes = scopes.map(&:to_sym)
@@ -34,6 +47,12 @@ module Admino
34
47
  def include_empty_scope?
35
48
  @options.fetch(:include_empty_scope) { false }
36
49
  end
50
+
51
+ def default_scope
52
+ if options[:default]
53
+ options[:default].to_sym
54
+ end
55
+ end
37
56
  end
38
57
 
39
58
  class Sorting
@@ -23,8 +23,8 @@ module Admino
23
23
  end
24
24
 
25
25
  def active_scope
26
- if value && scopes.include?(value.to_sym)
27
- value.to_sym
26
+ if value && scopes.include?(value)
27
+ value
28
28
  else
29
29
  nil
30
30
  end
@@ -35,8 +35,22 @@ module Admino
35
35
  end
36
36
 
37
37
  def value
38
- default_value = config.include_empty_scope? ? :empty : nil
39
- params.fetch(:query, {}).fetch(param_name, default_value)
38
+ value = params.fetch(:query, {}).fetch(param_name, default_value)
39
+ if value
40
+ value.to_sym
41
+ else
42
+ nil
43
+ end
44
+ end
45
+
46
+ def default_value
47
+ if config.default_scope
48
+ config.default_scope
49
+ elsif config.include_empty_scope?
50
+ :empty
51
+ else
52
+ nil
53
+ end
40
54
  end
41
55
 
42
56
  def param_name
@@ -23,16 +23,17 @@ module Admino
23
23
 
24
24
  def value
25
25
  value = params.fetch(:query, {}).fetch(param_name, nil)
26
+
26
27
  if config.coerce_to
27
- begin
28
- coercer = Coercible::Coercer.new
29
- coercer[value.class].send(config.coerce_to, value)
30
- rescue Coercible::UnsupportedCoercion
31
- nil
32
- end
33
- else
34
- value
28
+ value = begin
29
+ coercer = Coercible::Coercer.new
30
+ coercer[value.class].send(config.coerce_to, value)
31
+ rescue Coercible::UnsupportedCoercion
32
+ nil
33
+ end
35
34
  end
35
+
36
+ value || config.default_value
36
37
  end
37
38
 
38
39
  def present?
@@ -1,4 +1,4 @@
1
1
  module Admino
2
- VERSION = "0.0.10"
2
+ VERSION = "0.0.11"
3
3
  end
4
4
 
@@ -107,15 +107,19 @@ module Admino
107
107
  end
108
108
  end
109
109
 
110
- context 'with a set of search_fields and filter_groups' do
110
+ context 'with a set of search_fields, filter_groups and sortings' do
111
111
  let(:search_field_config) { config.add_search_field(:search_field) }
112
112
  let(:filter_group_config) { config.add_filter_group(:filter_group, [:one, :two]) }
113
+ let(:sorting_config) { config.add_sorting_scopes([:title, :year]) }
114
+
113
115
  let(:scope_chained_with_search_field) { double('scope 1') }
114
- let(:final_chain) { double('scope 2') }
116
+ let(:scope_chained_with_group_filter) { double('scope 2') }
117
+ let(:final_chain) { double('scope 3') }
115
118
 
116
119
  before do
117
120
  search_field_config
118
121
  filter_group_config
122
+ sorting_config
119
123
  query
120
124
 
121
125
  query.search_field_by_name(:search_field).
@@ -126,6 +130,10 @@ module Admino
126
130
  query.filter_group_by_name(:filter_group).
127
131
  stub(:augment_scope).
128
132
  with(scope_chained_with_search_field).
133
+ and_return(scope_chained_with_group_filter)
134
+
135
+ query.sorting.stub(:augment_scope).
136
+ with(scope_chained_with_group_filter).
129
137
  and_return(final_chain)
130
138
  end
131
139
 
@@ -4,7 +4,10 @@ module Admino
4
4
  module Query
5
5
  describe FilterGroup do
6
6
  subject(:filter_group) { FilterGroup.new(config, params) }
7
- let(:config) { Configuration::FilterGroup.new(:foo, [:bar]) }
7
+ let(:config) do
8
+ Configuration::FilterGroup.new(:foo, [:bar, :other], options)
9
+ end
10
+ let(:options) { {} }
8
11
  let(:params) { {} }
9
12
 
10
13
  describe '#active_scope' do
@@ -16,7 +19,34 @@ module Admino
16
19
  end
17
20
 
18
21
  context 'if include_empty_scope is true' do
19
- let(:config) { Configuration::FilterGroup.new(:foo, [:bar], include_empty_scope: true) }
22
+ let(:options) { { include_empty_scope: true } }
23
+
24
+ it 'returns the :empty scope' do
25
+ expect(filter_group.active_scope).to eq :empty
26
+ end
27
+
28
+ context 'if default scope is set' do
29
+ let(:config) do
30
+ Configuration::FilterGroup.new(
31
+ :foo,
32
+ [:bar],
33
+ include_empty_scope: true,
34
+ default: :bar
35
+ )
36
+ end
37
+
38
+ it 'returns it' do
39
+ expect(filter_group.active_scope).to eq :bar
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ context 'with "empty" param' do
46
+ let(:params) { { 'query' => { 'foo' => 'empty' } } }
47
+
48
+ context 'if include_empty_scope is true' do
49
+ let(:options) { { include_empty_scope: true, default: :bar } }
20
50
 
21
51
  it 'returns the :empty scope' do
22
52
  expect(filter_group.active_scope).to eq :empty
@@ -32,7 +62,7 @@ module Admino
32
62
  end
33
63
 
34
64
  context 'if include_empty_scope is true' do
35
- let(:config) { Configuration::FilterGroup.new(:foo, [:bar], include_empty_scope: true) }
65
+ let(:options) { { include_empty_scope: true, default: :bar } }
36
66
 
37
67
  it 'returns nil' do
38
68
  expect(filter_group.active_scope).to be_nil
@@ -67,7 +97,7 @@ module Admino
67
97
  end
68
98
 
69
99
  context 'if include_empty_scope is true' do
70
- let(:config) { Configuration::FilterGroup.new(:foo, [:bar], include_empty_scope: true) }
100
+ let(:options) { { include_empty_scope: true } }
71
101
 
72
102
  it 'returns the original scope' do
73
103
  expect(result).to eq scope
@@ -88,12 +118,13 @@ module Admino
88
118
  subject { filter_group.scopes }
89
119
 
90
120
  context 'if include_empty_scope is true' do
91
- let(:config) { Configuration::FilterGroup.new(:foo, [:bar], include_empty_scope: true) }
92
- it { should eq [:empty, :bar] }
121
+ let(:options) { { include_empty_scope: true } }
122
+
123
+ it { should eq [:empty, :bar, :other] }
93
124
  end
94
125
 
95
126
  context 'else' do
96
- it { should eq [:bar] }
127
+ it { should eq [:bar, :other] }
97
128
  end
98
129
  end
99
130
  end
@@ -20,6 +20,16 @@ module Admino
20
20
  it 'returns nil' do
21
21
  expect(search_field.value).to be_nil
22
22
  end
23
+
24
+ context 'with a default value' do
25
+ let(:config) {
26
+ Configuration::SearchField.new(:foo, default: 'foo')
27
+ }
28
+
29
+ it 'returns it' do
30
+ expect(search_field.value).to eq 'foo'
31
+ end
32
+ end
23
33
  end
24
34
 
25
35
  context 'with coertion' do
data/spec/spec_helper.rb CHANGED
@@ -32,10 +32,12 @@ class ScopeMock
32
32
  end
33
33
 
34
34
  class TestQuery < Admino::Query::Base
35
- search_field :foo
35
+ search_field :foo, default: 'bar'
36
36
  search_field :starting_from, coerce: :to_date
37
37
 
38
- filter_by :bar, [:one, :two], include_empty_scope: true
38
+ filter_by :bar, [:one, :two],
39
+ include_empty_scope: true,
40
+ default: :two
39
41
 
40
42
  sorting :by_title, :by_date,
41
43
  default_scope: :by_title,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: admino
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
4
+ version: 0.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefano Verna
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-31 00:00:00.000000000 Z
11
+ date: 2014-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: showcase
@@ -249,3 +249,4 @@ test_files:
249
249
  - spec/admino/table/resource_row_spec.rb
250
250
  - spec/admino/table/row_spec.rb
251
251
  - spec/spec_helper.rb
252
+ has_rdoc: