admino 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 032bc2648fb523ba0875508da85247a62ed9951a
4
- data.tar.gz: df81ccdbf54f9add70815106f98c7416b87e4e30
3
+ metadata.gz: e26dee36252bba0db083897fc29ced0358ab2046
4
+ data.tar.gz: 0efed84c06512abd26698ea33479d7ed1a7b4746
5
5
  SHA512:
6
- metadata.gz: c0e0faf1887177e8e1d98e872956707499ce89f203df38c8e66cc4a8dc562c03bd5d686ef2cd3c2fb462a75d5372565d52a23bc7363c17ef48024996d4c163d6
7
- data.tar.gz: b8881de3c6cecc14a8e91d80d887f7fd9a7bbf208c855875f36b51372857643079dc2fec608d5f0c1f4f861a7a371dd94cfc51c99aae02df2003df35fe4d53fd
6
+ metadata.gz: f036deab369232c67daf274146a06d1173a82ec26f77d444faf2e4bf66d550adce7224a6f0fe92d486b4eba44b5b9880a8fd216dd39309d3182178d083c69d19
7
+ data.tar.gz: 1342bbb40cea481a7e4459f74381746a64f6d12c54809a87aad7315fd247d602c5f60ce74bb2ab1fef9aca5ec1e68c51733f62a26aeeea659255fb769478a317
data/CHANGELOG.md CHANGED
@@ -1,4 +1,12 @@
1
- # v0.0.2
1
+ # v0.0.4
2
+
3
+ * Rename Group into FilterGroup
4
+ * Rename FilterGroup#available_scopes into #scopes
5
+ * Rename Sorting#available_scopes into #scopes
6
+ * Removed nil scope in FilterGroup
7
+ * Clicking on an active filter scope link will deactivate it
8
+
9
+ # v0.0.3
2
10
 
3
11
  * Fixed bug in SortingPresenter with default scope
4
12
 
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,40 @@
1
+ # Contributing
2
+
3
+ We love pull requests. Here's a quick guide:
4
+
5
+ 1. Fork the repo.
6
+ 2. Run the tests. We only take pull requests with passing tests, and it's great
7
+ to know that you have a clean slate: `bundle && rake`
8
+ 3. Add a test for your change. Only refactoring and documentation changes
9
+ require no new tests. If you are adding functionality or fixing a bug, we need
10
+ a test!
11
+ 4. Make the test pass.
12
+ 5. Make sure your changes adhere to the [thoughtbot Style
13
+ Guide](https://github.com/thoughtbot/guides/tree/master/style)
14
+ 6. Push to your fork and submit a pull request.
15
+ 7. At this point you're waiting on us. We like to at least comment on, if not
16
+ accept, pull requests within three business days (and, typically, one business
17
+ day). [We may suggest some changes or improvements or
18
+ alternatives](https://github.com/thoughtbot/guides/tree/master/code-review).
19
+
20
+ ## Increase your chances of getting merged
21
+
22
+ Some things that will increase the chance that your pull request is accepted,
23
+ taken straight from the Ruby on Rails guide:
24
+
25
+ * Use Rails idioms and helpers
26
+ * Include tests that fail without your code, and pass with it
27
+ * Update the documentation: that surrounding your change, examples elsewhere,
28
+ guides, and whatever else is affected by your contribution
29
+ * Syntax:
30
+ * Two spaces, no tabs.
31
+ * No trailing whitespace. Blank lines should not have any space.
32
+ * Make sure your [source files end with newline
33
+ characters](http://stackoverflow.com/questions/729692/why-should-files-end-with-a-newline#answer-729725).
34
+ * Prefer `&&`/`||` over `and`/`or`.
35
+ * `MyClass.my_method(my_arg)` not `my_method( my_arg )` or
36
+ `my_method my_arg`.
37
+ * `a = b` and not `a=b`.
38
+ * Follow the conventions you see used in the source already.
39
+ * And in case we didn't emphasize it enough: *We love tests!*
40
+
data/README.md CHANGED
@@ -1,9 +1,30 @@
1
1
  # Admino
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/admino.png)](http://badge.fury.io/rb/admino)
3
4
  [![Build Status](https://travis-ci.org/cantierecreativo/admino.png?branch=v0.0.1)](https://travis-ci.org/cantierecreativo/admino)
4
5
  [![Coverage Status](https://coveralls.io/repos/cantierecreativo/admino/badge.png?branch=master)](https://coveralls.io/r/cantierecreativo/admino?branch=master)
6
+ [![Code Climate](https://codeclimate.com/github/cantierecreativo/admino.png)](https://codeclimate.com/github/cantierecreativo/admino)
5
7
 
6
- TODO: Write a gem description
8
+ A minimal, object-oriented solution to generate Rails administrative index views. Through query objects and presenters, it features a customizable table generator and search forms with filtering/sorting.
9
+
10
+ ## The philosophy behind it
11
+
12
+ The Rails ecosystem has many [full-fledged solutions to generate administrative interfaces](https://www.ruby-toolbox.com/categories/rails_admin_interfaces).
13
+
14
+ Although these tools are very handy to bootstrap a project quickly, they all obey the [80%-20% rule](http://en.wikipedia.org/wiki/Pareto_principle) and tend to be very invasive, often mixing up different concerns on a single responsibility level, thus making tests unbelievably difficult to setup and write.
15
+
16
+ A time comes when these all-encompassing tools get in the way. And that will be the moment where all the cumulated saved time will be wasted to solve a single, trivial problem with ugly workarounds and [epic facepalms](http://i.imgur.com/ghKDGyv.jpg).
17
+
18
+ So yes, if you're starting a small, short-lived project, go ahead with them, it will be fine! If you're building something that's more valuable or is meant to last longer, there are better alternatives.
19
+
20
+ ### A modular approach to the problem
21
+
22
+ The great thing is that you don't need to write a lot of code to get a more maintainable and modular administrative area.
23
+ Gems like [Inherited Resources](https://github.com/josevalim/inherited_resources) and [Simple Form](https://github.com/plataformatec/simple_form), combined with [Rails 3.1+ template-inheritance](http://railscasts.com/episodes/269-template-inheritance) already give you ~90% of the time-saving features and the same super-DRY, declarative code that administrative interfaces offer, but with a far more relaxed contract.
24
+
25
+ If a particular controller or view needs something different from the standard CRUD/REST treatment, you can just avoid using those gems in that specific context, and fall back to standard Rails code. No workarounds, no facepalms. It seems easy, right? It is.
26
+
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.
7
28
 
8
29
  ## Installation
9
30
 
@@ -15,19 +36,185 @@ And then execute:
15
36
 
16
37
  $ bundle
17
38
 
18
- Or install it yourself as:
39
+ ## Admino::Query::Base
40
+
41
+ A subclass of `Admino::Query::Base` represents a [Query object](http://martinfowler.com/eaaCatalog/queryObject.html), that is, an object responsible for returning a result set (ie. an `ActiveRecord::Relation`) based on business rules (ie. action params).
42
+
43
+ Given a `Task` model with the following scopes:
44
+
45
+ ```ruby
46
+ class Task < ActiveRecord::Base
47
+ scope :text_matches, ->(text) { where(...) }
48
+
49
+ scope :completed, -> { where(completed: true) }
50
+ scope :pending, -> { where(completed: false) }
51
+
52
+ scope :by_due_date, ->(direction) { order(due_date: direction) }
53
+ scope :by_title, ->(direction) { order(title: direction) }
54
+ end
55
+ ```
56
+
57
+ The following `TasksQuery` class can be created:
58
+
59
+ ```ruby
60
+ class TasksQuery < Admino::Query::Base
61
+ starting_scope { ProjectTask.all }
62
+
63
+ field :text_matches
64
+ filter_by :status, [:completed, :pending]
65
+ sorting :by_due_date, :by_title
66
+ end
67
+ ```
68
+
69
+ Every query object can declare:
70
+
71
+ * a **starting scope**, that is, the scope that will start the filtering/ordering chain;
72
+ * a set of **search fields**, which represent model scopes that require an input to filter the result set;
73
+ * a set of **filtering groups**, each of which is composed by a set of scopes that take no argument;
74
+ * a set of **sorting scopes** that take a sigle argument (`:asc` or `:desc`) and thus are able to order the result set in both directions;
75
+
76
+ Each query object instance gets initialized with a hash of params. The `#scope` method will then perform the chaining of the scopes based on the given params, returning the final result set:
77
+
78
+ ```ruby
79
+ params = {
80
+ query: {
81
+ text_matches: 'ASAP'
82
+ },
83
+ status: 'pending',
84
+ sorting: 'by_title',
85
+ sort_order: 'desc'
86
+ }
87
+
88
+ tasks = TasksQuery.new(params).scope
89
+ ```
90
+
91
+ As you may have guessed, query objects can be great companions to index controller actions:
92
+
93
+ ```ruby
94
+ class ProjectTasksController < ApplicationController
95
+ def index
96
+ @query = TasksQuery.new(params)
97
+ @project_tasks = @query.scope
98
+ end
99
+ end
100
+ ```
101
+
102
+ But that's not all.
103
+
104
+ ### Presenting search form and filters to the user
105
+
106
+ Admino also offers a [Showcase presenter](https://github.com/stefanoverna/showcase) that makes it really easy to generate search forms and filtering links:
107
+
108
+ ```erb
109
+ <%# instanciate the the query object presenter %>
110
+ <% query = present(@query) %>
111
+
112
+ <%# generate the search form %>
113
+ <%= query.form do |q| %>
114
+ <p>
115
+ <%= q.label :text_matches %>
116
+ <%= q.text_field :text_matches %>
117
+ </p>
118
+ <p>
119
+ <%= q.submit %>
120
+ </p>
121
+ <% end %>
122
+
123
+ <%# generate the filtering links %>
124
+ <% query.filter_groups.each do |filter_group| %>
125
+ <h6><%= filter_group.name %></h6>
126
+ <ul>
127
+ <% filter_group.scopes.each do |scope| %>
128
+ <li>
129
+ <%= filter_group.scope_link(scope) %>
130
+ <li>
131
+ <% end %>
132
+ </ul>
133
+ <% end %>
134
+ ```
135
+
136
+ The great thing is that the search form gets automatically filled in with the last input the user submitted, and a CSS class `is-active` gets added to the currently active filter scopes.
137
+
138
+ If a particular filter has been clicked and is now active, it is possible to deactivate it by clicking it again.
139
+
140
+ ### Simple Form support
141
+
142
+ The presenter also offers a `#simple_form` method to make it work with [Simple Form](https://github.com/plataformatec/simple_form) out of the box.
143
+
144
+ ### I18n
145
+
146
+ To localize the search form labels, as well as the group filter names and scope links, please refer to the following YAML file:
147
+
148
+ ```yaml
149
+ en:
150
+ query:
151
+ attributes:
152
+ tasks_query:
153
+ text_matches: 'Contains text'
154
+ filter_groups:
155
+ tasks_query:
156
+ status:
157
+ name: 'Filter by status'
158
+ scopes:
159
+ completed: 'Completed'
160
+ pending: 'Pending'
161
+ ```
162
+
163
+ ### Output customisation
164
+
165
+ The query object and its presenter implement a number of additional methods and optional arguments that allow a great amount of flexibility: please refer to the tests to see all the possibile customisations available.
166
+
167
+ #### Overwriting the starting scope
168
+
169
+ Suppose you have to filter the tasks based on the `@current_user` work group. You can easily provide an alternative starting scope from the controller passing it as an argument to the `#scope` method:
170
+
171
+ ```ruby
172
+ def index
173
+ @query = TasksQuery.new(params)
174
+ @project_tasks = @query.scope(@current_user.team.tasks)
175
+ end
176
+ ```
177
+
178
+ ### Default sortings
179
+
180
+ #### Coertions
181
+
182
+ Admino can perform automatic coertions from a param string input to the type needed by the model named scope:
183
+
184
+ ```ruby
185
+ class TasksQuery < Admino::Query::Base
186
+ # ...
187
+ field :due_date_from, coerce: :to_date
188
+ field :due_date_to, coerce: :to_date
189
+ end
190
+ ```
191
+ The following coertions are available:
192
+
193
+ * `:to_boolean`
194
+ * `:to_constant`
195
+ * `:to_date`
196
+ * `:to_datetime`
197
+ * `:to_decimal`
198
+ * `:to_float`
199
+ * `:to_integer`
200
+ * `:to_symbol`
201
+ * `:to_time`
202
+
203
+ If a specific coercion cannot be performed with the provided input, the scope won't be chained.
204
+
205
+ Please see the [`Coercible::Coercer::String`](https://github.com/solnic/coercible/blob/master/lib/coercible/coercer/string.rb) class for details.
19
206
 
20
- $ gem install admino
207
+ ### Ending the scope chain
21
208
 
22
- ## Usage
209
+ It's very common ie. to paginate the result set. `Admino::Query::Base` DSL makes it easy to append any scope to the end of the chain:
23
210
 
24
- TODO: Write usage instructions here
211
+ ```ruby
212
+ class TasksQuery < Admino::Query::Base
213
+ ending_scope { |q| page(q.params[:page]) }
214
+ end
215
+ ```
25
216
 
26
- ## Contributing
217
+ ## Admino::Table::Presenter
27
218
 
28
- 1. Fork it
29
- 2. Create your feature branch (`git checkout -b my-new-feature`)
30
- 3. Commit your changes (`git commit -am 'Add some feature'`)
31
- 4. Push to the branch (`git push origin my-new-feature`)
32
- 5. Create new Pull Request
219
+ WIP
33
220
 
data/TODO.md ADDED
@@ -0,0 +1,4 @@
1
+ * Allow validations of input in Query::Base objects
2
+ * Support Rails date_select and datetime_select params
3
+ * Prepare a demo
4
+
data/lib/admino/query.rb CHANGED
@@ -2,8 +2,8 @@ require 'admino/query/base'
2
2
  require 'admino/query/base_presenter'
3
3
  require 'admino/query/configuration'
4
4
  require 'admino/query/field'
5
- require 'admino/query/group'
6
- require 'admino/query/group_presenter'
5
+ require 'admino/query/filter_group'
6
+ require 'admino/query/filter_group_presenter'
7
7
  require 'admino/query/sorting'
8
8
  require 'admino/query/sorting_presenter'
9
9
 
@@ -13,7 +13,7 @@ module Admino
13
13
  extend Dsl
14
14
 
15
15
  attr_reader :params
16
- attr_reader :groups
16
+ attr_reader :filter_groups
17
17
  attr_reader :fields
18
18
  attr_reader :sorting
19
19
 
@@ -25,7 +25,7 @@ module Admino
25
25
  @params = ActiveSupport::HashWithIndifferentAccess.new(params)
26
26
  @config = config
27
27
 
28
- init_groups
28
+ init_filter_groups
29
29
  init_fields
30
30
  init_sorting
31
31
  end
@@ -39,7 +39,7 @@ module Admino
39
39
 
40
40
  scope_builder = starting_scope
41
41
 
42
- scope_augmenters = fields + groups
42
+ scope_augmenters = fields + filter_groups
43
43
  scope_augmenters << sorting if sorting
44
44
 
45
45
  scope_augmenters.each do |field|
@@ -61,12 +61,12 @@ module Admino
61
61
  @config || self.class.config
62
62
  end
63
63
 
64
- def groups
65
- @groups.values
64
+ def filter_groups
65
+ @filter_groups.values
66
66
  end
67
67
 
68
- def group_by_name(name)
69
- @groups[name]
68
+ def filter_group_by_name(name)
69
+ @filter_groups[name]
70
70
  end
71
71
 
72
72
  def fields
@@ -79,11 +79,11 @@ module Admino
79
79
 
80
80
  private
81
81
 
82
- def init_groups
83
- @groups = {}
82
+ def init_filter_groups
83
+ @filter_groups = {}
84
84
  i18n_key = self.class.model_name.i18n_key
85
- config.groups.each do |config|
86
- @groups[config.name] = Group.new(config, params, i18n_key)
85
+ config.filter_groups.each do |config|
86
+ @filter_groups[config.name] = FilterGroup.new(config, params, i18n_key)
87
87
  end
88
88
  end
89
89
 
@@ -3,7 +3,7 @@ require 'showcase'
3
3
  module Admino
4
4
  module Query
5
5
  class BasePresenter < Showcase::Presenter
6
- presents_collection :groups
6
+ presents_collection :filter_groups
7
7
  presents :sorting
8
8
 
9
9
  def form(options = {}, &block)
@@ -17,7 +17,7 @@ module Admino
17
17
  end
18
18
  end
19
19
 
20
- class Group
20
+ class FilterGroup
21
21
  attr_reader :name
22
22
  attr_reader :scopes
23
23
 
@@ -48,14 +48,14 @@ module Admino
48
48
  end
49
49
 
50
50
  attr_reader :fields
51
- attr_reader :groups
51
+ attr_reader :filter_groups
52
52
  attr_reader :sorting
53
53
  attr_accessor :starting_scope_callable
54
54
  attr_accessor :ending_scope_callable
55
55
 
56
56
  def initialize
57
57
  @fields = []
58
- @groups = []
58
+ @filter_groups = []
59
59
  end
60
60
 
61
61
  def add_field(name, options = {})
@@ -64,9 +64,9 @@ module Admino
64
64
  end
65
65
  end
66
66
 
67
- def add_group(name, scopes)
68
- Group.new(name, scopes).tap do |group|
69
- self.groups << group
67
+ def add_filter_group(name, scopes)
68
+ FilterGroup.new(name, scopes).tap do |filter_group|
69
+ self.filter_groups << filter_group
70
70
  end
71
71
  end
72
72
 
@@ -13,8 +13,8 @@ module Admino
13
13
  end
14
14
  end
15
15
 
16
- def group(name, scopes)
17
- config.add_group(name, scopes)
16
+ def filter_by(name, scopes)
17
+ config.add_filter_group(name, scopes)
18
18
  end
19
19
 
20
20
  def sorting(*args)
@@ -3,7 +3,7 @@ require 'active_support/core_ext/hash'
3
3
 
4
4
  module Admino
5
5
  module Query
6
- class Group
6
+ class FilterGroup
7
7
  attr_reader :params
8
8
  attr_reader :config
9
9
  attr_reader :query_i18n_key
@@ -23,7 +23,7 @@ module Admino
23
23
  end
24
24
 
25
25
  def active_scope
26
- if param_value && available_scopes.include?(param_value.to_sym)
26
+ if param_value && scopes.include?(param_value.to_sym)
27
27
  param_value.to_sym
28
28
  else
29
29
  nil
@@ -42,8 +42,8 @@ module Admino
42
42
  config.name
43
43
  end
44
44
 
45
- def available_scopes
46
- [nil] + config.scopes
45
+ def scopes
46
+ config.scopes
47
47
  end
48
48
 
49
49
  def i18n_key
@@ -7,7 +7,7 @@ require 'active_support/core_ext/hash'
7
7
 
8
8
  module Admino
9
9
  module Query
10
- class GroupPresenter < Showcase::Presenter
10
+ class FilterGroupPresenter < Showcase::Presenter
11
11
  def scope_link(scope, *args)
12
12
  options = args.extract_options!
13
13
 
@@ -30,20 +30,19 @@ module Admino
30
30
  def scope_params(scope)
31
31
  params = ActiveSupport::HashWithIndifferentAccess.new(h.request.query_parameters)
32
32
 
33
- if scope
34
- params.merge!(param_name => scope.to_s)
35
- else
33
+ if is_scope_active?(scope)
36
34
  params.delete(param_name)
35
+ else
36
+ params.merge!(param_name => scope.to_s)
37
37
  end
38
38
 
39
39
  params
40
40
  end
41
41
 
42
42
  def scope_name(scope)
43
- scope ||= 'none'
44
43
  I18n.t(
45
44
  :"#{query_i18n_key}.#{i18n_key}.scopes.#{scope}",
46
- scope: 'query.groups',
45
+ scope: 'query.filter_groups',
47
46
  default: [
48
47
  :"#{i18n_key}.scopes.#{scope}",
49
48
  scope.to_s.titleize
@@ -54,7 +53,7 @@ module Admino
54
53
  def name
55
54
  I18n.t(
56
55
  :"#{query_i18n_key}.#{i18n_key}.name",
57
- scope: 'query.groups',
56
+ scope: 'query.filter_groups',
58
57
  default: [
59
58
  :"#{i18n_key}.name",
60
59
  i18n_key.to_s.titleize
@@ -36,7 +36,7 @@ module Admino
36
36
  end
37
37
 
38
38
  def active_scope
39
- if param_value && available_scopes.include?(param_value.to_sym)
39
+ if param_value && scopes.include?(param_value.to_sym)
40
40
  param_value.to_sym
41
41
  elsif default_scope
42
42
  default_scope
@@ -65,13 +65,9 @@ module Admino
65
65
  :sorting
66
66
  end
67
67
 
68
- def available_scopes
68
+ def scopes
69
69
  config.scopes
70
70
  end
71
-
72
- def scope_name
73
- config.name
74
- end
75
71
  end
76
72
  end
77
73
  end
@@ -43,13 +43,13 @@ module Admino
43
43
  html_options = html_options.to_h
44
44
 
45
45
  sorting_scope = html_options.delete(:sorting)
46
+ sorting_html_options = html_options.delete(:sorting_html_options) { {} }
46
47
  if sorting_scope
47
48
  raise ArgumentError, 'query object is required' unless query
48
- sorting_html_options = html_options.delete(:sorting_html_options) { {} }
49
49
  label = query.sorting.scope_link(sorting_scope, label, sorting_html_options)
50
50
  end
51
51
 
52
- @columns << h.content_tag(:th, label.to_s, html_options.to_h)
52
+ @columns << h.content_tag(:th, label.to_s, html_options)
53
53
  end
54
54
 
55
55
  def to_html
@@ -1,4 +1,4 @@
1
1
  module Admino
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
4
4
 
@@ -34,19 +34,19 @@ module Admino
34
34
  end
35
35
  end
36
36
 
37
- context 'with a declared group' do
37
+ context 'with a declared filter_group' do
38
38
  let(:config) { Configuration.new }
39
- let(:group_config) { config.add_group(:group, [:one, :two]) }
39
+ let(:filter_group_config) { config.add_filter_group(:filter_group, [:one, :two]) }
40
40
 
41
41
  before do
42
- group_config
42
+ filter_group_config
43
43
  end
44
44
 
45
- it 'returns a configured Group' do
46
- group = query.group_by_name(:group)
47
- expect(group.config).to eq group_config
48
- expect(group.params).to eq params
49
- expect(group.i18n_key).to eq :group
45
+ it 'returns a configured FilterGroup' do
46
+ filter_group = query.filter_group_by_name(:filter_group)
47
+ expect(filter_group.config).to eq filter_group_config
48
+ expect(filter_group.params).to eq params
49
+ expect(filter_group.i18n_key).to eq :filter_group
50
50
  end
51
51
  end
52
52
 
@@ -107,15 +107,15 @@ module Admino
107
107
  end
108
108
  end
109
109
 
110
- context 'with a set of fields and groups' do
110
+ context 'with a set of fields and filter_groups' do
111
111
  let(:field_config) { config.add_field(:field) }
112
- let(:group_config) { config.add_group(:group, [:one, :two]) }
112
+ let(:filter_group_config) { config.add_filter_group(:filter_group, [:one, :two]) }
113
113
  let(:scope_chained_with_field) { double('scope 1') }
114
114
  let(:final_chain) { double('scope 2') }
115
115
 
116
116
  before do
117
117
  field_config
118
- group_config
118
+ filter_group_config
119
119
  query
120
120
 
121
121
  query.field_by_name(:field).
@@ -123,7 +123,7 @@ module Admino
123
123
  with(starting_scope).
124
124
  and_return(scope_chained_with_field)
125
125
 
126
- query.group_by_name(:group).
126
+ query.filter_group_by_name(:filter_group).
127
127
  stub(:augment_scope).
128
128
  with(scope_chained_with_field).
129
129
  and_return(final_chain)
@@ -12,10 +12,10 @@ module Admino
12
12
  expect(field.coerce_to).to eq :to_date
13
13
  end
14
14
 
15
- it 'allows #group declaration' do
16
- group = config.groups.first
17
- expect(group.name).to eq :bar
18
- expect(group.scopes).to eq [:one, :two]
15
+ it 'allows #filter_by declaration' do
16
+ filter_group = config.filter_groups.first
17
+ expect(filter_group.name).to eq :bar
18
+ expect(filter_group.scopes).to eq [:one, :two]
19
19
  end
20
20
 
21
21
  it 'allows #sortings declaration' do
@@ -2,21 +2,21 @@ require 'spec_helper'
2
2
 
3
3
  module Admino
4
4
  module Query
5
- describe GroupPresenter do
6
- subject(:presenter) { GroupPresenter.new(group, view) }
5
+ describe FilterGroupPresenter do
6
+ subject(:presenter) { FilterGroupPresenter.new(filter_group, view) }
7
7
  let(:view) { RailsViewContext.new }
8
- let(:group) do
8
+ let(:filter_group) do
9
9
  double(
10
- 'Group',
10
+ 'FilterGroup',
11
11
  query_i18n_key: :query_name,
12
- i18n_key: :group,
13
- param_name: :group
12
+ i18n_key: :filter_group,
13
+ param_name: :filter_group
14
14
  )
15
15
  end
16
16
  let(:request_object) do
17
17
  double(
18
18
  'ActionDispatch::Request',
19
- query_parameters: { 'group' => 'bar' },
19
+ query_parameters: { 'filter_group' => 'bar' },
20
20
  path: '/'
21
21
  )
22
22
  end
@@ -27,15 +27,15 @@ module Admino
27
27
 
28
28
  describe '#scope_link' do
29
29
  subject { presenter.scope_link(:foo) }
30
+ let(:scope_active) { false }
30
31
 
31
32
  before do
32
- group.stub(:is_scope_active?).with(:foo).and_return(false)
33
+ filter_group.stub(:is_scope_active?).
34
+ with(:foo).and_return(scope_active)
33
35
  end
34
36
 
35
37
  context 'active CSS class' do
36
- before do
37
- group.stub(:is_scope_active?).with(:foo).and_return(true)
38
- end
38
+ let(:scope_active) { true }
39
39
 
40
40
  it 'adds an is-active class' do
41
41
  should have_tag(:a, with: { class: 'is-active' })
@@ -86,15 +86,23 @@ module Admino
86
86
  end
87
87
 
88
88
  describe '#scope_params' do
89
- context 'if scope is nil' do
90
- it 'deletes the group param' do
91
- expect(presenter.scope_params(nil)).not_to have_key 'group'
89
+ before do
90
+ filter_group.stub(:is_scope_active?).with(:foo).and_return(scope_active)
91
+ end
92
+
93
+ context 'if scope is active' do
94
+ let(:scope_active) { true }
95
+
96
+ it 'deletes the filter_group param' do
97
+ expect(presenter.scope_params(:foo)).not_to have_key 'filter_group'
92
98
  end
93
99
  end
94
100
 
95
101
  context 'else' do
96
- it 'deletes the group param' do
97
- expect(presenter.scope_params(:bar)[:group]).to eq 'bar'
102
+ let(:scope_active) { false }
103
+
104
+ it 'is set as filter group value' do
105
+ expect(presenter.scope_params(:foo)[:filter_group]).to eq 'foo'
98
106
  end
99
107
  end
100
108
  end
@@ -104,18 +112,18 @@ module Admino
104
112
  before do
105
113
  I18n.backend.store_translations(
106
114
  :en,
107
- query: { groups: { query_name: { group: { name: 'NAME' } } } }
115
+ query: { filter_groups: { query_name: { filter_group: { name: 'NAME' } } } }
108
116
  )
109
117
  end
110
118
 
111
- it 'returns a I18n translatable name for the group' do
119
+ it 'returns a I18n translatable name for the filter_group' do
112
120
  expect(presenter.name).to eq 'NAME'
113
121
  end
114
122
  end
115
123
 
116
124
  context 'if no translation is available' do
117
- it 'falls back to a titleized version of the group name' do
118
- expect(presenter.name).to eq 'Group'
125
+ it 'falls back to a titleized version of the filter_group name' do
126
+ expect(presenter.name).to eq 'Filter Group'
119
127
  end
120
128
  end
121
129
  end
@@ -125,7 +133,7 @@ module Admino
125
133
  before do
126
134
  I18n.backend.store_translations(
127
135
  :en,
128
- query: { groups: { query_name: { group: { scopes: { bar: 'NAME' } } } } }
136
+ query: { filter_groups: { query_name: { filter_group: { scopes: { bar: 'NAME' } } } } }
129
137
  )
130
138
  end
131
139
 
@@ -2,9 +2,9 @@ require 'spec_helper'
2
2
 
3
3
  module Admino
4
4
  module Query
5
- describe Group do
6
- subject(:group) { Group.new(config, params) }
7
- let(:config) { Configuration::Group.new(:foo, [:bar]) }
5
+ describe FilterGroup do
6
+ subject(:filter_group) { FilterGroup.new(config, params) }
7
+ let(:config) { Configuration::FilterGroup.new(:foo, [:bar]) }
8
8
  let(:params) { {} }
9
9
 
10
10
  describe '#active_scope' do
@@ -12,7 +12,7 @@ module Admino
12
12
  let(:params) { {} }
13
13
 
14
14
  it 'returns nil' do
15
- expect(group.active_scope).to be_nil
15
+ expect(filter_group.active_scope).to be_nil
16
16
  end
17
17
  end
18
18
 
@@ -20,7 +20,7 @@ module Admino
20
20
  let(:params) { { 'foo' => 'qux' } }
21
21
 
22
22
  it 'returns nil' do
23
- expect(group.active_scope).to be_nil
23
+ expect(filter_group.active_scope).to be_nil
24
24
  end
25
25
  end
26
26
 
@@ -28,19 +28,19 @@ module Admino
28
28
  let(:params) { { 'foo' => 'bar' } }
29
29
 
30
30
  it 'returns the scope name' do
31
- expect(group.active_scope).to eq :bar
31
+ expect(filter_group.active_scope).to eq :bar
32
32
  end
33
33
  end
34
34
  end
35
35
 
36
36
  describe '#augment_scope' do
37
- let(:result) { group.augment_scope(scope) }
37
+ let(:result) { filter_group.augment_scope(scope) }
38
38
  let(:scope) { ScopeMock.new('original') }
39
39
 
40
40
  context 'if the field has a value' do
41
41
  let(:params) { { 'foo' => 'bar' } }
42
42
 
43
- it 'returns the original scope chained with the group scope' do
43
+ it 'returns the original scope chained with the filter_group scope' do
44
44
  expect(result.chain).to eq [:bar, []]
45
45
  end
46
46
  end
@@ -56,7 +56,7 @@ module Admino
56
56
  let(:params) { { 'foo' => 'bar' } }
57
57
 
58
58
  it 'returns true if the provided scope is the one currently active' do
59
- expect(group.is_scope_active?(:bar)).to be_true
59
+ expect(filter_group.is_scope_active?(:bar)).to be_true
60
60
  end
61
61
  end
62
62
  end
@@ -123,6 +123,14 @@ module Admino
123
123
  end
124
124
  end
125
125
  end
126
+
127
+ describe '#is_scope_active?' do
128
+ let(:params) { { 'sorting' => 'by_date' } }
129
+
130
+ it 'returns true if the provided scope is the one currently active' do
131
+ expect(sorting.is_scope_active?(:by_date)).to be_true
132
+ end
133
+ end
126
134
  end
127
135
  end
128
136
  end
data/spec/spec_helper.rb CHANGED
@@ -35,7 +35,7 @@ class TestQuery < Admino::Query::Base
35
35
  field :foo
36
36
  field :starting_from, coerce: :to_date
37
37
 
38
- group :bar, [:one, :two]
38
+ filter_by :bar, [:one, :two]
39
39
 
40
40
  sorting :by_title, :by_date,
41
41
  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.3
4
+ version: 0.0.4
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-17 00:00:00.000000000 Z
11
+ date: 2014-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: showcase
@@ -174,10 +174,12 @@ files:
174
174
  - .gitignore
175
175
  - .travis.yml
176
176
  - CHANGELOG.md
177
+ - CONTRIBUTING.md
177
178
  - Gemfile
178
179
  - LICENSE.txt
179
180
  - README.md
180
181
  - Rakefile
182
+ - TODO.md
181
183
  - admino.gemspec
182
184
  - lib/admino.rb
183
185
  - lib/admino/query.rb
@@ -186,8 +188,8 @@ files:
186
188
  - lib/admino/query/configuration.rb
187
189
  - lib/admino/query/dsl.rb
188
190
  - lib/admino/query/field.rb
189
- - lib/admino/query/group.rb
190
- - lib/admino/query/group_presenter.rb
191
+ - lib/admino/query/filter_group.rb
192
+ - lib/admino/query/filter_group_presenter.rb
191
193
  - lib/admino/query/sorting.rb
192
194
  - lib/admino/query/sorting_presenter.rb
193
195
  - lib/admino/table.rb
@@ -200,8 +202,8 @@ files:
200
202
  - spec/admino/query/base_spec.rb
201
203
  - spec/admino/query/dsl_spec.rb
202
204
  - spec/admino/query/field_spec.rb
203
- - spec/admino/query/group_presenter_spec.rb
204
- - spec/admino/query/group_spec.rb
205
+ - spec/admino/query/filter_group_presenter_spec.rb
206
+ - spec/admino/query/filter_group_spec.rb
205
207
  - spec/admino/query/sorting_presenter_spec.rb
206
208
  - spec/admino/query/sorting_spec.rb
207
209
  - spec/admino/table/head_row_spec.rb
@@ -238,8 +240,8 @@ test_files:
238
240
  - spec/admino/query/base_spec.rb
239
241
  - spec/admino/query/dsl_spec.rb
240
242
  - spec/admino/query/field_spec.rb
241
- - spec/admino/query/group_presenter_spec.rb
242
- - spec/admino/query/group_spec.rb
243
+ - spec/admino/query/filter_group_presenter_spec.rb
244
+ - spec/admino/query/filter_group_spec.rb
243
245
  - spec/admino/query/sorting_presenter_spec.rb
244
246
  - spec/admino/query/sorting_spec.rb
245
247
  - spec/admino/table/head_row_spec.rb