From 992ca7887b0838ae520c6f9d570a9183357b0dd4 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sat, 2 Nov 2024 22:00:18 +0100 Subject: [PATCH 001/157] Refactor --- lib/datagrid/form_builder.rb | 41 +++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index d3c6a3f..02cfc48 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -24,7 +24,7 @@ def datagrid_label(filter_or_attribute, text = nil, **options, &block) end # @visibility private - def datagrid_filter_input(attribute_or_filter, **options) + def datagrid_filter_input(attribute_or_filter, **options, &block) filter = datagrid_get_filter(attribute_or_filter) value = object.filter_value_as_string(filter) type = options[:type]&.to_sym @@ -33,19 +33,33 @@ def datagrid_filter_input(attribute_or_filter, **options) options[:value] = "" end if type == :"datetime-local" - datetime_local_field filter.name, **options + datetime_local_field filter.name, **options, &block elsif type == :"date" - date_field filter.name, **options + date_field filter.name, **options, &block elsif type == :textarea - text_area filter.name, value: value, **options, type: nil + text_area filter.name, value: value, **options, type: nil, &block + elsif type == :select + select( + filter.name, + object.select_options(filter) || [], + { + include_blank: filter.include_blank, + prompt: filter.prompt, + include_hidden: false + }, + multiple: filter.multiple?, + **options, + type: nil, + &block + ) else - text_field filter.name, value: value, **options + text_field filter.name, value: value, **options, &block end end protected - def datagrid_extended_boolean_filter(filter, options = {}) - datagrid_enum_filter(filter, options) + def datagrid_extended_boolean_filter(filter, options = {}, &block) + datagrid_filter_input(filter, **options, type: :select, &block) end def datagrid_boolean_filter(filter, options = {}) @@ -82,18 +96,7 @@ def datagrid_enum_filter(filter, options = {}, &block) } ) else - select( - filter.name, - object.select_options(filter) || [], - { - include_blank: filter.include_blank, - prompt: filter.prompt, - include_hidden: false - }, - multiple: filter.multiple?, - **options, - &block - ) + datagrid_filter_input(filter, **options, type: :select, &block) end end From a3daafcd9113adad75c68f201fa516a699b37f75 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 3 Nov 2024 10:09:13 +0100 Subject: [PATCH 002/157] Add debugger --- Gemfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Gemfile b/Gemfile index 4a624e7..aed7bd1 100644 --- a/Gemfile +++ b/Gemfile @@ -9,6 +9,7 @@ group :development do gem "csv" # removed from standard library in Ruby 3.4 gem "nokogiri" # used to test html output gem "pry-byebug" + gem 'debug' gem "rspec" gem "sequel" gem "sqlite3", "~> 1.7.0" From f3337caf86402000b7869443eba7c8ec926fbb06 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 3 Nov 2024 10:34:39 +0100 Subject: [PATCH 003/157] Migrate to rails-dom-testing --- Gemfile | 1 + lib/datagrid/form_builder.rb | 4 +++- spec/support/matchers.rb | 8 +++++--- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index aed7bd1..cf03de9 100644 --- a/Gemfile +++ b/Gemfile @@ -10,6 +10,7 @@ group :development do gem "nokogiri" # used to test html output gem "pry-byebug" gem 'debug' + gem "rails-dom-testing", "~> 2.2" gem "rspec" gem "sequel" gem "sqlite3", "~> 1.7.0" diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 02cfc48..9542b27 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -38,6 +38,8 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) date_field filter.name, **options, &block elsif type == :textarea text_area filter.name, value: value, **options, type: nil, &block + elsif type == :checkbox + check_box filter.name, **options elsif type == :select select( filter.name, @@ -63,7 +65,7 @@ def datagrid_extended_boolean_filter(filter, options = {}, &block) end def datagrid_boolean_filter(filter, options = {}) - check_box(filter.name, options) + datagrid_filter_input(filter.name, **options, type: :checkbox) end def datagrid_date_filter(filter, options = {}) diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb index a0ae6cd..76dd2f1 100644 --- a/spec/support/matchers.rb +++ b/spec/support/matchers.rb @@ -1,4 +1,4 @@ -require "nokogiri" +require 'rails/dom/testing' def equal_to_dom(text) EqualToDom.new(text) @@ -8,7 +8,9 @@ def match_css_pattern(pattern) CssPattern.new(pattern) end + class EqualToDom + include Rails::Dom::Testing::Assertions::DomAssertions def initialize(expectation) @expectation = normalize(expectation) @@ -16,11 +18,11 @@ def initialize(expectation) def matches?(text) @matcher = normalize(text) - @matcher == @expectation + compare_doms(@expectation, @matcher, false) end def normalize(text) - Nokogiri::HTML::DocumentFragment.parse(text.split("\n").map(&:strip).join("")).to_s + fragment(text) end def failure_message From c278f0c458e28c6b456bd66a824adef4b6b7e832 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 3 Nov 2024 10:45:05 +0100 Subject: [PATCH 004/157] Refactor --- lib/datagrid/form_builder.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 9542b27..e9461e9 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -10,7 +10,7 @@ module FormBuilder # * <tt>text_field</tt> for other filter types def datagrid_filter(filter_or_attribute, partials: nil, **options, &block) filter = datagrid_get_filter(filter_or_attribute) - options = add_html_classes({**filter.input_options, **options}, filter.name, datagrid_filter_html_class(filter)) + options = add_html_classes({**filter.input_options, **options}, *datagrid_filter_html_classes(filter)) self.send( filter.form_builder_helper_name, filter, **options, &block) end @@ -26,7 +26,6 @@ def datagrid_label(filter_or_attribute, text = nil, **options, &block) # @visibility private def datagrid_filter_input(attribute_or_filter, **options, &block) filter = datagrid_get_filter(attribute_or_filter) - value = object.filter_value_as_string(filter) type = options[:type]&.to_sym if options.has_key?(:value) && options[:value].nil? && [:"datetime-local", :"date"].include?(type) # https://github.com/rails/rails/pull/53387 @@ -37,9 +36,11 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) elsif type == :"date" date_field filter.name, **options, &block elsif type == :textarea - text_area filter.name, value: value, **options, type: nil, &block + text_area filter.name, value: object.filter_value_as_string(filter) , **options, type: nil, &block elsif type == :checkbox check_box filter.name, **options + elsif type == :hidden + hidden_field filter.name, **options elsif type == :select select( filter.name, @@ -55,7 +56,7 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) &block ) else - text_field filter.name, value: value, **options, &block + text_field filter.name, value: object.filter_value_as_string(filter) , **options, &block end end @@ -209,8 +210,8 @@ def datagrid_get_filter(attribute_or_filter) end end - def datagrid_filter_html_class(filter) - filter.class.to_s.demodulize.underscore + def datagrid_filter_html_classes(filter) + [filter.name, filter.class.to_s.demodulize.underscore] end def add_html_classes(options, *classes) From 494b1832cfc7d27895edc888fab183f814ea1850 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 3 Nov 2024 13:41:37 +0100 Subject: [PATCH 005/157] Make CSS classes generation consistent --- app/views/datagrid/_enum_checkboxes.html.erb | 4 +- lib/datagrid/filters/base_filter.rb | 5 +- lib/datagrid/filters/enum_filter.rb | 6 +++ lib/datagrid/form_builder.rb | 20 ++++--- spec/datagrid/form_builder_spec.rb | 56 ++++++++++---------- 5 files changed, 52 insertions(+), 39 deletions(-) diff --git a/app/views/datagrid/_enum_checkboxes.html.erb b/app/views/datagrid/_enum_checkboxes.html.erb index 9f48319..f114c17 100644 --- a/app/views/datagrid/_enum_checkboxes.html.erb +++ b/app/views/datagrid/_enum_checkboxes.html.erb @@ -4,8 +4,8 @@ You can add indent if whitespace doesn't matter for you %> <%- elements.each do |value, text, checked| -%> <%- id = [form.object_name, filter.name, value].join('_').underscore -%> -<%= form.label filter.name, options.merge(for: id) do -%> -<%= form.check_box(filter.name, {multiple: true, id: id, checked: checked, include_hidden: false}, value.to_s, nil) -%> +<%= form.datagrid_label(filter.name, **options, for: id) do -%> +<%= form.datagrid_filter_input(filter.name, type: :checkbox, multiple: true, id: id, checked: checked, include_hidden: false, value: value.to_s) -%> <%= text -%> <%- end -%> <%- end -%> diff --git a/lib/datagrid/filters/base_filter.rb b/lib/datagrid/filters/base_filter.rb index db468d7..710d244 100644 --- a/lib/datagrid/filters/base_filter.rb +++ b/lib/datagrid/filters/base_filter.rb @@ -136,6 +136,10 @@ def enabled?(grid) ::Datagrid::Utils.process_availability(grid, options[:if], options[:unless]) end + def default_html_classes + [ name, self.class.to_s.demodulize.underscore ] + end + protected def default_filter_where(scope, value) @@ -179,6 +183,5 @@ def default_filter(value, scope, grid) default_filter_where(scope, value) end end - end diff --git a/lib/datagrid/filters/enum_filter.rb b/lib/datagrid/filters/enum_filter.rb index a76b097..809d10c 100644 --- a/lib/datagrid/filters/enum_filter.rb +++ b/lib/datagrid/filters/enum_filter.rb @@ -17,6 +17,12 @@ def parse(value) value end + def default_html_classes + res = super + res.push('checkboxes') if checkboxes? + res + end + def strict options[:strict] end diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index e9461e9..45f0fb2 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -10,7 +10,6 @@ module FormBuilder # * <tt>text_field</tt> for other filter types def datagrid_filter(filter_or_attribute, partials: nil, **options, &block) filter = datagrid_get_filter(filter_or_attribute) - options = add_html_classes({**filter.input_options, **options}, *datagrid_filter_html_classes(filter)) self.send( filter.form_builder_helper_name, filter, **options, &block) end @@ -20,12 +19,13 @@ def datagrid_filter(filter_or_attribute, partials: nil, **options, &block) # @return [String] a form label tag for the corresponding filter name def datagrid_label(filter_or_attribute, text = nil, **options, &block) filter = datagrid_get_filter(filter_or_attribute) - label(filter.name, text || filter.header, **filter.label_options, **options, &block) + label(filter.name, text || filter.header, class: filter.default_html_classes, **filter.label_options, **options, &block) end # @visibility private def datagrid_filter_input(attribute_or_filter, **options, &block) filter = datagrid_get_filter(attribute_or_filter) + options = add_filter_options(filter, **options) type = options[:type]&.to_sym if options.has_key?(:value) && options[:value].nil? && [:"datetime-local", :"date"].include?(type) # https://github.com/rails/rails/pull/53387 @@ -38,7 +38,8 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) elsif type == :textarea text_area filter.name, value: object.filter_value_as_string(filter) , **options, type: nil, &block elsif type == :checkbox - check_box filter.name, **options + # raise options.inspect + check_box filter.name, options, options.fetch(:value, 1) elsif type == :hidden hidden_field filter.name, **options elsif type == :select @@ -83,7 +84,6 @@ def datagrid_default_filter(filter, options = {}) def datagrid_enum_filter(filter, options = {}, &block) if filter.checkboxes? - options = add_html_classes(options, 'checkboxes') elements = object.select_options(filter).map do |element| text, value = @template.send(:option_text_and_value, element) checked = enum_checkbox_checked?(filter, value) @@ -124,6 +124,7 @@ def datagrid_integer_filter(filter, options = {}) def datagrid_dynamic_filter(filter, options = {}) input_name = "#{object_name}[#{filter.name.to_s}][]" field, operation, value = object.filter_value(filter) + options = add_filter_options(filter, **options) options = options.merge(name: input_name) field_input = dynamic_filter_select( filter.name, @@ -210,10 +211,6 @@ def datagrid_get_filter(attribute_or_filter) end end - def datagrid_filter_html_classes(filter) - [filter.name, filter.class.to_s.demodulize.underscore] - end - def add_html_classes(options, *classes) Datagrid::Utils.add_html_classes(options, *classes) end @@ -233,6 +230,13 @@ def render_partial(name, locals) @template.render partial: partial_path(name), locals: locals end + def add_filter_options(filter, **options) + add_html_classes( + {**filter.input_options, **options}, + *filter.default_html_classes, + ) + end + class Error < StandardError end end diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index c374330..1ca89a3 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -161,27 +161,27 @@ class MyTemplate let(:_filter_options) { {:id => "hello"} } let(:_range) { [1,2]} it { should equal_to_dom( - '<input value="1" id="from_hello" class="group_id integer_filter from" multiple type="text" name="report[group_id][]"/>' + + '<input value="1" id="from_hello" class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + '<span class="separator integer"> - </span>' + - '<input value="2" id="to_hello" class="group_id integer_filter to" multiple type="text" name="report[group_id][]"/>' + '<input value="2" id="to_hello" class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' )} end context "with only left bound" do let(:_range) { [10, nil]} it { should equal_to_dom( - '<input value="10" class="group_id integer_filter from" multiple type="text" name="report[group_id][]"/>' + + '<input value="10" class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + '<span class="separator integer"> - </span>' + - '<input class="group_id integer_filter to" multiple type="text" name="report[group_id][]"/>' + '<input class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' )} it { should be_html_safe } end context "with only right bound" do let(:_range) { [nil, 10]} it { should equal_to_dom( - '<input class="group_id integer_filter from" multiple type="text" name="report[group_id][]"/>' + + '<input class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + '<span class="separator integer"> - </span>' + - '<input value="10" class="group_id integer_filter to" multiple type="text" name="report[group_id][]"/>' + '<input value="10" class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' )} it { should be_html_safe } end @@ -189,9 +189,9 @@ class MyTemplate context "with invalid range value" do let(:_range) { 2..1 } it { should equal_to_dom( - '<input value="1" class="group_id integer_filter from" multiple type="text" name="report[group_id][]"/>' + + '<input value="1" class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + '<span class="separator integer"> - </span>' + - '<input value="2" class="group_id integer_filter to" multiple type="text" name="report[group_id][]"/>' + '<input value="2" class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' )} end @@ -207,7 +207,7 @@ class MyTemplate let(:view_options) { { :partials => 'not_existed' } } let(:_range) { nil } it { should equal_to_dom( - '<input class="group_id integer_filter from" multiple type="text" name="report[group_id][]"><span class="separator integer"> - </span><input class="group_id integer_filter to" multiple type="text" name="report[group_id][]">' + '<input class="from group_id integer_filter" multiple type="text" name="report[group_id][]"><span class="separator integer"> - </span><input class="to group_id integer_filter" multiple type="text" name="report[group_id][]">' ) } end @@ -223,9 +223,9 @@ class MyTemplate } let(:_range) { [1.5,2.5]} it { should equal_to_dom( - '<input value="1.5" class="rating float_filter from" multiple type="text" name="report[rating][]"/>' + + '<input value="1.5" class="from rating float_filter" multiple type="text" name="report[rating][]"/>' + '<span class="separator float"> - </span>' + - '<input value="2.5" class="rating float_filter to" multiple type="text" name="report[rating][]"/>' + '<input value="2.5" class="to rating float_filter" multiple type="text" name="report[rating][]"/>' )} end @@ -241,9 +241,9 @@ class MyTemplate let(:_range) { ["2012-01-03", nil]} it { should equal_to_dom( - '<input value="2012-01-03" class="created_at date_filter from" multiple type="text" name="report[created_at][]"/>' + + '<input value="2012-01-03" class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + '<span class="separator date"> - </span>' + - '<input class="created_at date_filter to" multiple type="text" name="report[created_at][]"/>' + '<input class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' )} it { should be_html_safe } end @@ -255,18 +255,18 @@ class MyTemplate end let(:_range) { ["2013/01/01", '2013/02/02']} it { should equal_to_dom( - '<input value="01/01/2013" class="created_at date_filter from" multiple type="text" name="report[created_at][]"/>' + + '<input value="01/01/2013" class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + '<span class="separator date"> - </span>' + - '<input value="02/02/2013" class="created_at date_filter to" multiple type="text" name="report[created_at][]"/>' + '<input value="02/02/2013" class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' )} end context "with only right bound" do let(:_range) { [nil, "2012-01-03"]} it { should equal_to_dom( - '<input class="created_at date_filter from" multiple type="text" name="report[created_at][]"/>' + + '<input class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + '<span class="separator date"> - </span>' + - '<input value="2012-01-03" class="created_at date_filter to" multiple type="text" name="report[created_at][]"/>' + '<input value="2012-01-03" class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' )} it { should be_html_safe } end @@ -274,9 +274,9 @@ class MyTemplate context "with invalid range value" do let(:_range) { Date.parse('2012-01-02')..Date.parse('2012-01-01') } it { should equal_to_dom( - '<input value="2012-01-01" class="created_at date_filter from" multiple type="text" name="report[created_at][]"/>' + + '<input value="2012-01-01" class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + '<span class="separator date"> - </span>' + - '<input value="2012-01-02" class="created_at date_filter to" multiple type="text" name="report[created_at][]"/>' + '<input value="2012-01-02" class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' )} end context "with blank range value" do @@ -287,9 +287,9 @@ class MyTemplate end let(:_range) { [nil, nil] } it { should equal_to_dom( - '<input class="created_at date_filter from" multiple type="text" name="report[created_at][]"/>' + + '<input class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + '<span class="separator date"> - </span>' + - '<input class="created_at date_filter to" multiple type="text" name="report[created_at][]"/>' + '<input class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' )} end end @@ -372,8 +372,8 @@ class MyTemplate let(:_category_filter_options) { {checkboxes: true} } it { should equal_to_dom( ' -<label class="category enum_filter checkboxes" for="report_category_first"><input id="report_category_first" type="checkbox" value="first" name="report[category][]" />first</label> -<label class="category enum_filter checkboxes" for="report_category_second"><input id="report_category_second" type="checkbox" value="second" name="report[category][]" />second</label> +<label class="category enum_filter checkboxes" for="report_category_first"><input class="category enum_filter checkboxes" type="checkbox" id="report_category_first" value="first" name="report[category][]" />first</label> +<label class="category enum_filter checkboxes" for="report_category_second"><input class="category enum_filter checkboxes" type="checkbox" id="report_category_second" value="second" name="report[category][]" />second</label> ' )} @@ -522,9 +522,9 @@ class MyTemplate let(:_filter) { :column_names } let(:expected_html) do <<DOM -<label class="column_names enum_filter checkboxes" for="report_column_names_id"><input id="report_column_names_id" type="checkbox" value="id" checked name="report[column_names][]">Id</label> -<label class="column_names enum_filter checkboxes" for="report_column_names_name"><input id="report_column_names_name" type="checkbox" value="name" checked name="report[column_names][]">Name</label> -<label class="column_names enum_filter checkboxes" for="report_column_names_category"><input id="report_column_names_category" type="checkbox" value="category" name="report[column_names][]">Category</label> +<label class="column_names enum_filter checkboxes" for="report_column_names_id"><input class="column_names enum_filter checkboxes" id="report_column_names_id" type="checkbox" value="id" checked name="report[column_names][]">Id</label> +<label class="column_names enum_filter checkboxes" for="report_column_names_name"><input class="column_names enum_filter checkboxes" id="report_column_names_name" type="checkbox" value="name" checked name="report[column_names][]">Name</label> +<label class="column_names enum_filter checkboxes" for="report_column_names_category"><input class="column_names enum_filter checkboxes" id="report_column_names_category" type="checkbox" value="category" name="report[column_names][]">Category</label> DOM end @@ -641,7 +641,7 @@ class MyTemplate end it "should generate label for filter" do expect(view.datagrid_label(:name)).to equal_to_dom( - '<label for="report_name">Name</label>' + '<label class="name string_filter", for="report_name">Name</label>' ) end it "should pass options through to the helper" do @@ -656,7 +656,7 @@ class MyTemplate end it "should support explicit label" do expect(view.datagrid_label(:name, "The Name")).to equal_to_dom( - '<label for="report_name">The Name</label>' + '<label class="name string_filter" for="report_name">The Name</label>' ) end end From bf68e7db36e38fe6dd049c4fb8a62a5d002a9f5a Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 3 Nov 2024 16:01:36 +0100 Subject: [PATCH 006/157] Never override built-in generated html classes --- app/views/datagrid/_form.html.erb | 2 +- lib/datagrid/form_builder.rb | 15 +++++++++------ spec/datagrid/form_builder_spec.rb | 12 ++++++------ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/app/views/datagrid/_form.html.erb b/app/views/datagrid/_form.html.erb index 7e175c1..b0132f5 100644 --- a/app/views/datagrid/_form.html.erb +++ b/app/views/datagrid/_form.html.erb @@ -1,4 +1,4 @@ -<%= form_for grid, options do |f| -%> +<%= form_for grid, **options do |f| -%> <% grid.filters.each do |filter| %> <div class="datagrid-filter filter"> <%= f.datagrid_label filter %> diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 45f0fb2..bfdd80e 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -19,24 +19,28 @@ def datagrid_filter(filter_or_attribute, partials: nil, **options, &block) # @return [String] a form label tag for the corresponding filter name def datagrid_label(filter_or_attribute, text = nil, **options, &block) filter = datagrid_get_filter(filter_or_attribute) - label(filter.name, text || filter.header, class: filter.default_html_classes, **filter.label_options, **options, &block) + options = add_html_classes( + {**filter.label_options, **options}, + filter.default_html_classes + ) + label(filter.name, text || filter.header, **options, &block) end # @visibility private def datagrid_filter_input(attribute_or_filter, **options, &block) filter = datagrid_get_filter(attribute_or_filter) options = add_filter_options(filter, **options) - type = options[:type]&.to_sym - if options.has_key?(:value) && options[:value].nil? && [:"datetime-local", :"date"].include?(type) + type = options.delete(:type)&.to_sym + if options.has_key?(:value) && options[:value].nil? && [:"datetime-local", :date].include?(type) # https://github.com/rails/rails/pull/53387 options[:value] = "" end if type == :"datetime-local" datetime_local_field filter.name, **options, &block - elsif type == :"date" + elsif type == :date date_field filter.name, **options, &block elsif type == :textarea - text_area filter.name, value: object.filter_value_as_string(filter) , **options, type: nil, &block + text_area filter.name, value: object.filter_value_as_string(filter) , **options, &block elsif type == :checkbox # raise options.inspect check_box filter.name, options, options.fetch(:value, 1) @@ -53,7 +57,6 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) }, multiple: filter.multiple?, **options, - type: nil, &block ) else diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 1ca89a3..6aa5826 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -636,22 +636,22 @@ class MyTemplate end it "should generate label for filter" do expect(view.datagrid_label(:created_at)).to equal_to_dom( - '<label class="js-date-selector" for="report_created_at">Created at</label>' + '<label class="js-date-selector created_at date_filter" for="report_created_at">Created at</label>' ) end it "should generate label for filter" do expect(view.datagrid_label(:name)).to equal_to_dom( - '<label class="name string_filter", for="report_name">Name</label>' + '<label class="name string_filter" for="report_name">Name</label>' ) end it "should pass options through to the helper" do - expect(view.datagrid_label(:name, :class => 'foo')).to equal_to_dom( - '<label class="foo" for="report_name">Name</label>' + expect(view.datagrid_label(:name, class: 'foo')).to equal_to_dom( + '<label class="foo name string_filter" for="report_name">Name</label>' ) end it "should support block" do - expect(view.datagrid_label(:name, :class => 'foo') { 'The Name' }).to equal_to_dom( - '<label class="foo" for="report_name">The Name</label>' + expect(view.datagrid_label(:name, class: 'foo') { 'The Name' }).to equal_to_dom( + '<label class="foo name string_filter" for="report_name">The Name</label>' ) end it "should support explicit label" do From 1f0b5a6f114c06b7c2993ac542c4e888c7aa4084 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 3 Nov 2024 19:30:01 +0100 Subject: [PATCH 007/157] Remove filter class from wrapping block --- app/views/datagrid/_form.html.erb | 2 +- spec/datagrid/helper_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/datagrid/_form.html.erb b/app/views/datagrid/_form.html.erb index b0132f5..911d163 100644 --- a/app/views/datagrid/_form.html.erb +++ b/app/views/datagrid/_form.html.erb @@ -1,6 +1,6 @@ <%= form_for grid, **options do |f| -%> <% grid.filters.each do |filter| %> - <div class="datagrid-filter filter"> + <div class="datagrid-filter"> <%= f.datagrid_label filter %> <%= f.datagrid_filter filter %> </div> diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 1cd558c..2ec195f 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -483,8 +483,8 @@ class FormForGrid expect(subject.datagrid_form_for(object, url: "/grid")).to match_css_pattern( "form.datagrid-form.form_for_grid[action='/grid']" => 1, "form input[name=utf8]" => 1, - "form .filter label" => "Category", - "form .filter input.category.default_filter[name='form_for_grid[category]'][value=hello]" => 1, + "form .datagrid-filter label" => "Category", + "form .datagrid-filter input.category.default_filter[name='form_for_grid[category]'][value=hello]" => 1, "form input[name=commit][value=Search]" => 1, "form a.datagrid-reset[href='/location']" => 1 ) From e1ad783f2d3bf43d0a34fd209d591837b10c9722 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 3 Nov 2024 19:37:37 +0100 Subject: [PATCH 008/157] Rubocop install --- .rubocop.yml | 3 + .rubocop_todo.yml | 1021 +++++++++++++++++ Gemfile | 6 +- Rakefile | 22 +- datagrid.gemspec | 5 +- gemfiles/rails_6.1.gemfile | 2 +- gemfiles/rails_7.0.gemfile | 2 +- gemfiles/rails_7.1.gemfile | 2 +- gemfiles/rails_7.2.gemfile | 2 +- lib/datagrid.rb | 8 +- lib/datagrid/active_model.rb | 10 +- lib/datagrid/column_names_attribute.rb | 15 +- lib/datagrid/columns.rb | 43 +- lib/datagrid/columns/column.rb | 24 +- lib/datagrid/configuration.rb | 1 - lib/datagrid/core.rb | 44 +- lib/datagrid/drivers.rb | 1 - lib/datagrid/drivers/abstract_driver.rb | 22 +- lib/datagrid/drivers/active_record.rb | 28 +- lib/datagrid/drivers/array.rb | 10 +- lib/datagrid/drivers/mongo_mapper.rb | 23 +- lib/datagrid/drivers/mongoid.rb | 28 +- lib/datagrid/drivers/sequel.rb | 17 +- lib/datagrid/engine.rb | 5 +- lib/datagrid/filters.rb | 22 +- lib/datagrid/filters/base_filter.rb | 28 +- lib/datagrid/filters/boolean_filter.rb | 2 - lib/datagrid/filters/composite_filters.rb | 20 +- lib/datagrid/filters/date_filter.rb | 11 +- lib/datagrid/filters/date_time_filter.rb | 2 - lib/datagrid/filters/dynamic_filter.rb | 48 +- lib/datagrid/filters/enum_filter.rb | 11 +- .../filters/extended_boolean_filter.rb | 7 +- lib/datagrid/filters/float_filter.rb | 2 +- lib/datagrid/filters/integer_filter.rb | 5 +- lib/datagrid/filters/ranged_filter.rb | 18 +- lib/datagrid/filters/select_options.rb | 17 +- lib/datagrid/filters/string_filter.rb | 1 - lib/datagrid/form_builder.rb | 47 +- lib/datagrid/helper.rb | 7 +- lib/datagrid/ordering.rb | 46 +- lib/datagrid/renderer.rb | 41 +- lib/datagrid/rspec.rb | 14 +- lib/datagrid/scaffold.rb | 38 +- lib/datagrid/utils.rb | 42 +- lib/tasks/datagrid_tasks.rake | 1 - spec/datagrid/active_model_spec.rb | 8 +- spec/datagrid/column_names_attribute_spec.rb | 34 +- spec/datagrid/columns/column_spec.rb | 7 +- spec/datagrid/columns_spec.rb | 233 ++-- spec/datagrid/core_spec.rb | 79 +- spec/datagrid/drivers/active_record_spec.rb | 31 +- spec/datagrid/drivers/array_spec.rb | 66 +- spec/datagrid/drivers/mongo_mapper_spec.rb | 72 +- spec/datagrid/drivers/mongoid_spec.rb | 68 +- spec/datagrid/drivers/sequel_spec.rb | 73 +- spec/datagrid/filters/base_filter_spec.rb | 17 +- .../filters/composite_filters_spec.rb | 33 +- spec/datagrid/filters/date_filter_spec.rb | 58 +- .../datagrid/filters/date_time_filter_spec.rb | 56 +- spec/datagrid/filters/dynamic_filter_spec.rb | 127 +- spec/datagrid/filters/enum_filter_spec.rb | 35 +- .../filters/extended_boolean_filter_spec.rb | 16 +- spec/datagrid/filters/float_filter_spec.rb | 9 +- spec/datagrid/filters/integer_filter_spec.rb | 31 +- spec/datagrid/filters/string_filter_spec.rb | 39 +- spec/datagrid/filters_spec.rb | 137 +-- spec/datagrid/form_builder_spec.rb | 540 +++++---- spec/datagrid/helper_spec.rb | 213 ++-- spec/datagrid/ordering_spec.rb | 43 +- spec/datagrid/scaffold_spec.rb | 17 +- spec/datagrid/stylesheet_spec.rb | 4 +- spec/datagrid/utils_spec.rb | 4 +- spec/datagrid_spec.rb | 27 +- spec/spec_helper.rb | 87 +- spec/support/active_record.rb | 7 +- spec/support/configuration.rb | 37 +- spec/support/i18n_helpers.rb | 2 +- spec/support/matchers.rb | 17 +- spec/support/mongo_mapper.rb | 2 - spec/support/mongoid.rb | 7 +- spec/support/sequel.rb | 5 - spec/support/simple_report.rb | 23 +- 83 files changed, 2442 insertions(+), 1596 deletions(-) create mode 100644 .rubocop.yml create mode 100644 .rubocop_todo.yml diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..e5ccac6 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,3 @@ +# inherit_from: .rubocop_todo.yml +Style/StringLiterals: + EnforcedStyle: double_quotes diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 0000000..88da75f --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,1021 @@ +# This configuration was generated by +# `rubocop --auto-gen-config` +# on 2024-11-03 18:32:09 UTC using RuboCop version 1.68.0. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 6 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include. +# Include: **/*.gemfile, **/Gemfile, **/gems.rb +Bundler/OrderedGems: + Exclude: + - 'Gemfile' + - 'gemfiles/rails_6.1.gemfile' + - 'gemfiles/rails_7.0.gemfile' + - 'gemfiles/rails_7.1.gemfile' + - 'gemfiles/rails_7.2.gemfile' + +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: with_first_argument, with_fixed_indentation +Layout/ArgumentAlignment: + Exclude: + - 'lib/datagrid/filters.rb' + - 'lib/datagrid/form_builder.rb' + +# Offense count: 5 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyleAlignWith. +# SupportedStylesAlignWith: either, start_of_block, start_of_line +Layout/BlockAlignment: + Exclude: + - 'spec/datagrid/drivers/mongo_mapper_spec.rb' + - 'spec/datagrid/filters/enum_filter_spec.rb' + +# Offense count: 35 +# This cop supports safe autocorrection (--autocorrect). +Layout/BlockEndNewline: + Exclude: + - 'spec/datagrid/form_builder_spec.rb' + - 'spec/datagrid/helper_spec.rb' + - 'spec/datagrid_spec.rb' + +# Offense count: 4 +# This cop supports safe autocorrection (--autocorrect). +Layout/ClosingHeredocIndentation: + Exclude: + - 'lib/datagrid/scaffold.rb' + - 'spec/datagrid/helper_spec.rb' + - 'spec/datagrid/scaffold_spec.rb' + +# Offense count: 40 +# This cop supports safe autocorrection (--autocorrect). +Layout/EmptyLineAfterGuardClause: + Exclude: + - 'lib/datagrid/columns.rb' + - 'lib/datagrid/columns/column.rb' + - 'lib/datagrid/drivers/active_record.rb' + - 'lib/datagrid/drivers/array.rb' + - 'lib/datagrid/drivers/mongo_mapper.rb' + - 'lib/datagrid/drivers/mongoid.rb' + - 'lib/datagrid/drivers/sequel.rb' + - 'lib/datagrid/filters.rb' + - 'lib/datagrid/filters/base_filter.rb' + - 'lib/datagrid/filters/dynamic_filter.rb' + - 'lib/datagrid/filters/enum_filter.rb' + - 'lib/datagrid/filters/float_filter.rb' + - 'lib/datagrid/filters/integer_filter.rb' + - 'lib/datagrid/ordering.rb' + - 'lib/datagrid/utils.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Layout/EmptyLineAfterMagicComment: + Exclude: + - 'spec/datagrid/form_builder_spec.rb' + +# Offense count: 14 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EmptyLineBetweenMethodDefs, EmptyLineBetweenClassDefs, EmptyLineBetweenModuleDefs, DefLikeMacros, AllowAdjacentOneLineDefs, NumberOfEmptyLines. +Layout/EmptyLineBetweenDefs: + Exclude: + - 'lib/datagrid/columns.rb' + - 'lib/datagrid/columns/column.rb' + - 'lib/datagrid/core.rb' + - 'lib/datagrid/filters/date_filter.rb' + - 'lib/datagrid/helper.rb' + - 'lib/datagrid/ordering.rb' + - 'spec/datagrid/columns_spec.rb' + - 'spec/support/active_record.rb' + - 'spec/support/matchers.rb' + - 'spec/support/sequel.rb' + +# Offense count: 60 +# This cop supports safe autocorrection (--autocorrect). +Layout/EmptyLines: + Enabled: false + +# Offense count: 6 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: around, only_before +Layout/EmptyLinesAroundAccessModifier: + Exclude: + - 'lib/datagrid/core.rb' + - 'lib/datagrid/drivers/abstract_driver.rb' + - 'lib/datagrid/form_builder.rb' + - 'lib/datagrid/renderer.rb' + - 'lib/datagrid/scaffold.rb' + - 'lib/datagrid/utils.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowAliasSyntax, AllowedMethods. +# AllowedMethods: alias_method, public, protected, private +Layout/EmptyLinesAroundAttributeAccessor: + Exclude: + - 'spec/datagrid/columns_spec.rb' + - 'spec/datagrid/filters_spec.rb' + +# Offense count: 96 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: empty_lines, no_empty_lines +Layout/EmptyLinesAroundBlockBody: + Enabled: false + +# Offense count: 37 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines, beginning_only, ending_only +Layout/EmptyLinesAroundClassBody: + Enabled: false + +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). +Layout/EmptyLinesAroundMethodBody: + Exclude: + - 'lib/datagrid/columns/column.rb' + - 'lib/datagrid/filters/ranged_filter.rb' + - 'lib/datagrid/utils.rb' + +# Offense count: 16 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines +Layout/EmptyLinesAroundModuleBody: + Exclude: + - 'lib/datagrid.rb' + - 'lib/datagrid/columns.rb' + - 'lib/datagrid/configuration.rb' + - 'lib/datagrid/core.rb' + - 'lib/datagrid/filters.rb' + - 'lib/datagrid/filters/composite_filters.rb' + - 'lib/datagrid/filters/ranged_filter.rb' + - 'lib/datagrid/helper.rb' + - 'lib/datagrid/ordering.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyleAlignWith, Severity. +# SupportedStylesAlignWith: keyword, variable, start_of_line +Layout/EndAlignment: + Exclude: + - 'spec/datagrid/drivers/mongo_mapper_spec.rb' + +# Offense count: 16 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment. +Layout/ExtraSpacing: + Exclude: + - 'lib/datagrid/active_model.rb' + - 'lib/datagrid/columns.rb' + - 'lib/datagrid/drivers/active_record.rb' + - 'lib/datagrid/drivers/sequel.rb' + - 'lib/datagrid/filters/composite_filters.rb' + - 'lib/datagrid/ordering.rb' + - 'spec/datagrid/columns_spec.rb' + - 'spec/datagrid/filters/dynamic_filter_spec.rb' + - 'spec/datagrid/filters/enum_filter_spec.rb' + - 'spec/datagrid/ordering_spec.rb' + +# Offense count: 6 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: IndentationWidth. +# SupportedStyles: special_inside_parentheses, consistent, align_brackets +Layout/FirstArrayElementIndentation: + EnforcedStyle: consistent + +# Offense count: 16 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: IndentationWidth. +# SupportedStyles: special_inside_parentheses, consistent, align_braces +Layout/FirstHashElementIndentation: + EnforcedStyle: consistent + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. +# SupportedHashRocketStyles: key, separator, table +# SupportedColonStyles: key, separator, table +# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit +Layout/HashAlignment: + Exclude: + - 'spec/spec_helper.rb' + +# Offense count: 6 +# This cop supports safe autocorrection (--autocorrect). +Layout/HeredocIndentation: + Exclude: + - 'lib/datagrid/scaffold.rb' + - 'spec/datagrid/form_builder_spec.rb' + - 'spec/datagrid/helper_spec.rb' + +# Offense count: 4 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: normal, indented_internal_methods +Layout/IndentationConsistency: + Exclude: + - 'spec/datagrid/columns_spec.rb' + +# Offense count: 5 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: Width, AllowedPatterns. +Layout/IndentationWidth: + Exclude: + - 'spec/datagrid/drivers/mongo_mapper_spec.rb' + - 'spec/datagrid/helper_spec.rb' + +# Offense count: 11 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowDoxygenCommentStyle, AllowGemfileRubyComment, AllowRBSInlineAnnotation, AllowSteepAnnotation. +Layout/LeadingCommentSpace: + Exclude: + - 'lib/datagrid/drivers/mongo_mapper.rb' + - 'lib/datagrid/rspec.rb' + - 'spec/datagrid/filters/dynamic_filter_spec.rb' + - 'spec/spec_helper.rb' + - 'spec/support/active_record.rb' + - 'spec/support/mongoid.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Layout/LeadingEmptyLines: + Exclude: + - 'spec/support/simple_report.rb' + +# Offense count: 35 +# This cop supports safe autocorrection (--autocorrect). +Layout/MultilineBlockLayout: + Exclude: + - 'spec/datagrid/form_builder_spec.rb' + - 'spec/datagrid/helper_spec.rb' + - 'spec/datagrid_spec.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: aligned, indented +Layout/MultilineOperationIndentation: + Exclude: + - 'lib/datagrid/filters/integer_filter.rb' + +# Offense count: 36 +# This cop supports safe autocorrection (--autocorrect). +Layout/SpaceAfterComma: + Exclude: + - 'lib/datagrid/columns.rb' + - 'spec/datagrid/drivers/array_spec.rb' + - 'spec/datagrid/drivers/sequel_spec.rb' + - 'spec/datagrid/filters/date_filter_spec.rb' + - 'spec/datagrid/filters/date_time_filter_spec.rb' + - 'spec/datagrid/filters/enum_filter_spec.rb' + - 'spec/datagrid/filters/integer_filter_spec.rb' + - 'spec/datagrid/filters_spec.rb' + - 'spec/datagrid/form_builder_spec.rb' + - 'spec/datagrid/helper_spec.rb' + +# Offense count: 5 +# This cop supports safe autocorrection (--autocorrect). +Layout/SpaceAfterNot: + Exclude: + - 'lib/datagrid/columns/column.rb' + - 'lib/datagrid/drivers/active_record.rb' + - 'lib/datagrid/drivers/mongoid.rb' + - 'lib/datagrid/drivers/sequel.rb' + +# Offense count: 14 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowForAlignment, EnforcedStyleForExponentOperator, EnforcedStyleForRationalLiterals. +# SupportedStylesForExponentOperator: space, no_space +# SupportedStylesForRationalLiterals: space, no_space +Layout/SpaceAroundOperators: + Exclude: + - 'lib/datagrid/columns.rb' + - 'lib/datagrid/drivers/active_record.rb' + - 'lib/datagrid/drivers/mongo_mapper.rb' + - 'lib/datagrid/drivers/mongoid.rb' + - 'lib/datagrid/drivers/sequel.rb' + - 'spec/datagrid/drivers/array_spec.rb' + - 'spec/datagrid/drivers/mongo_mapper_spec.rb' + - 'spec/datagrid/drivers/mongoid_spec.rb' + - 'spec/datagrid/drivers/sequel_spec.rb' + - 'spec/datagrid/filters/date_time_filter_spec.rb' + - 'spec/datagrid/filters/enum_filter_spec.rb' + - 'spec/datagrid/filters/integer_filter_spec.rb' + - 'spec/spec_helper.rb' + +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. +# SupportedStyles: space, no_space +# SupportedStylesForEmptyBraces: space, no_space +Layout/SpaceBeforeBlockBraces: + Exclude: + - 'lib/datagrid/filters.rb' + - 'spec/datagrid/filters/dynamic_filter_spec.rb' + - 'spec/datagrid/ordering_spec.rb' + +# Offense count: 5 +# This cop supports safe autocorrection (--autocorrect). +Layout/SpaceBeforeComma: + Exclude: + - 'lib/datagrid/drivers/mongoid.rb' + - 'lib/datagrid/filters.rb' + - 'lib/datagrid/form_builder.rb' + +# Offense count: 5 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowForAlignment. +Layout/SpaceBeforeFirstArg: + Exclude: + - 'lib/datagrid/active_model.rb' + - 'lib/datagrid/columns.rb' + - 'lib/datagrid/filters/composite_filters.rb' + - 'lib/datagrid/ordering.rb' + - 'spec/datagrid/columns_spec.rb' + +# Offense count: 16 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBrackets. +# SupportedStyles: space, no_space, compact +# SupportedStylesForEmptyBrackets: space, no_space +Layout/SpaceInsideArrayLiteralBrackets: + Exclude: + - 'lib/datagrid/drivers/mongoid.rb' + - 'lib/datagrid/filters/base_filter.rb' + - 'spec/datagrid/column_names_attribute_spec.rb' + - 'spec/datagrid/drivers/array_spec.rb' + - 'spec/datagrid/drivers/mongo_mapper_spec.rb' + - 'spec/datagrid/drivers/mongoid_spec.rb' + - 'spec/datagrid/drivers/sequel_spec.rb' + +# Offense count: 425 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters. +# SupportedStyles: space, no_space +# SupportedStylesForEmptyBraces: space, no_space +Layout/SpaceInsideBlockBraces: + Enabled: false + +# Offense count: 162 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. +# SupportedStyles: space, no_space, compact +# SupportedStylesForEmptyBraces: space, no_space +Layout/SpaceInsideHashLiteralBraces: + Enabled: false + +# Offense count: 18 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: space, compact, no_space +Layout/SpaceInsideParens: + Exclude: + - 'lib/datagrid/form_builder.rb' + - 'lib/datagrid/ordering.rb' + - 'spec/datagrid/filters/enum_filter_spec.rb' + - 'spec/datagrid/filters/integer_filter_spec.rb' + - 'spec/datagrid/filters/string_filter_spec.rb' + - 'spec/datagrid/filters_spec.rb' + - 'spec/datagrid/form_builder_spec.rb' + - 'spec/datagrid/helper_spec.rb' + +# Offense count: 15 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: final_newline, final_blank_line +Layout/TrailingEmptyLines: + Exclude: + - 'Rakefile' + - 'datagrid.gemspec' + - 'lib/datagrid.rb' + - 'lib/datagrid/column_names_attribute.rb' + - 'lib/datagrid/drivers/mongoid.rb' + - 'lib/datagrid/filters/base_filter.rb' + - 'lib/datagrid/filters/date_filter.rb' + - 'lib/datagrid/filters/date_time_filter.rb' + - 'lib/datagrid/filters/integer_filter.rb' + - 'lib/datagrid/helper.rb' + - 'spec/datagrid/helper_spec.rb' + - 'spec/support/configuration.rb' + - 'spec/support/mongoid.rb' + - 'spec/support/sequel.rb' + - 'spec/support/simple_report.rb' + +# Offense count: 4 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowInHeredoc. +Layout/TrailingWhitespace: + Exclude: + - 'spec/datagrid/columns/column_spec.rb' + - 'spec/datagrid/filters/base_filter_spec.rb' + - 'spec/datagrid/filters/float_filter_spec.rb' + - 'spec/datagrid/utils_spec.rb' + +# Offense count: 4 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: AllowSafeAssignment. +Lint/AssignmentInCondition: + Exclude: + - 'lib/datagrid/columns/column.rb' + - 'lib/datagrid/filters/base_filter.rb' + - 'lib/datagrid/form_builder.rb' + - 'lib/datagrid/renderer.rb' + +# Offense count: 31 +# Configuration parameters: AllowedMethods. +# AllowedMethods: enums +Lint/ConstantDefinitionInBlock: + Exclude: + - 'spec/datagrid/active_model_spec.rb' + - 'spec/datagrid/columns/column_spec.rb' + - 'spec/datagrid/columns_spec.rb' + - 'spec/datagrid/core_spec.rb' + - 'spec/datagrid/drivers/array_spec.rb' + - 'spec/datagrid/drivers/sequel_spec.rb' + - 'spec/datagrid/filters/enum_filter_spec.rb' + - 'spec/datagrid/filters_spec.rb' + - 'spec/datagrid/helper_spec.rb' + - 'spec/datagrid/ordering_spec.rb' + - 'spec/support/active_record.rb' + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +Lint/NonDeterministicRequireOrder: + Exclude: + - 'spec/spec_helper.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Lint/RedundantStringCoercion: + Exclude: + - 'lib/datagrid/form_builder.rb' + +# Offense count: 6 +# Configuration parameters: AllowComments, AllowNil. +Lint/SuppressedException: + Exclude: + - 'lib/datagrid/active_model.rb' + - 'lib/datagrid/utils.rb' + - 'spec/spec_helper.rb' + +# Offense count: 8 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AutoCorrect, IgnoreEmptyBlocks, AllowUnusedKeywordArguments. +Lint/UnusedBlockArgument: + Exclude: + - 'lib/datagrid/filters/extended_boolean_filter.rb' + - 'spec/datagrid/columns_spec.rb' + - 'spec/datagrid/drivers/active_record_spec.rb' + - 'spec/datagrid/form_builder_spec.rb' + - 'spec/datagrid/helper_spec.rb' + - 'spec/datagrid/ordering_spec.rb' + +# Offense count: 20 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AutoCorrect, AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods. +Lint/UnusedMethodArgument: + Exclude: + - 'lib/datagrid/columns.rb' + - 'lib/datagrid/drivers/array.rb' + - 'lib/datagrid/drivers/mongo_mapper.rb' + - 'lib/datagrid/drivers/mongoid.rb' + - 'lib/datagrid/filters/base_filter.rb' + - 'lib/datagrid/filters/composite_filters.rb' + - 'lib/datagrid/form_builder.rb' + - 'spec/support/i18n_helpers.rb' + +# Offense count: 3 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: AutoCorrect. +Lint/UselessMethodDefinition: + Exclude: + - 'lib/datagrid/core.rb' + - 'lib/datagrid/drivers/sequel.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AutoCorrect, CheckForMethodsWithNoSideEffects. +Lint/Void: + Exclude: + - 'spec/support/matchers.rb' + +# Offense count: 14 +# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. +Metrics/AbcSize: + Max: 39 + +# Offense count: 64 +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. +# AllowedMethods: refine +Metrics/BlockLength: + Max: 606 + +# Offense count: 5 +# Configuration parameters: CountComments, CountAsOne. +Metrics/ClassLength: + Max: 146 + +# Offense count: 10 +# Configuration parameters: AllowedMethods, AllowedPatterns. +Metrics/CyclomaticComplexity: + Max: 14 + +# Offense count: 32 +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. +Metrics/MethodLength: + Max: 34 + +# Offense count: 3 +# Configuration parameters: CountComments, CountAsOne. +Metrics/ModuleLength: + Max: 193 + +# Offense count: 10 +# Configuration parameters: AllowedMethods, AllowedPatterns. +Metrics/PerceivedComplexity: + Max: 14 + +# Offense count: 9 +# Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros. +# NamePrefix: is_, has_, have_ +# ForbiddenPrefixes: is_, has_, have_ +# AllowedMethods: is_a? +# MethodDefinitionMacros: define_method, define_singleton_method +Naming/PredicateName: + Exclude: + - 'spec/**/*' + - 'lib/datagrid/drivers/abstract_driver.rb' + - 'lib/datagrid/drivers/active_record.rb' + - 'lib/datagrid/drivers/array.rb' + - 'lib/datagrid/drivers/mongo_mapper.rb' + - 'lib/datagrid/drivers/mongoid.rb' + - 'lib/datagrid/drivers/sequel.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: prefer_alias, prefer_alias_method +Style/Alias: + Exclude: + - 'lib/datagrid/ordering.rb' + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: always, conditionals +Style/AndOr: + Exclude: + - 'spec/support/matchers.rb' + +# Offense count: 28 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods. +# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces +# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object +# FunctionalMethods: let, let!, subject, watch +# AllowedMethods: lambda, proc, it +Style/BlockDelimiters: + Exclude: + - 'spec/datagrid/columns_spec.rb' + - 'spec/datagrid/core_spec.rb' + - 'spec/datagrid/drivers/mongo_mapper_spec.rb' + - 'spec/datagrid/drivers/mongoid_spec.rb' + - 'spec/datagrid/drivers/sequel_spec.rb' + - 'spec/datagrid/filters/dynamic_filter_spec.rb' + - 'spec/datagrid/filters_spec.rb' + - 'spec/datagrid/form_builder_spec.rb' + - 'spec/datagrid/helper_spec.rb' + - 'spec/datagrid/ordering_spec.rb' + - 'spec/datagrid_spec.rb' + +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowOnConstant, AllowOnSelfClass. +Style/CaseEquality: + Exclude: + - 'lib/datagrid/filters/select_options.rb' + +# Offense count: 2 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: MinBranchesCount. +Style/CaseLikeIf: + Exclude: + - 'lib/datagrid/form_builder.rb' + - 'spec/support/matchers.rb' + +# Offense count: 16 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: nested, compact +Style/ClassAndModuleChildren: + Exclude: + - 'lib/datagrid/columns/column.rb' + - 'lib/datagrid/filters/base_filter.rb' + - 'lib/datagrid/filters/boolean_filter.rb' + - 'lib/datagrid/filters/date_filter.rb' + - 'lib/datagrid/filters/date_time_filter.rb' + - 'lib/datagrid/filters/default_filter.rb' + - 'lib/datagrid/filters/dynamic_filter.rb' + - 'lib/datagrid/filters/enum_filter.rb' + - 'lib/datagrid/filters/extended_boolean_filter.rb' + - 'lib/datagrid/filters/float_filter.rb' + - 'lib/datagrid/filters/integer_filter.rb' + - 'lib/datagrid/filters/ranged_filter.rb' + - 'lib/datagrid/filters/select_options.rb' + - 'lib/datagrid/filters/string_filter.rb' + - 'lib/datagrid/scaffold.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: Keywords, RequireColon. +# Keywords: TODO, FIXME, OPTIMIZE, HACK, REVIEW, NOTE +Style/CommentAnnotation: + Exclude: + - 'lib/datagrid/drivers/mongo_mapper.rb' + - 'spec/spec_helper.rb' + +# Offense count: 25 +# Configuration parameters: AllowedConstants. +Style/Documentation: + Enabled: false + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AutoCorrect, EnforcedStyle, AllowComments. +# SupportedStyles: empty, nil, both +Style/EmptyElse: + Exclude: + - 'lib/datagrid/ordering.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Style/EmptyLiteral: + Exclude: + - 'spec/datagrid/drivers/array_spec.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +Style/Encoding: + Exclude: + - 'Rakefile' + - 'spec/datagrid/form_builder_spec.rb' + +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). +Style/ExpandPathArguments: + Exclude: + - 'lib/datagrid.rb' + - 'spec/spec_helper.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +Style/ExplicitBlockArgument: + Exclude: + - 'lib/datagrid/drivers/mongo_mapper.rb' + - 'lib/datagrid/drivers/mongoid.rb' + +# Offense count: 82 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: always, always_true, never +Style/FrozenStringLiteralComment: + Enabled: false + +# Offense count: 3 +# Configuration parameters: AllowedVariables. +Style/GlobalVars: + Exclude: + - 'spec/datagrid/filters_spec.rb' + +# Offense count: 9 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: MinBodyLength, AllowConsecutiveConditionals. +Style/GuardClause: + Exclude: + - 'lib/datagrid/core.rb' + - 'lib/datagrid/drivers/abstract_driver.rb' + - 'lib/datagrid/filters/dynamic_filter.rb' + - 'lib/datagrid/filters/ranged_filter.rb' + - 'lib/datagrid/filters/select_options.rb' + - 'lib/datagrid/form_builder.rb' + - 'lib/datagrid/ordering.rb' + - 'spec/support/matchers.rb' + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: AllowedReceivers. +# AllowedReceivers: Thread.current +Style/HashEachMethods: + Exclude: + - 'spec/datagrid/form_builder_spec.rb' + +# Offense count: 226 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, EnforcedShorthandSyntax, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols. +# SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys +# SupportedShorthandSyntax: always, never, either, consistent, either_consistent +Style/HashSyntax: + Enabled: false + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowIfModifier. +Style/IfInsideElse: + Exclude: + - 'lib/datagrid/column_names_attribute.rb' + - 'lib/datagrid/ordering.rb' + +# Offense count: 45 +# This cop supports safe autocorrection (--autocorrect). +Style/IfUnlessModifier: + Enabled: false + +# Offense count: 6 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: line_count_dependent, lambda, literal +Style/Lambda: + Exclude: + - 'spec/datagrid/helper_spec.rb' + - 'spec/support/simple_report.rb' + +# Offense count: 20 +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/LineEndConcatenation: + Exclude: + - 'spec/datagrid/form_builder_spec.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowedMethods, AllowedPatterns. +Style/MethodCallWithoutArgsParentheses: + Exclude: + - 'spec/datagrid/form_builder_spec.rb' + +# Offense count: 2 +Style/MissingRespondToMissing: + Exclude: + - 'lib/datagrid/columns.rb' + - 'lib/datagrid/renderer.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +Style/MultilineTernaryOperator: + Exclude: + - 'lib/datagrid/drivers/active_record.rb' + - 'lib/datagrid/filters/select_options.rb' + +# Offense count: 14 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: literals, strict +Style/MutableConstant: + Exclude: + - 'lib/datagrid/drivers/abstract_driver.rb' + - 'lib/datagrid/filters.rb' + - 'lib/datagrid/filters/dynamic_filter.rb' + - 'lib/datagrid/filters/extended_boolean_filter.rb' + - 'lib/datagrid/utils.rb' + - 'lib/datagrid/version.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: both, prefix, postfix +Style/NegatedIf: + Exclude: + - 'spec/support/matchers.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Style/NestedTernaryOperator: + Exclude: + - 'lib/datagrid/helper.rb' + +# Offense count: 20 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedOctalStyle. +# SupportedOctalStyles: zero_with_o, zero_only +Style/NumericLiteralPrefix: + Exclude: + - 'spec/datagrid/filters/date_filter_spec.rb' + - 'spec/datagrid/filters/date_time_filter_spec.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: Strict, AllowedNumbers, AllowedPatterns. +Style/NumericLiterals: + MinDigits: 6 + +# Offense count: 4 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns. +# SupportedStyles: predicate, comparison +Style/NumericPredicate: + Exclude: + - 'spec/**/*' + - 'lib/datagrid/columns.rb' + - 'lib/datagrid/utils.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Style/ParallelAssignment: + Exclude: + - 'lib/datagrid/utils.rb' + +# Offense count: 6 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: PreferredDelimiters. +Style/PercentLiteralDelimiters: + Exclude: + - 'lib/datagrid/filters/dynamic_filter.rb' + - 'spec/datagrid/columns_spec.rb' + - 'spec/datagrid/form_builder_spec.rb' + +# Offense count: 7 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: short, verbose +Style/PreferredHashMethods: + Exclude: + - 'lib/datagrid/columns/column.rb' + - 'lib/datagrid/filters/base_filter.rb' + - 'lib/datagrid/filters/dynamic_filter.rb' + - 'lib/datagrid/filters/select_options.rb' + - 'lib/datagrid/form_builder.rb' + - 'lib/datagrid/renderer.rb' + +# Offense count: 4 +# This cop supports safe autocorrection (--autocorrect). +Style/RedundantBegin: + Exclude: + - 'lib/datagrid/utils.rb' + - 'spec/support/configuration.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowMultipleReturnValues. +Style/RedundantReturn: + Exclude: + - 'lib/datagrid/drivers/mongoid.rb' + +# Offense count: 38 +# This cop supports safe autocorrection (--autocorrect). +Style/RedundantSelf: + Exclude: + - 'lib/datagrid/active_model.rb' + - 'lib/datagrid/columns.rb' + - 'lib/datagrid/columns/column.rb' + - 'lib/datagrid/core.rb' + - 'lib/datagrid/drivers/abstract_driver.rb' + - 'lib/datagrid/filters.rb' + - 'lib/datagrid/filters/base_filter.rb' + - 'lib/datagrid/filters/enum_filter.rb' + - 'lib/datagrid/filters/select_options.rb' + - 'lib/datagrid/form_builder.rb' + - 'lib/datagrid/ordering.rb' + - 'spec/datagrid/helper_spec.rb' + - 'spec/support/simple_report.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, AllowInnerSlashes. +# SupportedStyles: slashes, percent_r, mixed +Style/RegexpLiteral: + Exclude: + - 'lib/datagrid/scaffold.rb' + +# Offense count: 4 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength. +# AllowedMethods: present?, blank?, presence, try, try! +Style/SafeNavigation: + Exclude: + - 'lib/datagrid/column_names_attribute.rb' + - 'lib/datagrid/filters/base_filter.rb' + - 'lib/datagrid/filters/string_filter.rb' + - 'lib/datagrid/renderer.rb' + +# Offense count: 4 +# This cop supports safe autocorrection (--autocorrect). +Style/StderrPuts: + Exclude: + - 'Rakefile' + - 'spec/spec_helper.rb' + +# Offense count: 17 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: Mode. +Style/StringConcatenation: + Exclude: + - 'lib/datagrid/scaffold.rb' + - 'lib/tasks/datagrid_tasks.rake' + - 'spec/datagrid/form_builder_spec.rb' + +# Offense count: 1090 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. +# SupportedStyles: single_quotes, double_quotes +Style/StringLiterals: + Enabled: false + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/StructInheritance: + Exclude: + - 'spec/datagrid/drivers/array_spec.rb' + +# Offense count: 20 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: MinSize. +# SupportedStyles: percent, brackets +Style/SymbolArray: + EnforcedStyle: brackets + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Style/SymbolLiteral: + Exclude: + - 'spec/datagrid/columns_spec.rb' + +# Offense count: 6 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: AllowMethodsWithArguments, AllowedMethods, AllowedPatterns, AllowComments. +# AllowedMethods: define_method +Style/SymbolProc: + Exclude: + - 'lib/datagrid/column_names_attribute.rb' + - 'spec/datagrid/filters/enum_filter_spec.rb' + - 'spec/datagrid/helper_spec.rb' + - 'spec/support/simple_report.rb' + +# Offense count: 9 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyleForMultiline. +# SupportedStylesForMultiline: comma, consistent_comma, no_comma +Style/TrailingCommaInArguments: + Exclude: + - 'lib/datagrid/column_names_attribute.rb' + - 'lib/datagrid/form_builder.rb' + - 'spec/datagrid/drivers/active_record_spec.rb' + - 'spec/datagrid/helper_spec.rb' + +# Offense count: 6 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyleForMultiline. +# SupportedStylesForMultiline: comma, consistent_comma, no_comma +Style/TrailingCommaInArrayLiteral: + Exclude: + - 'datagrid.gemspec' + - 'lib/datagrid/drivers/mongoid.rb' + - 'lib/datagrid/filters/dynamic_filter.rb' + - 'spec/datagrid/drivers/array_spec.rb' + - 'spec/datagrid/helper_spec.rb' + - 'spec/spec_helper.rb' + +# Offense count: 6 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyleForMultiline. +# SupportedStylesForMultiline: comma, consistent_comma, no_comma +Style/TrailingCommaInHashLiteral: + Exclude: + - 'datagrid.gemspec' + - 'lib/datagrid/drivers/mongoid.rb' + - 'lib/datagrid/form_builder.rb' + - 'lib/datagrid/scaffold.rb' + - 'spec/datagrid/filters_spec.rb' + +# Offense count: 31 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, MinSize, WordRegex. +# SupportedStyles: percent, brackets +Style/WordArray: + Exclude: + - 'spec/datagrid/column_names_attribute_spec.rb' + - 'spec/datagrid/columns_spec.rb' + - 'spec/datagrid/core_spec.rb' + - 'spec/datagrid/drivers/array_spec.rb' + - 'spec/datagrid/drivers/mongo_mapper_spec.rb' + - 'spec/datagrid/drivers/mongoid_spec.rb' + - 'spec/datagrid/drivers/sequel_spec.rb' + - 'spec/datagrid/filters/date_filter_spec.rb' + - 'spec/datagrid/filters/extended_boolean_filter_spec.rb' + - 'spec/datagrid/filters/string_filter_spec.rb' + - 'spec/datagrid/filters_spec.rb' + - 'spec/datagrid/form_builder_spec.rb' + - 'spec/datagrid/helper_spec.rb' + - 'spec/support/simple_report.rb' + +# Offense count: 36 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns. +# URISchemes: http, https +Layout/LineLength: + Max: 250 diff --git a/Gemfile b/Gemfile index cf03de9..909dbe7 100644 --- a/Gemfile +++ b/Gemfile @@ -3,13 +3,13 @@ source "https://rubygems.org" gemspec group :development do - gem "appraisal" gem "activerecord" + gem "appraisal" gem "bump" gem "csv" # removed from standard library in Ruby 3.4 + gem "debug" gem "nokogiri" # used to test html output gem "pry-byebug" - gem 'debug' gem "rails-dom-testing", "~> 2.2" gem "rspec" gem "sequel" @@ -20,3 +20,5 @@ group :development do gem "mongoid", "~> 9.0" end end + +gem "rubocop", "~> 1.68", group: :development diff --git a/Rakefile b/Rakefile index 7fd32b9..4de31ea 100644 --- a/Rakefile +++ b/Rakefile @@ -1,29 +1,27 @@ -# encoding: utf-8 # frozen_string_literal: true -require 'rubygems' -require 'bundler' +require "rubygems" +require "bundler" begin Bundler.setup(:default, :development) rescue Bundler::BundlerError => e - $stderr.puts e.message - $stderr.puts "Run `bundle install` to install missing gems" + warn e.message + warn "Run `bundle install` to install missing gems" exit e.status_code end -require 'rake' -require 'bundler/gem_tasks' +require "rake" +require "bundler/gem_tasks" -require 'rspec/core' -require 'rspec/core/rake_task' +require "rspec/core" +require "rspec/core/rake_task" RSpec::Core::RakeTask.new(:spec) do |spec| - spec.pattern = FileList['spec/**/*_spec.rb'] + spec.pattern = FileList["spec/**/*_spec.rb"] end RSpec::Core::RakeTask.new(:rcov) do |spec| - spec.pattern = 'spec/**/*_spec.rb' + spec.pattern = "spec/**/*_spec.rb" spec.rcov = true end task default: :spec - diff --git a/datagrid.gemspec b/datagrid.gemspec index 44299c9..662bdee 100644 --- a/datagrid.gemspec +++ b/datagrid.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |s| "LICENSE.txt", "CHANGELOG.md", "Readme.markdown", - "datagrid.gemspec", + "datagrid.gemspec" ] s.files += `git ls-files | grep -E '^(app|lib|templates)'`.split("\n") s.homepage = "https://github.com/bogdan/datagrid" @@ -29,9 +29,8 @@ Gem::Specification.new do |s| "bug_tracker_uri" => "#{s.homepage}/issues", "documentation_uri" => "#{s.homepage}/wiki", "changelog_uri" => "#{s.homepage}/blob/master/CHANGELOG.md", - "source_code_uri" => s.homepage, + "source_code_uri" => s.homepage } s.add_dependency "railties", ">= 6.1" end - diff --git a/gemfiles/rails_6.1.gemfile b/gemfiles/rails_6.1.gemfile index d92e1f4..512aa8a 100644 --- a/gemfiles/rails_6.1.gemfile +++ b/gemfiles/rails_6.1.gemfile @@ -8,10 +8,10 @@ group :development do gem "csv" gem "nokogiri" gem "pry-byebug" + gem "rails", "~> 6.1.0" gem "rspec" gem "sequel" gem "sqlite3", "~> 1.7.0" - gem "rails", "~> 6.1.0" group :mongo do gem "bson" diff --git a/gemfiles/rails_7.0.gemfile b/gemfiles/rails_7.0.gemfile index 92a7e74..61566c8 100644 --- a/gemfiles/rails_7.0.gemfile +++ b/gemfiles/rails_7.0.gemfile @@ -8,10 +8,10 @@ group :development do gem "csv" gem "nokogiri" gem "pry-byebug" + gem "rails", "~> 7.0.0" gem "rspec" gem "sequel" gem "sqlite3", "~> 1.7.0" - gem "rails", "~> 7.0.0" group :mongo do gem "bson" diff --git a/gemfiles/rails_7.1.gemfile b/gemfiles/rails_7.1.gemfile index ab3907f..bdd7ff4 100644 --- a/gemfiles/rails_7.1.gemfile +++ b/gemfiles/rails_7.1.gemfile @@ -8,10 +8,10 @@ group :development do gem "csv" gem "nokogiri" gem "pry-byebug" + gem "rails", "~> 7.1.0" gem "rspec" gem "sequel" gem "sqlite3", "~> 1.7.0" - gem "rails", "~> 7.1.0" group :mongo do gem "bson" diff --git a/gemfiles/rails_7.2.gemfile b/gemfiles/rails_7.2.gemfile index d1385b0..753268c 100644 --- a/gemfiles/rails_7.2.gemfile +++ b/gemfiles/rails_7.2.gemfile @@ -8,10 +8,10 @@ group :development do gem "csv" gem "nokogiri" gem "pry-byebug" + gem "rails", "~> 7.2.0" gem "rspec" gem "sequel" gem "sqlite3", "~> 2.0.0" - gem "rails", "~> 7.2.0" group :mongo do gem "bson" diff --git a/lib/datagrid.rb b/lib/datagrid.rb index b8fb9aa..82abe93 100644 --- a/lib/datagrid.rb +++ b/lib/datagrid.rb @@ -3,7 +3,6 @@ require "datagrid/engine" module Datagrid - extend ActiveSupport::Autoload autoload :Core @@ -24,24 +23,19 @@ module Datagrid # @!visibility private def self.included(base) base.class_eval do - include ::Datagrid::Core include ::Datagrid::ActiveModel include ::Datagrid::Filters include ::Datagrid::Columns include ::Datagrid::ColumnNamesAttribute include ::Datagrid::Ordering - end end class ConfigurationError < StandardError; end class ArgumentError < ::ArgumentError; end class ColumnUnavailableError < StandardError; end - end require "datagrid/scaffold" -I18n.load_path << File.expand_path('../datagrid/locale/en.yml', __FILE__) - - +I18n.load_path << File.expand_path("datagrid/locale/en.yml", __dir__) diff --git a/lib/datagrid/active_model.rb b/lib/datagrid/active_model.rb index deb7184..5284711 100644 --- a/lib/datagrid/active_model.rb +++ b/lib/datagrid/active_model.rb @@ -3,15 +3,15 @@ module Datagrid module ActiveModel # @!visibility private def self.included(base) - base.extend ClassMethods + base.extend ClassMethods base.class_eval do begin - require 'active_model/naming' + require "active_model/naming" extend ::ActiveModel::Naming rescue LoadError end begin - require 'active_model/attributes_assignment' + require "active_model/attributes_assignment" extend ::ActiveModel::AttributesAssignment rescue LoadError end @@ -21,7 +21,7 @@ def self.included(base) module ClassMethods # @return [String] URL query parameter name of the grid class def param_name - self.to_s.underscore.tr('/', '_') + to_s.underscore.tr("/", "_") end end @@ -48,7 +48,7 @@ def to_model end def to_param - self.param_name + param_name end end end diff --git a/lib/datagrid/column_names_attribute.rb b/lib/datagrid/column_names_attribute.rb index ae1a344..c04027c 100644 --- a/lib/datagrid/column_names_attribute.rb +++ b/lib/datagrid/column_names_attribute.rb @@ -31,7 +31,7 @@ def column_names_filter(**options) select: :optional_columns_select, multiple: true, dummy: true, - **options, + **options ) end end @@ -45,7 +45,7 @@ def columns(*args, **options) # If no mandatory columns specified than all of them considered mandatory # @return [Array<Datagrid::Columns::Column>] def mandatory_columns - available_columns.select {|c| c.mandatory? } + available_columns.select { |c| c.mandatory? } end # Returns a list of enabled columns without <tt>mandatory: true</tt> option @@ -58,7 +58,7 @@ def optional_columns protected def optional_columns_select - optional_columns.map {|c| [c.header, c.name] } + optional_columns.map { |c| [c.header, c.name] } end def selected_column_names(*args) @@ -68,12 +68,10 @@ def selected_column_names(*args) column.is_a?(Datagrid::Columns::Column) ? column.name : column.to_sym end args + elsif column_names && column_names.any? + column_names + mandatory_columns.map(&:name) else - if column_names && column_names.any? - column_names + mandatory_columns.map(&:name) - else - columns_enabled_by_default.map(&:name) - end + columns_enabled_by_default.map(&:name) end end @@ -88,4 +86,3 @@ def columns_enabled_by_default end end end - diff --git a/lib/datagrid/columns.rb b/lib/datagrid/columns.rb index b8bba41..d2fd850 100644 --- a/lib/datagrid/columns.rb +++ b/lib/datagrid/columns.rb @@ -2,7 +2,6 @@ require "active_support/core_ext/class/attribute" module Datagrid - module Columns require "datagrid/columns/column" @@ -34,7 +33,7 @@ module Columns # @visibility private def self.included(base) - base.extend ClassMethods + base.extend ClassMethods base.class_eval do include Datagrid::Core @@ -47,7 +46,6 @@ def self.included(base) end module ClassMethods - # @param data [Boolean] if true returns only columns with data representation. Default: false. # @param html [Boolean] if true returns only columns with html columns. Default: false. # @param column_names [Array<String>] list of column names if you want to limit data only to specified columns @@ -146,23 +144,25 @@ def decorate(model = nil, &block) end return self.decorator = block unless model return model unless decorator + presenter = ::Datagrid::Utils.apply_args(model, &decorator) - presenter = presenter.is_a?(Class) ? presenter.new(model) : presenter + presenter = presenter.is_a?(Class) ? presenter.new(model) : presenter block_given? ? yield(presenter) : presenter end # @!visibility private def inherited(child_class) super(child_class) - child_class.columns_array = self.columns_array.clone + child_class.columns_array = columns_array.clone end # @!visibility private def filter_columns(columns_array, *names, data: false, html: false) names.compact! - if names.size >= 1 && names.all? {|n| n.is_a?(Datagrid::Columns::Column) && n.grid_class == self.class} + if names.size >= 1 && names.all? { |n| n.is_a?(Datagrid::Columns::Column) && n.grid_class == self.class } return names end + names.map!(&:to_sym) columns_array.select do |column| (!data || column.data?) && @@ -186,13 +186,13 @@ def define_column(columns, name, query = nil, **options, &block) end # @!visibility private - def find_column_by_name(columns,name) + def find_column_by_name(columns, name) return name if name.is_a?(Datagrid::Columns::Column) + columns.find do |col| col.name.to_sym == name.to_sym end end - end # @!visibility private @@ -223,7 +223,7 @@ def row_for(asset, *column_names) # @return [Hash] A mapping where keys are column names and values are column values for the given asset def hash_for(asset) result = {} - self.data_columns.each do |column| + data_columns.each do |column| result[column.name] = data_value(column, asset) end result @@ -233,14 +233,14 @@ def hash_for(asset) # @return [Array<Array<Object>>] with data for each row in datagrid assets without header def rows(*column_names) map_with_batches do |asset| - self.row_for(asset, *column_names) + row_for(asset, *column_names) end end # @param column_names [Array<String>] list of column names if you want to limit data only to specified columns # @return [Array<Array<Object>>] data for each row in datagrid assets with header. def data(*column_names) - self.rows(*column_names).unshift(self.header(*column_names)) + rows(*column_names).unshift(header(*column_names)) end # @return [Array<{Symbol => Object}>] an array of hashes representing the rows in the filtered datagrid relation @@ -273,7 +273,7 @@ def data_hash def to_csv(*column_names, **options) require "csv" CSV.generate( - headers: self.header(*column_names), + headers: header(*column_names), write_headers: true, **options ) do |csv| @@ -283,7 +283,6 @@ def to_csv(*column_names, **options) end end - # @param column_names [Array<Symbol, String>] # @return [Array<Datagrid::Columns::Column>] all columns selected in grid instance # @example @@ -302,13 +301,13 @@ def columns(*column_names, data: false, html: false) # @param column_names [Array<String, Symbol>] list of column names if you want to limit data only to specified columns # @return [Array<Datagrid::Columns::Column>] columns that can be represented in plain data(non-html) way def data_columns(*column_names, **options) - self.columns(*column_names, **options, data: true) + columns(*column_names, **options, data: true) end # @param column_names [Array<String>] list of column names if you want to limit data only to specified columns # @return all columns that can be represented in HTML table def html_columns(*column_names, **options) - self.columns(*column_names, **options, html: true) + columns(*column_names, **options, html: true) end # Finds a column definition by name @@ -401,6 +400,7 @@ def data_value(column_name, asset) column = column_by_name(column_name) cache(column, asset, :data_value) do raise "no data value for #{column.name} column" unless column.data? + result = generic_value(column, asset) result.is_a?(Datagrid::Columns::Column::ResponseFormat) ? result.call_data : result end @@ -408,7 +408,7 @@ def data_value(column_name, asset) # @return [Object] a cell HTML value for given column name and asset and view context def html_value(column_name, context, asset) - column = column_by_name(column_name) + column = column_by_name(column_name) cache(column, asset, :html_value) do if column.html? && column.html_block value_from_html_block(context, asset, column) @@ -461,9 +461,8 @@ def cache(column, asset, type) return yield end key = cache_key(asset) - unless key - raise(Datagrid::CacheKeyError, "Datagrid Cache key is #{key.inspect} for #{asset.inspect}.") - end + raise(Datagrid::CacheKeyError, "Datagrid Cache key is #{key.inspect} for #{asset.inspect}.") unless key + @cache[column.name] ||= {} @cache[column.name][key] ||= {} @cache[column.name][key][type] ||= yield @@ -476,10 +475,10 @@ def cache_key(asset) driver.default_cache_key(asset) end rescue NotImplementedError - raise Datagrid::ConfigurationError, "#{self} is setup to use cache. But there was appropriate cache key found for #{asset.inspect}. Please set cached option to block with asset as argument and cache key as returning value to resolve the issue." + raise Datagrid::ConfigurationError, + "#{self} is setup to use cache. But there was appropriate cache key found for #{asset.inspect}. Please set cached option to block with asset as argument and cache key as returning value to resolve the issue." end - def map_with_batches(&block) result = [] each_with_batches do |asset| @@ -522,7 +521,7 @@ def initialize(grid, model) @model = model end - def method_missing(meth, *args, &blk) + def method_missing(meth, *_args) @grid.data_value(meth, @model) end end diff --git a/lib/datagrid/columns/column.rb b/lib/datagrid/columns/column.rb index 7236202..1d50c40 100644 --- a/lib/datagrid/columns/column.rb +++ b/lib/datagrid/columns/column.rb @@ -1,9 +1,7 @@ class Datagrid::Columns::Column - # Datagrid class holding an information of # how a column should be rendered in data/console/csv format and HTML format class ResponseFormat - attr_accessor :data_block, :html_block def initialize @@ -42,9 +40,7 @@ def initialize(grid_class, name, query, options = {}, &block) else self.data_block = block - if options[:html].is_a? Proc - self.html_block = options[:html] - end + self.html_block = options[:html] if options[:html].is_a? Proc end self.query = query end @@ -54,9 +50,8 @@ def data_value(model, grid) grid.data_value(name, model) end - def label - self.options[:label] + options[:label] end def header @@ -69,7 +64,7 @@ def header def order if options.has_key?(:order) && options[:order] != true - self.options[:order] + options[:order] else driver.default_order(grid_class.scope, name) end @@ -88,12 +83,13 @@ def order_by_value(model, grid) end def order_by_value? - !! options[:order_by_value] + !!options[:order_by_value] end def order_desc return nil unless order - self.options[:order_desc] + + options[:order_desc] end def html? @@ -101,11 +97,11 @@ def html? end def data? - self.data_block != nil + data_block != nil end def mandatory? - !! options[:mandatory] + !!options[:mandatory] end def mandatory_explicitly_set? @@ -128,15 +124,16 @@ def html_value(context, asset, grid) grid.html_value(name, context, asset) end - def generic_value(model, grid) grid.generic_value(self, model) end def append_preload(relation) return relation unless preload + if preload.respond_to?(:call) return relation unless preload + if preload.arity == 1 preload.call(relation) else @@ -155,7 +152,6 @@ def preload else preload end - end def driver diff --git a/lib/datagrid/configuration.rb b/lib/datagrid/configuration.rb index 0032c2b..65a1653 100644 --- a/lib/datagrid/configuration.rb +++ b/lib/datagrid/configuration.rb @@ -1,5 +1,4 @@ module Datagrid - def self.configuration @configuration ||= Configuration.new end diff --git a/lib/datagrid/core.rb b/lib/datagrid/core.rb index 4444aca..0f560a4 100644 --- a/lib/datagrid/core.rb +++ b/lib/datagrid/core.rb @@ -18,21 +18,20 @@ def self.included(base) end module ClassMethods - # @!visibility private def datagrid_attribute(name, &block) - unless datagrid_attributes.include?(name) - block ||= lambda do |value| - value - end - datagrid_attributes << name - define_method name do - instance_variable_get("@#{name}") - end + return if datagrid_attributes.include?(name) - define_method :"#{name}=" do |value| - instance_variable_set("@#{name}", instance_exec(value, &block)) - end + block ||= lambda do |value| + value + end + datagrid_attributes << name + define_method name do + instance_variable_get("@#{name}") + end + + define_method :"#{name}=" do |value| + instance_variable_set("@#{name}", instance_exec(value, &block)) end end @@ -117,9 +116,8 @@ def check_scope_defined!(message = nil) def inherited(child_class) super(child_class) - child_class.datagrid_attributes = self.datagrid_attributes.clone + child_class.datagrid_attributes = datagrid_attributes.clone end - end # @param [{String, Symbol => Object}, nil] attributes a hash of attributes to initialize the object @@ -128,21 +126,18 @@ def inherited(child_class) def initialize(attributes = nil, &block) super() - if attributes - self.attributes = attributes - end + self.attributes = attributes if attributes instance_eval(&dynamic_block) if dynamic_block - if block_given? - self.scope(&block) - end - end + return unless block_given? + scope(&block) + end # @return [Hash<Symbol, Object>] grid attributes including filter values and ordering values def attributes result = {} - self.datagrid_attributes.each do |name| + datagrid_attributes.each do |name| result[name] = self[name] end result @@ -161,7 +156,7 @@ def attributes=(attributes) # @return [Object] Any datagrid attribute value def [](attribute) - self.public_send(attribute) + public_send(attribute) end # Assigns any datagrid attribute @@ -169,7 +164,7 @@ def [](attribute) # @param value [Object] Datagrid attribute value # @return [void] def []=(attribute, value) - self.public_send(:"#{attribute}=", value) + public_send(:"#{attribute}=", value) end # @return [Object] a scope relation (e.g ActiveRecord::Relation) with all applied filters @@ -270,6 +265,7 @@ def reset end protected + def sanitize_for_mass_assignment(attributes) forbidden_attributes_protection ? super(attributes) : attributes end diff --git a/lib/datagrid/drivers.rb b/lib/datagrid/drivers.rb index 6194337..3e72d3f 100644 --- a/lib/datagrid/drivers.rb +++ b/lib/datagrid/drivers.rb @@ -5,7 +5,6 @@ require "datagrid/drivers/mongo_mapper" require "datagrid/drivers/sequel" - module Datagrid # @!visibility private module Drivers diff --git a/lib/datagrid/drivers/abstract_driver.rb b/lib/datagrid/drivers/abstract_driver.rb index bf9d940..99530a8 100644 --- a/lib/datagrid/drivers/abstract_driver.rb +++ b/lib/datagrid/drivers/abstract_driver.rb @@ -2,18 +2,17 @@ module Datagrid module Drivers # @!visibility private class AbstractDriver - TIMESTAMP_CLASSES = [DateTime, Time, ActiveSupport::TimeWithZone] class_attribute :subclasses, default: [] def self.inherited(base) super(base) - self.subclasses << base + subclasses << base end def self.guess_driver(scope) - self.subclasses.find do |driver_class| + subclasses.find do |driver_class| driver_class.match?(scope) end || raise(Datagrid::ConfigurationError, "ORM Driver not found for scope: #{scope.inspect}.") end @@ -83,11 +82,9 @@ def batch_each(scope, batch_size, &block) end def append_column_queries(assets, columns) - if columns.present? - raise NotImplementedError - else - assets - end + raise NotImplementedError if columns.present? + + assets end def default_cache_key(asset) @@ -96,12 +93,8 @@ def default_cache_key(asset) def where_by_timestamp_gotcha(scope, name, value) value = Datagrid::Utils.format_date_as_timestamp(value) - if value.first - scope = greater_equal(scope, name, value.first) - end - if value.last - scope = less_equal(scope, name, value.last) - end + scope = greater_equal(scope, name, value.first) if value.first + scope = less_equal(scope, name, value.last) if value.last scope end @@ -114,6 +107,7 @@ def can_preload?(scope, association) end protected + def timestamp_class?(klass) TIMESTAMP_CLASSES.include?(klass) end diff --git a/lib/datagrid/drivers/active_record.rb b/lib/datagrid/drivers/active_record.rb index 25224e3..3135df8 100644 --- a/lib/datagrid/drivers/active_record.rb +++ b/lib/datagrid/drivers/active_record.rb @@ -2,9 +2,9 @@ module Datagrid module Drivers # @!visibility private class ActiveRecord < AbstractDriver - def self.match?(scope) return false unless defined?(::ActiveRecord) + if scope.is_a?(Class) scope.ancestors.include?(::ActiveRecord::Base) else @@ -14,6 +14,7 @@ def self.match?(scope) def to_scope(scope) return scope if scope.is_a?(::ActiveRecord::Relation) + # Model class or Active record association # ActiveRecord association class hides itself under an Array # We can only reveal it by checking if it respond to some specific @@ -32,7 +33,7 @@ def append_column_queries(assets, columns) if assets.select_values.empty? assets = assets.select(Arel.respond_to?(:star) ? assets.klass.arel_table[Arel.star] : "#{assets.quoted_table_name}.*") end - columns = columns.map {|c| "#{c.query} AS #{c.name}"} + columns = columns.map { |c| "#{c.query} AS #{c.name}" } assets = assets.select(*columns) end assets @@ -89,13 +90,14 @@ def contains(scope, field, value) def normalized_column_type(scope, field) return nil unless has_column?(scope, field) + builtin_type = scope.columns_hash[field.to_s].type { - [:string, :text, :time, :binary] => :string, - [:integer, :primary_key] => :integer, - [:float, :decimal] => :float, + %i[string text time binary] => :string, + %i[integer primary_key] => :integer, + %i[float decimal] => :float, [:date] => :date, - [:datetime, :timestamp] => :timestamp, + %i[datetime timestamp] => :timestamp, [:boolean] => :boolean }.each do |keys, value| return value if keys.include?(builtin_type) @@ -106,6 +108,7 @@ def batch_each(scope, batch_size, &block) if scope.limit_value raise Datagrid::ConfigurationError, "ActiveRecord can not use batches in combination with SQL limit" end + options = batch_size ? { batch_size: batch_size } : {} scope.find_each(**options, &block) end @@ -119,19 +122,22 @@ def default_preload(scope, value) end def can_preload?(scope, association) - !! scope.klass.reflect_on_association(association) + !!scope.klass.reflect_on_association(association) end protected def prefix_table_name(scope, field) - has_column?(scope, field) ? [scope.table_name, field].join(".") : field + has_column?(scope, field) ? [scope.table_name, field].join(".") : field end def contains_predicate - defined?(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) && - ::ActiveRecord::Base.connection.is_a?(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) ? - 'ilike' : 'like' + if defined?(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) && + ::ActiveRecord::Base.connection.is_a?(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) + "ilike" + else + "like" + end end end end diff --git a/lib/datagrid/drivers/array.rb b/lib/datagrid/drivers/array.rb index 99d320c..3d2da1d 100644 --- a/lib/datagrid/drivers/array.rb +++ b/lib/datagrid/drivers/array.rb @@ -2,7 +2,6 @@ module Datagrid module Drivers # @!visibility private class Array < AbstractDriver - def self.match?(scope) !Datagrid::Drivers::ActiveRecord.match?(scope) && ( scope.is_a?(::Array) || scope.is_a?(Enumerator) || @@ -23,6 +22,7 @@ def where(scope, attribute, value) def asc(scope, order) return scope unless order return scope if order.empty? + scope.sort_by do |object| get(object, order) end @@ -32,7 +32,7 @@ def desc(scope, order) asc(scope, order).reverse end - def default_order(scope, column_name) + def default_order(_scope, column_name) column_name end @@ -67,11 +67,11 @@ def contains(scope, field, value) end end - def column_names(scope) + def column_names(_scope) [] end - def batch_each(scope, batch_size, &block) + def batch_each(scope, _batch_size, &block) scope.each(&block) end @@ -79,7 +79,7 @@ def default_cache_key(asset) asset end - def can_preload?(scope, association) + def can_preload?(_scope, _association) false end diff --git a/lib/datagrid/drivers/mongo_mapper.rb b/lib/datagrid/drivers/mongo_mapper.rb index 6d7d55b..e36fa51 100644 --- a/lib/datagrid/drivers/mongo_mapper.rb +++ b/lib/datagrid/drivers/mongo_mapper.rb @@ -2,9 +2,9 @@ module Datagrid module Drivers # @!visibility private class MongoMapper < AbstractDriver - def self.match?(scope) return false unless defined?(::MongoMapper) + if scope.is_a?(Class) scope.ancestors.include?(::MongoMapper::Document) else @@ -33,27 +33,27 @@ def default_order(scope, column_name) end def greater_equal(scope, field, value) - scope.where(field => {"$gte" => value}) + scope.where(field => { "$gte" => value }) end def less_equal(scope, field, value) - scope.where(field => {"$lte" => value}) + scope.where(field => { "$lte" => value }) end def has_column?(scope, column_name) scope.key?(column_name) end - def is_timestamp?(scope, column_name) - #TODO implement the support + def is_timestamp?(_scope, _column_name) + # TODO: implement the support false end - def contains(scope, field, value) + def contains(_scope, field, value) scope(field => Regexp.compile(Regexp.escape(value))) end - def column_names(scope) + def column_names(_scope) [] # TODO: implement support end @@ -62,10 +62,9 @@ def batch_each(scope, batch_size, &block) loop do batch = scope.skip(current_page * batch_size).limit(batch_size).to_a return if batch.empty? - scope.skip(current_page * batch_size).limit(batch_size).each do |item| - yield(item) - end - current_page+=1 + + scope.skip(current_page * batch_size).limit(batch_size).each(&block) + current_page += 1 end end @@ -77,7 +76,7 @@ def default_preload(scope, value) raise NotImplementedError end - def can_preload?(scope, association) + def can_preload?(_scope, _association) false end end diff --git a/lib/datagrid/drivers/mongoid.rb b/lib/datagrid/drivers/mongoid.rb index 5bb30c2..c737ff4 100644 --- a/lib/datagrid/drivers/mongoid.rb +++ b/lib/datagrid/drivers/mongoid.rb @@ -2,9 +2,9 @@ module Datagrid module Drivers # @!visibility private class Mongoid < AbstractDriver - def self.match?(scope) return false unless defined?(::Mongoid) + if scope.is_a?(Class) scope.ancestors.include?(::Mongoid::Document) else @@ -21,9 +21,7 @@ def to_scope(scope) end def where(scope, attribute, value) - if value.is_a?(Range) - value = {"$gte" => value.first, "$lte" => value.last} - end + value = { "$gte" => value.first, "$lte" => value.last } if value.is_a?(Range) scope.where(attribute => value) end @@ -40,11 +38,11 @@ def default_order(scope, column_name) end def greater_equal(scope, field, value) - scope.where(field => {"$gte" => value}) + scope.where(field => { "$gte" => value }) end def less_equal(scope, field, value) - scope.where(field => {"$lte" => value}) + scope.where(field => { "$lte" => value }) end def has_column?(scope, column_name) @@ -62,8 +60,9 @@ def column_names(scope) def normalized_column_type(scope, field) type = to_scope(scope).klass.fields[field.to_s]&.type return nil unless type + { - [BigDecimal , String, Symbol, Range, Array, Hash, ] => :string, + [BigDecimal, String, Symbol, Range, Array, Hash] => :string, [::Mongoid::Boolean] => :boolean, [Date] => :date, @@ -72,11 +71,11 @@ def normalized_column_type(scope, field) [Float] => :float, - [Integer] => :integer, + [Integer] => :integer }.each do |keys, value| return value if keys.include?(type) end - return :string + :string end def batch_each(scope, batch_size, &block) @@ -84,10 +83,9 @@ def batch_each(scope, batch_size, &block) loop do batch = scope.skip(current_page * batch_size).limit(batch_size).to_a return if batch.empty? - scope.skip(current_page * batch_size).limit(batch_size).each do |item| - yield(item) - end - current_page+=1 + + scope.skip(current_page * batch_size).limit(batch_size).each(&block) + current_page += 1 end end @@ -100,10 +98,8 @@ def default_preload(scope, value) end def can_preload?(scope, association) - !! scope.klass.reflect_on_association(association) + !!scope.klass.reflect_on_association(association) end - end end end - diff --git a/lib/datagrid/drivers/sequel.rb b/lib/datagrid/drivers/sequel.rb index 4ca8716..ce603b8 100644 --- a/lib/datagrid/drivers/sequel.rb +++ b/lib/datagrid/drivers/sequel.rb @@ -2,9 +2,9 @@ module Datagrid module Drivers # @!visibility private class Sequel < AbstractDriver - def self.match?(scope) return false unless defined?(::Sequel) + if scope.is_a?(Class) scope.ancestors.include?(::Sequel::Model) else @@ -14,6 +14,7 @@ def self.match?(scope) def to_scope(scope) return scope if scope.is_a?(::Sequel::Dataset) + scope.where({}) end @@ -38,7 +39,7 @@ def reverse_order(scope) end def default_order(scope, column_name) - has_column?(scope, column_name) ? ::Sequel.lit(prefix_table_name(scope, column_name)) : nil + has_column?(scope, column_name) ? ::Sequel.lit(prefix_table_name(scope, column_name)) : nil end def greater_equal(scope, field, value) @@ -65,10 +66,11 @@ def contains(scope, field, value) def normalized_column_type(scope, field) type = column_type(scope, field) return nil unless type + { - [:string, :blob, :time] => :string, - [:integer, :primary_key] => :integer, - [:float, :decimal] => :float, + %i[string blob time] => :string, + %i[integer primary_key] => :integer, + %i[float decimal] => :float, [:date] => :date, [:datetime] => :timestamp, [:boolean] => :boolean @@ -96,14 +98,13 @@ def default_preload(scope, value) end def can_preload?(scope, association) - !! scope.model.association_reflection(association) + !!scope.model.association_reflection(association) end - protected def prefix_table_name(scope, field) - has_column?(scope, field) ? [to_scope(scope).row_proc.table_name, field].join(".") : field + has_column?(scope, field) ? [to_scope(scope).row_proc.table_name, field].join(".") : field end def column_type(scope, field) diff --git a/lib/datagrid/engine.rb b/lib/datagrid/engine.rb index 11ae96b..b37dd4e 100644 --- a/lib/datagrid/engine.rb +++ b/lib/datagrid/engine.rb @@ -1,6 +1,6 @@ require "rails/engine" -require 'datagrid/helper' -require 'datagrid/form_builder' +require "datagrid/helper" +require "datagrid/form_builder" module Datagrid # @!private @@ -15,6 +15,5 @@ def self.extend_modules Engine.extend_modules end end - end end diff --git a/lib/datagrid/filters.rb b/lib/datagrid/filters.rb index a453f1b..3283c81 100644 --- a/lib/datagrid/filters.rb +++ b/lib/datagrid/filters.rb @@ -2,7 +2,6 @@ module Datagrid module Filters - require "datagrid/filters/base_filter" require "datagrid/filters/enum_filter" require "datagrid/filters/extended_boolean_filter" @@ -22,8 +21,8 @@ module Filters datetime: Filters::DateTimeFilter, string: Filters::StringFilter, default: Filters::DefaultFilter, - xboolean: Filters::ExtendedBooleanFilter , - boolean: Filters::BooleanFilter , + xboolean: Filters::ExtendedBooleanFilter, + boolean: Filters::BooleanFilter, integer: Filters::IntegerFilter, enum: Filters::EnumFilter, float: Filters::FloatFilter, @@ -37,25 +36,23 @@ module Filters def self.included(base) base.extend ClassMethods base.class_eval do - include Datagrid::Core include Datagrid::Filters::CompositeFilters class_attribute :filters_array, default: [] - end end module ClassMethods - # @return [Datagrid::Filters::BaseFilter, nil] filter definition object by name def filter_by_name(attribute) if attribute.is_a?(Datagrid::Filters::BaseFilter) unless ancestors.include?(attribute.grid_class) raise ArgumentError, "#{attribute.grid_class}##{attribute.name} filter doen't belong to #{self.class}" end + return attribute end - self.filters.find do |filter| + filters.find do |filter| filter.name == attribute.to_sym end end @@ -129,11 +126,12 @@ def filters def inherited(child_class) super(child_class) - child_class.filters_array = self.filters_array.clone + child_class.filters_array = filters_array.clone end def filters_inspection return "no filters" if filters.empty? + filters.map do |filter| "#{filter.name}: #{filter.type}" end.join(", ") @@ -143,7 +141,7 @@ def filters_inspection # @!visibility private def initialize(*args, &block) self.filters_array = self.class.filters_array.clone - self.filters_array.each do |filter| + filters_array.each do |filter| self[filter.name] = filter.default(self) end super(*args, &block) @@ -164,7 +162,7 @@ def filter_value_as_string(name) filter = filter_by_name(name) value = filter_value(filter) if value.is_a?(Array) - value.map {|v| filter.format(v) }.join(filter.separator) + value.map { |v| filter.format(v) }.join(filter.separator) else filter.format(value) end @@ -177,7 +175,7 @@ def filter_by_name(name) # @return [Array<Object>] assets filtered only by specified filters def filter_by(*filters) - apply_filters(scope, filters.map{|f| filter_by_name(f)}) + apply_filters(scope, filters.map { |f| filter_by_name(f) }) end # @return [Array] the select options for the filter @@ -215,7 +213,7 @@ def find_select_filter(filter) filter = filter_by_name(filter) unless filter.class.included_modules.include?(::Datagrid::Filters::SelectOptions) raise ::Datagrid::ArgumentError, - "#{self.class.name}##{filter.name} with type #{FILTER_TYPES.invert[filter.class].inspect} can not have select options" + "#{self.class.name}##{filter.name} with type #{FILTER_TYPES.invert[filter.class].inspect} can not have select options" end filter end diff --git a/lib/datagrid/filters/base_filter.rb b/lib/datagrid/filters/base_filter.rb index 710d244..608e8d9 100644 --- a/lib/datagrid/filters/base_filter.rb +++ b/lib/datagrid/filters/base_filter.rb @@ -5,7 +5,6 @@ class Datagrid::FilteringError < StandardError # @!visibility private class Datagrid::Filters::BaseFilter - class_attribute :input_helper_name, instance_writer: false attr_accessor :grid_class, :options, :block, :name @@ -30,11 +29,11 @@ def apply(grid_object, scope, value) result = execute(value, scope, grid_object) return scope unless result - if result == Datagrid::Filters::DEFAULT_FILTER_BLOCK - result = default_filter(value, scope, grid_object) - end + + result = default_filter(value, scope, grid_object) if result == Datagrid::Filters::DEFAULT_FILTER_BLOCK unless grid_object.driver.match?(result) - raise Datagrid::FilteringError, "Can not apply #{name.inspect} filter: result #{result.inspect} no longer match #{grid_object.driver.class}." + raise Datagrid::FilteringError, + "Can not apply #{name.inspect} filter: result #{result.inspect} no longer match #{grid_object.driver.class}." end result @@ -43,6 +42,7 @@ def apply(grid_object, scope, value) def parse_values(value) if multiple? return nil if value.nil? + normalize_multiple_value(value).map do |v| parse(v) end @@ -66,7 +66,7 @@ def header end def default(object) - default = self.options[:default] + default = options[:default] if default.is_a?(Symbol) object.send(default) elsif default.respond_to?(:call) @@ -77,7 +77,7 @@ def default(object) end def multiple? - self.options[:multiple] + options[:multiple] end def allow_nil? @@ -101,7 +101,7 @@ def form_builder_helper_name end def self.form_builder_helper_name - :"datagrid_#{self.to_s.demodulize.underscore}" + :"datagrid_#{to_s.demodulize.underscore}" end def default_filter_block @@ -125,9 +125,7 @@ def dummy? def type Datagrid::Filters::FILTER_TYPES.each do |type, klass| - if is_a?(klass) - return type - end + return type if is_a?(klass) end raise "wtf is #{inspect}" end @@ -137,7 +135,7 @@ def enabled?(grid) end def default_html_classes - [ name, self.class.to_s.demodulize.underscore ] + [name, self.class.to_s.demodulize.underscore] end protected @@ -168,15 +166,16 @@ def normalize_multiple_value(value) end def default_separator - ',' + "," end def driver grid_class.driver end - def default_filter(value, scope, grid) + def default_filter(value, scope, _grid) return nil if dummy? + if !driver.has_column?(scope, name) && scope.respond_to?(name, true) scope.public_send(name, value) else @@ -184,4 +183,3 @@ def default_filter(value, scope, grid) end end end - diff --git a/lib/datagrid/filters/boolean_filter.rb b/lib/datagrid/filters/boolean_filter.rb index 554fad7..89aed9b 100644 --- a/lib/datagrid/filters/boolean_filter.rb +++ b/lib/datagrid/filters/boolean_filter.rb @@ -1,9 +1,7 @@ require "datagrid/utils" # @!visibility private class Datagrid::Filters::BooleanFilter < Datagrid::Filters::BaseFilter - def parse(value) Datagrid::Utils.booleanize(value) end - end diff --git a/lib/datagrid/filters/composite_filters.rb b/lib/datagrid/filters/composite_filters.rb index c81f358..3eb405a 100644 --- a/lib/datagrid/filters/composite_filters.rb +++ b/lib/datagrid/filters/composite_filters.rb @@ -2,22 +2,21 @@ module Datagrid module Filters # @!visibility private module CompositeFilters - def self.included(base) - base.extend ClassMethods + base.extend ClassMethods base.class_eval do end end # @!visibility private module ClassMethods - def date_range_filters(field, from_options = {}, to_options = {}) - Utils.warn_once('date_range_filters is deprecated in favor of range option for date filter') + Utils.warn_once("date_range_filters is deprecated in favor of range option for date filter") from_options = normalize_composite_filter_options(from_options, field) to_options = normalize_composite_filter_options(to_options, field) - filter(from_options[:name] || :"from_#{field.to_s.tr('.', '_')}", :date, **from_options) do |date, scope, grid| + filter(from_options[:name] || :"from_#{field.to_s.tr('.', '_')}", :date, + **from_options) do |date, scope, grid| grid.driver.greater_equal(scope, field, date) end filter(to_options[:name] || :"to_#{field.to_s.tr('.', '_')}", :date, **to_options) do |date, scope, grid| @@ -26,10 +25,11 @@ def date_range_filters(field, from_options = {}, to_options = {}) end def integer_range_filters(field, from_options = {}, to_options = {}) - Utils.warn_once('integer_range_filters is deprecated in favor of range option for integer filter') + Utils.warn_once("integer_range_filters is deprecated in favor of range option for integer filter") from_options = normalize_composite_filter_options(from_options, field) to_options = normalize_composite_filter_options(to_options, field) - filter(from_options[:name] || :"from_#{field.to_s.tr('.', '_')}", :integer, **from_options) do |value, scope, grid| + filter(from_options[:name] || :"from_#{field.to_s.tr('.', '_')}", :integer, + **from_options) do |value, scope, grid| grid.driver.greater_equal(scope, field, value) end filter(to_options[:name] || :"to_#{field.to_s.tr('.', '_')}", :integer, **to_options) do |value, scope, grid| @@ -37,10 +37,8 @@ def integer_range_filters(field, from_options = {}, to_options = {}) end end - def normalize_composite_filter_options(options, field) - if options.is_a?(String) || options.is_a?(Symbol) - options = {name: options} - end + def normalize_composite_filter_options(options, _field) + options = { name: options } if options.is_a?(String) || options.is_a?(Symbol) options end end diff --git a/lib/datagrid/filters/date_filter.rb b/lib/datagrid/filters/date_filter.rb index db9c1d4..f9f47c9 100644 --- a/lib/datagrid/filters/date_filter.rb +++ b/lib/datagrid/filters/date_filter.rb @@ -1,13 +1,10 @@ require "datagrid/filters/ranged_filter" class Datagrid::Filters::DateFilter < Datagrid::Filters::BaseFilter - include Datagrid::Filters::RangedFilter def apply(grid_object, scope, value) - if value.is_a?(Range) - value = value.begin&.beginning_of_day..value.end&.end_of_day - end + value = value.begin&.beginning_of_day..value.end&.end_of_day if value.is_a?(Range) super(grid_object, scope, value) end @@ -15,7 +12,6 @@ def parse(value) Datagrid::Utils.parse_date(value) end - def format(value) if formats.any? && value value.strftime(formats.first) @@ -25,9 +21,7 @@ def format(value) end def default_filter_where(scope, value) - if driver.is_timestamp?(scope, name) - value = Datagrid::Utils.format_date_as_timestamp(value) - end + value = Datagrid::Utils.format_date_as_timestamp(value) if driver.is_timestamp?(scope, name) super(scope, value) end @@ -37,4 +31,3 @@ def formats Array(Datagrid.configuration.date_formats) end end - diff --git a/lib/datagrid/filters/date_time_filter.rb b/lib/datagrid/filters/date_time_filter.rb index 50d1331..9809f32 100644 --- a/lib/datagrid/filters/date_time_filter.rb +++ b/lib/datagrid/filters/date_time_filter.rb @@ -1,7 +1,6 @@ require "datagrid/filters/ranged_filter" class Datagrid::Filters::DateTimeFilter < Datagrid::Filters::BaseFilter - include Datagrid::Filters::RangedFilter def parse(value) @@ -22,4 +21,3 @@ def formats Array(Datagrid.configuration.datetime_formats) end end - diff --git a/lib/datagrid/filters/dynamic_filter.rb b/lib/datagrid/filters/dynamic_filter.rb index f3d0d0b..c2b29d3 100644 --- a/lib/datagrid/filters/dynamic_filter.rb +++ b/lib/datagrid/filters/dynamic_filter.rb @@ -1,28 +1,27 @@ require "datagrid/filters/select_options" class Datagrid::Filters::DynamicFilter < Datagrid::Filters::BaseFilter - include Datagrid::Filters::SelectOptions - EQUAL_OPERATION = '=' - LIKE_OPERATION = '=~' - MORE_EQUAL_OPERATION = '>=' - LESS_EQUAL_OPERATION = '<=' + EQUAL_OPERATION = "=" + LIKE_OPERATION = "=~" + MORE_EQUAL_OPERATION = ">=" + LESS_EQUAL_OPERATION = "<=" DEFAULT_OPERATIONS = [ EQUAL_OPERATION, LIKE_OPERATION, MORE_EQUAL_OPERATION, - LESS_EQUAL_OPERATION, + LESS_EQUAL_OPERATION ] - AVAILABLE_OPERATIONS = %w(= =~ >= <=) + AVAILABLE_OPERATIONS = %w[= =~ >= <=] def initialize(*) super options[:select] ||= default_select options[:operations] ||= DEFAULT_OPERATIONS - unless options.has_key?(:include_blank) - options[:include_blank] = false - end + return if options.has_key?(:include_blank) + + options[:include_blank] = false end def parse_values(filter) @@ -41,36 +40,32 @@ def default_filter_where(scope, filter) date_conversion = value.is_a?(Date) && driver.is_timestamp?(scope, field) return scope if field.blank? || operation.blank? + unless operations.include?(operation) - raise Datagrid::FilteringError, "Unknown operation: #{operation.inspect}. Available operations: #{operations.join(' ')}" + raise Datagrid::FilteringError, + "Unknown operation: #{operation.inspect}. Available operations: #{operations.join(' ')}" end + case operation when EQUAL_OPERATION - if date_conversion - value = Datagrid::Utils.format_date_as_timestamp(value) - end + value = Datagrid::Utils.format_date_as_timestamp(value) if date_conversion driver.where(scope, field, value) when LIKE_OPERATION if column_type(field) == :string driver.contains(scope, field, value) else - if date_conversion - value = Datagrid::Utils.format_date_as_timestamp(value) - end + value = Datagrid::Utils.format_date_as_timestamp(value) if date_conversion driver.where(scope, field, value) end when MORE_EQUAL_OPERATION - if date_conversion - value = value.beginning_of_day - end + value = value.beginning_of_day if date_conversion driver.greater_equal(scope, field, value) when LESS_EQUAL_OPERATION - if date_conversion - value = value.end_of_day - end + value = value.end_of_day if date_conversion driver.less_equal(scope, field, value) else - raise Datagrid::FilteringError, "Unknown operation: #{operation.inspect}. Use filter block argument to implement operation" + raise Datagrid::FilteringError, + "Unknown operation: #{operation.inspect}. Use filter block argument to implement operation" end end @@ -87,11 +82,11 @@ def operations_select protected def default_select - proc {|grid| + proc { |grid| grid.driver.column_names(grid.scope).map do |name| # Mongodb/Rails problem: # '_id'.humanize returns '' - [name.gsub(/^_/, '').humanize.strip, name] + [name.gsub(/^_/, "").humanize.strip, name] end } end @@ -99,6 +94,7 @@ def default_select def type_cast(field, value) type = column_type(field) return nil if value.blank? + case type when :string value.to_s diff --git a/lib/datagrid/filters/enum_filter.rb b/lib/datagrid/filters/enum_filter.rb index 809d10c..bc65cc6 100644 --- a/lib/datagrid/filters/enum_filter.rb +++ b/lib/datagrid/filters/enum_filter.rb @@ -1,25 +1,23 @@ require "datagrid/filters/select_options" class Datagrid::Filters::EnumFilter < Datagrid::Filters::BaseFilter - include Datagrid::Filters::SelectOptions def initialize(*args) super(*args) - if checkboxes? - options[:multiple] = true - end + options[:multiple] = true if checkboxes? raise Datagrid::ConfigurationError, ":select option not specified" unless options[:select] end def parse(value) - return nil if self.strict && !select.include?(value) + return nil if strict && !select.include?(value) + value end def default_html_classes res = super - res.push('checkboxes') if checkboxes? + res.push("checkboxes") if checkboxes? res end @@ -30,5 +28,4 @@ def strict def checkboxes? options[:checkboxes] end - end diff --git a/lib/datagrid/filters/extended_boolean_filter.rb b/lib/datagrid/filters/extended_boolean_filter.rb index cdad91a..521cf5e 100644 --- a/lib/datagrid/filters/extended_boolean_filter.rb +++ b/lib/datagrid/filters/extended_boolean_filter.rb @@ -1,10 +1,9 @@ # @!visibility private class Datagrid::Filters::ExtendedBooleanFilter < Datagrid::Filters::EnumFilter - YES = "YES" NO = "NO" - TRUTH_VALUES = [true, 'true', "y", "yes"] - FALSE_VALUES = [false, 'false', "n", "no"] + TRUTH_VALUES = [true, "true", "y", "yes"] + FALSE_VALUES = [false, "false", "n", "no"] def initialize(report, attribute, options = {}, &block) options[:select] = -> { boolean_select } @@ -33,7 +32,7 @@ def parse(value) protected def boolean_select - [YES, NO].map do |key, value| + [YES, NO].map do |key, _value| [I18n.t("datagrid.filters.xboolean.#{key.downcase}"), key] end end diff --git a/lib/datagrid/filters/float_filter.rb b/lib/datagrid/filters/float_filter.rb index 85676fa..4361d60 100644 --- a/lib/datagrid/filters/float_filter.rb +++ b/lib/datagrid/filters/float_filter.rb @@ -1,9 +1,9 @@ class Datagrid::Filters::FloatFilter < Datagrid::Filters::BaseFilter - include Datagrid::Filters::RangedFilter def parse(value) return nil if value.blank? + value.to_f end end diff --git a/lib/datagrid/filters/integer_filter.rb b/lib/datagrid/filters/integer_filter.rb index e1943aa..e05a14e 100644 --- a/lib/datagrid/filters/integer_filter.rb +++ b/lib/datagrid/filters/integer_filter.rb @@ -1,17 +1,16 @@ require "datagrid/filters/ranged_filter" class Datagrid::Filters::IntegerFilter < Datagrid::Filters::BaseFilter - include Datagrid::Filters::RangedFilter def parse(value) return nil if value.blank? if defined?(ActiveRecord) && value.is_a?(ActiveRecord::Base) && - value.respond_to?(:id) && value.id.is_a?(Integer) + value.respond_to?(:id) && value.id.is_a?(Integer) return value.id end return value if value.is_a?(Range) + value.to_i end end - diff --git a/lib/datagrid/filters/ranged_filter.rb b/lib/datagrid/filters/ranged_filter.rb index 399a82e..05ac2c9 100644 --- a/lib/datagrid/filters/ranged_filter.rb +++ b/lib/datagrid/filters/ranged_filter.rb @@ -1,10 +1,9 @@ module Datagrid::Filters::RangedFilter - def initialize(grid, name, options, &block) super(grid, name, options, &block) - if range? - options[:multiple] = true - end + return unless range? + + options[:multiple] = true end def parse_values(value) @@ -30,7 +29,6 @@ def parse_values(value) else raise ArgumentError, "Can not create a date range from array of more than two: #{result.inspect}" end - end def range? @@ -40,17 +38,11 @@ def range? def default_filter_where(scope, value) if range? && value.is_a?(Array) left, right = value - if left - scope = driver.greater_equal(scope, name, left) - end - if right - scope = driver.less_equal(scope, name, right) - end + scope = driver.greater_equal(scope, name, left) if left + scope = driver.less_equal(scope, name, right) if right scope else super(scope, value) end end - - end diff --git a/lib/datagrid/filters/select_options.rb b/lib/datagrid/filters/select_options.rb index bf560e4..68ae60b 100644 --- a/lib/datagrid/filters/select_options.rb +++ b/lib/datagrid/filters/select_options.rb @@ -1,6 +1,6 @@ module Datagrid::Filters::SelectOptions def select(object) - select = self.options[:select] + select = options[:select] if select.is_a?(Symbol) object.send(select) elsif select.respond_to?(:call) @@ -15,7 +15,7 @@ def select_values(object) groups_used = grouped_choices?(options) options.map do |option| if groups_used - option[1].map {|o| option_text_and_value(o)} + option[1].map { |o| option_text_and_value(o) } else option_text_and_value(option) end @@ -23,9 +23,12 @@ def select_values(object) end def include_blank - unless prompt - options.has_key?(:include_blank) ? - Datagrid::Utils.callable(options[:include_blank]) : !multiple? + return if prompt + + if options.has_key?(:include_blank) + Datagrid::Utils.callable(options[:include_blank]) + else + !multiple? end end @@ -41,7 +44,7 @@ def prompt def option_text_and_value(option) # Options are [text, value] pairs or strings used for both. if !option.is_a?(String) && option.respond_to?(:first) && option.respond_to?(:last) - option = option.reject { |e| Hash === e } if Array === option + option = option.reject { |e| e.is_a?(Hash) } if option.is_a?(Array) [option.first, option.last] else [option, option] @@ -52,6 +55,6 @@ def option_text_and_value(option) # https://github.com/rails/rails/blob/f95c0b7e96eb36bc3efc0c5beffbb9e84ea664e4/actionview/lib/action_view/helpers/tags/select.rb#L36 # Code reuse is difficult, so it is easier to duplicate it def grouped_choices?(choices) - !choices.blank? && choices.first.respond_to?(:last) && Array === choices.first.last + !choices.blank? && choices.first.respond_to?(:last) && choices.first.last.is_a?(Array) end end diff --git a/lib/datagrid/filters/string_filter.rb b/lib/datagrid/filters/string_filter.rb index 9ea428c..35d20dd 100644 --- a/lib/datagrid/filters/string_filter.rb +++ b/lib/datagrid/filters/string_filter.rb @@ -1,5 +1,4 @@ class Datagrid::Filters::StringFilter < Datagrid::Filters::BaseFilter - include Datagrid::Filters::RangedFilter def parse(value) diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index bfdd80e..a99888f 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -10,7 +10,7 @@ module FormBuilder # * <tt>text_field</tt> for other filter types def datagrid_filter(filter_or_attribute, partials: nil, **options, &block) filter = datagrid_get_filter(filter_or_attribute) - self.send( filter.form_builder_helper_name, filter, **options, &block) + send(filter.form_builder_helper_name, filter, **options, &block) end # @param filter_or_attribute [Datagrid::Filters::BaseFilter, String, Symbol] filter object or filter name @@ -20,7 +20,7 @@ def datagrid_filter(filter_or_attribute, partials: nil, **options, &block) def datagrid_label(filter_or_attribute, text = nil, **options, &block) filter = datagrid_get_filter(filter_or_attribute) options = add_html_classes( - {**filter.label_options, **options}, + { **filter.label_options, **options }, filter.default_html_classes ) label(filter.name, text || filter.header, **options, &block) @@ -31,7 +31,7 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) filter = datagrid_get_filter(attribute_or_filter) options = add_filter_options(filter, **options) type = options.delete(:type)&.to_sym - if options.has_key?(:value) && options[:value].nil? && [:"datetime-local", :date].include?(type) + if options.has_key?(:value) && options[:value].nil? && %i[datetime-local date].include?(type) # https://github.com/rails/rails/pull/53387 options[:value] = "" end @@ -40,7 +40,7 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) elsif type == :date date_field filter.name, **options, &block elsif type == :textarea - text_area filter.name, value: object.filter_value_as_string(filter) , **options, &block + text_area filter.name, value: object.filter_value_as_string(filter), **options, &block elsif type == :checkbox # raise options.inspect check_box filter.name, options, options.fetch(:value, 1) @@ -55,16 +55,17 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) prompt: filter.prompt, include_hidden: false }, - multiple: filter.multiple?, - **options, - &block + multiple: filter.multiple?, + **options, + &block ) else - text_field filter.name, value: object.filter_value_as_string(filter) , **options, &block + text_field filter.name, value: object.filter_value_as_string(filter), **options, &block end end protected + def datagrid_extended_boolean_filter(filter, options = {}, &block) datagrid_filter_input(filter, **options, type: :select, &block) end @@ -93,12 +94,12 @@ def datagrid_enum_filter(filter, options = {}, &block) [value, text, checked] end render_partial( - 'enum_checkboxes', + "enum_checkboxes", { elements: elements, form: self, filter: filter, - options: options, + options: options } ) else @@ -118,14 +119,12 @@ def enum_checkbox_checked?(filter, option_value) end def datagrid_integer_filter(filter, options = {}) - if filter.multiple? && object[filter.name].blank? - options[:value] = "" - end + options[:value] = "" if filter.multiple? && object[filter.name].blank? datagrid_range_filter(:integer, filter, options) end def datagrid_dynamic_filter(filter, options = {}) - input_name = "#{object_name}[#{filter.name.to_s}][]" + input_name = "#{object_name}[#{filter.name}][]" field, operation, value = object.filter_value(filter) options = add_filter_options(filter, **options) options = options.merge(name: input_name) @@ -146,7 +145,7 @@ def datagrid_dynamic_filter(filter, options = {}) include_blank: false, include_hidden: false, prompt: false, - selected: operation, + selected: operation }, add_html_classes(options, "operation") ) @@ -166,12 +165,12 @@ def dynamic_filter_select(name, variants, select_options, html_options) end end - def datagrid_range_filter(type, filter, options = {}) + def datagrid_range_filter(_type, filter, options = {}) if filter.range? options = options.merge(multiple: true) from_options = datagrid_range_filter_options(object, filter, :from, options) to_options = datagrid_range_filter_options(object, filter, :to, options) - render_partial 'range_filter', { + render_partial "range_filter", { from_options: from_options, to_options: to_options, filter: filter, form: self } else @@ -180,7 +179,7 @@ def datagrid_range_filter(type, filter, options = {}) end def datagrid_range_filter_options(object, filter, type, options) - type_method_map = {from: :first, to: :last} + type_method_map = { from: :first, to: :last } options = add_html_classes(options, type) options[:value] = filter.format(object[filter.name]&.public_send(type_method_map[type])) # In case of datagrid ranged filter @@ -219,14 +218,12 @@ def add_html_classes(options, *classes) end def partial_path(name) - if partials = self.options[:partials] + if partials = options[:partials] partial_name = File.join(partials, name) # Second argument is []: no magical namespaces to lookup added from controller - if @template.lookup_context.template_exists?(partial_name, [], true) - return partial_name - end + return partial_name if @template.lookup_context.template_exists?(partial_name, [], true) end - File.join('datagrid', name) + File.join("datagrid", name) end def render_partial(name, locals) @@ -235,8 +232,8 @@ def render_partial(name, locals) def add_filter_options(filter, **options) add_html_classes( - {**filter.input_options, **options}, - *filter.default_html_classes, + { **filter.input_options, **options }, + *filter.default_html_classes ) end diff --git a/lib/datagrid/helper.rb b/lib/datagrid/helper.rb index 2a76698..039bc13 100644 --- a/lib/datagrid/helper.rb +++ b/lib/datagrid/helper.rb @@ -2,7 +2,6 @@ module Datagrid module Helper - # @param grid [Datagrid] grid object # @param column [Datagrid::Columns::Column, String, Symbol] column name # @param model [Object] an object from grid scope @@ -62,7 +61,6 @@ def datagrid_header(grid, options = {}) datagrid_renderer.header(grid, options) end - # Renders HTML table rows using given grid definition using columns defined in it. # Allows to provide a custom layout for each for in place with a block # @@ -149,9 +147,10 @@ def datagrid_renderer end def datagrid_column_classes(grid, column) - order_class = grid.ordered_by?(column) ? ["ordered", grid.descending ? "desc" : "asc"] : nil + order_class = if grid.ordered_by?(column) + ["ordered", grid.descending ? "desc" : "asc"] + end [column.name, order_class, column.options[:class]].compact.join(" ") end end end - diff --git a/lib/datagrid/ordering.rb b/lib/datagrid/ordering.rb index 0f6cbee..83577c6 100644 --- a/lib/datagrid/ordering.rb +++ b/lib/datagrid/ordering.rb @@ -4,39 +4,32 @@ module Datagrid # Raised when grid order value is incorrect class OrderUnsupported < StandardError end - module Ordering + module Ordering # @!visibility private def self.included(base) - base.extend ClassMethods + base.extend ClassMethods base.class_eval do include Datagrid::Columns datagrid_attribute :order do |value| - if value.present? - value.to_sym - else - nil - end - + value.to_sym if value.present? end datagrid_attribute :descending do |value| Datagrid::Utils.booleanize(value) end - alias descending? descending - + alias_method :descending?, :descending end end # @!visibility private module ClassMethods def order_unsupported(name, reason) - raise Datagrid::OrderUnsupported, "Can not sort #{self.inspect} by ##{name}: #{reason}" + raise Datagrid::OrderUnsupported, "Can not sort #{inspect} by ##{name}: #{reason}" end end - # @!visibility private def assets check_order_valid! @@ -65,33 +58,31 @@ def ordered_by?(column) def apply_order(assets) return assets unless order + if order_column.order_by_value? assets = assets.sort_by do |asset| order_column.order_by_value(asset, self) end descending? ? assets.reverse : assets - else - if descending? - if order_column.order_desc - apply_asc_order(assets, order_column.order_desc) - else - apply_desc_order(assets, order_column.order) - end + elsif descending? + if order_column.order_desc + apply_asc_order(assets, order_column.order_desc) else - apply_asc_order(assets, order_column.order) + apply_desc_order(assets, order_column.order) end + else + apply_asc_order(assets, order_column.order) end end def check_order_valid! return unless order + column = column_by_name(order) - unless column - self.class.order_unsupported(order, "no column #{order} in #{self.class}") - end - unless column.supports_order? - self.class.order_unsupported(column.name, "column don't support order" ) - end + self.class.order_unsupported(order, "no column #{order} in #{self.class}") unless column + return if column.supports_order? + + self.class.order_unsupported(column.name, "column don't support order") end def apply_asc_order(assets, order) @@ -113,7 +104,8 @@ def apply_desc_order(assets, order) def reverse_order(assets) driver.reverse_order(assets) rescue NotImplementedError - self.class.order_unsupported(order_column.name, "Your ORM do not support reverse order: please specify :order_desc option manually") + self.class.order_unsupported(order_column.name, + "Your ORM do not support reverse order: please specify :order_desc option manually") end def apply_block_order(assets, order) diff --git a/lib/datagrid/renderer.rb b/lib/datagrid/renderer.rb index 3b472f0..3b23449 100644 --- a/lib/datagrid/renderer.rb +++ b/lib/datagrid/renderer.rb @@ -3,7 +3,6 @@ module Datagrid # @!visibility private class Renderer - def self.for(template) new(template) end @@ -13,9 +12,7 @@ def initialize(template) end def format_value(grid, column, asset) - if column.is_a?(String) || column.is_a?(Symbol) - column = grid.column_by_name(column) - end + column = grid.column_by_name(column) if column.is_a?(String) || column.is_a?(Symbol) value = grid.html_value(column, @template, asset) @@ -32,14 +29,14 @@ def form_for(grid, options = {}) options[:html] ||= {} options[:html][:class] ||= "datagrid-form #{@template.dom_class(grid)}" options[:as] ||= grid.param_name - _render_partial('form', options[:partials], {:grid => grid, :options => options}) + _render_partial("form", options[:partials], { grid: grid, options: options }) end def table(grid, assets, **options) options[:html] ||= {} options[:html][:class] ||= "datagrid #{@template.dom_class(grid)}" - _render_partial('table', options[:partials], + _render_partial("table", options[:partials], { grid: grid, options: options, @@ -50,8 +47,8 @@ def table(grid, assets, **options) def header(grid, options = {}) options[:order] = true unless options.has_key?(:order) - _render_partial('head', options[:partials], - { :grid => grid, :options => options }) + _render_partial("head", options[:partials], + { grid: grid, options: options }) end def rows(grid, assets = grid.assets, **options, &block) @@ -64,22 +61,20 @@ def rows(grid, assets = grid.assets, **options, &block) def row(grid, asset, **options, &block) Datagrid::Helper::HtmlRow.new(self, grid, asset, options).tap do |row| - if block_given? - return @template.capture(row, &block) - end + return @template.capture(row, &block) if block_given? end end def order_for(grid, column, options = {}) - _render_partial('order_for', options[:partials], - { :grid => grid, :column => column }) + _render_partial("order_for", options[:partials], + { grid: grid, column: column }) end def order_path(grid, column, descending, request) column = grid.column_by_name(column) query = request ? request.query_parameters : {} ActionDispatch::Http::URL.path_for( - path: request ? request.path : '/', + path: request ? request.path : "/", params: query.merge(grid.query_params(order: column.name, descending: descending)) ) end @@ -92,9 +87,9 @@ def _safe(string) def _render_partial(partial_name, partials_path, locals = {}) @template.render({ - :partial => File.join(partials_path || 'datagrid', partial_name), - :locals => locals - }) + partial: File.join(partials_path || "datagrid", partial_name), + locals: locals + }) end end @@ -110,7 +105,6 @@ module Helper # puts value # end class HtmlRow - include Enumerable attr_reader :grid, :asset, :options @@ -137,14 +131,15 @@ def each(&block) end def to_s - @renderer.send(:_render_partial, 'row', options[:partials], { - :grid => grid, - :options => options, - :asset => asset - }) + @renderer.send(:_render_partial, "row", options[:partials], { + grid: grid, + options: options, + asset: asset + }) end protected + def method_missing(method, *args, &blk) if column = @grid.column_by_name(method) get(column) diff --git a/lib/datagrid/rspec.rb b/lib/datagrid/rspec.rb index ce7ff83..6b07ea7 100644 --- a/lib/datagrid/rspec.rb +++ b/lib/datagrid/rspec.rb @@ -1,16 +1,14 @@ require "datagrid" -#TODO: refactor this experimental shit +# TODO: refactor this experimental shit shared_examples_for "Datagrid" do describe "as Datagrid" do - it "should have at least one entry if assets" do subject.assets.should_not be_empty end - described_class.columns(:data => true).each do |column| + described_class.columns(data: true).each do |column| describe "column ##{column.name}" do - it "should has value in #data_hash" do subject.data_hash.first.should have_key(column.name) end @@ -25,14 +23,11 @@ subject.assets.first.should_not be_nil end end - end described_class.filters.each do |filter| describe "filter ##{filter.name}" do - let(:filter_value) do - case Datagrid::Filters::FILTER_TYPES.invert[filter.class] when :default, :string "text" @@ -53,16 +48,15 @@ end before(:each) do - subject.attributes = {filter.name => filter_value} + subject.attributes = { filter.name => filter_value } subject.public_send(filter.name).should_not be_nil end it "should be supported" do subject.assets.should_not be_nil - #TODO: better matcher. + # TODO: better matcher. end end end - end end diff --git a/lib/datagrid/scaffold.rb b/lib/datagrid/scaffold.rb index aad238f..d6c6d23 100644 --- a/lib/datagrid/scaffold.rb +++ b/lib/datagrid/scaffold.rb @@ -2,36 +2,31 @@ # @!visibility private class Datagrid::Scaffold < Rails::Generators::NamedBase - include Rails::Generators::ResourceHelpers check_class_collision suffix: "Grid" source_root File.expand_path(__FILE__ + "/../../../templates") def create_scaffold - unless file_exists?(base_grid_file) - template "base.rb.erb", base_grid_file - end + template "base.rb.erb", base_grid_file unless file_exists?(base_grid_file) template "grid.rb.erb", "app/grids/#{grid_class_name.underscore}.rb" if file_exists?(grid_controller_file) - inject_into_file grid_controller_file, index_action, after: %r{class .*#{grid_controller_class_name}.*\n} + inject_into_file grid_controller_file, index_action, after: /class .*#{grid_controller_class_name}.*\n/ else template "controller.rb.erb", grid_controller_file end template "index.html.erb", view_file route(generate_routing_namespace("resources :#{grid_controller_short_name}")) - unless defined?(::Kaminari) || defined?(::WillPaginate) - gem 'kaminari' - end + gem "kaminari" unless defined?(::Kaminari) || defined?(::WillPaginate) in_root do { "css" => " *= require datagrid", "css.sass" => " *= require datagrid", - "css.scss" => " *= require datagrid", + "css.scss" => " *= require datagrid" }.each do |extension, string| file = "app/assets/stylesheets/application.#{extension}" if file_exists?(file) - inject_into_file file, string + "\n", {before: %r{.*require_self}} # before all + inject_into_file file, string + "\n", { before: /.*require_self/ } # before all end end end @@ -83,22 +78,23 @@ def grid_route_name end def index_action - indent(<<-RUBY) -def index - @grid = #{grid_class_name}.new(grid_params) do |scope| - scope.page(params[:page]) - end -end + indent(<<~RUBY) + def index + @grid = #{grid_class_name}.new(grid_params) do |scope| + scope.page(params[:page]) + end + end -protected + protected -def grid_params - params.fetch(:#{grid_param_name}, {}).permit! -end -RUBY + def grid_params + params.fetch(:#{grid_param_name}, {}).permit! + end + RUBY end protected + def generate_routing_namespace(code) depth = regular_class_path.length # Create 'namespace' ladder diff --git a/lib/datagrid/utils.rb b/lib/datagrid/utils.rb index 1114c85..254ab02 100644 --- a/lib/datagrid/utils.rb +++ b/lib/datagrid/utils.rb @@ -2,26 +2,19 @@ module Datagrid # @!visibility private module Utils class << self - - TRUTH = [true, 1, "1", "true", "yes", "on"] def booleanize(value) - if value.respond_to?(:downcase) - value = value.downcase - end + value = value.downcase if value.respond_to?(:downcase) TRUTH.include?(value) end def translate_from_namespace(namespace, grid_class, key) - lookups = [] namespaced_key = "#{namespace}.#{key}" grid_class.ancestors.each do |ancestor| - if ancestor.respond_to?(:model_name) - lookups << :"datagrid.#{ancestor.model_name.i18n_key}.#{namespaced_key}" - end + lookups << :"datagrid.#{ancestor.model_name.i18n_key}.#{namespaced_key}" if ancestor.respond_to?(:model_name) end lookups << :"datagrid.defaults.#{namespaced_key}" lookups << key.to_s.humanize @@ -32,6 +25,7 @@ def warn_once(message, delay = 5) @warnings ||= {} timestamp = @warnings[message] return false if timestamp && timestamp >= Time.now - delay + warn message @warnings[message] = Time.now true @@ -39,6 +33,7 @@ def warn_once(message, delay = 5) def add_html_classes(options, *classes) return options if classes.empty? + options = options.clone options[:class] ||= [] array = options[:class].is_a?(Array) @@ -52,18 +47,18 @@ def string_like?(value) end def extract_position_from_options(array, options) - before, after = options[:before], options[:after] - if before && after - raise Datagrid::ConfigurationError, "Options :before and :after can not be used together" - end + before = options[:before] + after = options[:after] + raise Datagrid::ConfigurationError, "Options :before and :after can not be used together" if before && after # Consider as before all return 0 if before == true + if before before = before.to_sym - array.index {|c| c.name.to_sym == before } + array.index { |c| c.name.to_sym == before } elsif after after = after.to_sym - array.index {|c| c.name.to_sym == after } + 1 + array.index { |c| c.name.to_sym == after } + 1 else -1 end @@ -77,16 +72,16 @@ def apply_args(*args, &block) def parse_date(value) return nil if value.blank? return value if value.is_a?(Range) + if value.is_a?(String) Array(Datagrid.configuration.date_formats).each do |format| - begin - return Date.strptime(value, format) - rescue ::ArgumentError - end + return Date.strptime(value, format) + rescue ::ArgumentError end end return Date.parse(value) if value.is_a?(String) return value.to_date if value.respond_to?(:to_date) + value rescue ::ArgumentError nil @@ -95,16 +90,16 @@ def parse_date(value) def parse_datetime(value) return nil if value.blank? return value if value.is_a?(Range) + if value.is_a?(String) Array(Datagrid.configuration.datetime_formats).each do |format| - begin - return Time.strptime(value, format) - rescue ::ArgumentError - end + return Time.strptime(value, format) + rescue ::ArgumentError end end return Time.parse(value) if value.is_a?(String) return value.to_time if value.respond_to?(:to_time) + value rescue ::ArgumentError nil @@ -132,6 +127,7 @@ def callable(value) end protected + def property_availability(grid, option, default) case option when nil diff --git a/lib/tasks/datagrid_tasks.rake b/lib/tasks/datagrid_tasks.rake index 5285bd0..27eb792 100644 --- a/lib/tasks/datagrid_tasks.rake +++ b/lib/tasks/datagrid_tasks.rake @@ -1,5 +1,4 @@ namespace :datagrid do - desc "Copy table partials into rails application" task :copy_partials do require "fileutils" diff --git a/spec/datagrid/active_model_spec.rb b/spec/datagrid/active_model_spec.rb index d0e4220..b42adbc 100644 --- a/spec/datagrid/active_model_spec.rb +++ b/spec/datagrid/active_model_spec.rb @@ -1,7 +1,6 @@ -require 'spec_helper' +require "spec_helper" describe Datagrid::ActiveModel do - class ActiveReport include Datagrid::ActiveModel end @@ -23,11 +22,10 @@ class ActiveReport describe ".param_name" do it "should make right param key from simple class name" do - expect(ActiveReport.param_name).to eq('active_report') + expect(ActiveReport.param_name).to eq("active_report") end it "should make right param key from class of module" do - expect(Grid::ActiveReport.param_name).to eq('grid_active_report') + expect(Grid::ActiveReport.param_name).to eq("grid_active_report") end end - end diff --git a/spec/datagrid/column_names_attribute_spec.rb b/spec/datagrid/column_names_attribute_spec.rb index 4a35c24..321cc5f 100644 --- a/spec/datagrid/column_names_attribute_spec.rb +++ b/spec/datagrid/column_names_attribute_spec.rb @@ -1,7 +1,6 @@ require "spec_helper" describe Datagrid::ColumnNamesAttribute do - let(:column_names_filter_options) do {} end @@ -12,37 +11,36 @@ scope { Entry } column_names_filter(**options) column(:id) - column(:name, :mandatory => true) + column(:name, mandatory: true) column(:category) end end subject { report } - let!(:entry) do - Entry.create!(:name => 'hello', :category => 'greeting') + Entry.create!(name: "hello", category: "greeting") end it "should work" do subject.column_names = [:id] expect(subject.mandatory_columns.map(&:name)).to eq([:name]) - expect(subject.optional_columns.map(&:name)).to eq([:id, :category]) - expect(subject.data).to eq([["Id", "Name"], [entry.id, "hello"]]) + expect(subject.optional_columns.map(&:name)).to eq(%i[id category]) + expect(subject.data).to eq([%w[Id Name], [entry.id, "hello"]]) columns_filter = subject.filter_by_name(:column_names) expect(columns_filter).not_to be_nil expect(columns_filter.select(subject)).to eq([["Id", :id], ["Category", :category]]) end it "should show only mandatory columns by default" do - expect(subject.row_for(entry)).to eq([ "hello" ]) - subject.column_names = ["name", "category"] - expect(subject.row_for(entry)).to eq(["hello", "greeting"]) + expect(subject.row_for(entry)).to eq(["hello"]) + subject.column_names = %w[name category] + expect(subject.row_for(entry)).to eq(%w[hello greeting]) end it "should show mandatory columns even if they are unselected" do subject.column_names = ["category"] - expect(subject.row_for(entry)).to eq(["hello", "greeting"]) - expect(subject.data).to eq([["Name", "Category"], ["hello", "greeting"]]) + expect(subject.row_for(entry)).to eq(%w[hello greeting]) + expect(subject.data).to eq([%w[Name Category], %w[hello greeting]]) end it "should find any column by name" do @@ -51,27 +49,25 @@ expect(subject.column_by_name(:category)).not_to be_nil end - context "when default option is passed to column_names_filter" do let(:column_names_filter_options) do - { :default => [:id] } + { default: [:id] } end - describe '#data' do + describe "#data" do subject { super().data } - it { should == [["Id", "Name"], [entry.id, 'hello']] } + it { should == [%w[Id Name], [entry.id, "hello"]] } end - end context "when some columns are disabled" do subject do test_report do - scope {Entry} - column(:id, :mandatory => true) + scope { Entry } + column(:id, mandatory: true) column(:name) column(:category, if: proc { false }) - column(:group, :mandatory => true, if: proc { false }) + column(:group, mandatory: true, if: proc { false }) end end diff --git a/spec/datagrid/columns/column_spec.rb b/spec/datagrid/columns/column_spec.rb index 8fc3d75..086ecbc 100644 --- a/spec/datagrid/columns/column_spec.rb +++ b/spec/datagrid/columns/column_spec.rb @@ -1,19 +1,18 @@ -require 'spec_helper' +require "spec_helper" describe Datagrid::Columns::Column do - describe ".inspect" do subject do class ColumnInspectTest include Datagrid - scope {Entry} + scope { Entry } column(:id, header: "ID") end ColumnInspectTest.column_by_name(:id) end it "shows inspect information" do - expect(subject.inspect).to eq("#<Datagrid::Columns::Column ColumnInspectTest#id {:header=>\"ID\"}>") + expect(subject.inspect).to eq('#<Datagrid::Columns::Column ColumnInspectTest#id {:header=>"ID"}>') end end end diff --git a/spec/datagrid/columns_spec.rb b/spec/datagrid/columns_spec.rb index bdefe02..c644800 100644 --- a/spec/datagrid/columns_spec.rb +++ b/spec/datagrid/columns_spec.rb @@ -1,7 +1,6 @@ -require 'spec_helper' +require "spec_helper" describe Datagrid::Columns do - let(:group) { Group.create!(name: "Pop") } subject do @@ -9,7 +8,6 @@ end describe "basic methods" do - let!(:entry) do Entry.create!( group: group, @@ -17,8 +15,8 @@ disabled: false, confirmed: false, category: "first", - access_level: 'admin', - pet: 'rottweiler', + access_level: "admin", + pet: "rottweiler", shipping_date: Date.new(2013, 8, 1) ) end @@ -27,19 +25,19 @@ it "should have data columns without html columns" do grid = test_report do - scope {Entry} + scope { Entry } column(:name) column(:action, html: true) do - 'dummy' + "dummy" end end expect(grid.data_columns.map(&:name)).to eq([:name]) - expect(grid.html_columns.map(&:name)).to eq([:name, :action]) + expect(grid.html_columns.map(&:name)).to eq(%i[name action]) end it "allows a column argument" do grid = test_report do - scope {Entry} + scope { Entry } column(:name) end expect(grid.data_columns(grid.column_by_name(:name)).map(&:name)).to eq([:name]) @@ -47,27 +45,26 @@ it "should build rows of data" do grid = test_report do - scope {Entry} + scope { Entry } column(:name) column(:action, html: true) do - 'dummy' + "dummy" end end expect(grid.rows).to eq([["Star"]]) end - it "should generate header without html columns" do + it "should generate header without html columns" do grid = test_report do - scope {Entry} + scope { Entry } column(:name) column(:action, html: true) do - 'dummy' + "dummy" end end expect(grid.header).to eq(["Name"]) end describe "translations" do - module ::Ns45 class TranslatedReport include Datagrid @@ -76,7 +73,7 @@ class TranslatedReport end end it "translates column-header with namespace" do - store_translations(:en, datagrid: {:"ns45/translated_report" => {columns: {name: "Navn"}}}) do + store_translations(:en, datagrid: { "ns45/translated_report": { columns: { name: "Navn" } } }) do expect(Ns45::TranslatedReport.new.header.first).to eq("Navn") end end @@ -84,11 +81,11 @@ class TranslatedReport it "translates column-header without namespace" do class Report27 include Datagrid - scope {Entry} + scope { Entry } column(:name) end - store_translations(:en, datagrid: {:"report27" => {columns: {name: "Nombre"}}}) do + store_translations(:en, datagrid: { "report27": { columns: { name: "Nombre" } } }) do expect(Report27.new.header.first).to eq("Nombre") end end @@ -96,20 +93,19 @@ class Report27 it "translates column-header in using defaults namespace" do class Report27 include Datagrid - scope {Entry} + scope { Entry } column(:name) end - store_translations(:en, datagrid: {defaults: {columns: {name: "Nombre"}}}) do + store_translations(:en, datagrid: { defaults: { columns: { name: "Nombre" } } }) do expect(Report27.new.header.first).to eq("Nombre") end end - end it "should return html_columns" do report = test_report do - scope {Entry} + scope { Entry } column(:id) column(:name, html: false) end @@ -118,7 +114,7 @@ class Report27 it "should return html_columns when column definition has 2 arguments" do report = test_report(name: "Hello") do - scope {Entry} + scope { Entry } filter(:name) column(:id) column(:name, html: false) do |model, grid| @@ -131,14 +127,14 @@ class Report27 it "should generate table data" do expect(subject.data).to eq([ - subject.header, - subject.row_for(entry) - ]) + subject.header, + subject.row_for(entry) + ]) end it "supports dynamic header" do grid = test_report do - scope {Entry} + scope { Entry } column(:id, header: proc { rand(10**9) }) end @@ -147,12 +143,12 @@ class Report27 it "should generate hash for given asset" do expect(subject.hash_for(entry)).to eq({ - group: "Pop", - name: "Star", - access_level: 'admin', - pet: 'ROTTWEILER', - shipping_date: date - }) + group: "Pop", + name: "Star", + access_level: "admin", + pet: "ROTTWEILER", + shipping_date: date + }) end it "should support csv export" do @@ -166,12 +162,11 @@ class Report27 it "should support csv export options" do expect(subject.to_csv(col_sep: ";")).to eq("Shipping date;Group;Name;Access level;Pet\n#{date};Pop;Star;admin;ROTTWEILER\n") end - end it "should support columns with model and report arguments" do report = test_report(category: "foo") do - scope {Entry.order(:category)} + scope { Entry.order(:category) } filter(:category) do |value| where("category LIKE '%#{value}%'") end @@ -203,64 +198,64 @@ class Report27 end it "should support defining a query for a column" do report = test_report do - scope {Entry} + scope { Entry } filter(:name) column(:id) - column(:sum_group_id, 'sum(group_id)') + column(:sum_group_id, "sum(group_id)") end Entry.create!(group: group) expect(report.assets.first.sum_group_id).to eq(group.id) end - it "should support post formatting for column defined with query" do - report = test_report do - scope {Group.joins(:entries).group("groups.id")} - filter(:name) - column(:entries_count, 'count(entries.id)') do |model| - format("(#{model.entries_count})") do |value| - content_tag(:span, value) - end + it "should support post formatting for column defined with query" do + report = test_report do + scope { Group.joins(:entries).group("groups.id") } + filter(:name) + column(:entries_count, "count(entries.id)") do |model| + format("(#{model.entries_count})") do |value| + content_tag(:span, value) end end - 3.times { Entry.create!(group: group) } - expect(report.rows).to eq([["(3)"]]) end - it "should support hidding columns through if and unless" do - report = test_report do - scope {Entry} - column(:id, if: :show?) - column(:name, unless: proc {|grid| !grid.show? }) - column(:category) + 3.times { Entry.create!(group: group) } + expect(report.rows).to eq([["(3)"]]) + end + it "should support hidding columns through if and unless" do + report = test_report do + scope { Entry } + column(:id, if: :show?) + column(:name, unless: proc { |grid| !grid.show? }) + column(:category) - def show? - false - end + def show? + false end - expect(report.columns(:id)).to eq([]) - expect(report.columns(:name)).to eq([]) - expect(report.available_columns.map(&:name)).to eq([:category]) end + expect(report.columns(:id)).to eq([]) + expect(report.columns(:name)).to eq([]) + expect(report.available_columns.map(&:name)).to eq([:category]) + end - it "raises when incorrect unless option is given" do - expect do - test_report do - column(:id, if: Object.new) - end - end.to raise_error(Datagrid::ConfigurationError) - end + it "raises when incorrect unless option is given" do + expect do + test_report do + column(:id, if: Object.new) + end + end.to raise_error(Datagrid::ConfigurationError) + end - it "raises when :before and :after used together" do - expect do - test_report do - column(:id) - column(:name, before: :id, after: :name) - end - end.to raise_error(Datagrid::ConfigurationError) - end + it "raises when :before and :after used together" do + expect do + test_report do + column(:id) + column(:name, before: :id, after: :name) + end + end.to raise_error(Datagrid::ConfigurationError) + end describe ".column_names attributes" do let(:grid) do - test_report(column_names: ["id", "name"]) do + test_report(column_names: %w[id name]) do scope { Entry } column(:id) column(:name) @@ -268,10 +263,10 @@ def show? end end let!(:entry) do - Entry.create!(name: 'hello') + Entry.create!(name: "hello") end it "should be suppored in header" do - expect(grid.header).to eq(["Id", "Name"]) + expect(grid.header).to eq(%w[Id Name]) end it "should be suppored in rows" do expect(grid.rows).to eq([[entry.id, "hello"]]) @@ -282,16 +277,14 @@ def show? end it "should support explicit overwrite" do - expect(grid.header(:id, :name, :category)).to eq(%w(Id Name Category)) + expect(grid.header(:id, :name, :category)).to eq(%w[Id Name Category]) end - end - context "when grid has formatted column" do it "should output correct data" do report = test_report do - scope {Entry} + scope { Entry } column(:name) do |entry| format(entry.name) do |value| "<strong>#{value}</strong" @@ -306,18 +299,18 @@ def show? describe ".default_column_options" do it "should pass default options to each column definition" do report = test_report do - scope {Entry} - self.default_column_options = {order: false} + scope { Entry } + self.default_column_options = { order: false } column(:id) column(:name, order: "name") end - first = Entry.create(name: '1st') - second = Entry.create(name: '2nd') + first = Entry.create(name: "1st") + second = Entry.create(name: "2nd") expect do - report.attributes = {order: :id} + report.attributes = { order: :id } report.assets end.to raise_error(Datagrid::OrderUnsupported) - report.attributes = {order: :name, descending: true} + report.attributes = { order: :name, descending: true } expect(report.assets).to eq([second, first]) end end @@ -353,7 +346,7 @@ def show? it "should support instance level batch size" do grid = test_report do - scope {Entry} + scope { Entry } column :id self.batch_size = 25 end @@ -370,7 +363,7 @@ def show? describe ".data_row" do it "should give access to column values via an object" do grid = test_report do - scope { Entry } + scope { Entry } column(:id) column(:name) do name.capitalize @@ -379,13 +372,13 @@ def show? "some link here" end end - entry = Entry.create!(name: 'hello') + entry = Entry.create!(name: "hello") row = grid.data_row(entry) expect(row.id).to eq(entry.id) expect(row.name).to eq("Hello") - expect { + expect do row.actions - }.to raise_error(RuntimeError) + end.to raise_error(RuntimeError) end end @@ -419,7 +412,7 @@ def show? end let(:basic_grid) { modified_grid.class.new } - let!(:entry) { Entry.create!(name: "Hello", category: 'first') } + let!(:entry) { Entry.create!(name: "Hello", category: "first") } it "should have correct columns" do expect(modified_grid.columns.size).to eq(2) @@ -428,83 +421,83 @@ def show? end it "should give correct header" do - expect(modified_grid.header).to eq(["Id", "Name"]) + expect(modified_grid.header).to eq(%w[Id Name]) expect(basic_grid.header).to eq(["Id"]) end it "should give correct rows" do - expect(modified_grid.rows).to eq([[entry.id, 'Hello']]) + expect(modified_grid.rows).to eq([[entry.id, "Hello"]]) expect(basic_grid.rows).to eq([[entry.id]]) end it "should support :before column name" do modified_grid.column(:category, before: :name) - expect(modified_grid.header).to eq(["Id", "Category", "Name"]) + expect(modified_grid.header).to eq(%w[Id Category Name]) end it "should support :before all" do modified_grid.column(:category, before: true) - expect(modified_grid.header).to eq(["Category", "Id", "Name"]) + expect(modified_grid.header).to eq(%w[Category Id Name]) end it "should support columns block" do modified_grid.column(:category) do category.capitalize end - expect(modified_grid.rows).to eq([[entry.id, "Hello", 'First']]) + expect(modified_grid.rows).to eq([[entry.id, "Hello", "First"]]) end it "should support column_names accessor" do modified_grid.column_names = [:name] - expect(modified_grid.rows).to eq([['Hello']]) + expect(modified_grid.rows).to eq([["Hello"]]) modified_grid.column_names = [:id] expect(modified_grid.rows).to eq([[entry.id]]) end it "should support column_names accessor with mandatory columns" do modified_grid.column(:category, mandatory: true) modified_grid.column_names = [:name] - expect(modified_grid.rows).to eq([['Hello', 'first']]) + expect(modified_grid.rows).to eq([%w[Hello first]]) basic_grid.column_names = [:id] expect(basic_grid.rows).to eq([[entry.id]]) end it "should support available columns" do modified_grid.column(:category, mandatory: true) - expect(modified_grid.available_columns.map(&:name)).to eq([:id, :name, :category]) + expect(modified_grid.available_columns.map(&:name)).to eq(%i[id name category]) end it "should respect column availability criteria" do modified_grid.column(:category, if: proc { false }) - expect(modified_grid.columns.map(&:name)).to eq([:id, :name]) + expect(modified_grid.columns.map(&:name)).to eq(%i[id name]) end end describe ".data_value" do it "should return value" do grid = test_report do - scope {Entry } + scope { Entry } column(:name) end - expect(grid.data_value(:name, Entry.create!(name: 'Hello'))).to eq('Hello') + expect(grid.data_value(:name, Entry.create!(name: "Hello"))).to eq("Hello") end it "should raise for disabled columns" do grid = test_report do - scope {Entry } + scope { Entry } column(:name, if: proc { false }) end - expect { - grid.data_value(:name, Entry.create!(name: 'Hello')) - }.to raise_error(Datagrid::ColumnUnavailableError) + expect do + grid.data_value(:name, Entry.create!(name: "Hello")) + end.to raise_error(Datagrid::ColumnUnavailableError) end end describe "caching" do it "should work when enabled in class" do grid = test_report do - scope {Entry} + scope { Entry } self.cached = true - column(:random1) {rand(10**9)} - column(:random2) {rand(10**9)} + column(:random1) { rand(10**9) } + column(:random2) { rand(10**9) } end row = grid.data_row(Entry.create!) @@ -526,16 +519,18 @@ def show? describe "decoration" do class EntryDecorator attr_reader :model + def initialize(model) @model = model end + def capitalized_name model.name.capitalize end end let!(:entry) do - Entry.create!(name: 'hello', category: 'first') + Entry.create!(name: "hello", category: "first") end it "delegates column values to decorator" do @@ -551,7 +546,7 @@ def capitalized_name end end - expect(grid.rows).to eq([['Hello', 'first', 'Hello']]) + expect(grid.rows).to eq([%w[Hello first Hello]]) end it "allows class decorator" do @@ -560,7 +555,7 @@ def capitalized_name decorate { EntryDecorator } column(:capitalized_name) end - expect(grid.rows).to eq([['Hello']]) + expect(grid.rows).to eq([["Hello"]]) end end @@ -601,7 +596,7 @@ def capitalized_name grid = test_report do scope { Entry } column(:id1, preload: ->(a) { a.order(:id) }) - column(:id2, preload: ->(a) { a.order(:id) }, if: ->(a) { false }) + column(:id2, preload: ->(a) { a.order(:id) }, if: ->(_a) { false }) column(:name) end grid.column_names = [:name] @@ -619,10 +614,10 @@ class DataHashGrid end grid1 = DataHashGrid.new(order: :name) grid2 = DataHashGrid.new(order: :name, descending: true) - Entry.create!(name: 'one') - Entry.create!(name: 'two') - expect(grid1.data_hash).to eq([{name: 'one'}, {name: 'two'}]) - expect(grid2.data_hash).to eq([{name: 'two'}, {name: 'one'}]) + Entry.create!(name: "one") + Entry.create!(name: "two") + expect(grid1.data_hash).to eq([{ name: "one" }, { name: "two" }]) + expect(grid2.data_hash).to eq([{ name: "two" }, { name: "one" }]) end end end diff --git a/spec/datagrid/core_spec.rb b/spec/datagrid/core_spec.rb index b78cd6f..e5c5d47 100644 --- a/spec/datagrid/core_spec.rb +++ b/spec/datagrid/core_spec.rb @@ -1,9 +1,9 @@ -require 'spec_helper' +require "spec_helper" require "action_controller/metal/strong_parameters" describe Datagrid::Core do - describe '#original_scope' do - it 'does not wrap instance scope' do + describe "#original_scope" do + it "does not wrap instance scope" do grid = test_report do scope { Entry } end @@ -11,7 +11,7 @@ expect(grid.original_scope).to eq(Entry) end - it 'does not wrap class scope' do + it "does not wrap class scope" do klass = test_report_class do scope { Entry } end @@ -20,7 +20,7 @@ end end - context 'with 2 persisted entries' do + context "with 2 persisted entries" do before { 2.times { Entry.create } } let(:report_class) do @@ -31,8 +31,7 @@ class ScopeTestReport ScopeTestReport end - describe '#scope' do - + describe "#scope" do it "wraps scope" do grid = test_report do scope { Entry } @@ -40,7 +39,7 @@ class ScopeTestReport expect(grid.scope).to be_kind_of(ActiveRecord::Relation) end - context 'in the class' do + context "in the class" do let(:report) { report_class.new } it { expect(report.scope.to_a.size).to eq(2) } @@ -61,10 +60,10 @@ class TestGrid < ScopeTestReport end end - context 'changes scope on the fly' do + context "changes scope on the fly" do let(:report) do report_class.new.tap do |r| - r.scope { Entry.limit(1)} + r.scope { Entry.limit(1) } end end @@ -72,7 +71,7 @@ class TestGrid < ScopeTestReport it { expect(report).to be_redefined_scope } end - context 'overriding scope by initializer' do + context "overriding scope by initializer" do let(:report) { report_class.new { Entry.limit(1) } } it { expect(report).to be_redefined_scope } @@ -88,7 +87,7 @@ class TestGrid < ScopeTestReport end context "appending scope by initializer " do - let(:report) { report_class.new {|scope| scope.limit(1)} } + let(:report) { report_class.new { |scope| scope.limit(1) } } it { expect(report.scope.to_a.size).to eq(1) } it { expect(report.scope.order_values.size).to eq(1) } it { expect(report).to be_redefined_scope } @@ -100,20 +99,20 @@ class TestGrid < ScopeTestReport it "should show all attribute values" do class InspectTest include Datagrid - scope {Entry} + scope { Entry } filter(:created_at, :date, range: true) column(:name) end - grid = InspectTest.new(created_at: ['2014-01-01', '2014-08-05'], descending: true, order: 'name') - expect(grid.inspect).to eq('#<InspectTest order: :name, descending: true, created_at: [Wed, 01 Jan 2014, Tue, 05 Aug 2014]>') + grid = InspectTest.new(created_at: %w[2014-01-01 2014-08-05], descending: true, order: "name") + expect(grid.inspect).to eq("#<InspectTest order: :name, descending: true, created_at: [Wed, 01 Jan 2014, Tue, 05 Aug 2014]>") end end describe "#==" do class EqualTest include Datagrid - scope {Entry} + scope { Entry } filter(:created_at, :date) column(:name) column(:created_at) @@ -131,14 +130,14 @@ class EqualTest expect(EqualTest.new(order: :created_at)).to eq(EqualTest.new(order: "created_at")) end it "checks for redefined scope" do - expect(EqualTest.new).to_not eq(EqualTest.new {|s| s.reorder(:name)}) + expect(EqualTest.new).to_not eq(EqualTest.new { |s| s.reorder(:name) }) end end - describe 'dynamic helper' do + describe "dynamic helper" do it "should work" do grid = test_report do - scope {Entry} + scope { Entry } column(:id) dynamic do column(:name) @@ -146,7 +145,7 @@ class EqualTest end end - expect(grid.columns.map(&:name)).to eq([:id, :name, :category]) + expect(grid.columns.map(&:name)).to eq(%i[id name category]) expect(grid.class.columns.map(&:name)).to eq([:id]) expect(grid.column_by_name(:id)).not_to be_nil @@ -154,8 +153,8 @@ class EqualTest end it "has access to attributes" do - grid = test_report(attribute_name: 'value') do - scope {Entry} + grid = test_report(attribute_name: "value") do + scope { Entry } datagrid_attribute :attribute_name dynamic do value = attribute_name @@ -163,12 +162,12 @@ class EqualTest end end - expect(grid.data_value(:name, Entry.create!)).to eq('value') + expect(grid.data_value(:name, Entry.create!)).to eq("value") end it "applies before instance scope" do klass = test_report_class do - scope {Entry} + scope { Entry } dynamic do scope do |s| s.limit(1) @@ -184,8 +183,8 @@ class EqualTest end it "has access to grid attributes within scope" do - grid = test_report(name: 'one') do - scope {Entry} + grid = test_report(name: "one") do + scope { Entry } dynamic do scope do |s| s.where(name: name) @@ -193,58 +192,56 @@ class EqualTest end filter(:name, dummy: true) end - one = Entry.create!(name: 'one') - two = Entry.create!(name: 'two') + one = Entry.create!(name: "one") + two = Entry.create!(name: "two") expect(grid.assets).to include(one) expect(grid.assets).to_not include(two) end end describe "ActionController::Parameters" do - let(:params) do - ::ActionController::Parameters.new(name: 'one') + ::ActionController::Parameters.new(name: "one") end it "permites all attributes by default" do - expect { + expect do test_report(params) do scope { Entry } filter(:name) end - }.to_not raise_error + end.to_not raise_error end it "doesn't permit attributes when forbidden_attributes_protection is set" do - expect { + expect do test_report(params) do scope { Entry } self.forbidden_attributes_protection = true filter(:name) end - }.to raise_error(ActiveModel::ForbiddenAttributesError) + end.to raise_error(ActiveModel::ForbiddenAttributesError) end it "permits attributes when forbidden_attributes_protection is set and attributes are permitted" do - expect { + expect do test_report(params.permit!) do scope { Entry } self.forbidden_attributes_protection = true filter(:name) end - }.to_not raise_error + end.to_not raise_error end end - describe ".query_param" do it "works" do - grid = test_report(name: 'value') do - scope {Entry} + grid = test_report(name: "value") do + scope { Entry } filter(:name) def param_name - 'grid' + "grid" end end - expect(grid.query_params).to eq({grid: {name: 'value'}}) + expect(grid.query_params).to eq({ grid: { name: "value" } }) end end end diff --git a/spec/datagrid/drivers/active_record_spec.rb b/spec/datagrid/drivers/active_record_spec.rb index a3c418d..c41a1cf 100644 --- a/spec/datagrid/drivers/active_record_spec.rb +++ b/spec/datagrid/drivers/active_record_spec.rb @@ -1,13 +1,12 @@ -require 'spec_helper' +require "spec_helper" describe Datagrid::Drivers::ActiveRecord do - describe ".match?" do subject { described_class } - it {should be_match(Entry)} - it {should be_match(Entry.where(:id => 1))} - it {should_not be_match(MongoidEntry)} + it { should be_match(Entry) } + it { should be_match(Entry.where(id: 1)) } + it { should_not be_match(MongoidEntry) } end it "should convert any scope to AR::Relation" do @@ -17,13 +16,15 @@ end it "should support append_column_queries" do - scope = subject.append_column_queries(Entry.where({}), [Datagrid::Columns::Column.new(test_report_class, :sum_group_id, 'sum(entries.group_id)')]) + scope = subject.append_column_queries(Entry.where({}), + [Datagrid::Columns::Column.new(test_report_class, :sum_group_id, + "sum(entries.group_id)")]) expect(scope.to_sql.strip).to eq('SELECT "entries".*, sum(entries.group_id) AS sum_group_id FROM "entries"') end describe "Arel" do subject do - test_report(:order => :test, :descending => true) do + test_report(order: :test, descending: true) do scope { Entry } column(:test, order: Entry.arel_table[:group_id].count) end.assets @@ -35,45 +36,41 @@ end describe "gotcha #datagrid_where_by_timestamp" do - subject do test_report(created_at: 10.days.ago..5.days.ago) do - scope {Entry} + scope { Entry } - filter(:created_at, :date, range: true) do |value, scope, grid| + filter(:created_at, :date, range: true) do |value, scope, _grid| scope.joins(:group).datagrid_where_by_timestamp("groups.created_at", value) end end.assets end it "includes object created in proper range" do expect(subject).to include( - Entry.create!(group: Group.create!(created_at: 7.days.ago)), + Entry.create!(group: Group.create!(created_at: 7.days.ago)) ) end it "excludes object created before the range" do expect(subject).to_not include( - Entry.create!(created_at: 7.days.ago, group: Group.create!(created_at: 11.days.ago)), + Entry.create!(created_at: 7.days.ago, group: Group.create!(created_at: 11.days.ago)) ) end it "excludes object created after the range" do expect(subject).to_not include( - Entry.create!(created_at: 7.days.ago, group: Group.create!(created_at: 4.days.ago)), + Entry.create!(created_at: 7.days.ago, group: Group.create!(created_at: 4.days.ago)) ) end end describe "batches usage" do - it "should be incompatible with scope with limit" do report = test_report do - scope {Entry.limit(5)} + scope { Entry.limit(5) } self.batch_size = 20 column(:id) end expect { report.data }.to raise_error(Datagrid::ConfigurationError) end end - - end diff --git a/spec/datagrid/drivers/array_spec.rb b/spec/datagrid/drivers/array_spec.rb index 1a82a27..c0263f9 100644 --- a/spec/datagrid/drivers/array_spec.rb +++ b/spec/datagrid/drivers/array_spec.rb @@ -1,17 +1,15 @@ -require 'spec_helper' +require "spec_helper" describe Datagrid::Drivers::Array do - describe ".match?" do subject { described_class } - it {should be_match(Array.new)} - it {should be_match(ActiveRecord::Result.new([], []))} - it {should_not be_match({})} + it { should be_match([]) } + it { should be_match(ActiveRecord::Result.new([], [])) } + it { should_not be_match({}) } end describe "api" do - class ArrayGrid class User < Struct.new(:name, :age); end include Datagrid @@ -20,7 +18,7 @@ class User < Struct.new(:name, :age); end end filter(:name) - filter(:age, :integer, :range => true) + filter(:age, :integer, range: true) column(:name) column(:age) @@ -33,70 +31,66 @@ class User < Struct.new(:name, :age); end subject do ArrayGrid.new(_attributes).scope do - [ first, second, third ] + [first, second, third] end end - - describe '#assets' do + describe "#assets" do subject { super().assets } - describe '#size' do + describe "#size" do subject { super().size } - it {should == 3} + it { should == 3 } end end - describe '#rows' do + describe "#rows" do subject { super().rows } - it {should == [["Vasya", 15], ["Petya", 12], ["Vova", 13]]} + it { should == [["Vasya", 15], ["Petya", 12], ["Vova", 13]] } end - describe '#header' do + describe "#header" do subject { super().header } - it {should ==[ "Name", "Age"]} + it { should == %w[Name Age] } end - describe '#data' do + describe "#data" do subject { super().data } - it {should == [[ "Name", "Age"], ["Vasya", 15], ["Petya", 12], ["Vova", 13]]} + it { should == [%w[Name Age], ["Vasya", 15], ["Petya", 12], ["Vova", 13]] } end - describe "when some filters specified" do - let(:_attributes) { {:age => [12,14]} } + let(:_attributes) { { age: [12, 14] } } - describe '#assets' do + describe "#assets" do subject { super().assets } - it {should_not include(first)} + it { should_not include(first) } end - describe '#assets' do + describe "#assets" do subject { super().assets } - it {should include(second)} + it { should include(second) } end - describe '#assets' do + describe "#assets" do subject { super().assets } - it {should include(third)} + it { should include(third) } end end describe "when reverse ordering is specified" do - let(:_attributes) { {:order => :name, :descending => true} } + let(:_attributes) { { order: :name, descending: true } } - describe '#assets' do + describe "#assets" do subject { super().assets } - it {should == [third, first, second]} + it { should == [third, first, second] } end end - end describe "when using enumerator scope" do - it "should work fine" do grid = test_report(to_enum: true) do - scope {[]} + scope { [] } filter(:to_enum, :boolean) do |_, scope| scope.to_enum end @@ -109,11 +103,11 @@ class User < Struct.new(:name, :age); end class HashGrid include Datagrid scope do - [{name: 'Bogdan', age: 30}, {name: 'Brad', age: 32}] + [{ name: "Bogdan", age: 30 }, { name: "Brad", age: 32 }] end filter(:name) - filter(:age, :integer, :range => true) + filter(:age, :integer, range: true) column(:name) column(:age) @@ -126,9 +120,9 @@ class HashGrid end context "ordered" do - let(:_attributes) { { order: :name, descending: true }} + let(:_attributes) { { order: :name, descending: true } } - it { subject.assets.should == [ {name: 'Brad', age: 32}, {name: 'Bogdan', age: 30},] } + it { subject.assets.should == [{ name: "Brad", age: 32 }, { name: "Bogdan", age: 30 }] } end end end diff --git a/spec/datagrid/drivers/mongo_mapper_spec.rb b/spec/datagrid/drivers/mongo_mapper_spec.rb index ad6ee89..6cacf76 100644 --- a/spec/datagrid/drivers/mongo_mapper_spec.rb +++ b/spec/datagrid/drivers/mongo_mapper_spec.rb @@ -1,20 +1,16 @@ require "spec_helper" describe Datagrid::Drivers::MongoMapper, :mongomapper do - if defined?(MongoMapper) describe ".match?" do - subject { described_class } - it {should be_match(MongoMapperEntry)} + it { should be_match(MongoMapperEntry) } # MongoMapper doesn't have a scoped method, instead it has a query method which returns a Plucky::Query object - it {should be_match(MongoMapperEntry.query)} - it {should_not be_match(Entry.where(:id => 1))} - + it { should be_match(MongoMapperEntry.query) } + it { should_not be_match(Entry.where(id: 1)) } end describe "api" do - subject do MongoMapperGrid.new( defined?(_attributes) ? _attributes : {} @@ -23,79 +19,77 @@ let!(:first) do MongoMapperEntry.create!( - :group_id => 2, - :name => "Main First", - :disabled => false + group_id: 2, + name: "Main First", + disabled: false ) end let!(:second) do MongoMapperEntry.create!( - :group_id => 3, - :name => "Main Second", - :disabled => true + group_id: 3, + name: "Main Second", + disabled: true ) end - - describe '#assets' do + describe "#assets" do subject { super().assets } - it {should include(first, second)} + it { should include(first, second) } end - describe '#assets' do + describe "#assets" do subject { super().assets } - describe '#size' do + describe "#size" do subject { super().size } - it {should == 2} + it { should == 2 } end end - describe '#rows' do + describe "#rows" do subject { super().rows } - it {should == [["Main First", 2, false], ["Main Second", 3, true]]} + it { should == [["Main First", 2, false], ["Main Second", 3, true]] } end - describe '#header' do + describe "#header" do subject { super().header } - it {should ==[ "Name", "Group", "Disabled"]} + it { should == %w[Name Group Disabled] } end - describe '#data' do + describe "#data" do subject { super().data } - it {should == [[ "Name", "Group", "Disabled"], ["Main First", 2, false], ["Main Second", 3, true]]} + it { should == [["Name", "Group", "Disabled"], ["Main First", 2, false], ["Main Second", 3, true]] } end - describe "when some filters specified" do - let(:_attributes) { {group_id: [3, nil]} } + let(:_attributes) { { group_id: [3, nil] } } - describe '#assets' do + describe "#assets" do subject { super().assets } - it {should_not include(first)} + it { should_not include(first) } end - describe '#assets' do + describe "#assets" do subject { super().assets } - it {should include(second)} + it { should include(second) } end end describe "when reverse ordering is specified" do - let(:_attributes) { {:order => :name, :descending => true} } + let(:_attributes) { { order: :name, descending: true } } - describe '#rows' do + describe "#rows" do subject { super().rows } - it {should == [["Main Second", 3, true], ["Main First", 2, false]]} + it { should == [["Main Second", 3, true], ["Main First", 2, false]] } end end it "should not provide default order for non declared fields" do - expect { - test_report(:order => :test) do + expect do + test_report(order: :test) do scope { MongoMapperEntry } column(:test) - end.assets - }.to raise_error(Datagrid::OrderUnsupported) - end + end.assets + end.to raise_error(Datagrid::OrderUnsupported) end end end +end diff --git a/spec/datagrid/drivers/mongoid_spec.rb b/spec/datagrid/drivers/mongoid_spec.rb index 32108f5..b119951 100644 --- a/spec/datagrid/drivers/mongoid_spec.rb +++ b/spec/datagrid/drivers/mongoid_spec.rb @@ -1,18 +1,14 @@ require "spec_helper" describe Datagrid::Drivers::Mongoid, :mongoid do - describe ".match?" do - subject { described_class } - it {should be_match(MongoidEntry)} - it {should be_match(MongoidEntry.scoped)} - it {should_not be_match(Entry.where(:id => 1))} - + it { should be_match(MongoidEntry) } + it { should be_match(MongoidEntry.scoped) } + it { should_not be_match(Entry.where(id: 1)) } end describe "api" do - subject do MongoidGrid.new( defined?(_attributes) ? _attributes : {} @@ -21,79 +17,77 @@ let!(:first) do MongoidEntry.create!( - :group_id => 2, - :name => "Main First", - :disabled => false + group_id: 2, + name: "Main First", + disabled: false ) end let!(:second) do MongoidEntry.create!( - :group_id => 3, - :name => "Main Second", - :disabled => true + group_id: 3, + name: "Main Second", + disabled: true ) end - - describe '#assets' do + describe "#assets" do subject { super().assets } - it {should include(first, second)} + it { should include(first, second) } end - describe '#assets' do + describe "#assets" do subject { super().assets } - describe '#size' do + describe "#size" do subject { super().size } - it {should == 2} + it { should == 2 } end end - describe '#rows' do + describe "#rows" do subject { super().rows } - it {should == [["Main First", 2, false], ["Main Second", 3, true]]} + it { should == [["Main First", 2, false], ["Main Second", 3, true]] } end - describe '#header' do + describe "#header" do subject { super().header } - it {should ==[ "Name", "Group", "Disabled"]} + it { should == %w[Name Group Disabled] } end - describe '#data' do + describe "#data" do subject { super().data } - it {should == [[ "Name", "Group", "Disabled"], ["Main First", 2, false], ["Main Second", 3, true]]} + it { should == [["Name", "Group", "Disabled"], ["Main First", 2, false], ["Main Second", 3, true]] } end - describe "when some filters specified" do - let(:_attributes) { {group_id: [3, nil]} } + let(:_attributes) { { group_id: [3, nil] } } - describe '#assets' do + describe "#assets" do subject { super().assets.map(&:_id) } - it {should_not include(first.id)} + it { should_not include(first.id) } end - describe '#assets' do + describe "#assets" do subject { super().assets } - it {should include(second)} + it { should include(second) } end end describe "when reverse ordering is specified" do - let(:_attributes) { {:order => :name, :descending => true} } + let(:_attributes) { { order: :name, descending: true } } - describe '#rows' do + describe "#rows" do subject { super().rows } - it {should == [["Main Second", 3, true], ["Main First", 2, false]]} + it { should == [["Main Second", 3, true], ["Main First", 2, false]] } end end it "should not provide default order for non declared fields" do - expect { - test_report(:order => :test) do + expect do + test_report(order: :test) do scope { MongoidEntry } column(:test) end.assets - }.to raise_error(Datagrid::OrderUnsupported) + end.to raise_error(Datagrid::OrderUnsupported) end it "should support batch_size" do diff --git a/spec/datagrid/drivers/sequel_spec.rb b/spec/datagrid/drivers/sequel_spec.rb index 7e462b7..731b19d 100644 --- a/spec/datagrid/drivers/sequel_spec.rb +++ b/spec/datagrid/drivers/sequel_spec.rb @@ -1,18 +1,14 @@ -require 'spec_helper' +require "spec_helper" describe Datagrid::Drivers::Sequel do - describe ".match?" do - subject { described_class } - it {should be_match(SequelEntry)} - it {should be_match(SequelEntry.where(:id => 1))} - it {should_not be_match(Entry.where(:id => 1))} - + it { should be_match(SequelEntry) } + it { should be_match(SequelEntry.where(id: 1)) } + it { should_not be_match(Entry.where(id: 1)) } end describe "api" do - subject do SequelGrid.new( defined?(_attributes) ? _attributes : {} @@ -21,16 +17,16 @@ let!(:first) do SequelEntry.create( - :group_id => 2, - :name => "Main First", - :disabled => false + group_id: 2, + name: "Main First", + disabled: false ) end let!(:second) do SequelEntry.create( - :group_id => 3, - :name => "Main Second", - :disabled => true + group_id: 3, + name: "Main Second", + disabled: true ) end @@ -40,73 +36,72 @@ class PaginationTest scope { SequelEntry } end grid = PaginationTest.new do |scope| - scope.paginate(1,25) + scope.paginate(1, 25) end expect(grid.rows.to_a).to be_kind_of(Array) expect(grid.assets.to_a).to be_kind_of(Array) end - describe '#assets' do + describe "#assets" do subject { super().assets } - it {should include(first, second)} + it { should include(first, second) } end - describe '#assets' do + describe "#assets" do subject { super().assets } - describe '#size' do + describe "#size" do subject { super().count } - it {should == 2} + it { should == 2 } end end - describe '#rows' do + describe "#rows" do subject { super().rows } - it {should == [["Main First", 2, false], ["Main Second", 3, true]]} + it { should == [["Main First", 2, false], ["Main Second", 3, true]] } end - describe '#header' do + describe "#header" do subject { super().header } - it {should ==[ "Name", "Group", "Disabled"]} + it { should == %w[Name Group Disabled] } end - describe '#data' do + describe "#data" do subject { super().data } - it {should == [[ "Name", "Group", "Disabled"], ["Main First", 2, false], ["Main Second", 3, true]]} + it { should == [["Name", "Group", "Disabled"], ["Main First", 2, false], ["Main Second", 3, true]] } end - describe "when some filters specified" do - let(:_attributes) { {group_id: 3..100} } + let(:_attributes) { { group_id: 3..100 } } - describe '#assets' do + describe "#assets" do subject { super().assets.map(&:id) } - it {should_not include(first.id)} + it { should_not include(first.id) } end - describe '#assets' do + describe "#assets" do subject { super().assets } - it {should include(second)} + it { should include(second) } end end describe "when reverse ordering is specified" do - let(:_attributes) { {:order => :name, :descending => true} } + let(:_attributes) { { order: :name, descending: true } } - describe '#rows' do + describe "#rows" do subject { super().rows } - it {should == [["Main Second", 3, true], ["Main First", 2, false]]} + it { should == [["Main Second", 3, true], ["Main First", 2, false]] } end end it "should provide default order for non declared fields" do - expect { - test_report(:order => :test) do + expect do + test_report(order: :test) do scope { SequelEntry } column(:test) do - 'test' + "test" end end.assets - }.to raise_error(Datagrid::OrderUnsupported) + end.to raise_error(Datagrid::OrderUnsupported) end it "should support batch_size" do diff --git a/spec/datagrid/filters/base_filter_spec.rb b/spec/datagrid/filters/base_filter_spec.rb index 10acc2c..44160da 100644 --- a/spec/datagrid/filters/base_filter_spec.rb +++ b/spec/datagrid/filters/base_filter_spec.rb @@ -1,19 +1,16 @@ -require 'spec_helper' +require "spec_helper" describe Datagrid::Filters::BaseFilter do - - it "should support default option as block" do report = test_report do - scope {Entry} - filter(:name, :string, :default => :name_default) + scope { Entry } + filter(:name, :string, default: :name_default) def name_default - 'hello' + "hello" end end - expect(report.assets).to include(Entry.create!(:name => "hello")) - expect(report.assets).not_to include(Entry.create!(:name => "world")) - expect(report.assets).not_to include(Entry.create!(:name => "")) + expect(report.assets).to include(Entry.create!(name: "hello")) + expect(report.assets).not_to include(Entry.create!(name: "world")) + expect(report.assets).not_to include(Entry.create!(name: "")) end - end diff --git a/spec/datagrid/filters/composite_filters_spec.rb b/spec/datagrid/filters/composite_filters_spec.rb index 8bb10ae..b40e2a4 100644 --- a/spec/datagrid/filters/composite_filters_spec.rb +++ b/spec/datagrid/filters/composite_filters_spec.rb @@ -1,15 +1,13 @@ -require 'spec_helper' +require "spec_helper" describe Datagrid::Filters::CompositeFilters do - describe ".date_range_filters" do - it "should generate from date and to date filters" do - e1 = Entry.create!(:shipping_date => 6.days.ago) - e2 = Entry.create!(:shipping_date => 4.days.ago) - e3 = Entry.create!(:shipping_date => 1.days.ago) - assets = test_report(:from_shipping_date => 5.days.ago, :to_shipping_date => 2.day.ago) do - scope {Entry} + e1 = Entry.create!(shipping_date: 6.days.ago) + e2 = Entry.create!(shipping_date: 4.days.ago) + e3 = Entry.create!(shipping_date: 1.days.ago) + assets = test_report(from_shipping_date: 5.days.ago, to_shipping_date: 2.day.ago) do + scope { Entry } silence_warnings do date_range_filters(:shipping_date) end @@ -22,7 +20,7 @@ it "should support options" do report = test_report do silence_warnings do - date_range_filters(:shipping_date, {:default => 10.days.ago.to_date}, {:default => Date.today}) + date_range_filters(:shipping_date, { default: 10.days.ago.to_date }, { default: Date.today }) end end expect(report.from_shipping_date).to eq(10.days.ago.to_date) @@ -31,7 +29,7 @@ it "should support table name in field" do report = test_report do silence_warnings do - date_range_filters("entries.shipping_date", {:default => 10.days.ago.to_date}, {:default => Date.today}) + date_range_filters("entries.shipping_date", { default: 10.days.ago.to_date }, { default: Date.today }) end end expect(report.from_entries_shipping_date).to eq(10.days.ago.to_date) @@ -40,13 +38,12 @@ end describe ".integer_range_filters" do - it "should generate from integer and to integer filters" do - e1 = Entry.create!(:group_id => 1) - e2 = Entry.create!(:group_id => 3) - e3 = Entry.create!(:group_id => 5) - assets = test_report(:from_group_id => 2, :to_group_id => 4) do - scope {Entry} + e1 = Entry.create!(group_id: 1) + e2 = Entry.create!(group_id: 3) + e3 = Entry.create!(group_id: 5) + assets = test_report(from_group_id: 2, to_group_id: 4) do + scope { Entry } silence_warnings do integer_range_filters(:group_id) end @@ -58,7 +55,7 @@ it "should support options" do report = test_report do silence_warnings do - integer_range_filters(:group_id, {:default => 0}, {:default => 100}) + integer_range_filters(:group_id, { default: 0 }, { default: 100 }) end end expect(report.from_group_id).to eq(0) @@ -67,7 +64,7 @@ it "should table name in field name" do report = test_report do silence_warnings do - integer_range_filters("entries.group_id", {:default => 0}, {:default => 100}) + integer_range_filters("entries.group_id", { default: 0 }, { default: 100 }) end end expect(report.from_entries_group_id).to eq(0) diff --git a/spec/datagrid/filters/date_filter_spec.rb b/spec/datagrid/filters/date_filter_spec.rb index e459283..56fd5ce 100644 --- a/spec/datagrid/filters/date_filter_spec.rb +++ b/spec/datagrid/filters/date_filter_spec.rb @@ -1,8 +1,7 @@ -require 'spec_helper' +require "spec_helper" require "active_support/testing/time_helpers" describe Datagrid::Filters::DateFilter do - it "supports date range argument" do e1 = Entry.create!(created_at: 7.days.ago) e2 = Entry.create!(created_at: 4.days.ago) @@ -30,7 +29,7 @@ expect(report.assets).not_to include(e2) end - {active_record: Entry, mongoid: MongoidEntry, sequel: SequelEntry}.each do |orm, klass| + { active_record: Entry, mongoid: MongoidEntry, sequel: SequelEntry }.each do |orm, klass| describe "with orm #{orm}", orm => true do describe "date to timestamp conversion" do let(:klass) { klass } @@ -47,20 +46,20 @@ def entry_dated(date) context "when single date paramter given" do let(:_created_at) { Date.today } - it { should include(entry_dated(1.second.ago))} - it { should include(entry_dated(Date.today.end_of_day))} - it { should_not include(entry_dated(Date.today.beginning_of_day - 1.second))} - it { should_not include(entry_dated(Date.today.end_of_day + 1.second))} + it { should include(entry_dated(1.second.ago)) } + it { should include(entry_dated(Date.today.end_of_day)) } + it { should_not include(entry_dated(Date.today.beginning_of_day - 1.second)) } + it { should_not include(entry_dated(Date.today.end_of_day + 1.second)) } end context "when range date range given" do let(:_created_at) { [Date.yesterday, Date.today] } - it { should include(entry_dated(1.second.ago))} - it { should include(entry_dated(1.day.ago))} - it { should include(entry_dated(Date.today.end_of_day))} - it { should include(entry_dated(Date.yesterday.beginning_of_day))} - it { should_not include(entry_dated(Date.yesterday.beginning_of_day - 1.second))} - it { should_not include(entry_dated(Date.today.end_of_day + 1.second))} + it { should include(entry_dated(1.second.ago)) } + it { should include(entry_dated(1.day.ago)) } + it { should include(entry_dated(Date.today.end_of_day)) } + it { should include(entry_dated(Date.yesterday.beginning_of_day)) } + it { should_not include(entry_dated(Date.yesterday.beginning_of_day - 1.second)) } + it { should_not include(entry_dated(Date.today.end_of_day + 1.second)) } end end end @@ -106,7 +105,6 @@ def entry_dated(date) end it "should find something in one day interval" do - e1 = Entry.create!(created_at: 7.days.ago) e2 = Entry.create!(created_at: 4.days.ago) e3 = Entry.create!(created_at: 1.day.ago) @@ -134,10 +132,9 @@ def entry_dated(date) expect(report.assets).to include(e3) end - it "should support block" do - date = Date.new(2018, 01, 07) - time = Time.utc(2018, 01, 07, 2, 2) + date = Date.new(2018, 0o1, 0o7) + time = Time.utc(2018, 0o1, 0o7, 2, 2) report = test_report(created_at: date) do scope { Entry } filter(:created_at, :date, range: true) do |value| @@ -148,7 +145,6 @@ def entry_dated(date) expect(report.assets).to include(Entry.create!(created_at: time)) end - context "when date format is configured" do around(:each) do |example| with_date_format do @@ -158,40 +154,39 @@ def entry_dated(date) it "should have configurable date format" do report = test_report(created_at: "10/01/2013") do - scope {Entry} + scope { Entry } filter(:created_at, :date) end - expect(report.created_at).to eq(Date.new(2013,10,01)) + expect(report.created_at).to eq(Date.new(2013, 10, 0o1)) end it "should support default explicit date" do report = test_report(created_at: Date.parse("2013-10-01")) do - scope {Entry} + scope { Entry } filter(:created_at, :date) end - expect(report.created_at).to eq(Date.new(2013,10,01)) + expect(report.created_at).to eq(Date.new(2013, 10, 0o1)) end end - it "should automatically reverse Array if first more than last" do - report = test_report(created_at: ["2013-01-01", "2012-01-01"]) do - scope {Entry} + report = test_report(created_at: %w[2013-01-01 2012-01-01]) do + scope { Entry } filter(:created_at, :date, range: true) end - expect(report.created_at).to eq([Date.new(2012, 01, 01), Date.new(2013, 01, 01)]) + expect(report.created_at).to eq([Date.new(2012, 0o1, 0o1), Date.new(2013, 0o1, 0o1)]) end it "should automatically reverse Array if first more than last" do - report = test_report(created_at: ["2013-01-01", "2012-01-01"]) do - scope {Entry} + report = test_report(created_at: %w[2013-01-01 2012-01-01]) do + scope { Entry } filter(:created_at, :date, range: true) end - expect(report.created_at).to eq([Date.new(2012, 01, 01), Date.new(2013, 01, 01)]) + expect(report.created_at).to eq([Date.new(2012, 0o1, 0o1), Date.new(2013, 0o1, 0o1)]) end it "should nullify blank range" do report = test_report(created_at: [nil, nil]) do - scope {Entry} + scope { Entry } filter(:created_at, :date, range: true) end @@ -201,11 +196,10 @@ def entry_dated(date) it "should properly format date in filter_value_as_string" do with_date_format do report = test_report(created_at: "2012-01-02") do - scope {Entry} + scope { Entry } filter(:created_at, :date) end expect(report.filter_value_as_string(:created_at)).to eq("01/02/2012") end end - end diff --git a/spec/datagrid/filters/date_time_filter_spec.rb b/spec/datagrid/filters/date_time_filter_spec.rb index 41c833c..425b442 100644 --- a/spec/datagrid/filters/date_time_filter_spec.rb +++ b/spec/datagrid/filters/date_time_filter_spec.rb @@ -1,7 +1,7 @@ -require 'spec_helper' +require "spec_helper" describe Datagrid::Filters::DateTimeFilter do - {:active_record => Entry, :mongoid => MongoidEntry}.each do |orm, klass| + { active_record: Entry, mongoid: MongoidEntry }.each do |orm, klass| describe "with orm #{orm}", orm => true do describe "timestamp to timestamp conversion" do let(:klass) { klass } @@ -24,38 +24,37 @@ def entry_dated(date) context "with single datetime paramter given" do let(:_created_at) { Time.now.change(sec: 0) } it { should include(entry_dated(_created_at)) } - it { should_not include(entry_dated(_created_at - 1.second))} - it { should_not include(entry_dated(_created_at + 1.second))} + it { should_not include(entry_dated(_created_at - 1.second)) } + it { should_not include(entry_dated(_created_at + 1.second)) } end context "with range datetime range given" do let(:_created_at) { [Time.now.beginning_of_day, Time.now.end_of_day] } - it { should include(entry_dated(1.second.ago))} - it { should include(entry_dated(Date.today.to_time))} - it { should include(entry_dated(Time.now.end_of_day.to_time))} - it { should_not include(entry_dated(Date.yesterday.end_of_day))} - it { should_not include(entry_dated(Date.tomorrow.beginning_of_day))} + it { should include(entry_dated(1.second.ago)) } + it { should include(entry_dated(Date.today.to_time)) } + it { should include(entry_dated(Time.now.end_of_day.to_time)) } + it { should_not include(entry_dated(Date.yesterday.end_of_day)) } + it { should_not include(entry_dated(Date.tomorrow.beginning_of_day)) } end context "with right open range" do let(:_created_at) { Time.now.beginning_of_day..nil } - it { should include(entry_dated(1.second.ago))} - it { should include(entry_dated(Date.today.to_time))} - it { should include(entry_dated(Time.now.end_of_day.to_time))} - it { should include(entry_dated(Date.tomorrow.beginning_of_day))} - it { should_not include(entry_dated(Date.yesterday.end_of_day))} + it { should include(entry_dated(1.second.ago)) } + it { should include(entry_dated(Date.today.to_time)) } + it { should include(entry_dated(Time.now.end_of_day.to_time)) } + it { should include(entry_dated(Date.tomorrow.beginning_of_day)) } + it { should_not include(entry_dated(Date.yesterday.end_of_day)) } end context "with left open range" do let(:_created_at) { nil..Time.now.end_of_day } - it { should include(entry_dated(1.second.ago))} - it { should include(entry_dated(Date.today.to_time))} - it { should include(entry_dated(Time.now.end_of_day.to_time))} - it { should include(entry_dated(Date.yesterday.end_of_day))} - it { should_not include(entry_dated(Date.tomorrow.beginning_of_day))} + it { should include(entry_dated(1.second.ago)) } + it { should include(entry_dated(Date.today.to_time)) } + it { should include(entry_dated(Time.now.end_of_day.to_time)) } + it { should include(entry_dated(Date.yesterday.end_of_day)) } + it { should_not include(entry_dated(Date.tomorrow.beginning_of_day)) } end end - end end @@ -126,7 +125,6 @@ def entry_dated(date) expect(report.assets).to include(e3) end - it "should support block" do report = test_report(created_at: Time.now) do scope { Entry } @@ -135,10 +133,9 @@ def entry_dated(date) end end expect(report.assets).not_to include(Entry.create!(created_at: 1.day.ago)) - expect(report.assets).to include(Entry.create!(created_at: Time.now+1.day)) + expect(report.assets).to include(Entry.create!(created_at: Time.now + 1.day)) end - context "when datetime format is configured" do around(:each) do |example| with_datetime_format("%m/%d/%Y %H:%M") do @@ -148,27 +145,26 @@ def entry_dated(date) it "should have configurable datetime format" do report = test_report(created_at: "10/01/2013 01:00") do - scope {Entry} + scope { Entry } filter(:created_at, :datetime) end - expect(report.created_at).to eq(Time.new(2013,10,01,1,0)) + expect(report.created_at).to eq(Time.new(2013, 10, 0o1, 1, 0)) end it "should support default explicit datetime" do report = test_report(created_at: Time.parse("2013-10-01 01:00")) do - scope {Entry} + scope { Entry } filter(:created_at, :datetime) end - expect(report.created_at).to eq(Time.new(2013,10,01,1,0)) + expect(report.created_at).to eq(Time.new(2013, 10, 0o1, 1, 0)) end end - it "should automatically reverse Array if first more than last" do report = test_report(created_at: ["2013-01-01 01:00", "2012-01-01 01:00"]) do - scope {Entry} + scope { Entry } filter(:created_at, :datetime, range: true) end - expect(report.created_at).to eq([Time.new(2012, 01, 01, 1, 0), Time.new(2013, 01, 01, 1, 0)]) + expect(report.created_at).to eq([Time.new(2012, 0o1, 0o1, 1, 0), Time.new(2013, 0o1, 0o1, 1, 0)]) end end diff --git a/spec/datagrid/filters/dynamic_filter_spec.rb b/spec/datagrid/filters/dynamic_filter_spec.rb index da6a052..6bbfa7c 100644 --- a/spec/datagrid/filters/dynamic_filter_spec.rb +++ b/spec/datagrid/filters/dynamic_filter_spec.rb @@ -1,128 +1,128 @@ require "spec_helper" - describe Datagrid::Filters::DynamicFilter do let(:report) do test_report do - scope {Entry} + scope { Entry } filter(:condition, :dynamic) end end it "should support = operation" do report.condition = [:name, "=", "hello"] - expect(report.assets).to include(Entry.create!(:name => 'hello')) - expect(report.assets).not_to include(Entry.create!(:name => 'bye')) + expect(report.assets).to include(Entry.create!(name: "hello")) + expect(report.assets).not_to include(Entry.create!(name: "bye")) end it "should support >= operation" do report.condition = [:name, ">=", "d"] - expect(report.assets).to include(Entry.create!(:name => 'x')) - expect(report.assets).to include(Entry.create!(:name => 'd')) - expect(report.assets).not_to include(Entry.create!(:name => 'a')) + expect(report.assets).to include(Entry.create!(name: "x")) + expect(report.assets).to include(Entry.create!(name: "d")) + expect(report.assets).not_to include(Entry.create!(name: "a")) end it "should blank value" do report.condition = [:name, "=", ""] - expect(report.assets).to include(Entry.create!(:name => 'hello')) + expect(report.assets).to include(Entry.create!(name: "hello")) end it "should support =~ operation on strings" do report.condition = [:name, "=~", "ell"] - expect(report.assets).to include(Entry.create!(:name => 'hello')) - expect(report.assets).not_to include(Entry.create!(:name => 'bye')) + expect(report.assets).to include(Entry.create!(name: "hello")) + expect(report.assets).not_to include(Entry.create!(name: "bye")) end it "should support =~ operation integers" do report.condition = [:group_id, "=~", 2] - expect(report.assets).to include(Entry.create!(:group_id => 2)) - expect(report.assets).not_to include(Entry.create!(:group_id => 1)) - expect(report.assets).not_to include(Entry.create!(:group_id => 3)) + expect(report.assets).to include(Entry.create!(group_id: 2)) + expect(report.assets).not_to include(Entry.create!(group_id: 1)) + expect(report.assets).not_to include(Entry.create!(group_id: 3)) end it "should support >= operation on integer" do report.condition = [:group_id, ">=", 2] - expect(report.assets).to include(Entry.create!(:group_id => 3)) - expect(report.assets).not_to include(Entry.create!(:group_id => 1)) + expect(report.assets).to include(Entry.create!(group_id: 3)) + expect(report.assets).not_to include(Entry.create!(group_id: 1)) end it "should support <= operation on integer" do report.condition = [:group_id, "<=", 2] - expect(report.assets).to include(Entry.create!(:group_id => 1)) - expect(report.assets).not_to include(Entry.create!(:group_id => 3)) + expect(report.assets).to include(Entry.create!(group_id: 1)) + expect(report.assets).not_to include(Entry.create!(group_id: 3)) end it "should support <= operation on integer with string value" do - report.condition = [:group_id, "<=", '2'] - expect(report.assets).to include(Entry.create!(:group_id => 1)) - expect(report.assets).to include(Entry.create!(:group_id => 2)) - expect(report.assets).not_to include(Entry.create!(:group_id => 3)) + report.condition = [:group_id, "<=", "2"] + expect(report.assets).to include(Entry.create!(group_id: 1)) + expect(report.assets).to include(Entry.create!(group_id: 2)) + expect(report.assets).not_to include(Entry.create!(group_id: 3)) end it "should nullify incorrect value for integer" do - report.condition = [:group_id, "<=", 'aa'] + report.condition = [:group_id, "<=", "aa"] expect(report.condition).to eq([:group_id, "<=", nil]) end it "should nullify incorrect value for date" do - report.condition = [:shipping_date, "<=", 'aa'] + report.condition = [:shipping_date, "<=", "aa"] expect(report.condition).to eq([:shipping_date, "<=", nil]) end it "should nullify incorrect value for datetime" do - report.condition = [:created_at, "<=", 'aa'] + report.condition = [:created_at, "<=", "aa"] expect(report.condition).to eq([:created_at, "<=", nil]) end it "should support date comparation operation by timestamp column" do - report.condition = [:created_at, "<=", '1986-08-05'] - expect(report.condition).to eq([:created_at, "<=", Date.parse('1986-08-05')]) - expect(report.assets).to include(Entry.create!(:created_at => Time.parse('1986-08-04 01:01:01'))) - expect(report.assets).to include(Entry.create!(:created_at => Time.parse('1986-08-05 23:59:59'))) - expect(report.assets).to include(Entry.create!(:created_at => Time.parse('1986-08-05 00:00:00'))) - expect(report.assets).not_to include(Entry.create!(:created_at => Time.parse('1986-08-06 00:00:00'))) - expect(report.assets).not_to include(Entry.create!(:created_at => Time.parse('1986-08-06 23:59:59'))) + report.condition = [:created_at, "<=", "1986-08-05"] + expect(report.condition).to eq([:created_at, "<=", Date.parse("1986-08-05")]) + expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-04 01:01:01"))) + expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 23:59:59"))) + expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 00:00:00"))) + expect(report.assets).not_to include(Entry.create!(created_at: Time.parse("1986-08-06 00:00:00"))) + expect(report.assets).not_to include(Entry.create!(created_at: Time.parse("1986-08-06 23:59:59"))) end it "should support date = operation by timestamp column" do - report.condition = [:created_at, "=", '1986-08-05'] - expect(report.condition).to eq([:created_at, "=", Date.parse('1986-08-05')]) - expect(report.assets).not_to include(Entry.create!(:created_at => Time.parse('1986-08-04 23:59:59'))) - expect(report.assets).to include(Entry.create!(:created_at => Time.parse('1986-08-05 23:59:59'))) - expect(report.assets).to include(Entry.create!(:created_at => Time.parse('1986-08-05 00:00:01'))) - #TODO: investigate SQLite issue and uncomment this line - #report.assets.should include(Entry.create!(:created_at => Time.parse('1986-08-05 00:00:00'))) - expect(report.assets).not_to include(Entry.create!(:created_at => Time.parse('1986-08-06 23:59:59'))) + report.condition = [:created_at, "=", "1986-08-05"] + expect(report.condition).to eq([:created_at, "=", Date.parse("1986-08-05")]) + expect(report.assets).not_to include(Entry.create!(created_at: Time.parse("1986-08-04 23:59:59"))) + expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 23:59:59"))) + expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 00:00:01"))) + # TODO: investigate SQLite issue and uncomment this line + # report.assets.should include(Entry.create!(:created_at => Time.parse('1986-08-05 00:00:00'))) + expect(report.assets).not_to include(Entry.create!(created_at: Time.parse("1986-08-06 23:59:59"))) end it "should support date =~ operation by timestamp column" do - report.condition = [:created_at, "=~", '1986-08-05'] - expect(report.condition).to eq([:created_at, "=~", Date.parse('1986-08-05')]) - expect(report.assets).not_to include(Entry.create!(:created_at => Time.parse('1986-08-04 23:59:59'))) - expect(report.assets).to include(Entry.create!(:created_at => Time.parse('1986-08-05 23:59:59'))) - expect(report.assets).to include(Entry.create!(:created_at => Time.parse('1986-08-05 00:00:01'))) - #TODO: investigate SQLite issue and uncomment this line - #report.assets.should include(Entry.create!(:created_at => Time.parse('1986-08-05 00:00:00'))) - expect(report.assets).not_to include(Entry.create!(:created_at => Time.parse('1986-08-06 23:59:59'))) + report.condition = [:created_at, "=~", "1986-08-05"] + expect(report.condition).to eq([:created_at, "=~", Date.parse("1986-08-05")]) + expect(report.assets).not_to include(Entry.create!(created_at: Time.parse("1986-08-04 23:59:59"))) + expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 23:59:59"))) + expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 00:00:01"))) + # TODO: investigate SQLite issue and uncomment this line + # report.assets.should include(Entry.create!(:created_at => Time.parse('1986-08-05 00:00:00'))) + expect(report.assets).not_to include(Entry.create!(created_at: Time.parse("1986-08-06 23:59:59"))) end it "should support operations for invalid date" do - report.condition = [:shipping_date, "<=", '1986-08-05'] - expect(report.assets).to include(Entry.create!(:shipping_date => '1986-08-04')) - expect(report.assets).to include(Entry.create!(:shipping_date => '1986-08-05')) - expect(report.assets).not_to include(Entry.create!(:shipping_date => '1986-08-06')) + report.condition = [:shipping_date, "<=", "1986-08-05"] + expect(report.assets).to include(Entry.create!(shipping_date: "1986-08-04")) + expect(report.assets).to include(Entry.create!(shipping_date: "1986-08-05")) + expect(report.assets).not_to include(Entry.create!(shipping_date: "1986-08-06")) end it "should support operations for invalid date" do - report.condition = [:shipping_date, "<=", Date.parse('1986-08-05')] - expect(report.assets).to include(Entry.create!(:shipping_date => '1986-08-04')) - expect(report.assets).to include(Entry.create!(:shipping_date => '1986-08-05')) - expect(report.assets).not_to include(Entry.create!(:shipping_date => '1986-08-06')) + report.condition = [:shipping_date, "<=", Date.parse("1986-08-05")] + expect(report.assets).to include(Entry.create!(shipping_date: "1986-08-04")) + expect(report.assets).to include(Entry.create!(shipping_date: "1986-08-05")) + expect(report.assets).not_to include(Entry.create!(shipping_date: "1986-08-06")) end it "should support allow_nil and allow_blank options" do grid = test_report do - scope {Entry} - filter(:condition, :dynamic, :allow_nil => true, :allow_blank => true, operations: ['>=', '<=']) do |(field, operation, value), scope| + scope { Entry } + filter(:condition, :dynamic, allow_nil: true, allow_blank: true, + operations: [">=", "<="]) do |(field, operation, value), scope| if value.blank? scope.where(disabled: false) else @@ -134,16 +134,16 @@ expect(grid.assets).to_not include(Entry.create!(disabled: true)) expect(grid.assets).to include(Entry.create!(disabled: false)) - grid.condition = [:group_id, '>=', 3] + grid.condition = [:group_id, ">=", 3] expect(grid.assets).to include(Entry.create!(disabled: true, group_id: 4)) expect(grid.assets).to_not include(Entry.create!(disabled: false, group_id: 2)) end it "should support custom operations" do - entry = Entry.create!(name: 'hello') + entry = Entry.create!(name: "hello") grid = test_report do - scope {Entry} + scope { Entry } filter( :condition, :dynamic, operations: ["=", "!="] ) do |(field, operation, value), scope| @@ -166,10 +166,9 @@ end it "should raise if unknown operation" do - report.condition = [:shipping_date, "<>", '1996-08-05'] - expect{ + report.condition = [:shipping_date, "<>", "1996-08-05"] + expect do report.assets - }.to raise_error(Datagrid::FilteringError) + end.to raise_error(Datagrid::FilteringError) end - end diff --git a/spec/datagrid/filters/enum_filter_spec.rb b/spec/datagrid/filters/enum_filter_spec.rb index 5b60348..7192614 100644 --- a/spec/datagrid/filters/enum_filter_spec.rb +++ b/spec/datagrid/filters/enum_filter_spec.rb @@ -1,28 +1,27 @@ -require 'spec_helper' +require "spec_helper" describe Datagrid::Filters::EnumFilter do - it "should support select option" do report = test_report do - scope {Entry} - filter(:group_id, :enum, :select => [1,2] ) + scope { Entry } + filter(:group_id, :enum, select: [1, 2]) end - expect(report.filter_by_name(:group_id).select(report)).to eq([1,2]) + expect(report.filter_by_name(:group_id).select(report)).to eq([1, 2]) end it "should support select option as proc" do grid = test_report do - scope {Entry} - filter(:group_id, :enum, :select => proc { [1,2] }) + scope { Entry } + filter(:group_id, :enum, select: proc { [1, 2] }) end - expect(grid.filter_by_name(:group_id).select(grid)).to eq([1,2]) + expect(grid.filter_by_name(:group_id).select(grid)).to eq([1, 2]) end it "should support select option as proc with instace input" do klass = test_report do - scope {Entry} - filter(:group_id, :enum, :select => proc { |obj| obj.object_id }) - end.class + scope { Entry } + filter(:group_id, :enum, select: proc { |obj| obj.object_id }) + end.class instance = klass.new expect(klass.filter_by_name(:group_id).select(instance)).to eq(instance.object_id) end @@ -30,22 +29,20 @@ it "should initialize select option only on instanciation" do class ReportWithLazySelect include Datagrid - scope {Entry} - filter(:group_id, :enum, :select => proc { raise 'hello' }) + scope { Entry } + filter(:group_id, :enum, select: proc { raise "hello" }) end end - it "should support select given as symbol" do report = test_report do - scope {Entry} - filter(:group_id, :enum, :select => :selectable_group_ids) + scope { Entry } + filter(:group_id, :enum, select: :selectable_group_ids) def selectable_group_ids - [1,3,5] + [1, 3, 5] end end - expect(report.filter_by_name(:group_id).select(report)).to eq([1,3,5]) + expect(report.filter_by_name(:group_id).select(report)).to eq([1, 3, 5]) end - end diff --git a/spec/datagrid/filters/extended_boolean_filter_spec.rb b/spec/datagrid/filters/extended_boolean_filter_spec.rb index 22e36e5..ebff604 100644 --- a/spec/datagrid/filters/extended_boolean_filter_spec.rb +++ b/spec/datagrid/filters/extended_boolean_filter_spec.rb @@ -1,23 +1,22 @@ -require 'spec_helper' +require "spec_helper" describe Datagrid::Filters::ExtendedBooleanFilter do - it "should support select option" do grid = test_report do - scope {Entry} + scope { Entry } filter(:disabled, :xboolean) end - expect(grid.filter_by_name(:disabled).select(grid)).to eq([["Yes", "YES"], ["No", "NO"]]) + expect(grid.filter_by_name(:disabled).select(grid)).to eq([%w[Yes YES], %w[No NO]]) end it "should generate pass boolean value to filter block" do grid = test_report do - scope {Entry} + scope { Entry } filter(:disabled, :xboolean) end - disabled_entry = Entry.create!(:disabled => true) - enabled_entry = Entry.create!(:disabled => false) + disabled_entry = Entry.create!(disabled: true) + enabled_entry = Entry.create!(disabled: false) expect(grid.disabled).to be_nil expect(grid.assets).to include(disabled_entry, enabled_entry) @@ -34,7 +33,7 @@ it "should normalize true/false as YES/NO" do grid = test_report do - scope {Entry} + scope { Entry } filter(:disabled, :xboolean) end grid.disabled = true @@ -46,5 +45,4 @@ grid.disabled = "false" expect(grid.disabled).to eq("NO") end - end diff --git a/spec/datagrid/filters/float_filter_spec.rb b/spec/datagrid/filters/float_filter_spec.rb index a745355..131cdd0 100644 --- a/spec/datagrid/filters/float_filter_spec.rb +++ b/spec/datagrid/filters/float_filter_spec.rb @@ -1,11 +1,10 @@ -require 'spec_helper' +require "spec_helper" describe Datagrid::Filters::FloatFilter do - it "should support float values" do - g1 = Group.create!(:rating => 1.5) - g2 = Group.create!(:rating => 1.6) - report = test_report(:rating => 1.5) do + g1 = Group.create!(rating: 1.5) + g2 = Group.create!(rating: 1.6) + report = test_report(rating: 1.5) do scope { Group } filter(:rating, :float) end diff --git a/spec/datagrid/filters/integer_filter_spec.rb b/spec/datagrid/filters/integer_filter_spec.rb index 5d5a9f2..a7f1855 100644 --- a/spec/datagrid/filters/integer_filter_spec.rb +++ b/spec/datagrid/filters/integer_filter_spec.rb @@ -1,7 +1,6 @@ -require 'spec_helper' +require "spec_helper" describe Datagrid::Filters::IntegerFilter do - let(:entry1) { Entry.create!(group_id: 1) } let(:entry2) { Entry.create!(group_id: 2) } let(:entry3) { Entry.create!(group_id: 3) } @@ -58,7 +57,6 @@ end it "should find something in one integer interval" do - report = test_report(group_id: (4..4)) do scope { Entry } filter(:group_id, :integer, range: true) @@ -69,18 +67,16 @@ end it "should support invalid range" do - report = test_report(group_id: (7..1)) do scope { Entry } filter(:group_id, :integer, range: true) end - expect(report.group_id).to eq([1,7]) + expect(report.group_id).to eq([1, 7]) expect(report.assets).to include(entry7) expect(report.assets).to include(entry4) expect(report.assets).to include(entry1) end - it "should support block" do report = test_report(group_id: 5) do scope { Entry } @@ -92,42 +88,41 @@ expect(report.assets).to include(entry5) end - it "should not prefix table name if column is joined" do - report = test_report(rating: [4,nil]) do + report = test_report(rating: [4, nil]) do scope { Entry.joins(:group) } filter(:rating, :integer, range: true) end - expect(report.rating).to eq([4,nil]) + expect(report.rating).to eq([4, nil]) expect(report.assets).not_to include(Entry.create!(group: Group.create!(rating: 3))) expect(report.assets).to include(Entry.create!(group: Group.create!(rating: 5))) end it "should support multiple values" do report = test_report(group_id: "1,2") do - scope {Entry} + scope { Entry } filter(:group_id, :integer, multiple: true) end - expect(report.group_id).to eq([1,2]) + expect(report.group_id).to eq([1, 2]) expect(report.assets).to include(entry1) expect(report.assets).to include(entry2) expect(report.assets).not_to include(entry3) end it "should support custom separator multiple values" do report = test_report(group_id: "1|2") do - scope {Entry} - filter(:group_id, :integer, multiple: '|') + scope { Entry } + filter(:group_id, :integer, multiple: "|") end - expect(report.group_id).to eq([1,2]) + expect(report.group_id).to eq([1, 2]) expect(report.assets).to include(entry1) expect(report.assets).to include(entry2) expect(report.assets).not_to include(entry3) end it "should support multiple with allow_blank allow_nil options" do - report = test_report do - scope {Entry} - filter(:group_id, :integer, multiple: true, allow_nil: false, allow_blank: true ) + report = test_report do + scope { Entry } + filter(:group_id, :integer, multiple: true, allow_nil: false, allow_blank: true) end report.group_id = [] expect(report.assets).to_not include(entry1) @@ -143,7 +138,7 @@ it "normalizes AR object to ID" do group = Group.create! report = test_report(group_id: group) do - scope {Entry} + scope { Entry } filter(:group_id, :integer) end diff --git a/spec/datagrid/filters/string_filter_spec.rb b/spec/datagrid/filters/string_filter_spec.rb index 63b702f..8e84de3 100644 --- a/spec/datagrid/filters/string_filter_spec.rb +++ b/spec/datagrid/filters/string_filter_spec.rb @@ -1,35 +1,34 @@ require "spec_helper" describe Datagrid::Filters::StringFilter do - it "should support multiple values" do - report = test_report(:name => "one,two") do - scope {Entry} - filter(:name, :string, :multiple => true) + report = test_report(name: "one,two") do + scope { Entry } + filter(:name, :string, multiple: true) end - expect(report.assets).to include(Entry.create!( :name => "one")) - expect(report.assets).to include(Entry.create!( :name => "two")) - expect(report.assets).not_to include(Entry.create!( :name => "three")) + expect(report.assets).to include(Entry.create!(name: "one")) + expect(report.assets).to include(Entry.create!(name: "two")) + expect(report.assets).not_to include(Entry.create!(name: "three")) end it "should support custom separator multiple values" do - report = test_report(:name => "one,1|two,2") do - scope {Entry} - filter(:name, :string, :multiple => '|') + report = test_report(name: "one,1|two,2") do + scope { Entry } + filter(:name, :string, multiple: "|") end - expect(report.assets).to include(Entry.create!( :name => "one,1")) - expect(report.assets).to include(Entry.create!( :name => "two,2")) - expect(report.assets).not_to include(Entry.create!( :name => "one")) - expect(report.assets).not_to include(Entry.create!( :name => "two")) + expect(report.assets).to include(Entry.create!(name: "one,1")) + expect(report.assets).to include(Entry.create!(name: "two,2")) + expect(report.assets).not_to include(Entry.create!(name: "one")) + expect(report.assets).not_to include(Entry.create!(name: "two")) end it "supports range" do - report = test_report(:name => ['ab', 'lm']) do - scope {Entry} + report = test_report(name: %w[ab lm]) do + scope { Entry } filter(:name, :string, range: true) end - expect(report.assets).to include(Entry.create!( :name => "ac")) - expect(report.assets).to include(Entry.create!( :name => "kl")) - expect(report.assets).not_to include(Entry.create!( :name => "aa")) - expect(report.assets).not_to include(Entry.create!( :name => "mn")) + expect(report.assets).to include(Entry.create!(name: "ac")) + expect(report.assets).to include(Entry.create!(name: "kl")) + expect(report.assets).not_to include(Entry.create!(name: "aa")) + expect(report.assets).not_to include(Entry.create!(name: "mn")) end end diff --git a/spec/datagrid/filters_spec.rb b/spec/datagrid/filters_spec.rb index 9f9325a..91614dc 100644 --- a/spec/datagrid/filters_spec.rb +++ b/spec/datagrid/filters_spec.rb @@ -1,65 +1,63 @@ -require 'spec_helper' +require "spec_helper" describe Datagrid::Filters do - it "should support default option as proc" do expect(test_report do - scope {Entry} - filter(:created_at, :date, :default => proc { Date.today } ) + scope { Entry } + filter(:created_at, :date, default: proc { Date.today }) end.created_at).to eq(Date.today) end it "should stack with other filters" do - Entry.create(:name => "ZZ", :category => "first") - report = test_report(:name => "Pop", :category => "first") do + Entry.create(name: "ZZ", category: "first") + report = test_report(name: "Pop", category: "first") do scope { Entry } filter(:name) - filter(:category, :enum, :select => ["first", "second"]) + filter(:category, :enum, select: %w[first second]) end expect(report.assets).to be_empty end it "should not support array argument for not multiple filter" do report = test_report do - scope {Entry} + scope { Entry } filter(:group_id, :integer) end - expect { - report.group_id = [1,2] - }.to raise_error(Datagrid::ArgumentError) + expect do + report.group_id = [1, 2] + end.to raise_error(Datagrid::ArgumentError) end it "should filter block with 2 arguments" do report = test_report do - scope {Entry} + scope { Entry } filter(:group_id, :integer) do |value, scope| - scope.where(:group_id => value) + scope.where(group_id: value) end end - expect { - report.group_id = [1,2] - }.to raise_error(Datagrid::ArgumentError) + expect do + report.group_id = [1, 2] + end.to raise_error(Datagrid::ArgumentError) end - it "should initialize when report Scope table not exists" do class ModelWithoutTable < ActiveRecord::Base; end expect(ModelWithoutTable).not_to be_table_exists class TheReport include Datagrid - scope {ModelWithoutTable} + scope { ModelWithoutTable } filter(:name) filter(:limit) end - expect(TheReport.new(:name => 'hello')).not_to be_nil + expect(TheReport.new(name: "hello")).not_to be_nil end it "should support inheritence" do parent = Class.new do include Datagrid - scope {Entry} + scope { Entry } filter(:name) end child = Class.new(parent) do @@ -70,11 +68,10 @@ class TheReport end describe "allow_blank and allow_nil options" do - def check_performed(value, result, **options) $FILTER_PERFORMED = false - report = test_report(:name => value) do - scope {Entry} + report = test_report(name: value) do + scope { Entry } filter(:name, **options) do |_| $FILTER_PERFORMED = true self @@ -87,18 +84,18 @@ def check_performed(value, result, **options) it "should support allow_blank argument" do [nil, "", " "].each do |value| - check_performed(value, true, :allow_blank => true) + check_performed(value, true, allow_blank: true) end end it "should support allow_nil argument" do - check_performed(nil, true, :allow_nil => true) + check_performed(nil, true, allow_nil: true) end it "should support combination on allow_nil and allow_blank" do - check_performed(nil, false, :allow_nil => false, :allow_blank => true) - check_performed("", true, :allow_nil => false, :allow_blank => true) - check_performed(nil, true, :allow_nil => true, :allow_blank => false) + check_performed(nil, false, allow_nil: false, allow_blank: true) + check_performed("", true, allow_nil: false, allow_blank: true) + check_performed(nil, true, allow_nil: true, allow_blank: false) end end @@ -106,71 +103,67 @@ def check_performed(value, result, **options) it "should create default filter if scope respond to filter name method" do Entry.create! Entry.create! - grid = test_report(:limit => 1) do - scope {Entry} + grid = test_report(limit: 1) do + scope { Entry } filter(:limit) end expect(grid.assets.to_a.size).to eq(1) end - end describe "default filter as scope" do it "should create default filter if scope respond to filter name method" do Entry.create! - grid = test_report(:custom => 'skip') do - scope {Entry} + grid = test_report(custom: "skip") do + scope { Entry } filter(:custom) do |value| - if value != 'skip' - where(:custom => value) - end + where(custom: value) if value != "skip" end end expect(grid.assets).not_to be_empty end - end describe "positioning filter before another" do it "should insert the filter before the specified element" do grid = test_report do - scope {Entry} + scope { Entry } filter(:limit) - filter(:name, :before => :limit) + filter(:name, before: :limit) end - expect(grid.filters.index {|f| f.name == :name}).to eq(0) + expect(grid.filters.index { |f| f.name == :name }).to eq(0) end end describe "positioning filter after another" do it "should insert the filter before the specified element" do grid = test_report do - scope {Entry} + scope { Entry } filter(:limit) filter(:name) - filter(:group_id, :after => :limit) + filter(:group_id, after: :limit) end - expect(grid.filters.index {|f| f.name == :group_id}).to eq(1) + expect(grid.filters.index { |f| f.name == :group_id }).to eq(1) end end it "should support dummy filter" do grid = test_report do scope { Entry } - filter(:period, :date, :dummy => true, :default => proc { Date.today }) + filter(:period, :date, dummy: true, default: proc { Date.today }) end - Entry.create!(:created_at => 3.days.ago) + Entry.create!(created_at: 3.days.ago) expect(grid.assets).not_to be_empty end describe "#filter_by" do it "should allow partial filtering" do grid = test_report do - scope {Entry} + scope { Entry } filter(:id) filter(:name) end - Entry.create!(:name => 'hello') - grid.attributes = {:id => -1, :name => 'hello'} + Entry.create!(name: "hello") + grid.attributes = { id: -1, name: "hello" } expect(grid.assets).to be_empty expect(grid.filter_by(:name)).not_to be_empty end @@ -178,7 +171,7 @@ def check_performed(value, result, **options) it "supports dynamic header" do grid = test_report do - scope {Entry} + scope { Entry } filter(:id, :integer, header: proc { rand(10**9) }) end @@ -186,11 +179,10 @@ def check_performed(value, result, **options) expect(filter.header).to_not eq(filter.header) end - describe "#filter_by_name" do it "should return filter object" do r = test_report do - scope {Entry} + scope { Entry } filter(:id, :integer) end @@ -200,7 +192,6 @@ def check_performed(value, result, **options) end describe "tranlations" do - module ::Ns46 class TranslatedReport include Datagrid @@ -214,66 +205,64 @@ class InheritedReport < TranslatedReport it "translates filter with namespace" do grid = Ns46::TranslatedReport.new - store_translations(:en, datagrid: {:"ns46/translated_report" => {filters: {name: "Navn"}}}) do + store_translations(:en, datagrid: { "ns46/translated_report": { filters: { name: "Navn" } } }) do expect(grid.filters.map(&:header)).to eq(["Navn"]) end end it "translates filter using defaults namespace" do grid = Ns46::TranslatedReport.new - store_translations(:en, datagrid: {defaults: {filters: {name: "Navn"}}}) do + store_translations(:en, datagrid: { defaults: { filters: { name: "Navn" } } }) do expect(grid.filters.map(&:header)).to eq(["Navn"]) end end it "translates filter using parent report" do grid = Ns46::InheritedReport.new - store_translations(:en, datagrid: {:"ns46/translated_report" => {filters: {name: "Navn"}}}) do + store_translations(:en, datagrid: { "ns46/translated_report": { filters: { name: "Navn" } } }) do expect(grid.filters.map(&:header)).to eq(["Navn"]) end end end - describe "#select_options" do it "should return select options" do filters = { - id: [1,2], - name: [['a', 1], ['b', 2]], - category: {a: 1, b: 2}, + id: [1, 2], + name: [["a", 1], ["b", 2]], + category: { a: 1, b: 2 } } grid = test_report do - scope {Entry} + scope { Entry } filters.each do |name, options| filter(name, :enum, select: options, multiple: true) end end filters.each do |name, options| expect(grid.select_options(name)).to eq(options) - expect(grid.select_values(name)).to eq([1,2]) + expect(grid.select_values(name)).to eq([1, 2]) grid.select_all(name) - expect(grid.public_send(name)).to eq([1,2]) + expect(grid.public_send(name)).to eq([1, 2]) end end it "should raise ArgumentError for filter without options" do grid = test_report do - scope {Entry} + scope { Entry } filter(:id, :integer) end - expect { + expect do grid.select_options(:id) - }.to raise_error(Datagrid::ArgumentError) + end.to raise_error(Datagrid::ArgumentError) end end describe "#inspect" do it "should list all fitlers with types" do - module ::NsInspect class TestGrid include Datagrid - scope {Entry} + scope { Entry } filter(:id, :integer) filter(:name, :string) filter(:current_user) @@ -288,18 +277,17 @@ class TestGrid it "dislays no filters" do class TestGrid8728 include Datagrid - scope {Entry} + scope { Entry } end expect(TestGrid8728.inspect).to eq("TestGrid8728(no filters)") end end - describe ":if :unless options" do it "supports :if option" do klass = test_report_class do - scope {Entry} + scope { Entry } filter(:admin_mode, :boolean, dummy: true) filter(:id, :integer, if: :admin_mode) filter(:name, :integer, unless: :admin_mode) @@ -313,11 +301,12 @@ class TestGrid8728 expect(non_admin_filters).to include(:name) end - context 'with delegation to attribute' do - let(:role) { OpenStruct.new('admin?' => admin) } + context "with delegation to attribute" do + let(:role) { OpenStruct.new("admin?" => admin) } let(:klass) do test_report_class do attr_accessor :role + delegate :admin?, to: :role scope { Entry } @@ -328,13 +317,13 @@ class TestGrid8728 subject { klass.new(role: role).filters.map(&:name) } - context 'when condition is true' do + context "when condition is true" do let(:admin) { true } it { is_expected.to include(:id) } end - context 'when condition is false' do + context "when condition is false" do let(:admin) { false } it { is_expected.to_not include(:id) } diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 6aa5826..dac013b 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -1,5 +1,4 @@ -# encoding: UTF-8 -require 'spec_helper' +require "spec_helper" require "action_controller" class MyFormBuilder @@ -10,18 +9,17 @@ class MyTemplate include ActionView::Helpers::FormHelper end - describe Datagrid::FormBuilder do let(:template) do action_view_template end - let(:view) { ActionView::Helpers::FormBuilder.new(:report, _grid, template, view_options)} + let(:view) { ActionView::Helpers::FormBuilder.new(:report, _grid, template, view_options) } let(:view_options) { {} } describe ".datagrid_filter" do it "should work for every filter type" do - Datagrid::Filters::FILTER_TYPES.each do |type, klass| + Datagrid::Filters::FILTER_TYPES.each do |_type, klass| expect(Datagrid::FormBuilder.instance_methods.map(&:to_sym)).to include(klass.form_builder_helper_name) end end @@ -33,218 +31,251 @@ class MyTemplate let(:_filter_options) { {} } let(:_filter_block) { nil } context "with default filter type" do - let(:_grid) { + let(:_grid) do test_report do - scope {Entry} + scope { Entry } filter(:name) end - } + end let(:_filter) { :name } - it { should equal_to_dom( - '<input class="name default_filter" type="text" name="report[name]" id="report_name"/>' - )} + it { + should equal_to_dom( + '<input class="name default_filter" type="text" name="report[name]" id="report_name"/>' + ) + } end context "with integer filter type" do let(:_filter) { :group_id } - let(:_grid) { + let(:_grid) do test_report do - scope {Entry} + scope { Entry } filter(:group_id, :integer) end + end + it { + should equal_to_dom( + '<input class="group_id integer_filter" type="text" name="report[group_id]" id="report_group_id"/>' + ) } - it { should equal_to_dom( - '<input class="group_id integer_filter" type="text" name="report[group_id]" id="report_group_id"/>' - )} context "when partials option is passed for filter that don't support range" do - let(:view_options) { {partials: 'anything' } } - it { should equal_to_dom( - '<input class="group_id integer_filter" type="text" name="report[group_id]" id="report_group_id"/>' - )} + let(:view_options) { { partials: "anything" } } + it { + should equal_to_dom( + '<input class="group_id integer_filter" type="text" name="report[group_id]" id="report_group_id"/>' + ) + } end end context "with date filter type" do let(:_filter) { :created_at } - let(:_grid) { + let(:_grid) do test_report do - scope {Entry} + scope { Entry } filter(:created_at, :date) end + end + it { + should equal_to_dom( + '<input class="created_at date_filter" type="text" name="report[created_at]" id="report_created_at"/>' + ) } - it { should equal_to_dom( - '<input class="created_at date_filter" type="text" name="report[created_at]" id="report_created_at"/>' - )} context "when special date format specified" do around(:each) do |example| - _grid.created_at = Date.parse('2012-01-02') + _grid.created_at = Date.parse("2012-01-02") with_date_format do example.run end end - it { should equal_to_dom( - '<input value="01/02/2012" class="created_at date_filter" type="text" name="report[created_at]" id="report_created_at"/>' - )} + it { + should equal_to_dom( + '<input value="01/02/2012" class="created_at date_filter" type="text" name="report[created_at]" id="report_created_at"/>' + ) + } end end context "with input_options" do context "type is date" do let(:_filter) { :created_at } - let(:_grid) { + let(:_grid) do test_report do - scope {Entry} - filter(:created_at, :date, input_options: {type: :date}) + scope { Entry } + filter(:created_at, :date, input_options: { type: :date }) end + end + it { + should equal_to_dom( + '<input type="date" class="created_at date_filter" name="report[created_at]" id="report_created_at"/>' + ) } - it { should equal_to_dom( - '<input type="date" class="created_at date_filter" name="report[created_at]" id="report_created_at"/>' - )} end context "type is textarea" do let(:_filter) { :name } - let(:_grid) { + let(:_grid) do test_report do - scope {Entry} - filter(:name, :string, input_options: {type: :textarea}) + scope { Entry } + filter(:name, :string, input_options: { type: :textarea }) end + end + it { + should equal_to_dom( + '<textarea class="name string_filter" name="report[name]" id="report_name"/>' + ) } - it { should equal_to_dom( - '<textarea class="name string_filter" name="report[name]" id="report_name"/>' - )} end context "type is datetime-local" do let(:_filter) { :created_at } - let(:_grid) { + let(:_grid) do test_report(created_at: Time.new(2024, 1, 1, 9, 25, 15)) do - scope {Entry} - filter(:created_at, :datetime, input_options: {type: "datetime-local"}) + scope { Entry } + filter(:created_at, :datetime, input_options: { type: "datetime-local" }) end + end + it { + should equal_to_dom( + '<input type="datetime-local" class="created_at date_time_filter" value="2024-01-01T09:25:15" name="report[created_at]" id="report_created_at"/>' + ) } - it { should equal_to_dom( - '<input type="datetime-local" class="created_at date_time_filter" value="2024-01-01T09:25:15" name="report[created_at]" id="report_created_at"/>' - )} context "nil value option" do let(:_filter_options) do { value: nil } end - it { should equal_to_dom( - '<input type="datetime-local" value="" class="created_at date_time_filter" name="report[created_at]" id="report_created_at"/>' - )} + it { + should equal_to_dom( + '<input type="datetime-local" value="" class="created_at date_time_filter" name="report[created_at]" id="report_created_at"/>' + ) + } end end context "type is date" do let(:_filter) { :created_at } - let(:_grid) { + let(:_grid) do test_report(created_at: Date.new(2024, 1, 1)) do - scope {Entry} - filter(:created_at, :datetime, input_options: {type: :date}) + scope { Entry } + filter(:created_at, :datetime, input_options: { type: :date }) end + end + it { + should equal_to_dom( + '<input type="date" class="created_at date_time_filter" value="2024-01-01" name="report[created_at]" id="report_created_at"/>' + ) } - it { should equal_to_dom( - '<input type="date" class="created_at date_time_filter" value="2024-01-01" name="report[created_at]" id="report_created_at"/>' - )} end end context "with integer filter type and range option" do let(:_filter) { :group_id } - let(:_grid) { - test_report(:group_id => _range) do - scope {Entry} - filter(:group_id, :integer, :range => true) + let(:_grid) do + test_report(group_id: _range) do + scope { Entry } + filter(:group_id, :integer, range: true) end - } + end context "when datagrid_filter options has id" do - let(:_filter_options) { {:id => "hello"} } - let(:_range) { [1,2]} - it { should equal_to_dom( - '<input value="1" id="from_hello" class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + - '<span class="separator integer"> - </span>' + - '<input value="2" id="to_hello" class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' - )} + let(:_filter_options) { { id: "hello" } } + let(:_range) { [1, 2] } + it { + should equal_to_dom( + '<input value="1" id="from_hello" class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + + '<span class="separator integer"> - </span>' + + '<input value="2" id="to_hello" class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + ) + } end context "with only left bound" do - - let(:_range) { [10, nil]} - it { should equal_to_dom( - '<input value="10" class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + - '<span class="separator integer"> - </span>' + - '<input class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' - )} + let(:_range) { [10, nil] } + it { + should equal_to_dom( + '<input value="10" class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + + '<span class="separator integer"> - </span>' + + '<input class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + ) + } it { should be_html_safe } end context "with only right bound" do - let(:_range) { [nil, 10]} - it { should equal_to_dom( - '<input class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + - '<span class="separator integer"> - </span>' + - '<input value="10" class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' - )} + let(:_range) { [nil, 10] } + it { + should equal_to_dom( + '<input class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + + '<span class="separator integer"> - </span>' + + '<input value="10" class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + ) + } it { should be_html_safe } end context "with invalid range value" do let(:_range) { 2..1 } - it { should equal_to_dom( - '<input value="1" class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + - '<span class="separator integer"> - </span>' + - '<input value="2" class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' - )} + it { + should equal_to_dom( + '<input value="1" class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + + '<span class="separator integer"> - </span>' + + '<input value="2" class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + ) + } end context "with custom partials option and template exists" do - let(:view_options) { { :partials => 'custom_range' } } + let(:view_options) { { partials: "custom_range" } } let(:_range) { nil } - it { should equal_to_dom( - "custom_range_partial" - ) } + it { + should equal_to_dom( + "custom_range_partial" + ) + } end context "when custom partial doesn't exist" do - let(:view_options) { { :partials => 'not_existed' } } + let(:view_options) { { partials: "not_existed" } } let(:_range) { nil } - it { should equal_to_dom( - '<input class="from group_id integer_filter" multiple type="text" name="report[group_id][]"><span class="separator integer"> - </span><input class="to group_id integer_filter" multiple type="text" name="report[group_id][]">' - ) } - + it { + should equal_to_dom( + '<input class="from group_id integer_filter" multiple type="text" name="report[group_id][]"><span class="separator integer"> - </span><input class="to group_id integer_filter" multiple type="text" name="report[group_id][]">' + ) + } end end context "with float filter type and range option" do let(:_filter) { :rating } - let(:_grid) { - test_report(:rating => _range) do - scope {Group} - filter(:rating, :float, :range => true) - end + let(:_grid) do + test_report(rating: _range) do + scope { Group } + filter(:rating, :float, range: true) + end + end + let(:_range) { [1.5, 2.5] } + it { + should equal_to_dom( + '<input value="1.5" class="from rating float_filter" multiple type="text" name="report[rating][]"/>' + + '<span class="separator float"> - </span>' + + '<input value="2.5" class="to rating float_filter" multiple type="text" name="report[rating][]"/>' + ) } - let(:_range) { [1.5,2.5]} - it { should equal_to_dom( - '<input value="1.5" class="from rating float_filter" multiple type="text" name="report[rating][]"/>' + - '<span class="separator float"> - </span>' + - '<input value="2.5" class="to rating float_filter" multiple type="text" name="report[rating][]"/>' - )} end context "with date filter type and range option" do let(:_filter) { :created_at } - let(:_grid) { - test_report(:created_at => _range) do - scope {Entry} - filter(:created_at, :date, :range => true) + let(:_grid) do + test_report(created_at: _range) do + scope { Entry } + filter(:created_at, :date, range: true) end - } + end context "with only left bound" do - - let(:_range) { ["2012-01-03", nil]} - it { should equal_to_dom( - '<input value="2012-01-03" class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + - '<span class="separator date"> - </span>' + - '<input class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' - )} + let(:_range) { ["2012-01-03", nil] } + it { + should equal_to_dom( + '<input value="2012-01-03" class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + + '<span class="separator date"> - </span>' + + '<input class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' + ) + } it { should be_html_safe } end context "when special date format specified" do @@ -253,31 +284,36 @@ class MyTemplate example.run end end - let(:_range) { ["2013/01/01", '2013/02/02']} - it { should equal_to_dom( - '<input value="01/01/2013" class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + - '<span class="separator date"> - </span>' + - '<input value="02/02/2013" class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' - )} + let(:_range) { ["2013/01/01", "2013/02/02"] } + it { + should equal_to_dom( + '<input value="01/01/2013" class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + + '<span class="separator date"> - </span>' + + '<input value="02/02/2013" class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' + ) + } end context "with only right bound" do - - let(:_range) { [nil, "2012-01-03"]} - it { should equal_to_dom( - '<input class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + - '<span class="separator date"> - </span>' + - '<input value="2012-01-03" class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' - )} + let(:_range) { [nil, "2012-01-03"] } + it { + should equal_to_dom( + '<input class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + + '<span class="separator date"> - </span>' + + '<input value="2012-01-03" class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' + ) + } it { should be_html_safe } end context "with invalid range value" do - let(:_range) { Date.parse('2012-01-02')..Date.parse('2012-01-01') } - it { should equal_to_dom( - '<input value="2012-01-01" class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + - '<span class="separator date"> - </span>' + - '<input value="2012-01-02" class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' - )} + let(:_range) { Date.parse("2012-01-02")..Date.parse("2012-01-01") } + it { + should equal_to_dom( + '<input value="2012-01-01" class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + + '<span class="separator date"> - </span>' + + '<input value="2012-01-02" class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' + ) + } end context "with blank range value" do around(:each) do |example| @@ -286,100 +322,118 @@ class MyTemplate end end let(:_range) { [nil, nil] } - it { should equal_to_dom( - '<input class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + - '<span class="separator date"> - </span>' + - '<input class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' - )} + it { + should equal_to_dom( + '<input class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + + '<span class="separator date"> - </span>' + + '<input class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' + ) + } end end context "with enum filter type" do let(:_filter) { :category } let(:_category_filter_options) { {} } - let(:_grid) { + let(:_grid) do filter_options = _category_filter_options test_report do - scope {Entry} - filter(:category, :enum, select: ["first", "second"], **filter_options) + scope { Entry } + filter(:category, :enum, select: %w[first second], **filter_options) end - } - it { should equal_to_dom( - %(<select class="category enum_filter" name="report[category]" id="report_category"> + end + it { + should equal_to_dom( + %(<select class="category enum_filter" name="report[category]" id="report_category"> <option value="" label=" "></option> <option value="first">first</option> <option value="second">second</option></select>) - )} + ) + } context "when block is given" do - let(:_filter_block ) do + let(:_filter_block) do proc do - template.content_tag(:option, 'block option', :value => 'block_value') + template.content_tag(:option, "block option", value: "block_value") end end - it { should equal_to_dom( - %(<select class="category enum_filter" name="report[category]" id="report_category"> + it { + should equal_to_dom( + %(<select class="category enum_filter" name="report[category]" id="report_category"> <option value="" label=" "></option> <option value="block_value">block option</option></select>) - )} + ) + } end context "when first option is selected" do before(:each) do _grid.category = "first" end - it { should equal_to_dom( - %(<select class="category enum_filter" name="report[category]" id="report_category"> + it { + should equal_to_dom( + %(<select class="category enum_filter" name="report[category]" id="report_category"> <option value="" label=" "></option> <option selected value="first">first</option> <option value="second">second</option></select>) - )} + ) + } end context "with include_blank option set to false" do let(:_category_filter_options) { { include_blank: false } } - it { should equal_to_dom( - '<select class="category enum_filter" name="report[category]" id="report_category"> + it { + should equal_to_dom( + '<select class="category enum_filter" name="report[category]" id="report_category"> <option value="first">first</option> <option value="second">second</option></select>' - )} + ) + } end context "with dynamic include_blank option" do - let(:_category_filter_options) { {include_blank: proc { "Choose plz" }} } - it { should equal_to_dom( - '<select class="category enum_filter" name="report[category]" id="report_category"> + let(:_category_filter_options) { { include_blank: proc { "Choose plz" } } } + it { + should equal_to_dom( + '<select class="category enum_filter" name="report[category]" id="report_category"> <option value="">Choose plz</option> <option value="first">first</option> <option value="second">second</option></select>' - )} + ) + } end context "with prompt option" do - let(:_category_filter_options) { {prompt: 'My Prompt'} } - it { should equal_to_dom( - '<select class="category enum_filter" name="report[category]" id="report_category"><option value="">My Prompt</option> + let(:_category_filter_options) { { prompt: "My Prompt" } } + it { + should equal_to_dom( + '<select class="category enum_filter" name="report[category]" id="report_category"><option value="">My Prompt</option> <option value="first">first</option> <option value="second">second</option></select>' - )} + ) + } end context "with input_options class" do - let(:_category_filter_options) { {input_options: {class: 'custom-class'}} } - it { should equal_to_dom( - '<select class="custom-class category enum_filter" name="report[category]" id="report_category"><option value="" label=" "></option> + let(:_category_filter_options) { { input_options: { class: "custom-class" } } } + it { + should equal_to_dom( + '<select class="custom-class category enum_filter" name="report[category]" id="report_category"><option value="" label=" "></option> <option value="first">first</option> <option value="second">second</option></select>' - )} + ) + } end context "with checkboxes option" do - let(:_category_filter_options) { {checkboxes: true} } - it { should equal_to_dom( - ' + let(:_category_filter_options) { { checkboxes: true } } + it { + should equal_to_dom( + ' <label class="category enum_filter checkboxes" for="report_category_first"><input class="category enum_filter checkboxes" type="checkbox" id="report_category_first" value="first" name="report[category][]" />first</label> <label class="category enum_filter checkboxes" for="report_category_second"><input class="category enum_filter checkboxes" type="checkbox" id="report_category_second" value="second" name="report[category][]" />second</label> ' - )} + ) + } context "when partials option passed and partial exists" do - let(:view_options) { {partials: 'custom_checkboxes'} } - it { should equal_to_dom('custom_enum_checkboxes') } + let(:view_options) { { partials: "custom_checkboxes" } } + it { should equal_to_dom("custom_enum_checkboxes") } end end end @@ -388,96 +442,104 @@ class MyTemplate let(:_filter) { :disabled } let(:_grid) do test_report do - scope {Entry} + scope { Entry } filter(:disabled, :boolean, default: true) end end - it { should equal_to_dom( - # hidden is important when default is set to true - %{<input name="report[disabled]" type="hidden" value="0" autocomplete="off"><input class="disabled boolean_filter" type="checkbox" value="1" checked name="report[disabled]" id="report_disabled">} - )} + it { + should equal_to_dom( + # hidden is important when default is set to true + %(<input name="report[disabled]" type="hidden" value="0" autocomplete="off"><input class="disabled boolean_filter" type="checkbox" value="1" checked name="report[disabled]" id="report_disabled">) + ) + } end context "with xboolean filter type" do let(:_filter) { :disabled } let(:_grid) do test_report do - scope {Entry} + scope { Entry } filter(:disabled, :xboolean) end end - it { should equal_to_dom( - %(<select class="disabled extended_boolean_filter" name="report[disabled]" id="report_disabled"> + it { + should equal_to_dom( + %(<select class="disabled extended_boolean_filter" name="report[disabled]" id="report_disabled"> <option value="" label=" "></option> <option value="YES">Yes</option> <option value="NO">No</option></select>) - )} + ) + } end context "with string filter" do let(:_grid) do test_report do - scope {Entry} + scope { Entry } filter(:name, :string) end end let(:_filter) { :name } - it {should equal_to_dom('<input class="name string_filter" type="text" name="report[name]" id="report_name">')} + it { should equal_to_dom('<input class="name string_filter" type="text" name="report[name]" id="report_name">') } context "when multiple option is set" do let(:_grid) do - test_report(:name => "one,two") do - scope {Entry} - filter(:name, :string, :multiple => true) + test_report(name: "one,two") do + scope { Entry } + filter(:name, :string, multiple: true) end end let(:_filter) { :name } - it {should equal_to_dom('<input value="one,two" class="name string_filter" type="text" name="report[name]" id="report_name">')} + it { + should equal_to_dom('<input value="one,two" class="name string_filter" type="text" name="report[name]" id="report_name">') + } end end context "with non multiple filter" do let(:_grid) do test_report do - scope {Entry} + scope { Entry } filter( :name, :enum, - :include_blank => false, - :multiple => false, - :select => [] + include_blank: false, + multiple: false, + select: [] ) end end let(:_filter) { :name } - it {should equal_to_dom('<select class="name enum_filter" name="report[name]" id="report_name"></select>')} + it { should equal_to_dom('<select class="name enum_filter" name="report[name]" id="report_name"></select>') } end context "with float filter type" do - let(:_grid) { + let(:_grid) do test_report do - scope {Entry} + scope { Entry } filter(:group_id, :float) end - } + end let(:_filter) { :group_id } - it { should equal_to_dom( - '<input class="group_id float_filter" type="text" name="report[group_id]" id="report_group_id"/>' - )} + it { + should equal_to_dom( + '<input class="group_id float_filter" type="text" name="report[group_id]" id="report_group_id"/>' + ) + } end context "with enum multiple filter" do let(:_grid) do test_report do - scope {Entry} - filter(:group_id, :enum, :select => ['hello'], :multiple => true) + scope { Entry } + filter(:group_id, :enum, select: ["hello"], multiple: true) end end let(:_filter) { :group_id } let(:expected_html) do - <<-HTML -<select multiple class="group_id enum_filter" name="report[group_id][]" id="report_group_id"> -<option value="hello">hello</option></select> + <<~HTML + <select multiple class="group_id enum_filter" name="report[group_id][]" id="report_group_id"> + <option value="hello">hello</option></select> HTML end @@ -486,8 +548,8 @@ class MyTemplate context "with column names filter" do let(:_grid) do - test_report(:column_names => [:id, :name]) do - scope {Entry} + test_report(column_names: %i[id name]) do + scope { Entry } column_names_filter @@ -498,10 +560,10 @@ class MyTemplate end let(:_filter) { :column_names } let(:expected_html) do - <<-HTML -<select multiple class="column_names enum_filter" name="report[column_names][]" id="report_column_names"><option selected value="id">Id</option> -<option selected value="name">Name</option> -<option value="category">Category</option></select> + <<~HTML + <select multiple class="column_names enum_filter" name="report[column_names][]" id="report_column_names"><option selected value="id">Id</option> + <option selected value="name">Name</option> + <option value="category">Category</option></select> HTML end @@ -509,10 +571,10 @@ class MyTemplate end context "with column_names_filter default given as symbols" do let(:_grid) do - test_report() do - scope {Entry} + test_report do + scope { Entry } - column_names_filter(:default => [:id, :name], :checkboxes => true) + column_names_filter(default: %i[id name], checkboxes: true) column(:id) column(:name) @@ -521,11 +583,11 @@ class MyTemplate end let(:_filter) { :column_names } let(:expected_html) do - <<DOM -<label class="column_names enum_filter checkboxes" for="report_column_names_id"><input class="column_names enum_filter checkboxes" id="report_column_names_id" type="checkbox" value="id" checked name="report[column_names][]">Id</label> -<label class="column_names enum_filter checkboxes" for="report_column_names_name"><input class="column_names enum_filter checkboxes" id="report_column_names_name" type="checkbox" value="name" checked name="report[column_names][]">Name</label> -<label class="column_names enum_filter checkboxes" for="report_column_names_category"><input class="column_names enum_filter checkboxes" id="report_column_names_category" type="checkbox" value="category" name="report[column_names][]">Category</label> -DOM + <<~DOM + <label class="column_names enum_filter checkboxes" for="report_column_names_id"><input class="column_names enum_filter checkboxes" id="report_column_names_id" type="checkbox" value="id" checked name="report[column_names][]">Id</label> + <label class="column_names enum_filter checkboxes" for="report_column_names_name"><input class="column_names enum_filter checkboxes" id="report_column_names_name" type="checkbox" value="name" checked name="report[column_names][]">Name</label> + <label class="column_names enum_filter checkboxes" for="report_column_names_category"><input class="column_names enum_filter checkboxes" id="report_column_names_category" type="checkbox" value="category" name="report[column_names][]">Category</label> + DOM end it do @@ -541,7 +603,7 @@ class MyTemplate let(:_grid) do options = filter_options test_report do - scope {Entry} + scope { Entry } filter(:condition, :dynamic, **options) end end @@ -565,12 +627,11 @@ class MyTemplate <option value="<=">≤</option></select><input class="condition dynamic_filter value" name="report[condition][]" type="text" id="report_condition"> HTML end - it {should equal_to_dom(expected_html)} - + it { should equal_to_dom(expected_html) } end context "when default option passed" do let(:filter_options) do - {:select => [:id, :name], :default => [:id, '>=', 1]} + { select: %i[id name], default: [:id, ">=", 1] } end let(:expected_html) do <<-HTML @@ -581,13 +642,12 @@ class MyTemplate <option value="<=">≤</option></select><input class="condition dynamic_filter value" name="report[condition][]" value="1" type="text" id="report_condition"> HTML end - it {should equal_to_dom(expected_html)} - + it { should equal_to_dom(expected_html) } end context "when operations and options are defined" do let(:filter_options) do - {:operations => %w(>= <=), :select => [:id, :name]} + { operations: %w[>= <=], select: %i[id name] } end let(:expected_html) do <<-HTML @@ -595,12 +655,12 @@ class MyTemplate <option value="<=">≤</option></select><input class="condition dynamic_filter value" name="report[condition][]" type="text" id="report_condition"> HTML end - it {should equal_to_dom(expected_html)} + it { should equal_to_dom(expected_html) } end context "when the field is predefined" do let(:filter_options) do - {:operations => %w(>= <=), :select => [:id]} + { operations: %w[>= <=], select: [:id] } end let(:expected_html) do <<-HTML @@ -608,30 +668,28 @@ class MyTemplate <option value="<=">≤</option></select><input class="condition dynamic_filter value" name="report[condition][]" type="text" id="report_condition"> HTML end - it {should equal_to_dom(expected_html)} + it { should equal_to_dom(expected_html) } end context "when operation is predefined" do let(:filter_options) do - {:operations => %w(=), :select => [:id, :name]} + { operations: %w[=], select: %i[id name] } end let(:expected_html) do <<-HTML <select class="condition dynamic_filter field" name="report[condition][]" id="report_condition"><option value="id">id</option><option value="name">name</option></select><input class="condition dynamic_filter operation" name="report[condition][]" value="=" autocomplete="off" type="hidden" id="report_condition"><input class="condition dynamic_filter value" name="report[condition][]" type="text" id="report_condition"> HTML end - it {should equal_to_dom(expected_html)} + it { should equal_to_dom(expected_html) } end - end end - describe ".datagrid_label" do let(:_grid) do test_report do - scope {Entry} + scope { Entry } filter(:name, :string) - filter(:created_at, :date, label_options: {class: 'js-date-selector'}) + filter(:created_at, :date, label_options: { class: "js-date-selector" }) end end it "should generate label for filter" do @@ -645,12 +703,12 @@ class MyTemplate ) end it "should pass options through to the helper" do - expect(view.datagrid_label(:name, class: 'foo')).to equal_to_dom( + expect(view.datagrid_label(:name, class: "foo")).to equal_to_dom( '<label class="foo name string_filter" for="report_name">Name</label>' ) end it "should support block" do - expect(view.datagrid_label(:name, class: 'foo') { 'The Name' }).to equal_to_dom( + expect(view.datagrid_label(:name, class: "foo") { "The Name" }).to equal_to_dom( '<label class="foo name string_filter" for="report_name">The Name</label>' ) end diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 2ec195f..adc8efa 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -1,9 +1,9 @@ -require 'spec_helper' +require "spec_helper" require "active_support/core_ext/hash" require "active_support/core_ext/object" require "action_controller" -require 'datagrid/renderer' +require "datagrid/renderer" describe Datagrid::Helper do subject do @@ -16,15 +16,16 @@ Struct.new(:path, :query_parameters).new("/location", {}) end allow(subject).to receive(:url_for) do |options| - options.is_a?(String) ? options : ["/location", options.to_param.presence].compact.join('?') + options.is_a?(String) ? options : ["/location", options.to_param.presence].compact.join("?") end - end - let(:group) { Group.create!(:name => "Pop") } - let!(:entry) { Entry.create!( - group: group, name: "Star", disabled: false, confirmed: false, category: "first" - ) } + let(:group) { Group.create!(name: "Pop") } + let!(:entry) do + Entry.create!( + group: group, name: "Star", disabled: false, confirmed: false, category: "first" + ) + end let(:grid) { SimpleReport.new } context "when grid has no records" do @@ -67,13 +68,13 @@ class TestGrid datagrid_table = subject.datagrid_table(grid) expect(datagrid_table).to match_css_pattern({ - "table.datagrid tr th.group div.order" => 1, - "table.datagrid tr th.group" => /Group.*/, - "table.datagrid tr th.name div.order" => 1, - "table.datagrid tr th.name" => /Name.*/, - "table.datagrid tr td.group" => "Pop", - "table.datagrid tr td.name" => "Star" - }) + "table.datagrid tr th.group div.order" => 1, + "table.datagrid tr th.group" => /Group.*/, + "table.datagrid tr th.name div.order" => 1, + "table.datagrid tr th.name" => /Name.*/, + "table.datagrid tr td.group" => "Pop", + "table.datagrid tr td.name" => "Star" + }) end it "should support giving assets explicitly" do @@ -81,13 +82,13 @@ class TestGrid datagrid_table = subject.datagrid_table(grid, [entry]) expect(datagrid_table).to match_css_pattern({ - "table.datagrid tr th.group div.order" => 1, - "table.datagrid tr th.group" => /Group.*/, - "table.datagrid tr th.name div.order" => 1, - "table.datagrid tr th.name" => /Name.*/, - "table.datagrid tr td.group" => "Pop", - "table.datagrid tr td.name" => "Star" - }) + "table.datagrid tr th.group div.order" => 1, + "table.datagrid tr th.group" => /Group.*/, + "table.datagrid tr th.name div.order" => 1, + "table.datagrid tr th.name" => /Name.*/, + "table.datagrid tr td.group" => "Pop", + "table.datagrid tr td.name" => "Star" + }) end it "should support no order given" do @@ -95,7 +96,7 @@ class TestGrid end it "should support columns option" do - expect(subject.datagrid_table(grid, [entry], :columns => [:name])).to match_css_pattern( + expect(subject.datagrid_table(grid, [entry], columns: [:name])).to match_css_pattern( "table.datagrid th.name" => 1, "table.datagrid td.name" => 1, "table.datagrid th.group" => 0, @@ -125,7 +126,7 @@ class TestGrid context "when grid has no columns" do let(:grid) do test_report do - scope {Entry} + scope { Entry } end end @@ -134,7 +135,7 @@ class TestGrid end end - context 'with partials attribute' do + context "with partials attribute" do let(:grid) do test_report do scope { Entry } @@ -143,21 +144,21 @@ class TestGrid end end - it 'renders namespaced table partial' do + it "renders namespaced table partial" do rendered_partial = subject.datagrid_table( - grid, [entry], partials: 'client/datagrid' + grid, [entry], partials: "client/datagrid" ) - expect(rendered_partial).to include 'Namespaced table partial.' - expect(rendered_partial).to include 'Namespaced row partial.' - expect(rendered_partial).to include 'Namespaced head partial.' - expect(rendered_partial).to include 'Namespaced order_for partial.' + expect(rendered_partial).to include "Namespaced table partial." + expect(rendered_partial).to include "Namespaced row partial." + expect(rendered_partial).to include "Namespaced head partial." + expect(rendered_partial).to include "Namespaced order_for partial." end end context "when scope is enumerator" do let(:grid) do test_report do - scope { ['a', 'b'].to_enum } + scope { %w[a b].to_enum } column(:name) do |value| value end @@ -166,14 +167,14 @@ class TestGrid it "should render table" do expect(subject.datagrid_table(grid)).to match_css_pattern( "table.datagrid th.name" => 1, - "table.datagrid td.name" => 2, + "table.datagrid td.name" => 2 ) end end context "when scope is lazy enumerator" do let(:grid) do test_report do - scope { ['a', 'b'].lazy } + scope { %w[a b].lazy } column(:name) do |value| value end @@ -182,7 +183,7 @@ class TestGrid it "should render table" do expect(subject.datagrid_table(grid)).to match_css_pattern( "table.datagrid th.name" => 1, - "table.datagrid td.name" => 2, + "table.datagrid td.name" => 2 ) end end @@ -192,7 +193,7 @@ class TestGrid it "should support urls" do rp = test_report do scope { Entry } - column(:name, url: lambda {|model| model.name}) + column(:name, url: ->(model) { model.name }) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( "tr td.name a[href=Star]" => "Star" @@ -202,7 +203,7 @@ class TestGrid it "should support conditional urls" do rp = test_report do scope { Entry } - column(:name, url: lambda {|model| false}) + column(:name, url: ->(_model) { false }) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( "tr td.name" => "Star" @@ -292,7 +293,7 @@ class TestGrid it "should render :html columns with &:symbol block with a data attribute" do rp = test_report do scope { Entry } - column(:name, html: true, data: 'DATA', &:name) + column(:name, html: true, data: "DATA", &:name) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( @@ -303,7 +304,7 @@ class TestGrid it "should render argument-based html columns" do rp = test_report do scope { Entry } - column(:name, html: lambda {|data| content_tag :h1, data}) + column(:name, html: ->(data) { content_tag :h1, data }) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( "tr td.name h1" => "Star" @@ -313,8 +314,8 @@ class TestGrid it "should render argument-based html columns with custom data" do rp = test_report do scope { Entry } - column(:name, html: lambda {|data| content_tag :em, data}) do - self.name.upcase + column(:name, html: ->(data) { content_tag :em, data }) do + name.upcase end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( @@ -326,7 +327,7 @@ class TestGrid rp = test_report do scope { Entry } column(:name, html: true) do |model, grid| - content_tag(:span, "#{model.name}-#{grid.assets.klass}" ) + content_tag(:span, "#{model.name}-#{grid.assets.klass}") end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( @@ -364,7 +365,7 @@ class TestGrid column(:name, html: lambda { |data, model| content_tag :h1, "#{data}-#{model.name}" }) do - self.name.upcase + name.upcase end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( @@ -378,7 +379,7 @@ class TestGrid column(:name, html: lambda { |data, model, grid| content_tag :h1, "#{data}-#{model.name}-#{grid.assets.klass}" }) do - self.name.upcase + name.upcase end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( @@ -392,10 +393,10 @@ class TestGrid column(:name) column(:category) end - expect(subject.datagrid_rows(rp, [entry], :columns => [:name])).to match_css_pattern( + expect(subject.datagrid_rows(rp, [entry], columns: [:name])).to match_css_pattern( "tr td.name" => "Star" ) - expect(subject.datagrid_rows(rp, [entry], :columns => [:name])).to match_css_pattern( + expect(subject.datagrid_rows(rp, [entry], columns: [:name])).to match_css_pattern( "tr td.category" => 0 ) end @@ -403,7 +404,7 @@ class TestGrid it "should allow CSS classes to be specified for a column" do rp = test_report do scope { Entry } - column(:name, :class => 'my_class') + column(:name, class: "my_class") end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( @@ -413,8 +414,8 @@ class TestGrid context "when grid has complicated columns" do let(:grid) do - test_report(:name => 'Hello') do - scope {Entry} + test_report(name: "Hello") do + scope { Entry } filter(:name) column(:name) do |model, grid| "'#{model.name}' filtered by '#{grid.name}'" @@ -429,23 +430,21 @@ class TestGrid end it "should escape html" do - entry.update!(:name => "<div>hello</div>") - expect(subject.datagrid_rows(grid, [entry], :columns => [:name])).to equal_to_dom(<<-HTML) + entry.update!(name: "<div>hello</div>") + expect(subject.datagrid_rows(grid, [entry], columns: [:name])).to equal_to_dom(<<-HTML) <tr><td class="name"><div>hello</div></td></tr> - HTML + HTML end it "should not escape safe html" do - entry.update!(:name => "<div>hello</div>") + entry.update!(name: "<div>hello</div>") grid.column(:safe_name) do |model| model.name.html_safe end - expect(subject.datagrid_rows(grid, [entry], :columns => [:safe_name])).to equal_to_dom(<<-HTML) + expect(subject.datagrid_rows(grid, [entry], columns: [:safe_name])).to equal_to_dom(<<-HTML) <tr><td class="safe_name"><div>hello</div></td></tr> - HTML - + HTML end - end describe ".datagrid_order_for" do @@ -456,22 +455,21 @@ class OrderedGrid column(:category) end object = OrderedGrid.new(descending: true, order: :category) - expect(subject.datagrid_order_for(object, object.column_by_name(:category))).to equal_to_dom(<<-HTML) -<div class="order"> -<a class="asc" href="/location?ordered_grid%5Bdescending%5D=false&ordered_grid%5Border%5D=category">↑</a> -<a class="desc" href="/location?ordered_grid%5Bdescending%5D=true&ordered_grid%5Border%5D=category">↓</a> -</div> + expect(subject.datagrid_order_for(object, object.column_by_name(:category))).to equal_to_dom(<<~HTML) + <div class="order"> + <a class="asc" href="/location?ordered_grid%5Bdescending%5D=false&ordered_grid%5Border%5D=category">↑</a> + <a class="desc" href="/location?ordered_grid%5Bdescending%5D=true&ordered_grid%5Border%5D=category">↓</a> + </div> HTML end - end describe ".datagrid_form_for" do - it 'returns namespaced partial if partials options is passed' do + it "returns namespaced partial if partials options is passed" do rendered_form = subject.datagrid_form_for(grid, { - url: '', - :partials => 'client/datagrid' - }) - expect(rendered_form).to include 'Namespaced form partial.' + url: "", + partials: "client/datagrid" + }) + expect(rendered_form).to include "Namespaced form partial." end it "should render form and filter inputs" do class FormForGrid @@ -479,7 +477,7 @@ class FormForGrid scope { Entry } filter(:category) end - object = FormForGrid.new(:category => "hello") + object = FormForGrid.new(category: "hello") expect(subject.datagrid_form_for(object, url: "/grid")).to match_css_pattern( "form.datagrid-form.form_for_grid[action='/grid']" => 1, "form input[name=utf8]" => 1, @@ -500,7 +498,7 @@ class TestGrid expect(subject.datagrid_form_for(::Ns22::TestGrid.new, url: "grid")).to match_css_pattern( "form.datagrid-form.ns22_test_grid" => 1, "form.datagrid-form label[for=ns22_test_grid_id]" => 1, - "form.datagrid-form input#ns22_test_grid_id[name='ns22_test_grid[id]']" => 1, + "form.datagrid-form input#ns22_test_grid_id[name='ns22_test_grid[id]']" => 1 ) end @@ -510,39 +508,38 @@ class ParamNameGrid81 scope { Entry } filter(:id) def param_name - 'g' + "g" end end expect(subject.datagrid_form_for(::ParamNameGrid81.new, url: "/grid")).to match_css_pattern( - "form.datagrid-form input[name='g[id]']" => 1, + "form.datagrid-form input[name='g[id]']" => 1 ) end it "takes default partials if custom doesn't exist" do class PartialDefaultGrid include Datagrid - scope {Entry} - filter(:id, :integer, :range => true) - filter(:group_id, :enum, :multiple => true, :checkboxes => true, :select => [1,2]) + scope { Entry } + filter(:id, :integer, range: true) + filter(:group_id, :enum, multiple: true, checkboxes: true, select: [1, 2]) def param_name - 'g' + "g" end end rendered_form = subject.datagrid_form_for(PartialDefaultGrid.new, { - url: '', - :partials => 'custom_form' - }) - expect(rendered_form).to include 'form_partial_test' + url: "", + partials: "custom_form" + }) + expect(rendered_form).to include "form_partial_test" expect(rendered_form).to match_css_pattern([ - 'input.integer_filter.from', - 'input.integer_filter.to', - ".enum_filter input[value='1']", - ".enum_filter input[value='2']", - ]) + "input.integer_filter.from", + "input.integer_filter.to", + ".enum_filter input[value='1']", + ".enum_filter input[value='2']" + ]) end end - describe ".datagrid_row" do let(:grid) do test_report do @@ -553,7 +550,7 @@ def param_name end let(:entry) do - Entry.create!(:name => "Hello", :category => "greetings") + Entry.create!(name: "Hello", category: "greetings") end it "should provide access to row data" do @@ -563,7 +560,7 @@ def param_name end it "should provide an interator" do r = subject.datagrid_row(grid, entry) - expect(r.map {|z| z.upcase}).to eq(["HELLO", "GREETINGS"]) + expect(r.map { |z| z.upcase }).to eq(%w[HELLO GREETINGS]) expect(r.name).to eq("Hello") expect(r.category).to eq("greetings") end @@ -592,10 +589,10 @@ def param_name it "should use cache" do grid = test_report do - scope {Entry} + scope { Entry } self.cached = true - column(:random1, html: true) {rand(10**9)} - column(:random2) {|model| format(rand(10**9)) {|value| value}} + column(:random1, html: true) { rand(10**9) } + column(:random2) { |_model| format(rand(10**9)) { |value| value } } end entry = Entry.create! @@ -615,15 +612,15 @@ def param_name it "converts to string using columns option" do r = subject.datagrid_row(grid, entry, columns: [:name]).to_s - expect(r).to match_css_pattern('tr td.name') - expect(r).to_not match_css_pattern('tr td.category') + expect(r).to match_css_pattern("tr td.name") + expect(r).to_not match_css_pattern("tr td.category") end end describe ".datagrid_value" do it "should format value by column name" do report = test_report do - scope {Entry} + scope { Entry } column(:name) do |e| "<b>#{e.name}</b>" end @@ -633,21 +630,21 @@ def param_name end it "should support format in column" do report = test_report do - scope {Entry} + scope { Entry } column(:name) do |e| format(e.name) do |value| - link_to value, "/profile" + link_to value, "/profile" end end end expect(subject.datagrid_value(report, :name, entry)).to be_html_safe - expect(subject.datagrid_value(report, :name, entry)).to eq("<a href=\"/profile\">Star</a>") + expect(subject.datagrid_value(report, :name, entry)).to eq('<a href="/profile">Star</a>') end it "applies decorator" do report = test_report do - scope {Entry} - decorate do |model| + scope { Entry } + decorate do |_model| Class.new(Struct.new(:model)) do def name model.name.upcase @@ -656,7 +653,7 @@ def name end column(:name, html: true) end - entry = Entry.create!(name: 'hello') + entry = Entry.create!(name: "hello") expect(subject.datagrid_value(report, :name, entry)).to eq("HELLO") end end @@ -668,17 +665,15 @@ def name column(:category, order: false, order_by_value: true) def param_name - 'grid' + "grid" end end - expect(subject.datagrid_header(grid)).to equal_to_dom(<<HTML) -<tr><th class="category ordered asc">Category<div class="order"> -<a class="asc" href="/location?grid%5Bdescending%5D=false&grid%5Border%5D=category">↑</a><a class="desc" href="/location?grid%5Bdescending%5D=true&grid%5Border%5D=category">↓</a> -</div> -</th></tr> -HTML + expect(subject.datagrid_header(grid)).to equal_to_dom(<<~HTML) + <tr><th class="category ordered asc">Category<div class="order"> + <a class="asc" href="/location?grid%5Bdescending%5D=false&grid%5Border%5D=category">↑</a><a class="desc" href="/location?grid%5Bdescending%5D=true&grid%5Border%5D=category">↓</a> + </div> + </th></tr> + HTML end end - end - diff --git a/spec/datagrid/ordering_spec.rb b/spec/datagrid/ordering_spec.rb index e688f42..701e6b0 100644 --- a/spec/datagrid/ordering_spec.rb +++ b/spec/datagrid/ordering_spec.rb @@ -1,12 +1,9 @@ -require 'spec_helper' +require "spec_helper" describe Datagrid::Ordering do - - - let!(:third) { Entry.create!(name: "cc")} - let!(:second) { Entry.create!(name: "bb")} - let!(:first) { Entry.create!(name: "aa")} - + let!(:third) { Entry.create!(name: "cc") } + let!(:second) { Entry.create!(name: "bb") } + let!(:first) { Entry.create!(name: "aa") } it "should support order" do expect(test_report(order: "name") do @@ -15,7 +12,6 @@ end column :name end.assets).to eq([first, second, third]) - end it "should support desc order" do @@ -27,17 +23,16 @@ end.assets).to eq([third, second, first]) end - it "should raise error if ordered by not existing column" do - expect { + expect do test_report(order: :hello).assets - }.to raise_error(Datagrid::OrderUnsupported) + end.to raise_error(Datagrid::OrderUnsupported) end it "should raise error if ordered by column without order" do expect do test_report(order: :category) do - filter(:category, :default, order: false) do |value| + filter(:category, :default, order: false) do |_value| self end end.assets @@ -46,7 +41,7 @@ it "should override default order" do expect(test_report(order: :name) do - scope { Entry.order("name desc")} + scope { Entry.order("name desc") } column(:name, order: "name asc") end.assets).to eq([first, second, third]) end @@ -68,20 +63,20 @@ it "should support order desc given as block" do expect(test_report(order: :name, descending: true) do scope { Entry } - column(:name, order_desc: proc { order("name desc")}) + column(:name, order_desc: proc { order("name desc") }) end.assets).to eq([third, second, first]) end it "should treat true order as default" do expect(test_report(order: :name) do scope { Entry } - column(:name, order: true) + column(:name, order: true) end.assets).to eq([first, second, third]) end it "should support order_by_value" do report = test_report(order: :the_name) do - scope {Entry} + scope { Entry } column(:the_name, order_by_value: true) do name end @@ -92,12 +87,10 @@ end it "should support order_by_value as block" do - - order = { aa: 2, bb: 3, cc: 1} + order = { aa: 2, bb: 3, cc: 1 } report = test_report(order: :the_name) do - - scope {Entry} - column(:the_name, order_by_value: proc{|model| order[model.name.to_sym]}) do + scope { Entry } + column(:the_name, order_by_value: proc { |model| order[model.name.to_sym] }) do name end end @@ -116,27 +109,25 @@ class OrderInheritenceChild < OrderInheritenceBase column(:name) end - grid = OrderInheritenceChild.new(order: 'name') + grid = OrderInheritenceChild.new(order: "name") expect(grid.assets).to eq([first, second, third]) grid.descending = true expect(grid.assets).to eq([third, second, first]) end it "should support ordering by dynamic columns" do - report = test_report(order: "name") do - scope {Entry} + scope { Entry } dynamic do column(:name) end end expect(report.assets).to eq([first, second, third]) - end it "should support #ordered_by? method" do report = test_report(order: "name") do - scope {Entry} + scope { Entry } column(:id) column(:name) end diff --git a/spec/datagrid/scaffold_spec.rb b/spec/datagrid/scaffold_spec.rb index 7ccc455..9bab5fc 100644 --- a/spec/datagrid/scaffold_spec.rb +++ b/spec/datagrid/scaffold_spec.rb @@ -1,20 +1,19 @@ -require 'spec_helper' +require "spec_helper" describe Datagrid::Scaffold do subject { Datagrid::Scaffold.new(["user"]) } - - describe '.pagination_helper_code' do - it 'uses kaminari by default' do - expect(subject.pagination_helper_code).to eql('paginate(@grid.assets)') + describe ".pagination_helper_code" do + it "uses kaminari by default" do + expect(subject.pagination_helper_code).to eql("paginate(@grid.assets)") end context "when WillPaginate exists" do before(:each) do Object.const_set("WillPaginate", 1) end - it 'uses willpaginate' do - expect(subject.pagination_helper_code).to eql('will_paginate(@grid.assets)') + it "uses willpaginate" do + expect(subject.pagination_helper_code).to eql("will_paginate(@grid.assets)") end after(:each) do @@ -24,7 +23,6 @@ end describe ".index_action" do - it "works" do expect(subject.index_action).to eq(<<-RUBY) def index @@ -38,8 +36,7 @@ def index def grid_params params.fetch(:users_grid, {}).permit! end -RUBY + RUBY end - end end diff --git a/spec/datagrid/stylesheet_spec.rb b/spec/datagrid/stylesheet_spec.rb index 0404561..0fc65ce 100644 --- a/spec/datagrid/stylesheet_spec.rb +++ b/spec/datagrid/stylesheet_spec.rb @@ -1,9 +1,7 @@ -require 'spec_helper' +require "spec_helper" describe "Datagrid stylesheet" do - it "should work correctly" do - if Rails.application.assets.respond_to?(:find_asset) asset = Rails.application.assets.find_asset("datagrid") asset diff --git a/spec/datagrid/utils_spec.rb b/spec/datagrid/utils_spec.rb index 89775cd..f66a495 100644 --- a/spec/datagrid/utils_spec.rb +++ b/spec/datagrid/utils_spec.rb @@ -1,8 +1,6 @@ -require 'spec_helper' +require "spec_helper" describe Datagrid::Utils do - - describe ".warn_once" do it "should work" do silence_warnings do diff --git a/spec/datagrid_spec.rb b/spec/datagrid_spec.rb index 6b3ecc5..3b04da1 100644 --- a/spec/datagrid_spec.rb +++ b/spec/datagrid_spec.rb @@ -1,11 +1,9 @@ -require 'spec_helper' +require "spec_helper" require "datagrid/rspec" - describe Datagrid do - describe SimpleReport do - it_should_behave_like 'Datagrid' + it_should_behave_like "Datagrid" end let(:group) { Group.create!(name: "Pop") } @@ -20,22 +18,23 @@ ) end - let!(:entry) { Entry.create!( - group: group, name: "Star", disabled: false, confirmed: false, category: "first" - ) } + let!(:entry) do + Entry.create!( + group: group, name: "Star", disabled: false, confirmed: false, category: "first" + ) + end - describe '#assets' do + describe "#assets" do subject { super().assets } it { should include(entry) } end describe ".attributes" do it "should return report attributes" do - (subject.filters.map(&:name) + [:order, :descending]).each do |attribute| + (subject.filters.map(&:name) + %i[order descending]).each do |attribute| expect(subject.attributes).to have_key(attribute) end end - end describe ".scope" do @@ -43,17 +42,15 @@ expect(subject.scope).to respond_to(:each) end - context "when not defined on class level" do subject do test_report {} end it "should raise ConfigurationError" do - expect { + expect do subject.scope - }.to raise_error(Datagrid::ConfigurationError) - + end.to raise_error(Datagrid::ConfigurationError) end end end @@ -89,6 +86,4 @@ end end end - - end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a555bb8..995e21f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,77 +1,71 @@ -require 'rubygems' -require 'bundler' +require "rubygems" +require "bundler" begin Bundler.setup(:default, :development) rescue Bundler::BundlerError => e - $stderr.puts e.message - $stderr.puts "Run `bundle install` to install missing gems" + warn e.message + warn "Run `bundle install` to install missing gems" exit e.status_code end -$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) +$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib")) $LOAD_PATH.unshift(File.dirname(__FILE__)) require "active_record" -require 'action_view' +require "action_view" require "rails" require "mongoid" begin - require 'mongo_mapper' + require "mongo_mapper" rescue LoadError end - - -require 'datagrid' +require "datagrid" begin - require 'ruby-debug' + require "ruby-debug" rescue LoadError end -require 'rspec' +require "rspec" require "logger" class DatagridTest < Rails::Application - config.eager_load = false - end -if I18n.respond_to?(:enforce_available_locales) - I18n.enforce_available_locales = true -end +I18n.enforce_available_locales = true if I18n.respond_to?(:enforce_available_locales) -File.open('spec.log', "w").close -TEST_LOGGER = Logger.new('spec.log') -NO_MONGO = ENV['NO_MONGO'] +File.open("spec.log", "w").close +TEST_LOGGER = Logger.new("spec.log") +NO_MONGO = ENV["NO_MONGO"] if NO_MONGO warn("MONGODB WARNING: Skipping Mongoid and Mongomapper tests.") else begin Mongoid.load_configuration({ - "clients" => - { - "default" => - { - "hosts" => ["localhost:27017"], - "database" =>"datagrid_mongoid", - options: { - max_read_retries: 0, - retry_reads: false, - connect_timeout: 2, - wait_queue_timeout: 2, - server_selection_timeout: 2, - socket_timeout: 1 - } - } - } - }) + "clients" => + { + "default" => + { + "hosts" => ["localhost:27017"], + "database" => "datagrid_mongoid", + options: { + max_read_retries: 0, + retry_reads: false, + connect_timeout: 2, + wait_queue_timeout: 2, + server_selection_timeout: 2, + socket_timeout: 1 + } + } + } + }) Mongoid.client(:default).collections # check mongo connection if defined?(MongoMapper) - MongoMapper.connection = Mongo::Connection.new('localhost', 27017) + MongoMapper.connection = Mongo::Connection.new("localhost", 27_017) MongoMapper.database = "datagrid_mongo_mapper" end rescue Mongo::Error::NoServerAvailable => e @@ -82,7 +76,7 @@ class DatagridTest < Rails::Application RSpec.configure do |config| config.after(:each) do - #TODO better database truncation + # TODO: better database truncation Group.delete_all Entry.delete_all SequelEntry.where({}).delete @@ -90,7 +84,6 @@ class DatagridTest < Rails::Application MongoidEntry.delete_all MongoMapperEntry.delete_all if defined?(MongoMapperEntry) end - end if NO_MONGO @@ -99,24 +92,22 @@ class DatagridTest < Rails::Application end config.expect_with :rspec do |c| - #c.syntax = :expect - c.syntax = [:should, :expect] + # c.syntax = :expect + c.syntax = %i[should expect] end end def action_view_template context = ActionView::LookupContext.new([ - File.expand_path("../../app/views", __FILE__), - File.expand_path("../support/test_partials", __FILE__), - ], {}) + File.expand_path("../app/views", __dir__), + File.expand_path("support/test_partials", __dir__) + ], {}) Datagrid::Engine.extend_modules template = ActionView::Base.with_empty_template_cache.new(context, {}, ::ActionController::Base.new) allow(template).to receive(:protect_against_forgery?).and_return(false) template end - - # Requires supporting files with custom matchers and macros, etc, # in ./support/ and its subdirectories. -Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f} +Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } diff --git a/spec/support/active_record.rb b/spec/support/active_record.rb index ed1f32e..3a9a2c4 100644 --- a/spec/support/active_record.rb +++ b/spec/support/active_record.rb @@ -1,16 +1,12 @@ require "sqlite3" ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") -#ActiveRecord::Base.configurations = true +# ActiveRecord::Base.configurations = true ActiveRecord::Base.logger = TEST_LOGGER - - - ActiveRecord::Schema.verbose = false ActiveRecord::Schema.define(version: 1) do - create_table :entries do |t| t.integer :group_id t.string :name @@ -32,6 +28,7 @@ class ::Entry < ActiveRecord::Base belongs_to :group end + class ::Group < ActiveRecord::Base has_many :entries end diff --git a/spec/support/configuration.rb b/spec/support/configuration.rb index 014c295..07e39a1 100644 --- a/spec/support/configuration.rb +++ b/spec/support/configuration.rb @@ -1,28 +1,23 @@ def with_date_format(format = "%m/%d/%Y") - begin - old_format = Datagrid.configuration.date_formats - Datagrid.configure do |config| - config.date_formats = format - end - yield - ensure - Datagrid.configure do |config| - config.date_formats = old_format - end + old_format = Datagrid.configuration.date_formats + Datagrid.configure do |config| + config.date_formats = format + end + yield +ensure + Datagrid.configure do |config| + config.date_formats = old_format end end def with_datetime_format(format = "%m/%d/%Y") - begin - old_format = Datagrid.configuration.datetime_formats - Datagrid.configure do |config| - config.datetime_formats = format - end - yield - ensure - Datagrid.configure do |config| - config.datetime_formats = old_format - end + old_format = Datagrid.configuration.datetime_formats + Datagrid.configure do |config| + config.datetime_formats = format + end + yield +ensure + Datagrid.configure do |config| + config.datetime_formats = old_format end end - diff --git a/spec/support/i18n_helpers.rb b/spec/support/i18n_helpers.rb index 280220d..9a52846 100644 --- a/spec/support/i18n_helpers.rb +++ b/spec/support/i18n_helpers.rb @@ -1,4 +1,4 @@ -def store_translations(locale, translations, &block) +def store_translations(locale, translations) I18n.backend.store_translations locale, translations yield ensure diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb index 76dd2f1..3a84ce6 100644 --- a/spec/support/matchers.rb +++ b/spec/support/matchers.rb @@ -1,4 +1,4 @@ -require 'rails/dom/testing' +require "rails/dom/testing" def equal_to_dom(text) EqualToDom.new(text) @@ -8,7 +8,6 @@ def match_css_pattern(pattern) CssPattern.new(pattern) end - class EqualToDom include Rails::Dom::Testing::Assertions::DomAssertions @@ -34,15 +33,14 @@ def description end end - class CssPattern def initialize(pattern) @css_pattern = pattern @error_message = nil - unless @css_pattern.is_a?(Hash) - @css_pattern = Array(@css_pattern).map do |key| - [key, 1] - end + return if @css_pattern.is_a?(Hash) + + @css_pattern = Array(@css_pattern).map do |key| + [key, 1] end end @@ -60,7 +58,7 @@ def matches?(text) if amount_or_pattern_or_string_or_proc.is_a?(String) or amount_or_pattern_or_string_or_proc.is_a?(Regexp) pattern_or_string = amount_or_pattern_or_string_or_proc html = path.inner_html - if !html.match(pattern_or_string) + unless html.match(pattern_or_string) return error!("#{css.inspect} did not match #{pattern_or_string.inspect}. It was \n:#{html.inspect}") end elsif amount_or_pattern_or_string_or_proc.is_a? Numeric @@ -70,13 +68,12 @@ def matches?(text) return error!("did not find #{css.inspect} #{expected_amount.inspect} times. It was #{amount.inspect}") end elsif amount_or_pattern_or_string_or_proc.is_a? Proc - if !amount_or_pattern_or_string_or_proc.call(path) + unless amount_or_pattern_or_string_or_proc.call(path) return error!("#{css.inspect} did not validate (proc must not return a falsy value)") end else raise "Instance of String, Rexexp, Proc or Fixnum required" end - true end end diff --git a/spec/support/mongo_mapper.rb b/spec/support/mongo_mapper.rb index 4f37240..5876028 100644 --- a/spec/support/mongo_mapper.rb +++ b/spec/support/mongo_mapper.rb @@ -10,7 +10,6 @@ class MongoMapperEntry key :confirmed, Boolean, default: false key :shipping_date, Time timestamps! - end class MongoMapperGrid @@ -27,6 +26,5 @@ class MongoMapperGrid column :name column :group_id column :disabled - end end diff --git a/spec/support/mongoid.rb b/spec/support/mongoid.rb index de617b7..014c008 100644 --- a/spec/support/mongoid.rb +++ b/spec/support/mongoid.rb @@ -1,10 +1,8 @@ require "rubygems" -#Mongoid.logger = TEST_LOGGER #TODO: understand why still output to STDOUT - +# Mongoid.logger = TEST_LOGGER #TODO: understand why still output to STDOUT class MongoidEntry - include Mongoid::Document include Mongoid::Timestamps @@ -14,7 +12,6 @@ class MongoidEntry field :disabled, default: false, type: Boolean field :confirmed, default: false, type: Boolean field :shipping_date, type: Time - end class MongoidGrid @@ -31,6 +28,4 @@ class MongoidGrid column :name column :group_id column :disabled - end - diff --git a/spec/support/sequel.rb b/spec/support/sequel.rb index 48fe2d4..5130fc9 100644 --- a/spec/support/sequel.rb +++ b/spec/support/sequel.rb @@ -1,6 +1,5 @@ require "sequel" - DB = Sequel.sqlite # memory database DB.extension(:pagination) @@ -17,10 +16,8 @@ end class SequelEntry < Sequel::Model - end - class SequelGrid include ::Datagrid @@ -35,6 +32,4 @@ class SequelGrid column :name column :group_id column :disabled - end - diff --git a/spec/support/simple_report.rb b/spec/support/simple_report.rb index 02591f9..57e553a 100644 --- a/spec/support/simple_report.rb +++ b/spec/support/simple_report.rb @@ -1,5 +1,3 @@ - - def test_report(attributes = {}, &block) klass = test_report_class(&block) klass.new(attributes) @@ -13,14 +11,11 @@ def self.name "TestGrid" end end - if block - klass.class_eval(&block) - end + klass.class_eval(&block) if block end end class SimpleReport - include Datagrid scope do @@ -28,16 +23,16 @@ class SimpleReport end filter(:group_id, :integer, multiple: true) - filter(:category, :enum, select: ["first", "second"]) + filter(:category, :enum, select: %w[first second]) filter(:disabled, :xboolean) filter(:confirmed, :boolean) filter(:name) do |value| - self.where(name: value) + where(name: value) end column(:group, order: "groups.name") do - self.group.name + group.name end column(:name) do |user| @@ -45,20 +40,18 @@ class SimpleReport end column(:actions, html: true) do |model| - render partial: "/actions", locals: {model: model} + render partial: "/actions", locals: { model: model } end - column(:pet, html: lambda {|data| content_tag :em, data}) do - self.pet&.upcase + column(:pet, html: ->(data) { content_tag :em, data }) do + pet&.upcase end column(:shipping_date, before: :group) - column(:access_level, html: lambda {|data| content_tag :h1, data}, after: :actions) + column(:access_level, html: ->(data) { content_tag :h1, data }, after: :actions) def param_name :report end - end - From fb7002fb7ab700e29b9324ce489492dacd4cf0ca Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 3 Nov 2024 19:38:26 +0100 Subject: [PATCH 009/157] Rubocop fixes --- Appraisals | 2 + Gemfile | 2 + gemfiles/rails_6.1.gemfile | 2 + gemfiles/rails_7.0.gemfile | 2 + gemfiles/rails_7.1.gemfile | 2 + gemfiles/rails_7.2.gemfile | 2 + lib/datagrid.rb | 2 + lib/datagrid/active_model.rb | 2 + lib/datagrid/column_names_attribute.rb | 10 +- lib/datagrid/columns.rb | 8 +- lib/datagrid/columns/column.rb | 264 ++++++++-------- lib/datagrid/configuration.rb | 2 + lib/datagrid/core.rb | 5 +- lib/datagrid/drivers.rb | 2 + lib/datagrid/drivers/abstract_driver.rb | 4 +- lib/datagrid/drivers/active_record.rb | 2 + lib/datagrid/drivers/array.rb | 2 + lib/datagrid/drivers/mongo_mapper.rb | 2 + lib/datagrid/drivers/mongoid.rb | 2 + lib/datagrid/drivers/sequel.rb | 10 +- lib/datagrid/engine.rb | 2 + lib/datagrid/filters.rb | 4 +- lib/datagrid/filters/base_filter.rb | 295 +++++++++--------- lib/datagrid/filters/boolean_filter.rb | 12 +- lib/datagrid/filters/composite_filters.rb | 2 + lib/datagrid/filters/date_filter.rb | 52 +-- lib/datagrid/filters/date_time_filter.rb | 36 ++- lib/datagrid/filters/default_filter.rb | 12 +- lib/datagrid/filters/dynamic_filter.rb | 214 +++++++------ lib/datagrid/filters/enum_filter.rb | 48 +-- .../filters/extended_boolean_filter.rb | 66 ++-- lib/datagrid/filters/float_filter.rb | 16 +- lib/datagrid/filters/integer_filter.rb | 26 +- lib/datagrid/filters/ranged_filter.rb | 84 ++--- lib/datagrid/filters/select_options.rb | 108 ++++--- lib/datagrid/filters/string_filter.rb | 14 +- lib/datagrid/form_builder.rb | 19 +- lib/datagrid/helper.rb | 2 + lib/datagrid/ordering.rb | 2 + lib/datagrid/renderer.rb | 8 +- lib/datagrid/rspec.rb | 2 + lib/datagrid/scaffold.rb | 206 ++++++------ lib/datagrid/utils.rb | 6 +- lib/datagrid/version.rb | 2 + lib/tasks/datagrid_tasks.rake | 4 +- spec/datagrid/active_model_spec.rb | 2 + spec/datagrid/column_names_attribute_spec.rb | 2 + spec/datagrid/columns/column_spec.rb | 2 + spec/datagrid/columns_spec.rb | 2 + spec/datagrid/core_spec.rb | 2 + spec/datagrid/drivers/active_record_spec.rb | 2 + spec/datagrid/drivers/array_spec.rb | 4 +- spec/datagrid/drivers/mongo_mapper_spec.rb | 2 + spec/datagrid/drivers/mongoid_spec.rb | 2 + spec/datagrid/drivers/sequel_spec.rb | 2 + spec/datagrid/filters/base_filter_spec.rb | 2 + .../filters/composite_filters_spec.rb | 2 + spec/datagrid/filters/date_filter_spec.rb | 2 + .../datagrid/filters/date_time_filter_spec.rb | 2 + spec/datagrid/filters/dynamic_filter_spec.rb | 2 + spec/datagrid/filters/enum_filter_spec.rb | 4 +- .../filters/extended_boolean_filter_spec.rb | 2 + spec/datagrid/filters/float_filter_spec.rb | 2 + spec/datagrid/filters/integer_filter_spec.rb | 2 + spec/datagrid/filters/string_filter_spec.rb | 2 + spec/datagrid/filters_spec.rb | 2 + spec/datagrid/form_builder_spec.rb | 44 +-- spec/datagrid/helper_spec.rb | 6 +- spec/datagrid/ordering_spec.rb | 2 + spec/datagrid/scaffold_spec.rb | 2 + spec/datagrid/stylesheet_spec.rb | 2 + spec/datagrid/utils_spec.rb | 2 + spec/datagrid_spec.rb | 2 + spec/spec_helper.rb | 4 +- spec/support/active_record.rb | 2 + spec/support/configuration.rb | 2 + spec/support/i18n_helpers.rb | 2 + spec/support/matchers.rb | 9 +- spec/support/mongo_mapper.rb | 2 + spec/support/mongoid.rb | 2 + spec/support/sequel.rb | 2 + spec/support/simple_report.rb | 6 +- 82 files changed, 960 insertions(+), 748 deletions(-) diff --git a/Appraisals b/Appraisals index fe1e44a..8e0cfff 100644 --- a/Appraisals +++ b/Appraisals @@ -1,3 +1,5 @@ +# frozen_string_literal: true + appraise "rails-6.1" do group :development do gem "rails", "~> 6.1.0" diff --git a/Gemfile b/Gemfile index 909dbe7..c0c942e 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + source "https://rubygems.org" gemspec diff --git a/gemfiles/rails_6.1.gemfile b/gemfiles/rails_6.1.gemfile index 512aa8a..1fd476f 100644 --- a/gemfiles/rails_6.1.gemfile +++ b/gemfiles/rails_6.1.gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This file was generated by Appraisal source "https://rubygems.org" diff --git a/gemfiles/rails_7.0.gemfile b/gemfiles/rails_7.0.gemfile index 61566c8..44cf0d6 100644 --- a/gemfiles/rails_7.0.gemfile +++ b/gemfiles/rails_7.0.gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This file was generated by Appraisal source "https://rubygems.org" diff --git a/gemfiles/rails_7.1.gemfile b/gemfiles/rails_7.1.gemfile index bdd7ff4..2bf4d9c 100644 --- a/gemfiles/rails_7.1.gemfile +++ b/gemfiles/rails_7.1.gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This file was generated by Appraisal source "https://rubygems.org" diff --git a/gemfiles/rails_7.2.gemfile b/gemfiles/rails_7.2.gemfile index 753268c..a21ea73 100644 --- a/gemfiles/rails_7.2.gemfile +++ b/gemfiles/rails_7.2.gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This file was generated by Appraisal source "https://rubygems.org" diff --git a/lib/datagrid.rb b/lib/datagrid.rb index 82abe93..4bf2bdf 100644 --- a/lib/datagrid.rb +++ b/lib/datagrid.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "action_view" require "datagrid/configuration" require "datagrid/engine" diff --git a/lib/datagrid/active_model.rb b/lib/datagrid/active_model.rb index 5284711..22860e0 100644 --- a/lib/datagrid/active_model.rb +++ b/lib/datagrid/active_model.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Datagrid # Required to be ActiveModel compatible module ActiveModel diff --git a/lib/datagrid/column_names_attribute.rb b/lib/datagrid/column_names_attribute.rb index c04027c..48041ae 100644 --- a/lib/datagrid/column_names_attribute.rb +++ b/lib/datagrid/column_names_attribute.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Datagrid module ColumnNamesAttribute extend ActiveSupport::Concern @@ -45,7 +47,7 @@ def columns(*args, **options) # If no mandatory columns specified than all of them considered mandatory # @return [Array<Datagrid::Columns::Column>] def mandatory_columns - available_columns.select { |c| c.mandatory? } + available_columns.select(&:mandatory?) end # Returns a list of enabled columns without <tt>mandatory: true</tt> option @@ -68,7 +70,7 @@ def selected_column_names(*args) column.is_a?(Datagrid::Columns::Column) ? column.name : column.to_sym end args - elsif column_names && column_names.any? + elsif column_names&.any? column_names + mandatory_columns.map(&:name) else columns_enabled_by_default.map(&:name) @@ -76,9 +78,7 @@ def selected_column_names(*args) end def columns_visibility_enabled? - columns_array.any? do |column| - column.mandatory_explicitly_set? - end + columns_array.any?(&:mandatory_explicitly_set?) end def columns_enabled_by_default diff --git a/lib/datagrid/columns.rb b/lib/datagrid/columns.rb index d2fd850..a388ab5 100644 --- a/lib/datagrid/columns.rb +++ b/lib/datagrid/columns.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "datagrid/utils" require "active_support/core_ext/class/attribute" @@ -488,7 +490,7 @@ def map_with_batches(&block) end def each_with_batches(&block) - if batch_size && batch_size > 0 + if batch_size&.positive? driver.batch_each(assets, batch_size, &block) else assets.each(&block) @@ -498,7 +500,7 @@ def each_with_batches(&block) def value_from_html_block(context, asset, column) args = [] remaining_arity = column.html_block.arity - remaining_arity = 1 if remaining_arity < 0 + remaining_arity = 1 if remaining_arity.negative? asset = decorate(asset) @@ -507,7 +509,7 @@ def value_from_html_block(context, asset, column) remaining_arity -= 1 end - args << asset if remaining_arity > 0 + args << asset if remaining_arity.positive? args << self if remaining_arity > 1 context.instance_exec(*args, &column.html_block) diff --git a/lib/datagrid/columns/column.rb b/lib/datagrid/columns/column.rb index 1d50c40..2f15359 100644 --- a/lib/datagrid/columns/column.rb +++ b/lib/datagrid/columns/column.rb @@ -1,160 +1,166 @@ -class Datagrid::Columns::Column - # Datagrid class holding an information of - # how a column should be rendered in data/console/csv format and HTML format - class ResponseFormat - attr_accessor :data_block, :html_block - - def initialize - yield(self) - end - - def data(&block) - self.data_block = block - end - - def html(&block) - self.html_block = block - end +# frozen_string_literal: true + +module Datagrid + module Columns + class Column + # Datagrid class holding an information of + # how a column should be rendered in data/console/csv format and HTML format + class ResponseFormat + attr_accessor :data_block, :html_block + + def initialize + yield(self) + end + + def data(&block) + self.data_block = block + end + + def html(&block) + self.html_block = block + end + + def call_data + data_block.call + end + + def to_s + call_data.to_s + end + + def call_html(context) + context.instance_eval(&html_block) + end + end - def call_data - data_block.call - end + attr_accessor :grid_class, :options, :data_block, :name, :html_block, :query - def to_s - call_data.to_s - end + def initialize(grid_class, name, query, options = {}, &block) + self.grid_class = grid_class + self.name = name.to_sym + self.options = options + if options[:html] == true + self.html_block = block + else + self.data_block = block - def call_html(context) - context.instance_eval(&html_block) - end - end - - attr_accessor :grid_class, :options, :data_block, :name, :html_block, :query + self.html_block = options[:html] if options[:html].is_a? Proc + end + self.query = query + end - def initialize(grid_class, name, query, options = {}, &block) - self.grid_class = grid_class - self.name = name.to_sym - self.options = options - if options[:html] == true - self.html_block = block - else - self.data_block = block + def data_value(model, grid) + # backward compatibility method + grid.data_value(name, model) + end - self.html_block = options[:html] if options[:html].is_a? Proc - end - self.query = query - end + def label + options[:label] + end - def data_value(model, grid) - # backward compatibility method - grid.data_value(name, model) - end + def header + if (header = options[:header]) + Datagrid::Utils.callable(header) + else + Datagrid::Utils.translate_from_namespace(:columns, grid_class, name) + end + end - def label - options[:label] - end + def order + if options.key?(:order) && options[:order] != true + options[:order] + else + driver.default_order(grid_class.scope, name) + end + end - def header - if header = options[:header] - Datagrid::Utils.callable(header) - else - Datagrid::Utils.translate_from_namespace(:columns, grid_class, name) - end - end + def supports_order? + order || order_by_value? + end - def order - if options.has_key?(:order) && options[:order] != true - options[:order] - else - driver.default_order(grid_class.scope, name) - end - end + def order_by_value(model, grid) + if options[:order_by_value] == true + grid.data_value(self, model) + else + Datagrid::Utils.apply_args(model, grid, &options[:order_by_value]) + end + end - def supports_order? - order || order_by_value? - end + def order_by_value? + !!options[:order_by_value] + end - def order_by_value(model, grid) - if options[:order_by_value] == true - grid.data_value(self, model) - else - Datagrid::Utils.apply_args(model, grid, &options[:order_by_value]) - end - end + def order_desc + return nil unless order - def order_by_value? - !!options[:order_by_value] - end + options[:order_desc] + end - def order_desc - return nil unless order + def html? + options[:html] != false + end - options[:order_desc] - end + def data? + data_block != nil + end - def html? - options[:html] != false - end + def mandatory? + !!options[:mandatory] + end - def data? - data_block != nil - end + def mandatory_explicitly_set? + options.key?(:mandatory) + end - def mandatory? - !!options[:mandatory] - end + def enabled?(grid) + ::Datagrid::Utils.process_availability(grid, options[:if], options[:unless]) + end - def mandatory_explicitly_set? - options.key?(:mandatory) - end + def inspect + "#<#{self.class} #{grid_class}##{name} #{options.inspect}>" + end - def enabled?(grid) - ::Datagrid::Utils.process_availability(grid, options[:if], options[:unless]) - end + def to_s + header + end - def inspect - "#<#{self.class} #{grid_class}##{name} #{options.inspect}>" - end + def html_value(context, asset, grid) + grid.html_value(name, context, asset) + end - def to_s - header - end + def generic_value(model, grid) + grid.generic_value(self, model) + end - def html_value(context, asset, grid) - grid.html_value(name, context, asset) - end + def append_preload(relation) + return relation unless preload - def generic_value(model, grid) - grid.generic_value(self, model) - end + if preload.respond_to?(:call) + return relation unless preload - def append_preload(relation) - return relation unless preload + if preload.arity == 1 + preload.call(relation) + else + relation.instance_exec(&preload) + end + else + driver.default_preload(relation, preload) + end + end - if preload.respond_to?(:call) - return relation unless preload + def preload + preload = options[:preload] - if preload.arity == 1 - preload.call(relation) - else - relation.instance_exec(&preload) + if preload == true && driver.can_preload?(grid_class.scope, name) + name + else + preload + end end - else - driver.default_preload(relation, preload) - end - end - - def preload - preload = options[:preload] - if preload == true && driver.can_preload?(grid_class.scope, name) - name - else - preload + def driver + grid_class.driver + end end end - - def driver - grid_class.driver - end end diff --git a/lib/datagrid/configuration.rb b/lib/datagrid/configuration.rb index 65a1653..2f956e2 100644 --- a/lib/datagrid/configuration.rb +++ b/lib/datagrid/configuration.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Datagrid def self.configuration @configuration ||= Configuration.new diff --git a/lib/datagrid/core.rb b/lib/datagrid/core.rb index 0f560a4..4fc1166 100644 --- a/lib/datagrid/core.rb +++ b/lib/datagrid/core.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "datagrid/drivers" require "active_support/core_ext/class/attribute" require "active_model/attribute_assignment" @@ -150,9 +152,6 @@ def attributes # grid.attributes = {first_name: 'John', last_name: 'Smith'} # grid.first_name # => 'John' # grid.last_name # => 'Smith' - def attributes=(attributes) - super(attributes) - end # @return [Object] Any datagrid attribute value def [](attribute) diff --git a/lib/datagrid/drivers.rb b/lib/datagrid/drivers.rb index 3e72d3f..03953af 100644 --- a/lib/datagrid/drivers.rb +++ b/lib/datagrid/drivers.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "datagrid/drivers/abstract_driver" require "datagrid/drivers/active_record" require "datagrid/drivers/array" diff --git a/lib/datagrid/drivers/abstract_driver.rb b/lib/datagrid/drivers/abstract_driver.rb index 99530a8..8807c1b 100644 --- a/lib/datagrid/drivers/abstract_driver.rb +++ b/lib/datagrid/drivers/abstract_driver.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + module Datagrid module Drivers # @!visibility private class AbstractDriver - TIMESTAMP_CLASSES = [DateTime, Time, ActiveSupport::TimeWithZone] + TIMESTAMP_CLASSES = [DateTime, Time, ActiveSupport::TimeWithZone].freeze class_attribute :subclasses, default: [] diff --git a/lib/datagrid/drivers/active_record.rb b/lib/datagrid/drivers/active_record.rb index 3135df8..5be39b1 100644 --- a/lib/datagrid/drivers/active_record.rb +++ b/lib/datagrid/drivers/active_record.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Datagrid module Drivers # @!visibility private diff --git a/lib/datagrid/drivers/array.rb b/lib/datagrid/drivers/array.rb index 3d2da1d..bfa36ef 100644 --- a/lib/datagrid/drivers/array.rb +++ b/lib/datagrid/drivers/array.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Datagrid module Drivers # @!visibility private diff --git a/lib/datagrid/drivers/mongo_mapper.rb b/lib/datagrid/drivers/mongo_mapper.rb index e36fa51..df1c178 100644 --- a/lib/datagrid/drivers/mongo_mapper.rb +++ b/lib/datagrid/drivers/mongo_mapper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Datagrid module Drivers # @!visibility private diff --git a/lib/datagrid/drivers/mongoid.rb b/lib/datagrid/drivers/mongoid.rb index c737ff4..aa166a8 100644 --- a/lib/datagrid/drivers/mongoid.rb +++ b/lib/datagrid/drivers/mongoid.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Datagrid module Drivers # @!visibility private diff --git a/lib/datagrid/drivers/sequel.rb b/lib/datagrid/drivers/sequel.rb index ce603b8..a450642 100644 --- a/lib/datagrid/drivers/sequel.rb +++ b/lib/datagrid/drivers/sequel.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Datagrid module Drivers # @!visibility private @@ -18,10 +20,6 @@ def to_scope(scope) scope.where({}) end - def append_column_queries(assets, columns) - super - end - def where(scope, attribute, value) scope.where(attribute => value) end @@ -34,10 +32,6 @@ def desc(scope, order) scope.order(::Sequel.desc(::Sequel.lit(order))) end - def reverse_order(scope) - super - end - def default_order(scope, column_name) has_column?(scope, column_name) ? ::Sequel.lit(prefix_table_name(scope, column_name)) : nil end diff --git a/lib/datagrid/engine.rb b/lib/datagrid/engine.rb index b37dd4e..3a52dd6 100644 --- a/lib/datagrid/engine.rb +++ b/lib/datagrid/engine.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "rails/engine" require "datagrid/helper" require "datagrid/form_builder" diff --git a/lib/datagrid/filters.rb b/lib/datagrid/filters.rb index 3283c81..ecca158 100644 --- a/lib/datagrid/filters.rb +++ b/lib/datagrid/filters.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "active_support/core_ext/class/attribute" module Datagrid @@ -27,7 +29,7 @@ module Filters enum: Filters::EnumFilter, float: Filters::FloatFilter, dynamic: Filters::DynamicFilter - } + }.freeze # @!visibility private DEFAULT_FILTER_BLOCK = Object.new diff --git a/lib/datagrid/filters/base_filter.rb b/lib/datagrid/filters/base_filter.rb index 608e8d9..ab43023 100644 --- a/lib/datagrid/filters/base_filter.rb +++ b/lib/datagrid/filters/base_filter.rb @@ -1,185 +1,194 @@ +# frozen_string_literal: true + # An error raise when datagrid filter is defined incorrectly and # causes filtering chain to be broken -class Datagrid::FilteringError < StandardError +module Datagrid + class FilteringError < StandardError + end end # @!visibility private -class Datagrid::Filters::BaseFilter - class_attribute :input_helper_name, instance_writer: false - attr_accessor :grid_class, :options, :block, :name - - def initialize(grid_class, name, options = {}, &block) - self.grid_class = grid_class - self.name = name.to_sym - self.options = options - self.block = block || default_filter_block - end +module Datagrid + module Filters + class BaseFilter + class_attribute :input_helper_name, instance_writer: false + attr_accessor :grid_class, :options, :block, :name + + def initialize(grid_class, name, options = {}, &block) + self.grid_class = grid_class + self.name = name.to_sym + self.options = options + self.block = block || default_filter_block + end - def parse(value) - raise NotImplementedError, "#parse(value) suppose to be overwritten" - end + def parse(value) + raise NotImplementedError, "#parse(value) suppose to be overwritten" + end - def unapplicable_value?(value) - value.nil? ? !allow_nil? : value.blank? && !allow_blank? - end + def unapplicable_value?(value) + value.nil? ? !allow_nil? : value.blank? && !allow_blank? + end - def apply(grid_object, scope, value) - return scope if unapplicable_value?(value) + def apply(grid_object, scope, value) + return scope if unapplicable_value?(value) - result = execute(value, scope, grid_object) + result = execute(value, scope, grid_object) - return scope unless result + return scope unless result - result = default_filter(value, scope, grid_object) if result == Datagrid::Filters::DEFAULT_FILTER_BLOCK - unless grid_object.driver.match?(result) - raise Datagrid::FilteringError, - "Can not apply #{name.inspect} filter: result #{result.inspect} no longer match #{grid_object.driver.class}." - end + result = default_filter(value, scope, grid_object) if result == Datagrid::Filters::DEFAULT_FILTER_BLOCK + unless grid_object.driver.match?(result) + raise Datagrid::FilteringError, + "Can not apply #{name.inspect} filter: result #{result.inspect} no longer match #{grid_object.driver.class}." + end - result - end - - def parse_values(value) - if multiple? - return nil if value.nil? + result + end - normalize_multiple_value(value).map do |v| - parse(v) + def parse_values(value) + if multiple? + return nil if value.nil? + + normalize_multiple_value(value).map do |v| + parse(v) + end + elsif value.is_a?(Array) + raise Datagrid::ArgumentError, + "#{grid_class}##{name} filter can not accept Array argument. Use :multiple option." + else + parse(value) + end end - elsif value.is_a?(Array) - raise Datagrid::ArgumentError, "#{grid_class}##{name} filter can not accept Array argument. Use :multiple option." - else - parse(value) - end - end - def separator - options[:multiple].is_a?(String) ? options[:multiple] : default_separator - end + def separator + options[:multiple].is_a?(String) ? options[:multiple] : default_separator + end - def header - if header = options[:header] - Datagrid::Utils.callable(header) - else - Datagrid::Utils.translate_from_namespace(:filters, grid_class, name) - end - end + def header + if (header = options[:header]) + Datagrid::Utils.callable(header) + else + Datagrid::Utils.translate_from_namespace(:filters, grid_class, name) + end + end - def default(object) - default = options[:default] - if default.is_a?(Symbol) - object.send(default) - elsif default.respond_to?(:call) - Datagrid::Utils.apply_args(object, &default) - else - default - end - end + def default(object) + default = options[:default] + if default.is_a?(Symbol) + object.send(default) + elsif default.respond_to?(:call) + Datagrid::Utils.apply_args(object, &default) + else + default + end + end - def multiple? - options[:multiple] - end + def multiple? + options[:multiple] + end - def allow_nil? - options.has_key?(:allow_nil) ? options[:allow_nil] : options[:allow_blank] - end + def allow_nil? + options.key?(:allow_nil) ? options[:allow_nil] : options[:allow_blank] + end - def allow_blank? - options[:allow_blank] - end + def allow_blank? + options[:allow_blank] + end - def input_options - options[:input_options] || {} - end + def input_options + options[:input_options] || {} + end - def label_options - options[:label_options] || {} - end + def label_options + options[:label_options] || {} + end - def form_builder_helper_name - self.class.form_builder_helper_name - end + def form_builder_helper_name + self.class.form_builder_helper_name + end - def self.form_builder_helper_name - :"datagrid_#{to_s.demodulize.underscore}" - end + def self.form_builder_helper_name + :"datagrid_#{to_s.demodulize.underscore}" + end - def default_filter_block - filter = self - lambda do |value, scope, grid| - filter.default_filter(value, scope, grid) - end - end + def default_filter_block + filter = self + lambda do |value, scope, grid| + filter.default_filter(value, scope, grid) + end + end - def supports_range? - self.class.ancestors.include?(::Datagrid::Filters::RangedFilter) - end + def supports_range? + self.class.ancestors.include?(::Datagrid::Filters::RangedFilter) + end - def format(value) - value.nil? ? nil : value.to_s - end + def format(value) + value&.to_s + end - def dummy? - options[:dummy] - end + def dummy? + options[:dummy] + end - def type - Datagrid::Filters::FILTER_TYPES.each do |type, klass| - return type if is_a?(klass) - end - raise "wtf is #{inspect}" - end + def type + Datagrid::Filters::FILTER_TYPES.each do |type, klass| + return type if is_a?(klass) + end + raise "wtf is #{inspect}" + end - def enabled?(grid) - ::Datagrid::Utils.process_availability(grid, options[:if], options[:unless]) - end + def enabled?(grid) + ::Datagrid::Utils.process_availability(grid, options[:if], options[:unless]) + end - def default_html_classes - [name, self.class.to_s.demodulize.underscore] - end + def default_html_classes + [name, self.class.to_s.demodulize.underscore] + end - protected + protected - def default_filter_where(scope, value) - driver.where(scope, name, value) - end + def default_filter_where(scope, value) + driver.where(scope, name, value) + end - def execute(value, scope, grid_object) - if block.arity == 1 - scope.instance_exec(value, &block) - else - Datagrid::Utils.apply_args(value, scope, grid_object, &block) - end - end + def execute(value, scope, grid_object) + if block.arity == 1 + scope.instance_exec(value, &block) + else + Datagrid::Utils.apply_args(value, scope, grid_object, &block) + end + end - def normalize_multiple_value(value) - case value - when String - value.split(separator) - when Range - [value.begin, value.end] - when Array - value - else - Array.wrap(value) - end - end + def normalize_multiple_value(value) + case value + when String + value.split(separator) + when Range + [value.begin, value.end] + when Array + value + else + Array.wrap(value) + end + end - def default_separator - "," - end + def default_separator + "," + end - def driver - grid_class.driver - end + def driver + grid_class.driver + end - def default_filter(value, scope, _grid) - return nil if dummy? + def default_filter(value, scope, _grid) + return nil if dummy? - if !driver.has_column?(scope, name) && scope.respond_to?(name, true) - scope.public_send(name, value) - else - default_filter_where(scope, value) + if !driver.has_column?(scope, name) && scope.respond_to?(name, true) + scope.public_send(name, value) + else + default_filter_where(scope, value) + end + end end end end diff --git a/lib/datagrid/filters/boolean_filter.rb b/lib/datagrid/filters/boolean_filter.rb index 89aed9b..4248b7b 100644 --- a/lib/datagrid/filters/boolean_filter.rb +++ b/lib/datagrid/filters/boolean_filter.rb @@ -1,7 +1,13 @@ +# frozen_string_literal: true + require "datagrid/utils" # @!visibility private -class Datagrid::Filters::BooleanFilter < Datagrid::Filters::BaseFilter - def parse(value) - Datagrid::Utils.booleanize(value) +module Datagrid + module Filters + class BooleanFilter < Datagrid::Filters::BaseFilter + def parse(value) + Datagrid::Utils.booleanize(value) + end + end end end diff --git a/lib/datagrid/filters/composite_filters.rb b/lib/datagrid/filters/composite_filters.rb index 3eb405a..a3d9238 100644 --- a/lib/datagrid/filters/composite_filters.rb +++ b/lib/datagrid/filters/composite_filters.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Datagrid module Filters # @!visibility private diff --git a/lib/datagrid/filters/date_filter.rb b/lib/datagrid/filters/date_filter.rb index f9f47c9..170e249 100644 --- a/lib/datagrid/filters/date_filter.rb +++ b/lib/datagrid/filters/date_filter.rb @@ -1,33 +1,39 @@ +# frozen_string_literal: true + require "datagrid/filters/ranged_filter" -class Datagrid::Filters::DateFilter < Datagrid::Filters::BaseFilter - include Datagrid::Filters::RangedFilter +module Datagrid + module Filters + class DateFilter < Datagrid::Filters::BaseFilter + include Datagrid::Filters::RangedFilter - def apply(grid_object, scope, value) - value = value.begin&.beginning_of_day..value.end&.end_of_day if value.is_a?(Range) - super(grid_object, scope, value) - end + def apply(grid_object, scope, value) + value = value.begin&.beginning_of_day..value.end&.end_of_day if value.is_a?(Range) + super(grid_object, scope, value) + end - def parse(value) - Datagrid::Utils.parse_date(value) - end + def parse(value) + Datagrid::Utils.parse_date(value) + end - def format(value) - if formats.any? && value - value.strftime(formats.first) - else - super - end - end + def format(value) + if formats.any? && value + value.strftime(formats.first) + else + super + end + end - def default_filter_where(scope, value) - value = Datagrid::Utils.format_date_as_timestamp(value) if driver.is_timestamp?(scope, name) - super(scope, value) - end + def default_filter_where(scope, value) + value = Datagrid::Utils.format_date_as_timestamp(value) if driver.is_timestamp?(scope, name) + super(scope, value) + end - protected + protected - def formats - Array(Datagrid.configuration.date_formats) + def formats + Array(Datagrid.configuration.date_formats) + end + end end end diff --git a/lib/datagrid/filters/date_time_filter.rb b/lib/datagrid/filters/date_time_filter.rb index 9809f32..0014eb1 100644 --- a/lib/datagrid/filters/date_time_filter.rb +++ b/lib/datagrid/filters/date_time_filter.rb @@ -1,23 +1,29 @@ +# frozen_string_literal: true + require "datagrid/filters/ranged_filter" -class Datagrid::Filters::DateTimeFilter < Datagrid::Filters::BaseFilter - include Datagrid::Filters::RangedFilter +module Datagrid + module Filters + class DateTimeFilter < Datagrid::Filters::BaseFilter + include Datagrid::Filters::RangedFilter - def parse(value) - Datagrid::Utils.parse_datetime(value) - end + def parse(value) + Datagrid::Utils.parse_datetime(value) + end - def format(value) - if formats.any? && value - value.strftime(formats.first) - else - super - end - end + def format(value) + if formats.any? && value + value.strftime(formats.first) + else + super + end + end - protected + protected - def formats - Array(Datagrid.configuration.datetime_formats) + def formats + Array(Datagrid.configuration.datetime_formats) + end + end end end diff --git a/lib/datagrid/filters/default_filter.rb b/lib/datagrid/filters/default_filter.rb index d547c78..c0a6f39 100644 --- a/lib/datagrid/filters/default_filter.rb +++ b/lib/datagrid/filters/default_filter.rb @@ -1,5 +1,11 @@ -class Datagrid::Filters::DefaultFilter < Datagrid::Filters::BaseFilter - def parse(value) - value +# frozen_string_literal: true + +module Datagrid + module Filters + class DefaultFilter < Datagrid::Filters::BaseFilter + def parse(value) + value + end + end end end diff --git a/lib/datagrid/filters/dynamic_filter.rb b/lib/datagrid/filters/dynamic_filter.rb index c2b29d3..0a0ae83 100644 --- a/lib/datagrid/filters/dynamic_filter.rb +++ b/lib/datagrid/filters/dynamic_filter.rb @@ -1,121 +1,127 @@ -require "datagrid/filters/select_options" +# frozen_string_literal: true -class Datagrid::Filters::DynamicFilter < Datagrid::Filters::BaseFilter - include Datagrid::Filters::SelectOptions - - EQUAL_OPERATION = "=" - LIKE_OPERATION = "=~" - MORE_EQUAL_OPERATION = ">=" - LESS_EQUAL_OPERATION = "<=" - DEFAULT_OPERATIONS = [ - EQUAL_OPERATION, - LIKE_OPERATION, - MORE_EQUAL_OPERATION, - LESS_EQUAL_OPERATION - ] - AVAILABLE_OPERATIONS = %w[= =~ >= <=] - - def initialize(*) - super - options[:select] ||= default_select - options[:operations] ||= DEFAULT_OPERATIONS - return if options.has_key?(:include_blank) - - options[:include_blank] = false - end +require "datagrid/filters/select_options" - def parse_values(filter) - field, operation, value = filter +module Datagrid + module Filters + class DynamicFilter < Datagrid::Filters::BaseFilter + include Datagrid::Filters::SelectOptions + + EQUAL_OPERATION = "=" + LIKE_OPERATION = "=~" + MORE_EQUAL_OPERATION = ">=" + LESS_EQUAL_OPERATION = "<=" + DEFAULT_OPERATIONS = [ + EQUAL_OPERATION, + LIKE_OPERATION, + MORE_EQUAL_OPERATION, + LESS_EQUAL_OPERATION + ].freeze + AVAILABLE_OPERATIONS = %w[= =~ >= <=].freeze + + def initialize(*) + super + options[:select] ||= default_select + options[:operations] ||= DEFAULT_OPERATIONS + return if options.key?(:include_blank) + + options[:include_blank] = false + end - [field, operation, type_cast(field, value)] - end + def parse_values(filter) + field, operation, value = filter - def unapplicable_value?(filter) - _, _, value = filter - super(value) - end - - def default_filter_where(scope, filter) - field, operation, value = filter - date_conversion = value.is_a?(Date) && driver.is_timestamp?(scope, field) + [field, operation, type_cast(field, value)] + end - return scope if field.blank? || operation.blank? + def unapplicable_value?(filter) + _, _, value = filter + super(value) + end - unless operations.include?(operation) - raise Datagrid::FilteringError, - "Unknown operation: #{operation.inspect}. Available operations: #{operations.join(' ')}" - end + def default_filter_where(scope, filter) + field, operation, value = filter + date_conversion = value.is_a?(Date) && driver.is_timestamp?(scope, field) + + return scope if field.blank? || operation.blank? + + unless operations.include?(operation) + raise Datagrid::FilteringError, + "Unknown operation: #{operation.inspect}. Available operations: #{operations.join(' ')}" + end + + case operation + when EQUAL_OPERATION + value = Datagrid::Utils.format_date_as_timestamp(value) if date_conversion + driver.where(scope, field, value) + when LIKE_OPERATION + if column_type(field) == :string + driver.contains(scope, field, value) + else + value = Datagrid::Utils.format_date_as_timestamp(value) if date_conversion + driver.where(scope, field, value) + end + when MORE_EQUAL_OPERATION + value = value.beginning_of_day if date_conversion + driver.greater_equal(scope, field, value) + when LESS_EQUAL_OPERATION + value = value.end_of_day if date_conversion + driver.less_equal(scope, field, value) + else + raise Datagrid::FilteringError, + "Unknown operation: #{operation.inspect}. Use filter block argument to implement operation" + end + end - case operation - when EQUAL_OPERATION - value = Datagrid::Utils.format_date_as_timestamp(value) if date_conversion - driver.where(scope, field, value) - when LIKE_OPERATION - if column_type(field) == :string - driver.contains(scope, field, value) - else - value = Datagrid::Utils.format_date_as_timestamp(value) if date_conversion - driver.where(scope, field, value) + def operations + options[:operations] end - when MORE_EQUAL_OPERATION - value = value.beginning_of_day if date_conversion - driver.greater_equal(scope, field, value) - when LESS_EQUAL_OPERATION - value = value.end_of_day if date_conversion - driver.less_equal(scope, field, value) - else - raise Datagrid::FilteringError, - "Unknown operation: #{operation.inspect}. Use filter block argument to implement operation" - end - end - def operations - options[:operations] - end + def operations_select + operations.map do |operation| + [I18n.t(operation, scope: "datagrid.filters.dynamic.operations").html_safe, operation] + end + end - def operations_select - operations.map do |operation| - [I18n.t(operation, scope: "datagrid.filters.dynamic.operations").html_safe, operation] - end - end + protected - protected + def default_select + proc { |grid| + grid.driver.column_names(grid.scope).map do |name| + # Mongodb/Rails problem: + # '_id'.humanize returns '' + [name.gsub(/^_/, "").humanize.strip, name] + end + } + end - def default_select - proc { |grid| - grid.driver.column_names(grid.scope).map do |name| - # Mongodb/Rails problem: - # '_id'.humanize returns '' - [name.gsub(/^_/, "").humanize.strip, name] + def type_cast(field, value) + type = column_type(field) + return nil if value.blank? + + case type + when :string + value.to_s + when :integer + value.is_a?(Numeric) || value =~ /^\d/ ? value.to_i : nil + when :float + value.is_a?(Numeric) || value =~ /^\d/ ? value.to_f : nil + when :date + Datagrid::Utils.parse_date(value) + when :timestamp + Datagrid::Utils.parse_date(value) + when :boolean + Datagrid::Utils.booleanize(value) + when nil + value + else + raise NotImplementedError, "unknown column type: #{type.inspect}" + end end - } - end - def type_cast(field, value) - type = column_type(field) - return nil if value.blank? - - case type - when :string - value.to_s - when :integer - value.is_a?(Numeric) || value =~ /^\d/ ? value.to_i : nil - when :float - value.is_a?(Numeric) || value =~ /^\d/ ? value.to_f : nil - when :date - Datagrid::Utils.parse_date(value) - when :timestamp - Datagrid::Utils.parse_date(value) - when :boolean - Datagrid::Utils.booleanize(value) - when nil - value - else - raise NotImplementedError, "unknown column type: #{type.inspect}" + def column_type(field) + grid_class.driver.normalized_column_type(grid_class.scope, field) + end end end - - def column_type(field) - grid_class.driver.normalized_column_type(grid_class.scope, field) - end end diff --git a/lib/datagrid/filters/enum_filter.rb b/lib/datagrid/filters/enum_filter.rb index bc65cc6..d16f7c1 100644 --- a/lib/datagrid/filters/enum_filter.rb +++ b/lib/datagrid/filters/enum_filter.rb @@ -1,31 +1,37 @@ +# frozen_string_literal: true + require "datagrid/filters/select_options" -class Datagrid::Filters::EnumFilter < Datagrid::Filters::BaseFilter - include Datagrid::Filters::SelectOptions +module Datagrid + module Filters + class EnumFilter < Datagrid::Filters::BaseFilter + include Datagrid::Filters::SelectOptions - def initialize(*args) - super(*args) - options[:multiple] = true if checkboxes? - raise Datagrid::ConfigurationError, ":select option not specified" unless options[:select] - end + def initialize(*args) + super(*args) + options[:multiple] = true if checkboxes? + raise Datagrid::ConfigurationError, ":select option not specified" unless options[:select] + end - def parse(value) - return nil if strict && !select.include?(value) + def parse(value) + return nil if strict && !select.include?(value) - value - end + value + end - def default_html_classes - res = super - res.push("checkboxes") if checkboxes? - res - end + def default_html_classes + res = super + res.push("checkboxes") if checkboxes? + res + end - def strict - options[:strict] - end + def strict + options[:strict] + end - def checkboxes? - options[:checkboxes] + def checkboxes? + options[:checkboxes] + end + end end end diff --git a/lib/datagrid/filters/extended_boolean_filter.rb b/lib/datagrid/filters/extended_boolean_filter.rb index 521cf5e..1e2b96a 100644 --- a/lib/datagrid/filters/extended_boolean_filter.rb +++ b/lib/datagrid/filters/extended_boolean_filter.rb @@ -1,39 +1,45 @@ +# frozen_string_literal: true + # @!visibility private -class Datagrid::Filters::ExtendedBooleanFilter < Datagrid::Filters::EnumFilter - YES = "YES" - NO = "NO" - TRUTH_VALUES = [true, "true", "y", "yes"] - FALSE_VALUES = [false, "false", "n", "no"] +module Datagrid + module Filters + class ExtendedBooleanFilter < Datagrid::Filters::EnumFilter + YES = "YES" + NO = "NO" + TRUTH_VALUES = [true, "true", "y", "yes"].freeze + FALSE_VALUES = [false, "false", "n", "no"].freeze - def initialize(report, attribute, options = {}, &block) - options[:select] = -> { boolean_select } - super(report, attribute, options, &block) - end + def initialize(report, attribute, options = {}, &block) + options[:select] = -> { boolean_select } + super(report, attribute, options, &block) + end - def execute(value, scope, grid_object) - value = value.blank? ? nil : ::Datagrid::Utils.booleanize(value) - super(value, scope, grid_object) - end + def execute(value, scope, grid_object) + value = value.blank? ? nil : ::Datagrid::Utils.booleanize(value) + super(value, scope, grid_object) + end - def parse(value) - value = value.downcase if value.is_a?(String) - case value - when *TRUTH_VALUES - YES - when *FALSE_VALUES - NO - when value.blank? - nil - else - super(value) - end - end + def parse(value) + value = value.downcase if value.is_a?(String) + case value + when *TRUTH_VALUES + YES + when *FALSE_VALUES + NO + when value.blank? + nil + else + super(value) + end + end - protected + protected - def boolean_select - [YES, NO].map do |key, _value| - [I18n.t("datagrid.filters.xboolean.#{key.downcase}"), key] + def boolean_select + [YES, NO].map do |key, _value| + [I18n.t("datagrid.filters.xboolean.#{key.downcase}"), key] + end + end end end end diff --git a/lib/datagrid/filters/float_filter.rb b/lib/datagrid/filters/float_filter.rb index 4361d60..d84f6e1 100644 --- a/lib/datagrid/filters/float_filter.rb +++ b/lib/datagrid/filters/float_filter.rb @@ -1,9 +1,15 @@ -class Datagrid::Filters::FloatFilter < Datagrid::Filters::BaseFilter - include Datagrid::Filters::RangedFilter +# frozen_string_literal: true - def parse(value) - return nil if value.blank? +module Datagrid + module Filters + class FloatFilter < Datagrid::Filters::BaseFilter + include Datagrid::Filters::RangedFilter - value.to_f + def parse(value) + return nil if value.blank? + + value.to_f + end + end end end diff --git a/lib/datagrid/filters/integer_filter.rb b/lib/datagrid/filters/integer_filter.rb index e05a14e..6395b0b 100644 --- a/lib/datagrid/filters/integer_filter.rb +++ b/lib/datagrid/filters/integer_filter.rb @@ -1,16 +1,22 @@ +# frozen_string_literal: true + require "datagrid/filters/ranged_filter" -class Datagrid::Filters::IntegerFilter < Datagrid::Filters::BaseFilter - include Datagrid::Filters::RangedFilter +module Datagrid + module Filters + class IntegerFilter < Datagrid::Filters::BaseFilter + include Datagrid::Filters::RangedFilter - def parse(value) - return nil if value.blank? - if defined?(ActiveRecord) && value.is_a?(ActiveRecord::Base) && - value.respond_to?(:id) && value.id.is_a?(Integer) - return value.id - end - return value if value.is_a?(Range) + def parse(value) + return nil if value.blank? + if defined?(ActiveRecord) && value.is_a?(ActiveRecord::Base) && + value.respond_to?(:id) && value.id.is_a?(Integer) + return value.id + end + return value if value.is_a?(Range) - value.to_i + value.to_i + end + end end end diff --git a/lib/datagrid/filters/ranged_filter.rb b/lib/datagrid/filters/ranged_filter.rb index 05ac2c9..be2c683 100644 --- a/lib/datagrid/filters/ranged_filter.rb +++ b/lib/datagrid/filters/ranged_filter.rb @@ -1,48 +1,54 @@ -module Datagrid::Filters::RangedFilter - def initialize(grid, name, options, &block) - super(grid, name, options, &block) - return unless range? +# frozen_string_literal: true - options[:multiple] = true - end +module Datagrid + module Filters + module RangedFilter + def initialize(grid, name, options, &block) + super(grid, name, options, &block) + return unless range? + + options[:multiple] = true + end - def parse_values(value) - result = super(value) - return result if !range? || result.nil? - # Simulate single point range - return [result, result] unless result.is_a?(Array) + def parse_values(value) + result = super(value) + return result if !range? || result.nil? + # Simulate single point range + return [result, result] unless result.is_a?(Array) - case result.size - when 0 - nil - when 1 - result.first - when 2 - if result.first && result.last && result.first > result.last - # If wrong range is given - reverse it to be always valid - result.reverse - elsif !result.first && !result.last - nil - else - result + case result.size + when 0 + nil + when 1 + result.first + when 2 + if result.first && result.last && result.first > result.last + # If wrong range is given - reverse it to be always valid + result.reverse + elsif !result.first && !result.last + nil + else + result + end + else + raise ArgumentError, "Can not create a date range from array of more than two: #{result.inspect}" + end end - else - raise ArgumentError, "Can not create a date range from array of more than two: #{result.inspect}" - end - end - def range? - options[:range] - end + def range? + options[:range] + end - def default_filter_where(scope, value) - if range? && value.is_a?(Array) - left, right = value - scope = driver.greater_equal(scope, name, left) if left - scope = driver.less_equal(scope, name, right) if right - scope - else - super(scope, value) + def default_filter_where(scope, value) + if range? && value.is_a?(Array) + left, right = value + scope = driver.greater_equal(scope, name, left) if left + scope = driver.less_equal(scope, name, right) if right + scope + else + super(scope, value) + end + end end end end diff --git a/lib/datagrid/filters/select_options.rb b/lib/datagrid/filters/select_options.rb index 68ae60b..75b2409 100644 --- a/lib/datagrid/filters/select_options.rb +++ b/lib/datagrid/filters/select_options.rb @@ -1,60 +1,66 @@ -module Datagrid::Filters::SelectOptions - def select(object) - select = options[:select] - if select.is_a?(Symbol) - object.send(select) - elsif select.respond_to?(:call) - Datagrid::Utils.apply_args(object, &select) - else - select - end - end +# frozen_string_literal: true - def select_values(object) - options = select(object) - groups_used = grouped_choices?(options) - options.map do |option| - if groups_used - option[1].map { |o| option_text_and_value(o) } - else - option_text_and_value(option) +module Datagrid + module Filters + module SelectOptions + def select(object) + select = options[:select] + if select.is_a?(Symbol) + object.send(select) + elsif select.respond_to?(:call) + Datagrid::Utils.apply_args(object, &select) + else + select + end end - end.map(&:last) - end - def include_blank - return if prompt + def select_values(object) + options = select(object) + groups_used = grouped_choices?(options) + options.map do |option| + if groups_used + option[1].map { |o| option_text_and_value(o) } + else + option_text_and_value(option) + end + end.map(&:last) + end - if options.has_key?(:include_blank) - Datagrid::Utils.callable(options[:include_blank]) - else - !multiple? - end - end + def include_blank + return if prompt - def prompt - options.has_key?(:prompt) ? Datagrid::Utils.callable(options[:prompt]) : false - end + if options.key?(:include_blank) + Datagrid::Utils.callable(options[:include_blank]) + else + !multiple? + end + end - protected - - # Rails built-in method: - # https://github.com/rails/rails/blob/94e80269e36caf7b2d22a7ab68e6898d3a824122/actionview/lib/action_view/helpers/form_options_helper.rb#L789 - # Code reuse is difficult, so it is easier to duplicate it - def option_text_and_value(option) - # Options are [text, value] pairs or strings used for both. - if !option.is_a?(String) && option.respond_to?(:first) && option.respond_to?(:last) - option = option.reject { |e| e.is_a?(Hash) } if option.is_a?(Array) - [option.first, option.last] - else - [option, option] - end - end + def prompt + options.key?(:prompt) ? Datagrid::Utils.callable(options[:prompt]) : false + end + + protected - # Rails built-in method: - # https://github.com/rails/rails/blob/f95c0b7e96eb36bc3efc0c5beffbb9e84ea664e4/actionview/lib/action_view/helpers/tags/select.rb#L36 - # Code reuse is difficult, so it is easier to duplicate it - def grouped_choices?(choices) - !choices.blank? && choices.first.respond_to?(:last) && choices.first.last.is_a?(Array) + # Rails built-in method: + # https://github.com/rails/rails/blob/94e80269e36caf7b2d22a7ab68e6898d3a824122/actionview/lib/action_view/helpers/form_options_helper.rb#L789 + # Code reuse is difficult, so it is easier to duplicate it + def option_text_and_value(option) + # Options are [text, value] pairs or strings used for both. + if !option.is_a?(String) && option.respond_to?(:first) && option.respond_to?(:last) + option = option.reject { |e| e.is_a?(Hash) } if option.is_a?(Array) + [option.first, option.last] + else + [option, option] + end + end + + # Rails built-in method: + # https://github.com/rails/rails/blob/f95c0b7e96eb36bc3efc0c5beffbb9e84ea664e4/actionview/lib/action_view/helpers/tags/select.rb#L36 + # Code reuse is difficult, so it is easier to duplicate it + def grouped_choices?(choices) + !choices.blank? && choices.first.respond_to?(:last) && choices.first.last.is_a?(Array) + end + end end end diff --git a/lib/datagrid/filters/string_filter.rb b/lib/datagrid/filters/string_filter.rb index 35d20dd..a753efb 100644 --- a/lib/datagrid/filters/string_filter.rb +++ b/lib/datagrid/filters/string_filter.rb @@ -1,7 +1,13 @@ -class Datagrid::Filters::StringFilter < Datagrid::Filters::BaseFilter - include Datagrid::Filters::RangedFilter +# frozen_string_literal: true - def parse(value) - value.nil? ? nil : value.to_s +module Datagrid + module Filters + class StringFilter < Datagrid::Filters::BaseFilter + include Datagrid::Filters::RangedFilter + + def parse(value) + value&.to_s + end + end end end diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index a99888f..65347fe 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "action_view" module Datagrid @@ -31,22 +33,23 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) filter = datagrid_get_filter(attribute_or_filter) options = add_filter_options(filter, **options) type = options.delete(:type)&.to_sym - if options.has_key?(:value) && options[:value].nil? && %i[datetime-local date].include?(type) + if options.key?(:value) && options[:value].nil? && %i[datetime-local date].include?(type) # https://github.com/rails/rails/pull/53387 options[:value] = "" end - if type == :"datetime-local" + case type + when :"datetime-local" datetime_local_field filter.name, **options, &block - elsif type == :date + when :date date_field filter.name, **options, &block - elsif type == :textarea + when :textarea text_area filter.name, value: object.filter_value_as_string(filter), **options, &block - elsif type == :checkbox + when :checkbox # raise options.inspect check_box filter.name, options, options.fetch(:value, 1) - elsif type == :hidden + when :hidden hidden_field filter.name, **options - elsif type == :select + when :select select( filter.name, object.select_options(filter) || [], @@ -218,7 +221,7 @@ def add_html_classes(options, *classes) end def partial_path(name) - if partials = options[:partials] + if (partials = options[:partials]) partial_name = File.join(partials, name) # Second argument is []: no magical namespaces to lookup added from controller return partial_name if @template.lookup_context.template_exists?(partial_name, [], true) diff --git a/lib/datagrid/helper.rb b/lib/datagrid/helper.rb index 039bc13..6e16ac8 100644 --- a/lib/datagrid/helper.rb +++ b/lib/datagrid/helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "action_view" module Datagrid diff --git a/lib/datagrid/ordering.rb b/lib/datagrid/ordering.rb index 83577c6..cab6ee9 100644 --- a/lib/datagrid/ordering.rb +++ b/lib/datagrid/ordering.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "datagrid/columns" module Datagrid diff --git a/lib/datagrid/renderer.rb b/lib/datagrid/renderer.rb index 3b23449..c838ed6 100644 --- a/lib/datagrid/renderer.rb +++ b/lib/datagrid/renderer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "action_view" module Datagrid @@ -16,7 +18,7 @@ def format_value(grid, column, asset) value = grid.html_value(column, @template, asset) - url = column.options[:url] && column.options[:url].call(asset) + url = column.options[:url]&.call(asset) if url @template.link_to(value, url) else @@ -45,7 +47,7 @@ def table(grid, assets, **options) end def header(grid, options = {}) - options[:order] = true unless options.has_key?(:order) + options[:order] = true unless options.key?(:order) _render_partial("head", options[:partials], { grid: grid, options: options }) @@ -141,7 +143,7 @@ def to_s protected def method_missing(method, *args, &blk) - if column = @grid.column_by_name(method) + if (column = @grid.column_by_name(method)) get(column) else super diff --git a/lib/datagrid/rspec.rb b/lib/datagrid/rspec.rb index 6b07ea7..8f78993 100644 --- a/lib/datagrid/rspec.rb +++ b/lib/datagrid/rspec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "datagrid" # TODO: refactor this experimental shit diff --git a/lib/datagrid/scaffold.rb b/lib/datagrid/scaffold.rb index d6c6d23..89bdc73 100644 --- a/lib/datagrid/scaffold.rb +++ b/lib/datagrid/scaffold.rb @@ -1,126 +1,130 @@ +# frozen_string_literal: true + require "rails/generators" # @!visibility private -class Datagrid::Scaffold < Rails::Generators::NamedBase - include Rails::Generators::ResourceHelpers - - check_class_collision suffix: "Grid" - source_root File.expand_path(__FILE__ + "/../../../templates") - - def create_scaffold - template "base.rb.erb", base_grid_file unless file_exists?(base_grid_file) - template "grid.rb.erb", "app/grids/#{grid_class_name.underscore}.rb" - if file_exists?(grid_controller_file) - inject_into_file grid_controller_file, index_action, after: /class .*#{grid_controller_class_name}.*\n/ - else - template "controller.rb.erb", grid_controller_file - end - template "index.html.erb", view_file - route(generate_routing_namespace("resources :#{grid_controller_short_name}")) - gem "kaminari" unless defined?(::Kaminari) || defined?(::WillPaginate) - in_root do - { - "css" => " *= require datagrid", - "css.sass" => " *= require datagrid", - "css.scss" => " *= require datagrid" - }.each do |extension, string| - file = "app/assets/stylesheets/application.#{extension}" - if file_exists?(file) - inject_into_file file, string + "\n", { before: /.*require_self/ } # before all +module Datagrid + class Scaffold < Rails::Generators::NamedBase + include Rails::Generators::ResourceHelpers + + check_class_collision suffix: "Grid" + source_root File.expand_path("/Users/bogdan/makabu/my/datagrid/lib/datagrid/scaffold.rb/../../../templates") + + def create_scaffold + template "base.rb.erb", base_grid_file unless file_exists?(base_grid_file) + template "grid.rb.erb", "app/grids/#{grid_class_name.underscore}.rb" + if file_exists?(grid_controller_file) + inject_into_file grid_controller_file, index_action, after: /class .*#{grid_controller_class_name}.*\n/ + else + template "controller.rb.erb", grid_controller_file + end + template "index.html.erb", view_file + route(generate_routing_namespace("resources :#{grid_controller_short_name}")) + gem "kaminari" unless defined?(::Kaminari) || defined?(::WillPaginate) + in_root do + { + "css" => " *= require datagrid", + "css.sass" => " *= require datagrid", + "css.scss" => " *= require datagrid" + }.each do |extension, string| + file = "app/assets/stylesheets/application.#{extension}" + if file_exists?(file) + inject_into_file file, "#{string}\n", { before: /.*require_self/ } # before all + end end end end - end - def view_file - Rails.root.join("app/views").join(controller_file_path).join("index.html.erb") - end + def view_file + Rails.root.join("app/views").join(controller_file_path).join("index.html.erb") + end - def grid_class_name - file_name.camelize.pluralize + "Grid" - end + def grid_class_name + "#{file_name.camelize.pluralize}Grid" + end - def grid_controller_class_name - controller_class_name.camelize + "Controller" - end + def grid_controller_class_name + "#{controller_class_name.camelize}Controller" + end - def grid_controller_file - Rails.root.join("app/controllers").join("#{grid_controller_class_name.underscore}.rb") - end + def grid_controller_file + Rails.root.join("app/controllers").join("#{grid_controller_class_name.underscore}.rb") + end - def grid_controller_short_name - controller_file_name - end + def grid_controller_short_name + controller_file_name + end - def grid_model_name - file_name.camelize.singularize - end + def grid_model_name + file_name.camelize.singularize + end - def grid_param_name - grid_class_name.underscore - end + def grid_param_name + grid_class_name.underscore + end - def pagination_helper_code - if defined?(::WillPaginate) - "will_paginate(@grid.assets)" - else - # Kaminari is default - "paginate(@grid.assets)" + def pagination_helper_code + if defined?(::WillPaginate) + "will_paginate(@grid.assets)" + else + # Kaminari is default + "paginate(@grid.assets)" + end end - end - def base_grid_file - "app/grids/base_grid.rb" - end + def base_grid_file + "app/grids/base_grid.rb" + end - def grid_route_name - controller_class_name.underscore.gsub("/", "_") + "_path" - end + def grid_route_name + "#{controller_class_name.underscore.gsub('/', '_')}_path" + end - def index_action - indent(<<~RUBY) - def index - @grid = #{grid_class_name}.new(grid_params) do |scope| - scope.page(params[:page]) + def index_action + indent(<<~RUBY) + def index + @grid = #{grid_class_name}.new(grid_params) do |scope| + scope.page(params[:page]) + end end - end - protected + protected - def grid_params - params.fetch(:#{grid_param_name}, {}).permit! - end - RUBY - end + def grid_params + params.fetch(:#{grid_param_name}, {}).permit! + end + RUBY + end - protected - - def generate_routing_namespace(code) - depth = regular_class_path.length - # Create 'namespace' ladder - # namespace :foo do - # namespace :bar do - namespace_ladder = regular_class_path.each_with_index.map do |ns, i| - indent("namespace :#{ns} do\n", i * 2) - end.join - - # Create route - # get 'baz/index' - route = indent(code, depth * 2) - - # Create `end` ladder - # end - # end - end_ladder = (1..depth).reverse_each.map do |i| - indent("end\n", i * 2) - end.join - - # Combine the 3 parts to generate complete route entry - namespace_ladder + route + "\n" + end_ladder - end + protected + + def generate_routing_namespace(code) + depth = regular_class_path.length + # Create 'namespace' ladder + # namespace :foo do + # namespace :bar do + namespace_ladder = regular_class_path.each_with_index.map do |ns, i| + indent("namespace :#{ns} do\n", i * 2) + end.join + + # Create route + # get 'baz/index' + route = indent(code, depth * 2) + + # Create `end` ladder + # end + # end + end_ladder = (1..depth).reverse_each.map do |i| + indent("end\n", i * 2) + end.join + + # Combine the 3 parts to generate complete route entry + "#{namespace_ladder}#{route}\n#{end_ladder}" + end - def file_exists?(name) - name = Rails.root.join(name) unless name.to_s.first == "/" - File.exist?(name) + def file_exists?(name) + name = Rails.root.join(name) unless name.to_s.first == "/" + File.exist?(name) + end end end diff --git a/lib/datagrid/utils.rb b/lib/datagrid/utils.rb index 254ab02..3a2a18d 100644 --- a/lib/datagrid/utils.rb +++ b/lib/datagrid/utils.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + module Datagrid # @!visibility private module Utils class << self - TRUTH = [true, 1, "1", "true", "yes", "on"] + TRUTH = [true, 1, "1", "true", "yes", "on"].freeze def booleanize(value) value = value.downcase if value.respond_to?(:downcase) @@ -65,7 +67,7 @@ def extract_position_from_options(array, options) end def apply_args(*args, &block) - size = block.arity < 0 ? args.size : block.arity + size = block.arity.negative? ? args.size : block.arity block.call(*args.slice(0, size)) end diff --git a/lib/datagrid/version.rb b/lib/datagrid/version.rb index 962d03c..12d0cd3 100644 --- a/lib/datagrid/version.rb +++ b/lib/datagrid/version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Datagrid VERSION = "1.8.4" end diff --git a/lib/tasks/datagrid_tasks.rake b/lib/tasks/datagrid_tasks.rake index 27eb792..e1ca194 100644 --- a/lib/tasks/datagrid_tasks.rake +++ b/lib/tasks/datagrid_tasks.rake @@ -1,10 +1,12 @@ +# frozen_string_literal: true + namespace :datagrid do desc "Copy table partials into rails application" task :copy_partials do require "fileutils" views_path = "app/views/datagrid" destination_dir = (Rails.root + views_path).to_s - pattern = File.expand_path(File.dirname(__FILE__) + "/../../#{views_path}") + "/*" + pattern = "#{File.expand_path(File.dirname(__FILE__) + "/../../#{views_path}")}/*" Dir[pattern].each do |template| puts "* copy #{template} => #{destination_dir}" FileUtils.mkdir_p destination_dir diff --git a/spec/datagrid/active_model_spec.rb b/spec/datagrid/active_model_spec.rb index b42adbc..a0d8502 100644 --- a/spec/datagrid/active_model_spec.rb +++ b/spec/datagrid/active_model_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::ActiveModel do diff --git a/spec/datagrid/column_names_attribute_spec.rb b/spec/datagrid/column_names_attribute_spec.rb index 321cc5f..1cb04d9 100644 --- a/spec/datagrid/column_names_attribute_spec.rb +++ b/spec/datagrid/column_names_attribute_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::ColumnNamesAttribute do diff --git a/spec/datagrid/columns/column_spec.rb b/spec/datagrid/columns/column_spec.rb index 086ecbc..a2fe70e 100644 --- a/spec/datagrid/columns/column_spec.rb +++ b/spec/datagrid/columns/column_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Columns::Column do diff --git a/spec/datagrid/columns_spec.rb b/spec/datagrid/columns_spec.rb index c644800..13d0378 100644 --- a/spec/datagrid/columns_spec.rb +++ b/spec/datagrid/columns_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Columns do diff --git a/spec/datagrid/core_spec.rb b/spec/datagrid/core_spec.rb index e5c5d47..40c4f47 100644 --- a/spec/datagrid/core_spec.rb +++ b/spec/datagrid/core_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" require "action_controller/metal/strong_parameters" diff --git a/spec/datagrid/drivers/active_record_spec.rb b/spec/datagrid/drivers/active_record_spec.rb index c41a1cf..fbc6c06 100644 --- a/spec/datagrid/drivers/active_record_spec.rb +++ b/spec/datagrid/drivers/active_record_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Drivers::ActiveRecord do diff --git a/spec/datagrid/drivers/array_spec.rb b/spec/datagrid/drivers/array_spec.rb index c0263f9..5fdaa2c 100644 --- a/spec/datagrid/drivers/array_spec.rb +++ b/spec/datagrid/drivers/array_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Drivers::Array do @@ -11,7 +13,7 @@ describe "api" do class ArrayGrid - class User < Struct.new(:name, :age); end + User = Struct.new(:name, :age) include Datagrid scope do [] diff --git a/spec/datagrid/drivers/mongo_mapper_spec.rb b/spec/datagrid/drivers/mongo_mapper_spec.rb index 6cacf76..2deec97 100644 --- a/spec/datagrid/drivers/mongo_mapper_spec.rb +++ b/spec/datagrid/drivers/mongo_mapper_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Drivers::MongoMapper, :mongomapper do diff --git a/spec/datagrid/drivers/mongoid_spec.rb b/spec/datagrid/drivers/mongoid_spec.rb index b119951..1f9646e 100644 --- a/spec/datagrid/drivers/mongoid_spec.rb +++ b/spec/datagrid/drivers/mongoid_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Drivers::Mongoid, :mongoid do diff --git a/spec/datagrid/drivers/sequel_spec.rb b/spec/datagrid/drivers/sequel_spec.rb index 731b19d..e95165b 100644 --- a/spec/datagrid/drivers/sequel_spec.rb +++ b/spec/datagrid/drivers/sequel_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Drivers::Sequel do diff --git a/spec/datagrid/filters/base_filter_spec.rb b/spec/datagrid/filters/base_filter_spec.rb index 44160da..fc60ca1 100644 --- a/spec/datagrid/filters/base_filter_spec.rb +++ b/spec/datagrid/filters/base_filter_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Filters::BaseFilter do diff --git a/spec/datagrid/filters/composite_filters_spec.rb b/spec/datagrid/filters/composite_filters_spec.rb index b40e2a4..3a0e96c 100644 --- a/spec/datagrid/filters/composite_filters_spec.rb +++ b/spec/datagrid/filters/composite_filters_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Filters::CompositeFilters do diff --git a/spec/datagrid/filters/date_filter_spec.rb b/spec/datagrid/filters/date_filter_spec.rb index 56fd5ce..865b61d 100644 --- a/spec/datagrid/filters/date_filter_spec.rb +++ b/spec/datagrid/filters/date_filter_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" require "active_support/testing/time_helpers" diff --git a/spec/datagrid/filters/date_time_filter_spec.rb b/spec/datagrid/filters/date_time_filter_spec.rb index 425b442..b0d1627 100644 --- a/spec/datagrid/filters/date_time_filter_spec.rb +++ b/spec/datagrid/filters/date_time_filter_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Filters::DateTimeFilter do diff --git a/spec/datagrid/filters/dynamic_filter_spec.rb b/spec/datagrid/filters/dynamic_filter_spec.rb index 6bbfa7c..149a461 100644 --- a/spec/datagrid/filters/dynamic_filter_spec.rb +++ b/spec/datagrid/filters/dynamic_filter_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Filters::DynamicFilter do diff --git a/spec/datagrid/filters/enum_filter_spec.rb b/spec/datagrid/filters/enum_filter_spec.rb index 7192614..6ea8ec7 100644 --- a/spec/datagrid/filters/enum_filter_spec.rb +++ b/spec/datagrid/filters/enum_filter_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Filters::EnumFilter do @@ -20,7 +22,7 @@ it "should support select option as proc with instace input" do klass = test_report do scope { Entry } - filter(:group_id, :enum, select: proc { |obj| obj.object_id }) + filter(:group_id, :enum, select: proc(&:object_id)) end.class instance = klass.new expect(klass.filter_by_name(:group_id).select(instance)).to eq(instance.object_id) diff --git a/spec/datagrid/filters/extended_boolean_filter_spec.rb b/spec/datagrid/filters/extended_boolean_filter_spec.rb index ebff604..f70f6da 100644 --- a/spec/datagrid/filters/extended_boolean_filter_spec.rb +++ b/spec/datagrid/filters/extended_boolean_filter_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Filters::ExtendedBooleanFilter do diff --git a/spec/datagrid/filters/float_filter_spec.rb b/spec/datagrid/filters/float_filter_spec.rb index 131cdd0..e45066f 100644 --- a/spec/datagrid/filters/float_filter_spec.rb +++ b/spec/datagrid/filters/float_filter_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Filters::FloatFilter do diff --git a/spec/datagrid/filters/integer_filter_spec.rb b/spec/datagrid/filters/integer_filter_spec.rb index a7f1855..fb6f5d7 100644 --- a/spec/datagrid/filters/integer_filter_spec.rb +++ b/spec/datagrid/filters/integer_filter_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Filters::IntegerFilter do diff --git a/spec/datagrid/filters/string_filter_spec.rb b/spec/datagrid/filters/string_filter_spec.rb index 8e84de3..c55fb58 100644 --- a/spec/datagrid/filters/string_filter_spec.rb +++ b/spec/datagrid/filters/string_filter_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Filters::StringFilter do diff --git a/spec/datagrid/filters_spec.rb b/spec/datagrid/filters_spec.rb index 91614dc..7f335e9 100644 --- a/spec/datagrid/filters_spec.rb +++ b/spec/datagrid/filters_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Filters do diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index dac013b..d42acce 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" require "action_controller" @@ -19,7 +21,7 @@ class MyTemplate describe ".datagrid_filter" do it "should work for every filter type" do - Datagrid::Filters::FILTER_TYPES.each do |_type, klass| + Datagrid::Filters::FILTER_TYPES.each_value do |klass| expect(Datagrid::FormBuilder.instance_methods.map(&:to_sym)).to include(klass.form_builder_helper_name) end end @@ -180,8 +182,8 @@ class MyTemplate let(:_range) { [1, 2] } it { should equal_to_dom( - '<input value="1" id="from_hello" class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + - '<span class="separator integer"> - </span>' + + '<input value="1" id="from_hello" class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' \ + '<span class="separator integer"> - </span>' \ '<input value="2" id="to_hello" class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' ) } @@ -190,8 +192,8 @@ class MyTemplate let(:_range) { [10, nil] } it { should equal_to_dom( - '<input value="10" class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + - '<span class="separator integer"> - </span>' + + '<input value="10" class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' \ + '<span class="separator integer"> - </span>' \ '<input class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' ) } @@ -201,8 +203,8 @@ class MyTemplate let(:_range) { [nil, 10] } it { should equal_to_dom( - '<input class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + - '<span class="separator integer"> - </span>' + + '<input class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' \ + '<span class="separator integer"> - </span>' \ '<input value="10" class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' ) } @@ -213,8 +215,8 @@ class MyTemplate let(:_range) { 2..1 } it { should equal_to_dom( - '<input value="1" class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + - '<span class="separator integer"> - </span>' + + '<input value="1" class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' \ + '<span class="separator integer"> - </span>' \ '<input value="2" class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' ) } @@ -252,8 +254,8 @@ class MyTemplate let(:_range) { [1.5, 2.5] } it { should equal_to_dom( - '<input value="1.5" class="from rating float_filter" multiple type="text" name="report[rating][]"/>' + - '<span class="separator float"> - </span>' + + '<input value="1.5" class="from rating float_filter" multiple type="text" name="report[rating][]"/>' \ + '<span class="separator float"> - </span>' \ '<input value="2.5" class="to rating float_filter" multiple type="text" name="report[rating][]"/>' ) } @@ -271,8 +273,8 @@ class MyTemplate let(:_range) { ["2012-01-03", nil] } it { should equal_to_dom( - '<input value="2012-01-03" class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + - '<span class="separator date"> - </span>' + + '<input value="2012-01-03" class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' \ + '<span class="separator date"> - </span>' \ '<input class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' ) } @@ -287,8 +289,8 @@ class MyTemplate let(:_range) { ["2013/01/01", "2013/02/02"] } it { should equal_to_dom( - '<input value="01/01/2013" class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + - '<span class="separator date"> - </span>' + + '<input value="01/01/2013" class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' \ + '<span class="separator date"> - </span>' \ '<input value="02/02/2013" class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' ) } @@ -297,8 +299,8 @@ class MyTemplate let(:_range) { [nil, "2012-01-03"] } it { should equal_to_dom( - '<input class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + - '<span class="separator date"> - </span>' + + '<input class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' \ + '<span class="separator date"> - </span>' \ '<input value="2012-01-03" class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' ) } @@ -309,8 +311,8 @@ class MyTemplate let(:_range) { Date.parse("2012-01-02")..Date.parse("2012-01-01") } it { should equal_to_dom( - '<input value="2012-01-01" class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + - '<span class="separator date"> - </span>' + + '<input value="2012-01-01" class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' \ + '<span class="separator date"> - </span>' \ '<input value="2012-01-02" class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' ) } @@ -324,8 +326,8 @@ class MyTemplate let(:_range) { [nil, nil] } it { should equal_to_dom( - '<input class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' + - '<span class="separator date"> - </span>' + + '<input class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' \ + '<span class="separator date"> - </span>' \ '<input class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' ) } diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index adc8efa..bd9a871 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" require "active_support/core_ext/hash" require "active_support/core_ext/object" @@ -193,7 +195,7 @@ class TestGrid it "should support urls" do rp = test_report do scope { Entry } - column(:name, url: ->(model) { model.name }) + column(:name, url: lambda(&:name)) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( "tr td.name a[href=Star]" => "Star" @@ -560,7 +562,7 @@ def param_name end it "should provide an interator" do r = subject.datagrid_row(grid, entry) - expect(r.map { |z| z.upcase }).to eq(%w[HELLO GREETINGS]) + expect(r.map(&:upcase)).to eq(%w[HELLO GREETINGS]) expect(r.name).to eq("Hello") expect(r.category).to eq("greetings") end diff --git a/spec/datagrid/ordering_spec.rb b/spec/datagrid/ordering_spec.rb index 701e6b0..028a448 100644 --- a/spec/datagrid/ordering_spec.rb +++ b/spec/datagrid/ordering_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Ordering do diff --git a/spec/datagrid/scaffold_spec.rb b/spec/datagrid/scaffold_spec.rb index 9bab5fc..6c1bd16 100644 --- a/spec/datagrid/scaffold_spec.rb +++ b/spec/datagrid/scaffold_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Scaffold do diff --git a/spec/datagrid/stylesheet_spec.rb b/spec/datagrid/stylesheet_spec.rb index 0fc65ce..c8888a1 100644 --- a/spec/datagrid/stylesheet_spec.rb +++ b/spec/datagrid/stylesheet_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe "Datagrid stylesheet" do diff --git a/spec/datagrid/utils_spec.rb b/spec/datagrid/utils_spec.rb index f66a495..1128edb 100644 --- a/spec/datagrid/utils_spec.rb +++ b/spec/datagrid/utils_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe Datagrid::Utils do diff --git a/spec/datagrid_spec.rb b/spec/datagrid_spec.rb index 3b04da1..b05b6f4 100644 --- a/spec/datagrid_spec.rb +++ b/spec/datagrid_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" require "datagrid/rspec" diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 995e21f..a5560d5 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "rubygems" require "bundler" @@ -110,4 +112,4 @@ def action_view_template # Requires supporting files with custom matchers and macros, etc, # in ./support/ and its subdirectories. -Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } +Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].sort.each { |f| require f } diff --git a/spec/support/active_record.rb b/spec/support/active_record.rb index 3a9a2c4..d20aa2a 100644 --- a/spec/support/active_record.rb +++ b/spec/support/active_record.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "sqlite3" ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") diff --git a/spec/support/configuration.rb b/spec/support/configuration.rb index 07e39a1..c99d4e4 100644 --- a/spec/support/configuration.rb +++ b/spec/support/configuration.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + def with_date_format(format = "%m/%d/%Y") old_format = Datagrid.configuration.date_formats Datagrid.configure do |config| diff --git a/spec/support/i18n_helpers.rb b/spec/support/i18n_helpers.rb index 9a52846..5ae24ad 100644 --- a/spec/support/i18n_helpers.rb +++ b/spec/support/i18n_helpers.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + def store_translations(locale, translations) I18n.backend.store_translations locale, translations yield diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb index 3a84ce6..745b40e 100644 --- a/spec/support/matchers.rb +++ b/spec/support/matchers.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "rails/dom/testing" def equal_to_dom(text) @@ -55,19 +57,20 @@ def matches?(text) @matcher = Nokogiri::HTML::DocumentFragment.parse(text) @css_pattern.each do |css, amount_or_pattern_or_string_or_proc| path = @matcher.css(css) - if amount_or_pattern_or_string_or_proc.is_a?(String) or amount_or_pattern_or_string_or_proc.is_a?(Regexp) + case amount_or_pattern_or_string_or_proc + when String, Regexp pattern_or_string = amount_or_pattern_or_string_or_proc html = path.inner_html unless html.match(pattern_or_string) return error!("#{css.inspect} did not match #{pattern_or_string.inspect}. It was \n:#{html.inspect}") end - elsif amount_or_pattern_or_string_or_proc.is_a? Numeric + when Numeric expected_amount = amount_or_pattern_or_string_or_proc amount = path.size if amount != expected_amount return error!("did not find #{css.inspect} #{expected_amount.inspect} times. It was #{amount.inspect}") end - elsif amount_or_pattern_or_string_or_proc.is_a? Proc + when Proc unless amount_or_pattern_or_string_or_proc.call(path) return error!("#{css.inspect} did not validate (proc must not return a falsy value)") end diff --git a/spec/support/mongo_mapper.rb b/spec/support/mongo_mapper.rb index 5876028..2d381df 100644 --- a/spec/support/mongo_mapper.rb +++ b/spec/support/mongo_mapper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + if defined?(MongoMapper) class MongoMapperEntry diff --git a/spec/support/mongoid.rb b/spec/support/mongoid.rb index 014c008..878a20c 100644 --- a/spec/support/mongoid.rb +++ b/spec/support/mongoid.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "rubygems" # Mongoid.logger = TEST_LOGGER #TODO: understand why still output to STDOUT diff --git a/spec/support/sequel.rb b/spec/support/sequel.rb index 5130fc9..77da337 100644 --- a/spec/support/sequel.rb +++ b/spec/support/sequel.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "sequel" DB = Sequel.sqlite # memory database diff --git a/spec/support/simple_report.rb b/spec/support/simple_report.rb index 57e553a..ed5afab 100644 --- a/spec/support/simple_report.rb +++ b/spec/support/simple_report.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + def test_report(attributes = {}, &block) klass = test_report_class(&block) klass.new(attributes) @@ -35,9 +37,7 @@ class SimpleReport group.name end - column(:name) do |user| - user.name - end + column(:name, &:name) column(:actions, html: true) do |model| render partial: "/actions", locals: { model: model } From f9fe54f4761d2d0a404f8308bb5d3d2ba3d78d03 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 3 Nov 2024 19:43:42 +0100 Subject: [PATCH 010/157] Rubocop fixes --- .rubocop.yml | 10 ++++++++++ lib/datagrid/filters/float_filter.rb | 1 + spec/datagrid/form_builder_spec.rb | 4 +++- spec/spec_helper.rb | 9 +-------- spec/support/active_record.rb | 12 ++++++------ 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index e5ccac6..11ed854 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,3 +1,13 @@ # inherit_from: .rubocop_todo.yml Style/StringLiterals: EnforcedStyle: double_quotes +Metrics/BlockLength: + Enabled: false +Metrics/MethodLength: + Enabled: false +Metrics/AbcSize: + Enabled: false +Lint/ConstantDefinitionInBlock: + Enabled: false +Metrics/CyclomaticComplexity: + Enabled: false diff --git a/lib/datagrid/filters/float_filter.rb b/lib/datagrid/filters/float_filter.rb index d84f6e1..6cc4aa9 100644 --- a/lib/datagrid/filters/float_filter.rb +++ b/lib/datagrid/filters/float_filter.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +# @!visibility private module Datagrid module Filters class FloatFilter < Datagrid::Filters::BaseFilter diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index d42acce..c8f7a83 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -495,7 +495,9 @@ class MyTemplate let(:_filter) { :name } it { - should equal_to_dom('<input value="one,two" class="name string_filter" type="text" name="report[name]" id="report_name">') + should equal_to_dom( + '<input value="one,two" class="name string_filter" type="text" name="report[name]" id="report_name">' + ) } end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a5560d5..9ddfab4 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -18,16 +18,9 @@ require "action_view" require "rails" require "mongoid" -begin - require "mongo_mapper" -rescue LoadError -end require "datagrid" -begin - require "ruby-debug" -rescue LoadError -end +require "debug" require "rspec" require "logger" diff --git a/spec/support/active_record.rb b/spec/support/active_record.rb index d20aa2a..d248295 100644 --- a/spec/support/active_record.rb +++ b/spec/support/active_record.rb @@ -26,12 +26,12 @@ t.float :rating t.timestamps end +end - class ::Entry < ActiveRecord::Base - belongs_to :group - end +class ::Entry < ActiveRecord::Base + belongs_to :group +end - class ::Group < ActiveRecord::Base - has_many :entries - end +class ::Group < ActiveRecord::Base + has_many :entries end From dd944db3e5426ac65a0f443837e5af2f9af47d90 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 3 Nov 2024 19:51:27 +0100 Subject: [PATCH 011/157] Rubocop --- .rubocop.yml | 3 ++- datagrid.gemspec | 3 ++- lib/datagrid/columns.rb | 4 ++-- lib/datagrid/core.rb | 4 ++-- lib/datagrid/drivers/abstract_driver.rb | 2 +- lib/datagrid/filters.rb | 6 +++--- lib/datagrid/filters/date_filter.rb | 4 ++-- lib/datagrid/filters/enum_filter.rb | 2 +- lib/datagrid/filters/extended_boolean_filter.rb | 6 +++--- lib/datagrid/filters/ranged_filter.rb | 6 +++--- spec/datagrid/columns_spec.rb | 2 +- spec/datagrid/core_spec.rb | 2 +- spec/datagrid/form_builder_spec.rb | 16 ++++++++++++---- spec/datagrid/helper_spec.rb | 6 +++--- spec/spec_helper.rb | 4 ++-- 15 files changed, 40 insertions(+), 30 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 11ed854..8560090 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,4 +1,5 @@ -# inherit_from: .rubocop_todo.yml +AllCops: + NewCops: enable Style/StringLiterals: EnforcedStyle: double_quotes Metrics/BlockLength: diff --git a/datagrid.gemspec b/datagrid.gemspec index 662bdee..49add80 100644 --- a/datagrid.gemspec +++ b/datagrid.gemspec @@ -29,7 +29,8 @@ Gem::Specification.new do |s| "bug_tracker_uri" => "#{s.homepage}/issues", "documentation_uri" => "#{s.homepage}/wiki", "changelog_uri" => "#{s.homepage}/blob/master/CHANGELOG.md", - "source_code_uri" => s.homepage + "source_code_uri" => s.homepage, + "rubygems_mfa_required" => "true" } s.add_dependency "railties", ">= 6.1" diff --git a/lib/datagrid/columns.rb b/lib/datagrid/columns.rb index a388ab5..81b3ec9 100644 --- a/lib/datagrid/columns.rb +++ b/lib/datagrid/columns.rb @@ -148,13 +148,13 @@ def decorate(model = nil, &block) return model unless decorator presenter = ::Datagrid::Utils.apply_args(model, &decorator) - presenter = presenter.is_a?(Class) ? presenter.new(model) : presenter + presenter = presenter.new(model) if presenter.is_a?(Class) block_given? ? yield(presenter) : presenter end # @!visibility private def inherited(child_class) - super(child_class) + super child_class.columns_array = columns_array.clone end diff --git a/lib/datagrid/core.rb b/lib/datagrid/core.rb index 4fc1166..44df516 100644 --- a/lib/datagrid/core.rb +++ b/lib/datagrid/core.rb @@ -117,7 +117,7 @@ def check_scope_defined!(message = nil) end def inherited(child_class) - super(child_class) + super child_class.datagrid_attributes = datagrid_attributes.clone end end @@ -266,7 +266,7 @@ def reset protected def sanitize_for_mass_assignment(attributes) - forbidden_attributes_protection ? super(attributes) : attributes + forbidden_attributes_protection ? super : attributes end end end diff --git a/lib/datagrid/drivers/abstract_driver.rb b/lib/datagrid/drivers/abstract_driver.rb index 8807c1b..90f5038 100644 --- a/lib/datagrid/drivers/abstract_driver.rb +++ b/lib/datagrid/drivers/abstract_driver.rb @@ -9,7 +9,7 @@ class AbstractDriver class_attribute :subclasses, default: [] def self.inherited(base) - super(base) + super subclasses << base end diff --git a/lib/datagrid/filters.rb b/lib/datagrid/filters.rb index ecca158..4a3d31e 100644 --- a/lib/datagrid/filters.rb +++ b/lib/datagrid/filters.rb @@ -127,7 +127,7 @@ def filters protected def inherited(child_class) - super(child_class) + super child_class.filters_array = filters_array.clone end @@ -141,12 +141,12 @@ def filters_inspection end # @!visibility private - def initialize(*args, &block) + def initialize(...) self.filters_array = self.class.filters_array.clone filters_array.each do |filter| self[filter.name] = filter.default(self) end - super(*args, &block) + super end # @!visibility private diff --git a/lib/datagrid/filters/date_filter.rb b/lib/datagrid/filters/date_filter.rb index 170e249..2a7d29d 100644 --- a/lib/datagrid/filters/date_filter.rb +++ b/lib/datagrid/filters/date_filter.rb @@ -9,7 +9,7 @@ class DateFilter < Datagrid::Filters::BaseFilter def apply(grid_object, scope, value) value = value.begin&.beginning_of_day..value.end&.end_of_day if value.is_a?(Range) - super(grid_object, scope, value) + super end def parse(value) @@ -26,7 +26,7 @@ def format(value) def default_filter_where(scope, value) value = Datagrid::Utils.format_date_as_timestamp(value) if driver.is_timestamp?(scope, name) - super(scope, value) + super end protected diff --git a/lib/datagrid/filters/enum_filter.rb b/lib/datagrid/filters/enum_filter.rb index d16f7c1..6e5a12b 100644 --- a/lib/datagrid/filters/enum_filter.rb +++ b/lib/datagrid/filters/enum_filter.rb @@ -8,7 +8,7 @@ class EnumFilter < Datagrid::Filters::BaseFilter include Datagrid::Filters::SelectOptions def initialize(*args) - super(*args) + super options[:multiple] = true if checkboxes? raise Datagrid::ConfigurationError, ":select option not specified" unless options[:select] end diff --git a/lib/datagrid/filters/extended_boolean_filter.rb b/lib/datagrid/filters/extended_boolean_filter.rb index 1e2b96a..5cf418a 100644 --- a/lib/datagrid/filters/extended_boolean_filter.rb +++ b/lib/datagrid/filters/extended_boolean_filter.rb @@ -11,12 +11,12 @@ class ExtendedBooleanFilter < Datagrid::Filters::EnumFilter def initialize(report, attribute, options = {}, &block) options[:select] = -> { boolean_select } - super(report, attribute, options, &block) + super end def execute(value, scope, grid_object) value = value.blank? ? nil : ::Datagrid::Utils.booleanize(value) - super(value, scope, grid_object) + super end def parse(value) @@ -29,7 +29,7 @@ def parse(value) when value.blank? nil else - super(value) + super end end diff --git a/lib/datagrid/filters/ranged_filter.rb b/lib/datagrid/filters/ranged_filter.rb index be2c683..9fa95d2 100644 --- a/lib/datagrid/filters/ranged_filter.rb +++ b/lib/datagrid/filters/ranged_filter.rb @@ -4,14 +4,14 @@ module Datagrid module Filters module RangedFilter def initialize(grid, name, options, &block) - super(grid, name, options, &block) + super return unless range? options[:multiple] = true end def parse_values(value) - result = super(value) + result = super return result if !range? || result.nil? # Simulate single point range return [result, result] unless result.is_a?(Array) @@ -46,7 +46,7 @@ def default_filter_where(scope, value) scope = driver.less_equal(scope, name, right) if right scope else - super(scope, value) + super end end end diff --git a/spec/datagrid/columns_spec.rb b/spec/datagrid/columns_spec.rb index 13d0378..b7f90cc 100644 --- a/spec/datagrid/columns_spec.rb +++ b/spec/datagrid/columns_spec.rb @@ -87,7 +87,7 @@ class Report27 column(:name) end - store_translations(:en, datagrid: { "report27": { columns: { name: "Nombre" } } }) do + store_translations(:en, datagrid: { report27: { columns: { name: "Nombre" } } }) do expect(Report27.new.header.first).to eq("Nombre") end end diff --git a/spec/datagrid/core_spec.rb b/spec/datagrid/core_spec.rb index 40c4f47..14626ba 100644 --- a/spec/datagrid/core_spec.rb +++ b/spec/datagrid/core_spec.rb @@ -203,7 +203,7 @@ class EqualTest describe "ActionController::Parameters" do let(:params) do - ::ActionController::Parameters.new(name: "one") + ActionController::Parameters.new(name: "one") end it "permites all attributes by default" do diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index c8f7a83..0b5004f 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -427,9 +427,15 @@ class MyTemplate it { should equal_to_dom( ' -<label class="category enum_filter checkboxes" for="report_category_first"><input class="category enum_filter checkboxes" type="checkbox" id="report_category_first" value="first" name="report[category][]" />first</label> -<label class="category enum_filter checkboxes" for="report_category_second"><input class="category enum_filter checkboxes" type="checkbox" id="report_category_second" value="second" name="report[category][]" />second</label> - ' +<label class="category enum_filter checkboxes" for="report_category_first"> +<input class="category enum_filter checkboxes" type="checkbox" id="report_category_first" value="first" name="report[category][]" /> +first +</label> +<label class="category enum_filter checkboxes" for="report_category_second"> +<input class="category enum_filter checkboxes" type="checkbox" id="report_category_second" value="second" name="report[category][]" /> +second +</label> +' ) } @@ -451,7 +457,9 @@ class MyTemplate it { should equal_to_dom( # hidden is important when default is set to true - %(<input name="report[disabled]" type="hidden" value="0" autocomplete="off"><input class="disabled boolean_filter" type="checkbox" value="1" checked name="report[disabled]" id="report_disabled">) + %(<input name="report[disabled]" type="hidden" value="0" autocomplete="off"> + <input class="disabled boolean_filter" type="checkbox" value="1" + checked name="report[disabled]" id="report_disabled">) ) } end diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index bd9a871..04fd4bf 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -62,7 +62,7 @@ class TestGrid column(:id) end end - expect(subject.datagrid_table(::Ns23::TestGrid.new)).to match_css_pattern( + expect(subject.datagrid_table(Ns23::TestGrid.new)).to match_css_pattern( "table.datagrid.ns23_test_grid" => 1 ) end @@ -497,7 +497,7 @@ class TestGrid filter(:id) end end - expect(subject.datagrid_form_for(::Ns22::TestGrid.new, url: "grid")).to match_css_pattern( + expect(subject.datagrid_form_for(Ns22::TestGrid.new, url: "grid")).to match_css_pattern( "form.datagrid-form.ns22_test_grid" => 1, "form.datagrid-form label[for=ns22_test_grid_id]" => 1, "form.datagrid-form input#ns22_test_grid_id[name='ns22_test_grid[id]']" => 1 @@ -513,7 +513,7 @@ def param_name "g" end end - expect(subject.datagrid_form_for(::ParamNameGrid81.new, url: "/grid")).to match_css_pattern( + expect(subject.datagrid_form_for(ParamNameGrid81.new, url: "/grid")).to match_css_pattern( "form.datagrid-form input[name='g[id]']" => 1 ) end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9ddfab4..b8cb418 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -32,7 +32,7 @@ class DatagridTest < Rails::Application File.open("spec.log", "w").close TEST_LOGGER = Logger.new("spec.log") -NO_MONGO = ENV["NO_MONGO"] +NO_MONGO = ENV.fetch("NO_MONGO", nil) if NO_MONGO warn("MONGODB WARNING: Skipping Mongoid and Mongomapper tests.") @@ -98,7 +98,7 @@ def action_view_template File.expand_path("support/test_partials", __dir__) ], {}) Datagrid::Engine.extend_modules - template = ActionView::Base.with_empty_template_cache.new(context, {}, ::ActionController::Base.new) + template = ActionView::Base.with_empty_template_cache.new(context, {}, ActionController::Base.new) allow(template).to receive(:protect_against_forgery?).and_return(false) template end From d0786ae2a6d49cb306b834f80008fb8e1b0d9fb2 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 3 Nov 2024 20:16:47 +0100 Subject: [PATCH 012/157] Rubocop --- spec/datagrid/filters_spec.rb | 8 +-- spec/datagrid/form_builder_spec.rb | 78 ++++++++++++++++++++---------- spec/datagrid_spec.rb | 4 +- 3 files changed, 60 insertions(+), 30 deletions(-) diff --git a/spec/datagrid/filters_spec.rb b/spec/datagrid/filters_spec.rb index 7f335e9..afd239c 100644 --- a/spec/datagrid/filters_spec.rb +++ b/spec/datagrid/filters_spec.rb @@ -71,17 +71,17 @@ class TheReport describe "allow_blank and allow_nil options" do def check_performed(value, result, **options) - $FILTER_PERFORMED = false + filter_performed = false report = test_report(name: value) do scope { Entry } filter(:name, **options) do |_| - $FILTER_PERFORMED = true + filter_performed = true self end end expect(report.name).to eq(value) report.assets - expect($FILTER_PERFORMED).to eq(result) + expect(filter_performed).to eq(result) end it "should support allow_blank argument" do @@ -304,7 +304,7 @@ class TestGrid8728 end context "with delegation to attribute" do - let(:role) { OpenStruct.new("admin?" => admin) } + let(:role) { Struct.new(:admin?).new(admin) } let(:klass) do test_report_class do attr_accessor :role diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 0b5004f..5cf5ac0 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -92,7 +92,8 @@ class MyTemplate end it { should equal_to_dom( - '<input value="01/02/2012" class="created_at date_filter" type="text" name="report[created_at]" id="report_created_at"/>' + '<input value="01/02/2012" class="created_at date_filter" type="text" + name="report[created_at]" id="report_created_at"/>' ) } end @@ -137,7 +138,8 @@ class MyTemplate end it { should equal_to_dom( - '<input type="datetime-local" class="created_at date_time_filter" value="2024-01-01T09:25:15" name="report[created_at]" id="report_created_at"/>' + '<input type="datetime-local" class="created_at date_time_filter" + value="2024-01-01T09:25:15" name="report[created_at]" id="report_created_at"/>' ) } @@ -147,7 +149,8 @@ class MyTemplate end it { should equal_to_dom( - '<input type="datetime-local" value="" class="created_at date_time_filter" name="report[created_at]" id="report_created_at"/>' + '<input type="datetime-local" value="" class="created_at date_time_filter" + name="report[created_at]" id="report_created_at"/>' ) } end @@ -163,7 +166,8 @@ class MyTemplate end it { should equal_to_dom( - '<input type="date" class="created_at date_time_filter" value="2024-01-01" name="report[created_at]" id="report_created_at"/>' + '<input type="date" class="created_at date_time_filter" value="2024-01-01" + name="report[created_at]" id="report_created_at"/>' ) } end @@ -182,9 +186,11 @@ class MyTemplate let(:_range) { [1, 2] } it { should equal_to_dom( - '<input value="1" id="from_hello" class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' \ + '<input value="1" id="from_hello" class="from group_id integer_filter" + multiple type="text" name="report[group_id][]"/>' \ '<span class="separator integer"> - </span>' \ - '<input value="2" id="to_hello" class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + '<input value="2" id="to_hello" class="to group_id integer_filter" + multiple type="text" name="report[group_id][]"/>' ) } end @@ -192,9 +198,11 @@ class MyTemplate let(:_range) { [10, nil] } it { should equal_to_dom( - '<input value="10" class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' \ + '<input value="10" class="from group_id integer_filter" + multiple type="text" name="report[group_id][]"/>' \ '<span class="separator integer"> - </span>' \ - '<input class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + '<input class="to group_id integer_filter" + multiple type="text" name="report[group_id][]"/>' ) } it { should be_html_safe } @@ -237,7 +245,11 @@ class MyTemplate let(:_range) { nil } it { should equal_to_dom( - '<input class="from group_id integer_filter" multiple type="text" name="report[group_id][]"><span class="separator integer"> - </span><input class="to group_id integer_filter" multiple type="text" name="report[group_id][]">' + '<input class="from group_id integer_filter" + multiple type="text" name="report[group_id][]"> + <span class="separator integer"> - </span> + <input class="to group_id integer_filter" + multiple type="text" name="report[group_id][]">' ) } end @@ -254,9 +266,11 @@ class MyTemplate let(:_range) { [1.5, 2.5] } it { should equal_to_dom( - '<input value="1.5" class="from rating float_filter" multiple type="text" name="report[rating][]"/>' \ + '<input value="1.5" class="from rating float_filter" + multiple type="text" name="report[rating][]"/>' \ '<span class="separator float"> - </span>' \ - '<input value="2.5" class="to rating float_filter" multiple type="text" name="report[rating][]"/>' + '<input value="2.5" class="to rating float_filter" + multiple type="text" name="report[rating][]"/>' ) } end @@ -273,9 +287,11 @@ class MyTemplate let(:_range) { ["2012-01-03", nil] } it { should equal_to_dom( - '<input value="2012-01-03" class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' \ + '<input value="2012-01-03" class="from created_at date_filter" + multiple type="text" name="report[created_at][]"/>' \ '<span class="separator date"> - </span>' \ - '<input class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' + '<input class="to created_at date_filter" + multiple type="text" name="report[created_at][]"/>' ) } it { should be_html_safe } @@ -289,9 +305,11 @@ class MyTemplate let(:_range) { ["2013/01/01", "2013/02/02"] } it { should equal_to_dom( - '<input value="01/01/2013" class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' \ + '<input value="01/01/2013" class="from created_at date_filter" + multiple type="text" name="report[created_at][]"/>' \ '<span class="separator date"> - </span>' \ - '<input value="02/02/2013" class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' + '<input value="02/02/2013" class="to created_at date_filter" + multiple type="text" name="report[created_at][]"/>' ) } end @@ -299,9 +317,11 @@ class MyTemplate let(:_range) { [nil, "2012-01-03"] } it { should equal_to_dom( - '<input class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' \ + '<input class="from created_at date_filter" + multiple type="text" name="report[created_at][]"/>' \ '<span class="separator date"> - </span>' \ - '<input value="2012-01-03" class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' + '<input value="2012-01-03" class="to created_at date_filter" + multiple type="text" name="report[created_at][]"/>' ) } it { should be_html_safe } @@ -311,9 +331,11 @@ class MyTemplate let(:_range) { Date.parse("2012-01-02")..Date.parse("2012-01-01") } it { should equal_to_dom( - '<input value="2012-01-01" class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' \ + '<input value="2012-01-01" class="from created_at date_filter" + multiple type="text" name="report[created_at][]"/>' \ '<span class="separator date"> - </span>' \ - '<input value="2012-01-02" class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' + '<input value="2012-01-02" class="to created_at date_filter" + multiple type="text" name="report[created_at][]"/>' ) } end @@ -326,9 +348,11 @@ class MyTemplate let(:_range) { [nil, nil] } it { should equal_to_dom( - '<input class="from created_at date_filter" multiple type="text" name="report[created_at][]"/>' \ + '<input class="from created_at date_filter" + multiple type="text" name="report[created_at][]"/>' \ '<span class="separator date"> - </span>' \ - '<input class="to created_at date_filter" multiple type="text" name="report[created_at][]"/>' + '<input class="to created_at date_filter" + multiple type="text" name="report[created_at][]"/>' ) } end @@ -405,7 +429,8 @@ class MyTemplate let(:_category_filter_options) { { prompt: "My Prompt" } } it { should equal_to_dom( - '<select class="category enum_filter" name="report[category]" id="report_category"><option value="">My Prompt</option> + '<select class="category enum_filter" name="report[category]" id="report_category"> + <option value="">My Prompt</option> <option value="first">first</option> <option value="second">second</option></select>' ) @@ -416,7 +441,8 @@ class MyTemplate let(:_category_filter_options) { { input_options: { class: "custom-class" } } } it { should equal_to_dom( - '<select class="custom-class category enum_filter" name="report[category]" id="report_category"><option value="" label=" "></option> + '<select class="custom-class category enum_filter" name="report[category]" id="report_category"> + <option value="" label=" "></option> <option value="first">first</option> <option value="second">second</option></select>' ) @@ -428,11 +454,13 @@ class MyTemplate should equal_to_dom( ' <label class="category enum_filter checkboxes" for="report_category_first"> -<input class="category enum_filter checkboxes" type="checkbox" id="report_category_first" value="first" name="report[category][]" /> +<input class="category enum_filter checkboxes" type="checkbox" id="report_category_first" + value="first" name="report[category][]" /> first </label> <label class="category enum_filter checkboxes" for="report_category_second"> -<input class="category enum_filter checkboxes" type="checkbox" id="report_category_second" value="second" name="report[category][]" /> +<input class="category enum_filter checkboxes" type="checkbox" id="report_category_second" + value="second" name="report[category][]" /> second </label> ' diff --git a/spec/datagrid_spec.rb b/spec/datagrid_spec.rb index b05b6f4..074ca2c 100644 --- a/spec/datagrid_spec.rb +++ b/spec/datagrid_spec.rb @@ -46,7 +46,9 @@ context "when not defined on class level" do subject do - test_report {} + test_report do + column(:id) + end end it "should raise ConfigurationError" do From b426776361a1467cc33291284002d28aba4cdfb6 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 3 Nov 2024 20:37:10 +0100 Subject: [PATCH 013/157] Rubocop --- .rubocop.yml | 8 ++++++++ lib/datagrid.rb | 9 +++++++++ lib/datagrid/active_model.rb | 12 ++---------- lib/datagrid/filters.rb | 7 +++++-- lib/datagrid/form_builder.rb | 2 +- lib/datagrid/helper.rb | 1 + lib/datagrid/ordering.rb | 1 + lib/datagrid/scaffold.rb | 1 + lib/datagrid/utils.rb | 1 + spec/datagrid/columns_spec.rb | 8 ++++++-- spec/datagrid/core_spec.rb | 4 +++- 11 files changed, 38 insertions(+), 16 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 8560090..4421b7b 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -12,3 +12,11 @@ Lint/ConstantDefinitionInBlock: Enabled: false Metrics/CyclomaticComplexity: Enabled: false +Metrics/PerceivedComplexity: + Enabled: false +Metrics/ClassLength: + Enabled: false +Metrics/ModuleLength: + Enabled: false +Style/Documentation: + Enabled: false diff --git a/lib/datagrid.rb b/lib/datagrid.rb index 4bf2bdf..616d779 100644 --- a/lib/datagrid.rb +++ b/lib/datagrid.rb @@ -4,6 +4,15 @@ require "datagrid/configuration" require "datagrid/engine" +# Main datagrid module that needs to be included in grid class +# +# @example +# class UsersGrid +# include Datagrid +# scope { User } +# column(:id) +# column(:name) +# end module Datagrid extend ActiveSupport::Autoload diff --git a/lib/datagrid/active_model.rb b/lib/datagrid/active_model.rb index 22860e0..f139ab0 100644 --- a/lib/datagrid/active_model.rb +++ b/lib/datagrid/active_model.rb @@ -7,16 +7,8 @@ module ActiveModel def self.included(base) base.extend ClassMethods base.class_eval do - begin - require "active_model/naming" - extend ::ActiveModel::Naming - rescue LoadError - end - begin - require "active_model/attributes_assignment" - extend ::ActiveModel::AttributesAssignment - rescue LoadError - end + require "active_model/naming" + extend ::ActiveModel::Naming end end diff --git a/lib/datagrid/filters.rb b/lib/datagrid/filters.rb index 4a3d31e..6b14f3c 100644 --- a/lib/datagrid/filters.rb +++ b/lib/datagrid/filters.rb @@ -44,6 +44,7 @@ def self.included(base) end end + # Grid class methods related to filters module ClassMethods # @return [Datagrid::Filters::BaseFilter, nil] filter definition object by name def filter_by_name(attribute) @@ -73,8 +74,10 @@ def filter_by_name(attribute) # Available options: # # * <tt>:header</tt> - determines the header of the filter - # * <tt>:default</tt> - the default filter value. Able to accept a <tt>Proc</tt> in case default should be recalculated - # * <tt>:range</tt> - if true, filter can accept two values that are treated as a range that will be used for filtering + # * <tt>:default</tt> - the default filter value. + # Can be a <tt>Proc</tt> in case default should be recalculated. + # * <tt>:range</tt> - if true, filter can accept two values that are treated + # as a range that will be used for filtering. # Not all of the filter types support this option. Here are the list of types that do: # <tt>:integer</tt>, <tt>:float</tt>, <tt>:date</tt>, <tt>:datetime</tt>, <tt>:string</tt> # * <tt>:multiple</tt> - if true multiple values can be assigned to this filter. diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 65347fe..e7dfa8a 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -10,7 +10,7 @@ module FormBuilder # * <tt>select</tt> for enum, xboolean filter types # * <tt>check_box</tt> for boolean filter type # * <tt>text_field</tt> for other filter types - def datagrid_filter(filter_or_attribute, partials: nil, **options, &block) + def datagrid_filter(filter_or_attribute, **options, &block) filter = datagrid_get_filter(filter_or_attribute) send(filter.form_builder_helper_name, filter, **options, &block) end diff --git a/lib/datagrid/helper.rb b/lib/datagrid/helper.rb index 6e16ac8..925af9d 100644 --- a/lib/datagrid/helper.rb +++ b/lib/datagrid/helper.rb @@ -3,6 +3,7 @@ require "action_view" module Datagrid + # Datagrid methods available as helpers in Rails views module Helper # @param grid [Datagrid] grid object # @param column [Datagrid::Columns::Column, String, Symbol] column name diff --git a/lib/datagrid/ordering.rb b/lib/datagrid/ordering.rb index cab6ee9..963d7c4 100644 --- a/lib/datagrid/ordering.rb +++ b/lib/datagrid/ordering.rb @@ -7,6 +7,7 @@ module Datagrid class OrderUnsupported < StandardError end + # Module adds support for ordering by defined columns for Datagrid. module Ordering # @!visibility private def self.included(base) diff --git a/lib/datagrid/scaffold.rb b/lib/datagrid/scaffold.rb index 89bdc73..b1faa50 100644 --- a/lib/datagrid/scaffold.rb +++ b/lib/datagrid/scaffold.rb @@ -4,6 +4,7 @@ # @!visibility private module Datagrid + # @!visibility private class Scaffold < Rails::Generators::NamedBase include Rails::Generators::ResourceHelpers diff --git a/lib/datagrid/utils.rb b/lib/datagrid/utils.rb index 3a2a18d..43152ce 100644 --- a/lib/datagrid/utils.rb +++ b/lib/datagrid/utils.rb @@ -79,6 +79,7 @@ def parse_date(value) Array(Datagrid.configuration.date_formats).each do |format| return Date.strptime(value, format) rescue ::ArgumentError + nil end end return Date.parse(value) if value.is_a?(String) diff --git a/spec/datagrid/columns_spec.rb b/spec/datagrid/columns_spec.rb index b7f90cc..9fdb23e 100644 --- a/spec/datagrid/columns_spec.rb +++ b/spec/datagrid/columns_spec.rb @@ -154,7 +154,9 @@ class Report27 end it "should support csv export" do - expect(subject.to_csv).to eq("Shipping date,Group,Name,Access level,Pet\n#{date},Pop,Star,admin,ROTTWEILER\n") + expect(subject.to_csv).to eq( + "Shipping date,Group,Name,Access level,Pet\n#{date},Pop,Star,admin,ROTTWEILER\n" + ) end it "should support csv export of particular columns" do @@ -162,7 +164,9 @@ class Report27 end it "should support csv export options" do - expect(subject.to_csv(col_sep: ";")).to eq("Shipping date;Group;Name;Access level;Pet\n#{date};Pop;Star;admin;ROTTWEILER\n") + expect(subject.to_csv(col_sep: ";")).to eq( + "Shipping date;Group;Name;Access level;Pet\n#{date};Pop;Star;admin;ROTTWEILER\n" + ) end end diff --git a/spec/datagrid/core_spec.rb b/spec/datagrid/core_spec.rb index 14626ba..ca14b37 100644 --- a/spec/datagrid/core_spec.rb +++ b/spec/datagrid/core_spec.rb @@ -107,7 +107,9 @@ class InspectTest end grid = InspectTest.new(created_at: %w[2014-01-01 2014-08-05], descending: true, order: "name") - expect(grid.inspect).to eq("#<InspectTest order: :name, descending: true, created_at: [Wed, 01 Jan 2014, Tue, 05 Aug 2014]>") + expect(grid.inspect).to eq( + "#<InspectTest order: :name, descending: true, created_at: [Wed, 01 Jan 2014, Tue, 05 Aug 2014]>" + ) end end From 7d6b8f1d1781beac97b683a9cc3d8f5499ef6fe1 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 3 Nov 2024 20:46:33 +0100 Subject: [PATCH 014/157] Cleanup --- lib/datagrid/columns.rb | 14 +++++++++++--- lib/datagrid/filters/dynamic_filter.rb | 4 +--- lib/datagrid/renderer.rb | 4 ++++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/datagrid/columns.rb b/lib/datagrid/columns.rb index 81b3ec9..360cd0f 100644 --- a/lib/datagrid/columns.rb +++ b/lib/datagrid/columns.rb @@ -300,7 +300,8 @@ def columns(*column_names, data: false, html: false) end end - # @param column_names [Array<String, Symbol>] list of column names if you want to limit data only to specified columns + # @param column_names [Array<String, Symbol>] list of column names + # if you want to limit data only to specified columns # @return [Array<Datagrid::Columns::Column>] columns that can be represented in plain data(non-html) way def data_columns(*column_names, **options) columns(*column_names, **options, data: true) @@ -374,7 +375,8 @@ def initialize(*) super end - # @return [Array<Datagrid::Columns::Column>] all columns that are possible to be displayed for the current grid object + # @return [Array<Datagrid::Columns::Column>] all columns + # that are possible to be displayed for the current grid object # # @example # class MyGrid @@ -478,7 +480,9 @@ def cache_key(asset) end rescue NotImplementedError raise Datagrid::ConfigurationError, - "#{self} is setup to use cache. But there was appropriate cache key found for #{asset.inspect}. Please set cached option to block with asset as argument and cache key as returning value to resolve the issue." + <<~MSG + #{self} is setup to use cache. But there was appropriate cache key found for #{asset.inspect}. + MSG end def map_with_batches(&block) @@ -526,6 +530,10 @@ def initialize(grid, model) def method_missing(meth, *_args) @grid.data_value(meth, @model) end + + def respond_to_missing?(meth, include_private = false) + !!@grid.column_by_name(meth) || super + end end end end diff --git a/lib/datagrid/filters/dynamic_filter.rb b/lib/datagrid/filters/dynamic_filter.rb index 0a0ae83..636512c 100644 --- a/lib/datagrid/filters/dynamic_filter.rb +++ b/lib/datagrid/filters/dynamic_filter.rb @@ -106,9 +106,7 @@ def type_cast(field, value) value.is_a?(Numeric) || value =~ /^\d/ ? value.to_i : nil when :float value.is_a?(Numeric) || value =~ /^\d/ ? value.to_f : nil - when :date - Datagrid::Utils.parse_date(value) - when :timestamp + when :date, :timestamp Datagrid::Utils.parse_date(value) when :boolean Datagrid::Utils.booleanize(value) diff --git a/lib/datagrid/renderer.rb b/lib/datagrid/renderer.rb index c838ed6..d485241 100644 --- a/lib/datagrid/renderer.rb +++ b/lib/datagrid/renderer.rb @@ -149,6 +149,10 @@ def method_missing(method, *args, &blk) super end end + + def respond_to_missing?(method, include_private = false) + !!@grid.column_by_name(method) || super + end end end end From 9b76d771d122f83be3443a41c45e8c1ebb76ba07 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 3 Nov 2024 20:53:11 +0100 Subject: [PATCH 015/157] Rubocop --- lib/datagrid/drivers/active_record.rb | 12 +++++------- lib/datagrid/drivers/array.rb | 4 ++-- lib/datagrid/drivers/mongo_mapper.rb | 4 ++-- lib/datagrid/drivers/mongoid.rb | 4 ++-- lib/datagrid/drivers/sequel.rb | 8 ++++---- lib/datagrid/filters.rb | 7 +++++-- lib/datagrid/filters/base_filter.rb | 8 +++++--- lib/datagrid/filters/composite_filters.rb | 2 -- lib/datagrid/form_builder.rb | 10 ++++------ 9 files changed, 29 insertions(+), 30 deletions(-) diff --git a/lib/datagrid/drivers/active_record.rb b/lib/datagrid/drivers/active_record.rb index 5be39b1..64f5949 100644 --- a/lib/datagrid/drivers/active_record.rb +++ b/lib/datagrid/drivers/active_record.rb @@ -32,9 +32,7 @@ def to_scope(scope) def append_column_queries(assets, columns) if columns.present? - if assets.select_values.empty? - assets = assets.select(Arel.respond_to?(:star) ? assets.klass.arel_table[Arel.star] : "#{assets.quoted_table_name}.*") - end + assets = assets.select(assets.klass.arel_table[Arel.star]) if assets.select_values.empty? columns = columns.map { |c| "#{c.query} AS #{c.name}" } assets = assets.select(*columns) end @@ -64,7 +62,7 @@ def reverse_order(scope) end def default_order(scope, column_name) - has_column?(scope, column_name) ? prefix_table_name(scope, column_name) : nil + scope_has_column?(scope, column_name) ? prefix_table_name(scope, column_name) : nil end def greater_equal(scope, field, value) @@ -75,7 +73,7 @@ def less_equal(scope, field, value) scope.where(["#{prefix_table_name(scope, field)} <= ?", value]) end - def has_column?(scope, column_name) + def scope_has_column?(scope, column_name) scope.column_names.include?(column_name.to_s) rescue ::ActiveRecord::StatementInvalid false @@ -91,7 +89,7 @@ def contains(scope, field, value) end def normalized_column_type(scope, field) - return nil unless has_column?(scope, field) + return nil unless scope_has_column?(scope, field) builtin_type = scope.columns_hash[field.to_s].type { @@ -130,7 +128,7 @@ def can_preload?(scope, association) protected def prefix_table_name(scope, field) - has_column?(scope, field) ? [scope.table_name, field].join(".") : field + scope_has_column?(scope, field) ? [scope.table_name, field].join(".") : field end def contains_predicate diff --git a/lib/datagrid/drivers/array.rb b/lib/datagrid/drivers/array.rb index bfa36ef..32007cd 100644 --- a/lib/datagrid/drivers/array.rb +++ b/lib/datagrid/drivers/array.rb @@ -54,12 +54,12 @@ def less_equal(scope, field, value) end end - def has_column?(scope, column_name) + def scope_has_column?(scope, column_name) scope.any? && scope.first.respond_to?(column_name) end def is_timestamp?(scope, column_name) - has_column?(scope, column_name) && + scope_has_column?(scope, column_name) && timestamp_class?(get(scope.first, column_name).class) end diff --git a/lib/datagrid/drivers/mongo_mapper.rb b/lib/datagrid/drivers/mongo_mapper.rb index df1c178..48871ac 100644 --- a/lib/datagrid/drivers/mongo_mapper.rb +++ b/lib/datagrid/drivers/mongo_mapper.rb @@ -31,7 +31,7 @@ def desc(scope, order) end def default_order(scope, column_name) - has_column?(scope, column_name) ? column_name : nil + scope_has_column?(scope, column_name) ? column_name : nil end def greater_equal(scope, field, value) @@ -42,7 +42,7 @@ def less_equal(scope, field, value) scope.where(field => { "$lte" => value }) end - def has_column?(scope, column_name) + def scope_has_column?(scope, column_name) scope.key?(column_name) end diff --git a/lib/datagrid/drivers/mongoid.rb b/lib/datagrid/drivers/mongoid.rb index aa166a8..e75b674 100644 --- a/lib/datagrid/drivers/mongoid.rb +++ b/lib/datagrid/drivers/mongoid.rb @@ -36,7 +36,7 @@ def desc(scope, order) end def default_order(scope, column_name) - has_column?(scope, column_name) ? column_name : nil + scope_has_column?(scope, column_name) ? column_name : nil end def greater_equal(scope, field, value) @@ -47,7 +47,7 @@ def less_equal(scope, field, value) scope.where(field => { "$lte" => value }) end - def has_column?(scope, column_name) + def scope_has_column?(scope, column_name) column_names(scope).include?(column_name.to_s) end diff --git a/lib/datagrid/drivers/sequel.rb b/lib/datagrid/drivers/sequel.rb index a450642..a84766e 100644 --- a/lib/datagrid/drivers/sequel.rb +++ b/lib/datagrid/drivers/sequel.rb @@ -33,7 +33,7 @@ def desc(scope, order) end def default_order(scope, column_name) - has_column?(scope, column_name) ? ::Sequel.lit(prefix_table_name(scope, column_name)) : nil + scope_has_column?(scope, column_name) ? ::Sequel.lit(prefix_table_name(scope, column_name)) : nil end def greater_equal(scope, field, value) @@ -44,7 +44,7 @@ def less_equal(scope, field, value) scope.where(::Sequel.lit("#{prefix_table_name(scope, field)} <= ?", value)) end - def has_column?(scope, column_name) + def scope_has_column?(scope, column_name) scope.columns.include?(column_name.to_sym) end @@ -98,11 +98,11 @@ def can_preload?(scope, association) protected def prefix_table_name(scope, field) - has_column?(scope, field) ? [to_scope(scope).row_proc.table_name, field].join(".") : field + scope_has_column?(scope, field) ? [to_scope(scope).row_proc.table_name, field].join(".") : field end def column_type(scope, field) - has_column?(scope, field) ? to_scope(scope).row_proc.db_schema[field.to_sym][:type] : nil + scope_has_column?(scope, field) ? to_scope(scope).row_proc.db_schema[field.to_sym][:type] : nil end end end diff --git a/lib/datagrid/filters.rb b/lib/datagrid/filters.rb index 6b14f3c..67f387b 100644 --- a/lib/datagrid/filters.rb +++ b/lib/datagrid/filters.rb @@ -217,8 +217,11 @@ def default_filter def find_select_filter(filter) filter = filter_by_name(filter) unless filter.class.included_modules.include?(::Datagrid::Filters::SelectOptions) - raise ::Datagrid::ArgumentError, - "#{self.class.name}##{filter.name} with type #{FILTER_TYPES.invert[filter.class].inspect} can not have select options" + type = FILTER_TYPES.invert[filter.class].inspect + raise( + ::Datagrid::ArgumentError, + "#{self.class.name}##{filter.name} with type #{type} can not have select options" + ) end filter end diff --git a/lib/datagrid/filters/base_filter.rb b/lib/datagrid/filters/base_filter.rb index ab43023..00ec275 100644 --- a/lib/datagrid/filters/base_filter.rb +++ b/lib/datagrid/filters/base_filter.rb @@ -38,8 +38,10 @@ def apply(grid_object, scope, value) result = default_filter(value, scope, grid_object) if result == Datagrid::Filters::DEFAULT_FILTER_BLOCK unless grid_object.driver.match?(result) - raise Datagrid::FilteringError, - "Can not apply #{name.inspect} filter: result #{result.inspect} no longer match #{grid_object.driver.class}." + raise( + Datagrid::FilteringError, + "Filter #{name.inspect} unapplicable: result no longer match #{grid_object.driver.class}." + ) end result @@ -183,7 +185,7 @@ def driver def default_filter(value, scope, _grid) return nil if dummy? - if !driver.has_column?(scope, name) && scope.respond_to?(name, true) + if !driver.scope_has_column?(scope, name) && scope.respond_to?(name, true) scope.public_send(name, value) else default_filter_where(scope, value) diff --git a/lib/datagrid/filters/composite_filters.rb b/lib/datagrid/filters/composite_filters.rb index a3d9238..53cac78 100644 --- a/lib/datagrid/filters/composite_filters.rb +++ b/lib/datagrid/filters/composite_filters.rb @@ -6,8 +6,6 @@ module Filters module CompositeFilters def self.included(base) base.extend ClassMethods - base.class_eval do - end end # @!visibility private diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index e7dfa8a..41ff7d1 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -208,12 +208,10 @@ def datagrid_float_filter(filter, options = {}) end def datagrid_get_filter(attribute_or_filter) - if Utils.string_like?(attribute_or_filter) - object.class.filter_by_name(attribute_or_filter) || - raise(Error, "Datagrid filter #{attribute_or_filter} not found") - else - attribute_or_filter - end + return attribute_or_filter unless Utils.string_like?(attribute_or_filter) + + object.class.filter_by_name(attribute_or_filter) || + raise(Error, "Datagrid filter #{attribute_or_filter} not found") end def add_html_classes(options, *classes) From e2fc7fb542daef8feef3cb4837c25cbcc647bf3a Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 4 Nov 2024 11:28:19 +0100 Subject: [PATCH 016/157] Move formatting classes from input/label to wrapping div --- app/views/datagrid/_form.html.erb | 2 +- lib/datagrid/filters/base_filter.rb | 5 +- lib/datagrid/filters/enum_filter.rb | 2 +- lib/datagrid/form_builder.rb | 10 +- spec/datagrid/form_builder_spec.rb | 155 ++++++++++++++-------------- spec/datagrid/helper_spec.rb | 8 +- 6 files changed, 88 insertions(+), 94 deletions(-) diff --git a/app/views/datagrid/_form.html.erb b/app/views/datagrid/_form.html.erb index 911d163..06f0414 100644 --- a/app/views/datagrid/_form.html.erb +++ b/app/views/datagrid/_form.html.erb @@ -1,6 +1,6 @@ <%= form_for grid, **options do |f| -%> <% grid.filters.each do |filter| %> - <div class="datagrid-filter"> + <div class="datagrid-filter <%= filter.default_html_classes.join(' ') %>"> <%= f.datagrid_label filter %> <%= f.datagrid_filter filter %> </div> diff --git a/lib/datagrid/filters/base_filter.rb b/lib/datagrid/filters/base_filter.rb index 00ec275..eee49eb 100644 --- a/lib/datagrid/filters/base_filter.rb +++ b/lib/datagrid/filters/base_filter.rb @@ -144,7 +144,10 @@ def enabled?(grid) end def default_html_classes - [name, self.class.to_s.demodulize.underscore] + [ + "datagrid-filter-#{name}", + "datagrid-filter-type-#{type}", + ] end protected diff --git a/lib/datagrid/filters/enum_filter.rb b/lib/datagrid/filters/enum_filter.rb index 6e5a12b..687fb1b 100644 --- a/lib/datagrid/filters/enum_filter.rb +++ b/lib/datagrid/filters/enum_filter.rb @@ -21,7 +21,7 @@ def parse(value) def default_html_classes res = super - res.push("checkboxes") if checkboxes? + res.push("datagrid-checkboxes") if checkboxes? res end diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 41ff7d1..b45262f 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -21,10 +21,7 @@ def datagrid_filter(filter_or_attribute, **options, &block) # @return [String] a form label tag for the corresponding filter name def datagrid_label(filter_or_attribute, text = nil, **options, &block) filter = datagrid_get_filter(filter_or_attribute) - options = add_html_classes( - { **filter.label_options, **options }, - filter.default_html_classes - ) + options = { **filter.label_options, **options } label(filter.name, text || filter.header, **options, &block) end @@ -232,10 +229,7 @@ def render_partial(name, locals) end def add_filter_options(filter, **options) - add_html_classes( - { **filter.input_options, **options }, - *filter.default_html_classes - ) + { **filter.input_options, **options } end class Error < StandardError diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 5cf5ac0..fb2d5d4 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -42,7 +42,7 @@ class MyTemplate let(:_filter) { :name } it { should equal_to_dom( - '<input class="name default_filter" type="text" name="report[name]" id="report_name"/>' + '<input type="text" name="report[name]" id="report_name"/>' ) } end @@ -56,7 +56,7 @@ class MyTemplate end it { should equal_to_dom( - '<input class="group_id integer_filter" type="text" name="report[group_id]" id="report_group_id"/>' + '<input type="text" name="report[group_id]" id="report_group_id"/>' ) } @@ -64,7 +64,7 @@ class MyTemplate let(:view_options) { { partials: "anything" } } it { should equal_to_dom( - '<input class="group_id integer_filter" type="text" name="report[group_id]" id="report_group_id"/>' + '<input type="text" name="report[group_id]" id="report_group_id"/>' ) } end @@ -80,7 +80,7 @@ class MyTemplate end it { should equal_to_dom( - '<input class="created_at date_filter" type="text" name="report[created_at]" id="report_created_at"/>' + '<input type="text" name="report[created_at]" id="report_created_at"/>' ) } context "when special date format specified" do @@ -92,7 +92,7 @@ class MyTemplate end it { should equal_to_dom( - '<input value="01/02/2012" class="created_at date_filter" type="text" + '<input value="01/02/2012" type="text" name="report[created_at]" id="report_created_at"/>' ) } @@ -109,7 +109,7 @@ class MyTemplate end it { should equal_to_dom( - '<input type="date" class="created_at date_filter" name="report[created_at]" id="report_created_at"/>' + '<input type="date" name="report[created_at]" id="report_created_at"/>' ) } end @@ -123,7 +123,7 @@ class MyTemplate end it { should equal_to_dom( - '<textarea class="name string_filter" name="report[name]" id="report_name"/>' + '<textarea name="report[name]" id="report_name"/>' ) } end @@ -138,7 +138,7 @@ class MyTemplate end it { should equal_to_dom( - '<input type="datetime-local" class="created_at date_time_filter" + '<input type="datetime-local" value="2024-01-01T09:25:15" name="report[created_at]" id="report_created_at"/>' ) } @@ -149,7 +149,7 @@ class MyTemplate end it { should equal_to_dom( - '<input type="datetime-local" value="" class="created_at date_time_filter" + '<input type="datetime-local" value="" name="report[created_at]" id="report_created_at"/>' ) } @@ -166,7 +166,7 @@ class MyTemplate end it { should equal_to_dom( - '<input type="date" class="created_at date_time_filter" value="2024-01-01" + '<input type="date" value="2024-01-01" name="report[created_at]" id="report_created_at"/>' ) } @@ -186,10 +186,10 @@ class MyTemplate let(:_range) { [1, 2] } it { should equal_to_dom( - '<input value="1" id="from_hello" class="from group_id integer_filter" + '<input value="1" id="from_hello" class="from" multiple type="text" name="report[group_id][]"/>' \ '<span class="separator integer"> - </span>' \ - '<input value="2" id="to_hello" class="to group_id integer_filter" + '<input value="2" id="to_hello" class="to" multiple type="text" name="report[group_id][]"/>' ) } @@ -198,10 +198,10 @@ class MyTemplate let(:_range) { [10, nil] } it { should equal_to_dom( - '<input value="10" class="from group_id integer_filter" + '<input value="10" class="from" multiple type="text" name="report[group_id][]"/>' \ '<span class="separator integer"> - </span>' \ - '<input class="to group_id integer_filter" + '<input class="to" multiple type="text" name="report[group_id][]"/>' ) } @@ -211,9 +211,9 @@ class MyTemplate let(:_range) { [nil, 10] } it { should equal_to_dom( - '<input class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' \ + '<input class="from" multiple type="text" name="report[group_id][]"/>' \ '<span class="separator integer"> - </span>' \ - '<input value="10" class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + '<input value="10" class="to" multiple type="text" name="report[group_id][]"/>' ) } it { should be_html_safe } @@ -223,9 +223,9 @@ class MyTemplate let(:_range) { 2..1 } it { should equal_to_dom( - '<input value="1" class="from group_id integer_filter" multiple type="text" name="report[group_id][]"/>' \ + '<input value="1" class="from" multiple type="text" name="report[group_id][]"/>' \ '<span class="separator integer"> - </span>' \ - '<input value="2" class="to group_id integer_filter" multiple type="text" name="report[group_id][]"/>' + '<input value="2" class="to" multiple type="text" name="report[group_id][]"/>' ) } end @@ -245,11 +245,9 @@ class MyTemplate let(:_range) { nil } it { should equal_to_dom( - '<input class="from group_id integer_filter" - multiple type="text" name="report[group_id][]"> + '<input class="from" multiple type="text" name="report[group_id][]"> <span class="separator integer"> - </span> - <input class="to group_id integer_filter" - multiple type="text" name="report[group_id][]">' + <input class="to" multiple type="text" name="report[group_id][]">' ) } end @@ -266,10 +264,10 @@ class MyTemplate let(:_range) { [1.5, 2.5] } it { should equal_to_dom( - '<input value="1.5" class="from rating float_filter" + '<input value="1.5" class="from" multiple type="text" name="report[rating][]"/>' \ '<span class="separator float"> - </span>' \ - '<input value="2.5" class="to rating float_filter" + '<input value="2.5" class="to" multiple type="text" name="report[rating][]"/>' ) } @@ -287,11 +285,9 @@ class MyTemplate let(:_range) { ["2012-01-03", nil] } it { should equal_to_dom( - '<input value="2012-01-03" class="from created_at date_filter" - multiple type="text" name="report[created_at][]"/>' \ + '<input value="2012-01-03" class="from" multiple type="text" name="report[created_at][]"/>' \ '<span class="separator date"> - </span>' \ - '<input class="to created_at date_filter" - multiple type="text" name="report[created_at][]"/>' + '<input class="to" multiple type="text" name="report[created_at][]"/>' ) } it { should be_html_safe } @@ -305,10 +301,10 @@ class MyTemplate let(:_range) { ["2013/01/01", "2013/02/02"] } it { should equal_to_dom( - '<input value="01/01/2013" class="from created_at date_filter" + '<input value="01/01/2013" class="from" multiple type="text" name="report[created_at][]"/>' \ '<span class="separator date"> - </span>' \ - '<input value="02/02/2013" class="to created_at date_filter" + '<input value="02/02/2013" class="to" multiple type="text" name="report[created_at][]"/>' ) } @@ -317,10 +313,10 @@ class MyTemplate let(:_range) { [nil, "2012-01-03"] } it { should equal_to_dom( - '<input class="from created_at date_filter" + '<input class="from" multiple type="text" name="report[created_at][]"/>' \ '<span class="separator date"> - </span>' \ - '<input value="2012-01-03" class="to created_at date_filter" + '<input value="2012-01-03" class="to" multiple type="text" name="report[created_at][]"/>' ) } @@ -331,10 +327,10 @@ class MyTemplate let(:_range) { Date.parse("2012-01-02")..Date.parse("2012-01-01") } it { should equal_to_dom( - '<input value="2012-01-01" class="from created_at date_filter" + '<input value="2012-01-01" class="from" multiple type="text" name="report[created_at][]"/>' \ '<span class="separator date"> - </span>' \ - '<input value="2012-01-02" class="to created_at date_filter" + '<input value="2012-01-02" class="to" multiple type="text" name="report[created_at][]"/>' ) } @@ -348,11 +344,9 @@ class MyTemplate let(:_range) { [nil, nil] } it { should equal_to_dom( - '<input class="from created_at date_filter" - multiple type="text" name="report[created_at][]"/>' \ + '<input class="from" multiple type="text" name="report[created_at][]"/>' \ '<span class="separator date"> - </span>' \ - '<input class="to created_at date_filter" - multiple type="text" name="report[created_at][]"/>' + '<input class="to" multiple type="text" name="report[created_at][]"/>' ) } end @@ -369,7 +363,7 @@ class MyTemplate end it { should equal_to_dom( - %(<select class="category enum_filter" name="report[category]" id="report_category"> + %(<select name="report[category]" id="report_category"> <option value="" label=" "></option> <option value="first">first</option> <option value="second">second</option></select>) @@ -384,7 +378,7 @@ class MyTemplate end it { should equal_to_dom( - %(<select class="category enum_filter" name="report[category]" id="report_category"> + %(<select name="report[category]" id="report_category"> <option value="" label=" "></option> <option value="block_value">block option</option></select>) ) @@ -396,7 +390,7 @@ class MyTemplate end it { should equal_to_dom( - %(<select class="category enum_filter" name="report[category]" id="report_category"> + %(<select name="report[category]" id="report_category"> <option value="" label=" "></option> <option selected value="first">first</option> <option value="second">second</option></select>) @@ -407,7 +401,7 @@ class MyTemplate let(:_category_filter_options) { { include_blank: false } } it { should equal_to_dom( - '<select class="category enum_filter" name="report[category]" id="report_category"> + '<select name="report[category]" id="report_category"> <option value="first">first</option> <option value="second">second</option></select>' ) @@ -417,7 +411,7 @@ class MyTemplate let(:_category_filter_options) { { include_blank: proc { "Choose plz" } } } it { should equal_to_dom( - '<select class="category enum_filter" name="report[category]" id="report_category"> + '<select name="report[category]" id="report_category"> <option value="">Choose plz</option> <option value="first">first</option> <option value="second">second</option></select>' @@ -429,7 +423,7 @@ class MyTemplate let(:_category_filter_options) { { prompt: "My Prompt" } } it { should equal_to_dom( - '<select class="category enum_filter" name="report[category]" id="report_category"> + '<select name="report[category]" id="report_category"> <option value="">My Prompt</option> <option value="first">first</option> <option value="second">second</option></select>' @@ -441,7 +435,7 @@ class MyTemplate let(:_category_filter_options) { { input_options: { class: "custom-class" } } } it { should equal_to_dom( - '<select class="custom-class category enum_filter" name="report[category]" id="report_category"> + '<select class="custom-class" name="report[category]" id="report_category"> <option value="" label=" "></option> <option value="first">first</option> <option value="second">second</option></select>' @@ -453,13 +447,13 @@ class MyTemplate it { should equal_to_dom( ' -<label class="category enum_filter checkboxes" for="report_category_first"> -<input class="category enum_filter checkboxes" type="checkbox" id="report_category_first" +<label for="report_category_first"> +<input type="checkbox" id="report_category_first" value="first" name="report[category][]" /> first </label> -<label class="category enum_filter checkboxes" for="report_category_second"> -<input class="category enum_filter checkboxes" type="checkbox" id="report_category_second" +<label for="report_category_second"> +<input type="checkbox" id="report_category_second" value="second" name="report[category][]" /> second </label> @@ -486,7 +480,7 @@ class MyTemplate should equal_to_dom( # hidden is important when default is set to true %(<input name="report[disabled]" type="hidden" value="0" autocomplete="off"> - <input class="disabled boolean_filter" type="checkbox" value="1" + <input type="checkbox" value="1" checked name="report[disabled]" id="report_disabled">) ) } @@ -501,7 +495,7 @@ class MyTemplate end it { should equal_to_dom( - %(<select class="disabled extended_boolean_filter" name="report[disabled]" id="report_disabled"> + %(<select name="report[disabled]" id="report_disabled"> <option value="" label=" "></option> <option value="YES">Yes</option> <option value="NO">No</option></select>) @@ -518,7 +512,7 @@ class MyTemplate let(:_filter) { :name } - it { should equal_to_dom('<input class="name string_filter" type="text" name="report[name]" id="report_name">') } + it { should equal_to_dom('<input type="text" name="report[name]" id="report_name">') } context "when multiple option is set" do let(:_grid) do @@ -532,7 +526,7 @@ class MyTemplate it { should equal_to_dom( - '<input value="one,two" class="name string_filter" type="text" name="report[name]" id="report_name">' + '<input value="one,two" type="text" name="report[name]" id="report_name">' ) } end @@ -551,7 +545,7 @@ class MyTemplate end end let(:_filter) { :name } - it { should equal_to_dom('<select class="name enum_filter" name="report[name]" id="report_name"></select>') } + it { should equal_to_dom('<select name="report[name]" id="report_name"></select>') } end context "with float filter type" do let(:_grid) do @@ -563,7 +557,7 @@ class MyTemplate let(:_filter) { :group_id } it { should equal_to_dom( - '<input class="group_id float_filter" type="text" name="report[group_id]" id="report_group_id"/>' + '<input type="text" name="report[group_id]" id="report_group_id"/>' ) } end @@ -578,7 +572,7 @@ class MyTemplate let(:_filter) { :group_id } let(:expected_html) do <<~HTML - <select multiple class="group_id enum_filter" name="report[group_id][]" id="report_group_id"> + <select multiple name="report[group_id][]" id="report_group_id"> <option value="hello">hello</option></select> HTML end @@ -601,7 +595,7 @@ class MyTemplate let(:_filter) { :column_names } let(:expected_html) do <<~HTML - <select multiple class="column_names enum_filter" name="report[column_names][]" id="report_column_names"><option selected value="id">Id</option> + <select multiple name="report[column_names][]" id="report_column_names"><option selected value="id">Id</option> <option selected value="name">Name</option> <option value="category">Category</option></select> HTML @@ -624,9 +618,18 @@ class MyTemplate let(:_filter) { :column_names } let(:expected_html) do <<~DOM - <label class="column_names enum_filter checkboxes" for="report_column_names_id"><input class="column_names enum_filter checkboxes" id="report_column_names_id" type="checkbox" value="id" checked name="report[column_names][]">Id</label> - <label class="column_names enum_filter checkboxes" for="report_column_names_name"><input class="column_names enum_filter checkboxes" id="report_column_names_name" type="checkbox" value="name" checked name="report[column_names][]">Name</label> - <label class="column_names enum_filter checkboxes" for="report_column_names_category"><input class="column_names enum_filter checkboxes" id="report_column_names_category" type="checkbox" value="category" name="report[column_names][]">Category</label> + <label for="report_column_names_id"> + <input id="report_column_names_id" type="checkbox" value="id" checked name="report[column_names][]"> + Id + </label> + <label for="report_column_names_name"> + <input id="report_column_names_name" type="checkbox" value="name" checked name="report[column_names][]"/> + Name + </label> + <label for="report_column_names_category"> + <input id="report_column_names_category" type="checkbox" value="category" name="report[column_names][]"> + Category + </label> DOM end @@ -651,7 +654,7 @@ class MyTemplate context "with no options" do let(:expected_html) do <<-HTML - <select class="condition dynamic_filter field" name="report[condition][]" id="report_condition"><option value="id">Id</option> + <select class="field" name="report[condition][]" id="report_condition"><option value="id">Id</option> <option value="group_id">Group</option> <option value="name">Name</option> <option value="category">Category</option> @@ -661,10 +664,10 @@ class MyTemplate <option value="confirmed">Confirmed</option> <option value="shipping_date">Shipping date</option> <option value="created_at">Created at</option> - <option value="updated_at">Updated at</option></select><select class="condition dynamic_filter operation" name="report[condition][]" id="report_condition"><option value="=">=</option> + <option value="updated_at">Updated at</option></select><select class="operation" name="report[condition][]" id="report_condition"><option value="=">=</option> <option value="=~">≈</option> <option value=">=">≥</option> - <option value="<=">≤</option></select><input class="condition dynamic_filter value" name="report[condition][]" type="text" id="report_condition"> + <option value="<=">≤</option></select><input class="value" name="report[condition][]" type="text" id="report_condition"> HTML end it { should equal_to_dom(expected_html) } @@ -675,11 +678,11 @@ class MyTemplate end let(:expected_html) do <<-HTML - <select class="condition dynamic_filter field" name="report[condition][]" id="report_condition"><option selected value="id">id</option> - <option value="name">name</option></select><select class="condition dynamic_filter operation" name="report[condition][]" id="report_condition"><option value="=">=</option> + <select class="field" name="report[condition][]" id="report_condition"><option selected value="id">id</option> + <option value="name">name</option></select><select class="operation" name="report[condition][]" id="report_condition"><option value="=">=</option> <option value="=~">≈</option> <option selected value=">=">≥</option> - <option value="<=">≤</option></select><input class="condition dynamic_filter value" name="report[condition][]" value="1" type="text" id="report_condition"> + <option value="<=">≤</option></select><input class="value" name="report[condition][]" value="1" type="text" id="report_condition"> HTML end it { should equal_to_dom(expected_html) } @@ -691,8 +694,8 @@ class MyTemplate end let(:expected_html) do <<-HTML - <select class="condition dynamic_filter field" name="report[condition][]" id="report_condition"><option value="id">id</option><option value="name">name</option></select><select class="condition dynamic_filter operation" name="report[condition][]" id="report_condition"><option value=">=">≥</option> - <option value="<=">≤</option></select><input class="condition dynamic_filter value" name="report[condition][]" type="text" id="report_condition"> + <select class="field" name="report[condition][]" id="report_condition"><option value="id">id</option><option value="name">name</option></select><select class="operation" name="report[condition][]" id="report_condition"><option value=">=">≥</option> + <option value="<=">≤</option></select><input class="value" name="report[condition][]" type="text" id="report_condition"> HTML end it { should equal_to_dom(expected_html) } @@ -704,8 +707,8 @@ class MyTemplate end let(:expected_html) do <<-HTML - <input class="condition dynamic_filter field" name="report[condition][]" value="id" autocomplete="off" type="hidden" id="report_condition"><select class="condition dynamic_filter operation" name="report[condition][]" id="report_condition"><option value=">=">≥</option> - <option value="<=">≤</option></select><input class="condition dynamic_filter value" name="report[condition][]" type="text" id="report_condition"> + <input class="field" name="report[condition][]" value="id" autocomplete="off" type="hidden" id="report_condition"><select class="operation" name="report[condition][]" id="report_condition"><option value=">=">≥</option> + <option value="<=">≤</option></select><input class="value" name="report[condition][]" type="text" id="report_condition"> HTML end it { should equal_to_dom(expected_html) } @@ -716,7 +719,7 @@ class MyTemplate end let(:expected_html) do <<-HTML - <select class="condition dynamic_filter field" name="report[condition][]" id="report_condition"><option value="id">id</option><option value="name">name</option></select><input class="condition dynamic_filter operation" name="report[condition][]" value="=" autocomplete="off" type="hidden" id="report_condition"><input class="condition dynamic_filter value" name="report[condition][]" type="text" id="report_condition"> + <select class="field" name="report[condition][]" id="report_condition"><option value="id">id</option><option value="name">name</option></select><input class="operation" name="report[condition][]" value="=" autocomplete="off" type="hidden" id="report_condition"><input class="value" name="report[condition][]" type="text" id="report_condition"> HTML end it { should equal_to_dom(expected_html) } @@ -734,27 +737,27 @@ class MyTemplate end it "should generate label for filter" do expect(view.datagrid_label(:created_at)).to equal_to_dom( - '<label class="js-date-selector created_at date_filter" for="report_created_at">Created at</label>' + '<label class="js-date-selector" for="report_created_at">Created at</label>' ) end it "should generate label for filter" do expect(view.datagrid_label(:name)).to equal_to_dom( - '<label class="name string_filter" for="report_name">Name</label>' + '<label for="report_name">Name</label>' ) end it "should pass options through to the helper" do expect(view.datagrid_label(:name, class: "foo")).to equal_to_dom( - '<label class="foo name string_filter" for="report_name">Name</label>' + '<label class="foo" for="report_name">Name</label>' ) end it "should support block" do expect(view.datagrid_label(:name, class: "foo") { "The Name" }).to equal_to_dom( - '<label class="foo name string_filter" for="report_name">The Name</label>' + '<label class="foo" for="report_name">The Name</label>' ) end it "should support explicit label" do expect(view.datagrid_label(:name, "The Name")).to equal_to_dom( - '<label class="name string_filter" for="report_name">The Name</label>' + '<label for="report_name">The Name</label>' ) end end diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 04fd4bf..55617c5 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -484,7 +484,7 @@ class FormForGrid "form.datagrid-form.form_for_grid[action='/grid']" => 1, "form input[name=utf8]" => 1, "form .datagrid-filter label" => "Category", - "form .datagrid-filter input.category.default_filter[name='form_for_grid[category]'][value=hello]" => 1, + "form .datagrid-filter-category input[name='form_for_grid[category]'][value=hello]" => 1, "form input[name=commit][value=Search]" => 1, "form a.datagrid-reset[href='/location']" => 1 ) @@ -533,12 +533,6 @@ def param_name partials: "custom_form" }) expect(rendered_form).to include "form_partial_test" - expect(rendered_form).to match_css_pattern([ - "input.integer_filter.from", - "input.integer_filter.to", - ".enum_filter input[value='1']", - ".enum_filter input[value='2']" - ]) end end From 948efc57eacd01450c451d0330aa06427201f84d Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 4 Nov 2024 11:32:13 +0100 Subject: [PATCH 017/157] Add datagrid-range- prefix for from/to css classes --- lib/datagrid/form_builder.rb | 2 +- spec/datagrid/form_builder_spec.rb | 44 +++++++++++++++--------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index b45262f..7746068 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -180,7 +180,7 @@ def datagrid_range_filter(_type, filter, options = {}) def datagrid_range_filter_options(object, filter, type, options) type_method_map = { from: :first, to: :last } - options = add_html_classes(options, type) + options = add_html_classes(options, "datagrid-range-#{type}") options[:value] = filter.format(object[filter.name]&.public_send(type_method_map[type])) # In case of datagrid ranged filter # from and to input will have same id diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index fb2d5d4..2f4df49 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -186,10 +186,10 @@ class MyTemplate let(:_range) { [1, 2] } it { should equal_to_dom( - '<input value="1" id="from_hello" class="from" + '<input value="1" id="from_hello" class="datagrid-range-from" multiple type="text" name="report[group_id][]"/>' \ '<span class="separator integer"> - </span>' \ - '<input value="2" id="to_hello" class="to" + '<input value="2" id="to_hello" class="datagrid-range-to" multiple type="text" name="report[group_id][]"/>' ) } @@ -198,10 +198,10 @@ class MyTemplate let(:_range) { [10, nil] } it { should equal_to_dom( - '<input value="10" class="from" + '<input value="10" class="datagrid-range-from" multiple type="text" name="report[group_id][]"/>' \ '<span class="separator integer"> - </span>' \ - '<input class="to" + '<input class="datagrid-range-to" multiple type="text" name="report[group_id][]"/>' ) } @@ -211,9 +211,9 @@ class MyTemplate let(:_range) { [nil, 10] } it { should equal_to_dom( - '<input class="from" multiple type="text" name="report[group_id][]"/>' \ + '<input class="datagrid-range-from" multiple type="text" name="report[group_id][]"/>' \ '<span class="separator integer"> - </span>' \ - '<input value="10" class="to" multiple type="text" name="report[group_id][]"/>' + '<input value="10" class="datagrid-range-to" multiple type="text" name="report[group_id][]"/>' ) } it { should be_html_safe } @@ -223,9 +223,9 @@ class MyTemplate let(:_range) { 2..1 } it { should equal_to_dom( - '<input value="1" class="from" multiple type="text" name="report[group_id][]"/>' \ + '<input value="1" class="datagrid-range-from" multiple type="text" name="report[group_id][]"/>' \ '<span class="separator integer"> - </span>' \ - '<input value="2" class="to" multiple type="text" name="report[group_id][]"/>' + '<input value="2" class="datagrid-range-to" multiple type="text" name="report[group_id][]"/>' ) } end @@ -245,9 +245,9 @@ class MyTemplate let(:_range) { nil } it { should equal_to_dom( - '<input class="from" multiple type="text" name="report[group_id][]"> + '<input class="datagrid-range-from" multiple type="text" name="report[group_id][]"> <span class="separator integer"> - </span> - <input class="to" multiple type="text" name="report[group_id][]">' + <input class="datagrid-range-to" multiple type="text" name="report[group_id][]">' ) } end @@ -264,10 +264,10 @@ class MyTemplate let(:_range) { [1.5, 2.5] } it { should equal_to_dom( - '<input value="1.5" class="from" + '<input value="1.5" class="datagrid-range-from" multiple type="text" name="report[rating][]"/>' \ '<span class="separator float"> - </span>' \ - '<input value="2.5" class="to" + '<input value="2.5" class="datagrid-range-to" multiple type="text" name="report[rating][]"/>' ) } @@ -285,9 +285,9 @@ class MyTemplate let(:_range) { ["2012-01-03", nil] } it { should equal_to_dom( - '<input value="2012-01-03" class="from" multiple type="text" name="report[created_at][]"/>' \ + '<input value="2012-01-03" class="datagrid-range-from" multiple type="text" name="report[created_at][]"/>' \ '<span class="separator date"> - </span>' \ - '<input class="to" multiple type="text" name="report[created_at][]"/>' + '<input class="datagrid-range-to" multiple type="text" name="report[created_at][]"/>' ) } it { should be_html_safe } @@ -301,10 +301,10 @@ class MyTemplate let(:_range) { ["2013/01/01", "2013/02/02"] } it { should equal_to_dom( - '<input value="01/01/2013" class="from" + '<input value="01/01/2013" class="datagrid-range-from" multiple type="text" name="report[created_at][]"/>' \ '<span class="separator date"> - </span>' \ - '<input value="02/02/2013" class="to" + '<input value="02/02/2013" class="datagrid-range-to" multiple type="text" name="report[created_at][]"/>' ) } @@ -313,10 +313,10 @@ class MyTemplate let(:_range) { [nil, "2012-01-03"] } it { should equal_to_dom( - '<input class="from" + '<input class="datagrid-range-from" multiple type="text" name="report[created_at][]"/>' \ '<span class="separator date"> - </span>' \ - '<input value="2012-01-03" class="to" + '<input value="2012-01-03" class="datagrid-range-to" multiple type="text" name="report[created_at][]"/>' ) } @@ -327,10 +327,10 @@ class MyTemplate let(:_range) { Date.parse("2012-01-02")..Date.parse("2012-01-01") } it { should equal_to_dom( - '<input value="2012-01-01" class="from" + '<input value="2012-01-01" class="datagrid-range-from" multiple type="text" name="report[created_at][]"/>' \ '<span class="separator date"> - </span>' \ - '<input value="2012-01-02" class="to" + '<input value="2012-01-02" class="datagrid-range-to" multiple type="text" name="report[created_at][]"/>' ) } @@ -344,9 +344,9 @@ class MyTemplate let(:_range) { [nil, nil] } it { should equal_to_dom( - '<input class="from" multiple type="text" name="report[created_at][]"/>' \ + '<input class="datagrid-range-from" multiple type="text" name="report[created_at][]"/>' \ '<span class="separator date"> - </span>' \ - '<input class="to" multiple type="text" name="report[created_at][]"/>' + '<input class="datagrid-range-to" multiple type="text" name="report[created_at][]"/>' ) } end From 36bf694a16106bee064c706eb85a13d62bbf504b Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 4 Nov 2024 11:34:51 +0100 Subject: [PATCH 018/157] Add datagrid-dynamic- prefix for field/operation/value css classes --- lib/datagrid/form_builder.rb | 6 +++--- spec/datagrid/form_builder_spec.rb | 22 +++++++++++----------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 7746068..617d492 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -137,7 +137,7 @@ def datagrid_dynamic_filter(filter, options = {}) include_hidden: false, selected: field }, - add_html_classes(options, "field") + add_html_classes(options, "datagrid-dynamic-field") ) operation_input = dynamic_filter_select( filter.name, filter.operations_select, @@ -147,9 +147,9 @@ def datagrid_dynamic_filter(filter, options = {}) prompt: false, selected: operation }, - add_html_classes(options, "operation") + add_html_classes(options, "datagrid-dynamic-operation") ) - value_input = text_field(filter.name, **add_html_classes(options, "value"), value: value) + value_input = text_field(filter.name, **add_html_classes(options, "datagrid-dynamic-value"), value: value) [field_input, operation_input, value_input].join("\n").html_safe end diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 2f4df49..755b78e 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -654,7 +654,7 @@ class MyTemplate context "with no options" do let(:expected_html) do <<-HTML - <select class="field" name="report[condition][]" id="report_condition"><option value="id">Id</option> + <select class="datagrid-dynamic-field" name="report[condition][]" id="report_condition"><option value="id">Id</option> <option value="group_id">Group</option> <option value="name">Name</option> <option value="category">Category</option> @@ -664,10 +664,10 @@ class MyTemplate <option value="confirmed">Confirmed</option> <option value="shipping_date">Shipping date</option> <option value="created_at">Created at</option> - <option value="updated_at">Updated at</option></select><select class="operation" name="report[condition][]" id="report_condition"><option value="=">=</option> + <option value="updated_at">Updated at</option></select><select class="datagrid-dynamic-operation" name="report[condition][]" id="report_condition"><option value="=">=</option> <option value="=~">≈</option> <option value=">=">≥</option> - <option value="<=">≤</option></select><input class="value" name="report[condition][]" type="text" id="report_condition"> + <option value="<=">≤</option></select><input class="datagrid-dynamic-value" name="report[condition][]" type="text" id="report_condition"> HTML end it { should equal_to_dom(expected_html) } @@ -678,11 +678,11 @@ class MyTemplate end let(:expected_html) do <<-HTML - <select class="field" name="report[condition][]" id="report_condition"><option selected value="id">id</option> - <option value="name">name</option></select><select class="operation" name="report[condition][]" id="report_condition"><option value="=">=</option> + <select class="datagrid-dynamic-field" name="report[condition][]" id="report_condition"><option selected value="id">id</option> + <option value="name">name</option></select><select class="datagrid-dynamic-operation" name="report[condition][]" id="report_condition"><option value="=">=</option> <option value="=~">≈</option> <option selected value=">=">≥</option> - <option value="<=">≤</option></select><input class="value" name="report[condition][]" value="1" type="text" id="report_condition"> + <option value="<=">≤</option></select><input class="datagrid-dynamic-value" name="report[condition][]" value="1" type="text" id="report_condition"> HTML end it { should equal_to_dom(expected_html) } @@ -694,8 +694,8 @@ class MyTemplate end let(:expected_html) do <<-HTML - <select class="field" name="report[condition][]" id="report_condition"><option value="id">id</option><option value="name">name</option></select><select class="operation" name="report[condition][]" id="report_condition"><option value=">=">≥</option> - <option value="<=">≤</option></select><input class="value" name="report[condition][]" type="text" id="report_condition"> + <select class="datagrid-dynamic-field" name="report[condition][]" id="report_condition"><option value="id">id</option><option value="name">name</option></select><select class="datagrid-dynamic-operation" name="report[condition][]" id="report_condition"><option value=">=">≥</option> + <option value="<=">≤</option></select><input class="datagrid-dynamic-value" name="report[condition][]" type="text" id="report_condition"> HTML end it { should equal_to_dom(expected_html) } @@ -707,8 +707,8 @@ class MyTemplate end let(:expected_html) do <<-HTML - <input class="field" name="report[condition][]" value="id" autocomplete="off" type="hidden" id="report_condition"><select class="operation" name="report[condition][]" id="report_condition"><option value=">=">≥</option> - <option value="<=">≤</option></select><input class="value" name="report[condition][]" type="text" id="report_condition"> + <input class="datagrid-dynamic-field" name="report[condition][]" value="id" autocomplete="off" type="hidden" id="report_condition"><select class="datagrid-dynamic-operation" name="report[condition][]" id="report_condition"><option value=">=">≥</option> + <option value="<=">≤</option></select><input class="datagrid-dynamic-value" name="report[condition][]" type="text" id="report_condition"> HTML end it { should equal_to_dom(expected_html) } @@ -719,7 +719,7 @@ class MyTemplate end let(:expected_html) do <<-HTML - <select class="field" name="report[condition][]" id="report_condition"><option value="id">id</option><option value="name">name</option></select><input class="operation" name="report[condition][]" value="=" autocomplete="off" type="hidden" id="report_condition"><input class="value" name="report[condition][]" type="text" id="report_condition"> + <select class="datagrid-dynamic-field" name="report[condition][]" id="report_condition"><option value="id">id</option><option value="name">name</option></select><input class="datagrid-dynamic-operation" name="report[condition][]" value="=" autocomplete="off" type="hidden" id="report_condition"><input class="datagrid-dynamic-value" name="report[condition][]" type="text" id="report_condition"> HTML end it { should equal_to_dom(expected_html) } From a8d4cf6746a2d10f9ac6b436f5fba934c8769d53 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 4 Nov 2024 11:41:46 +0100 Subject: [PATCH 019/157] Update CSS --- app/assets/stylesheets/datagrid.sass | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/app/assets/stylesheets/datagrid.sass b/app/assets/stylesheets/datagrid.sass index 63fa4d6..f38e93c 100644 --- a/app/assets/stylesheets/datagrid.sass +++ b/app/assets/stylesheets/datagrid.sass @@ -65,14 +65,14 @@ table.datagrid a float: left - input[class*='filter'] + input border: 2px solid #ccc border-radius: 4px float: left padding: 5px 12px width: 207px - &.from, &.to + &.datagrid-range-from, &.datagrid-range-to width: 83px select @@ -83,26 +83,26 @@ table.datagrid border: 2px solid #ccc border-radius: 5px height: 100px - &.dynamic_filter - &.field - width: 178px - &.operation - margin-left: 7px - width: 50px - input.dynamic_filter.value + .datagrid-dynamic-field + width: 178px + .datagrid-dynamic-operation + margin-left: 7px + width: 50px + .datagrid-dynamic-value margin: 10px 0 0 $dg-form-label clear: both .separator float: left margin: 6px 4px 0 - .enum_filter.checkboxes - float: none - display: block - width: 100% + &.datagrid-checkboxes + label + float: none + display: block + width: 100% + margin-left: 150px input margin: 7px - margin-left: 150px .datagrid-actions From dc926b67bdba5b8e066b9b1298098f21b1030164 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 4 Nov 2024 11:44:10 +0100 Subject: [PATCH 020/157] Rename separator to datagrid-range-separator --- app/assets/stylesheets/datagrid.sass | 2 +- app/views/datagrid/_range_filter.html.erb | 2 +- spec/datagrid/form_builder_spec.rb | 22 +++++++++++----------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/app/assets/stylesheets/datagrid.sass b/app/assets/stylesheets/datagrid.sass index f38e93c..915ceaf 100644 --- a/app/assets/stylesheets/datagrid.sass +++ b/app/assets/stylesheets/datagrid.sass @@ -92,7 +92,7 @@ table.datagrid margin: 10px 0 0 $dg-form-label clear: both - .separator + .datagrid-range-separator float: left margin: 6px 4px 0 &.datagrid-checkboxes diff --git a/app/views/datagrid/_range_filter.html.erb b/app/views/datagrid/_range_filter.html.erb index 7a8a123..1b90dc8 100644 --- a/app/views/datagrid/_range_filter.html.erb +++ b/app/views/datagrid/_range_filter.html.erb @@ -1,3 +1,3 @@ <%= form.datagrid_filter_input(filter, **from_options) %> -<span class="separator <%= filter.type %>"><%= I18n.t('datagrid.filters.range.separator') %></span> +<span class="datagrid-range-separator"><%= I18n.t('datagrid.filters.range.separator') %></span> <%= form.datagrid_filter_input(filter, **to_options) %> diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 755b78e..b619e3b 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -188,7 +188,7 @@ class MyTemplate should equal_to_dom( '<input value="1" id="from_hello" class="datagrid-range-from" multiple type="text" name="report[group_id][]"/>' \ - '<span class="separator integer"> - </span>' \ + '<span class="datagrid-range-separator"> - </span>' \ '<input value="2" id="to_hello" class="datagrid-range-to" multiple type="text" name="report[group_id][]"/>' ) @@ -200,7 +200,7 @@ class MyTemplate should equal_to_dom( '<input value="10" class="datagrid-range-from" multiple type="text" name="report[group_id][]"/>' \ - '<span class="separator integer"> - </span>' \ + '<span class="datagrid-range-separator"> - </span>' \ '<input class="datagrid-range-to" multiple type="text" name="report[group_id][]"/>' ) @@ -212,7 +212,7 @@ class MyTemplate it { should equal_to_dom( '<input class="datagrid-range-from" multiple type="text" name="report[group_id][]"/>' \ - '<span class="separator integer"> - </span>' \ + '<span class="datagrid-range-separator"> - </span>' \ '<input value="10" class="datagrid-range-to" multiple type="text" name="report[group_id][]"/>' ) } @@ -224,7 +224,7 @@ class MyTemplate it { should equal_to_dom( '<input value="1" class="datagrid-range-from" multiple type="text" name="report[group_id][]"/>' \ - '<span class="separator integer"> - </span>' \ + '<span class="datagrid-range-separator"> - </span>' \ '<input value="2" class="datagrid-range-to" multiple type="text" name="report[group_id][]"/>' ) } @@ -246,7 +246,7 @@ class MyTemplate it { should equal_to_dom( '<input class="datagrid-range-from" multiple type="text" name="report[group_id][]"> - <span class="separator integer"> - </span> + <span class="datagrid-range-separator"> - </span> <input class="datagrid-range-to" multiple type="text" name="report[group_id][]">' ) } @@ -266,7 +266,7 @@ class MyTemplate should equal_to_dom( '<input value="1.5" class="datagrid-range-from" multiple type="text" name="report[rating][]"/>' \ - '<span class="separator float"> - </span>' \ + '<span class="datagrid-range-separator"> - </span>' \ '<input value="2.5" class="datagrid-range-to" multiple type="text" name="report[rating][]"/>' ) @@ -286,7 +286,7 @@ class MyTemplate it { should equal_to_dom( '<input value="2012-01-03" class="datagrid-range-from" multiple type="text" name="report[created_at][]"/>' \ - '<span class="separator date"> - </span>' \ + '<span class="datagrid-range-separator"> - </span>' \ '<input class="datagrid-range-to" multiple type="text" name="report[created_at][]"/>' ) } @@ -303,7 +303,7 @@ class MyTemplate should equal_to_dom( '<input value="01/01/2013" class="datagrid-range-from" multiple type="text" name="report[created_at][]"/>' \ - '<span class="separator date"> - </span>' \ + '<span class="datagrid-range-separator"> - </span>' \ '<input value="02/02/2013" class="datagrid-range-to" multiple type="text" name="report[created_at][]"/>' ) @@ -315,7 +315,7 @@ class MyTemplate should equal_to_dom( '<input class="datagrid-range-from" multiple type="text" name="report[created_at][]"/>' \ - '<span class="separator date"> - </span>' \ + '<span class="datagrid-range-separator"> - </span>' \ '<input value="2012-01-03" class="datagrid-range-to" multiple type="text" name="report[created_at][]"/>' ) @@ -329,7 +329,7 @@ class MyTemplate should equal_to_dom( '<input value="2012-01-01" class="datagrid-range-from" multiple type="text" name="report[created_at][]"/>' \ - '<span class="separator date"> - </span>' \ + '<span class="datagrid-range-separator"> - </span>' \ '<input value="2012-01-02" class="datagrid-range-to" multiple type="text" name="report[created_at][]"/>' ) @@ -345,7 +345,7 @@ class MyTemplate it { should equal_to_dom( '<input class="datagrid-range-from" multiple type="text" name="report[created_at][]"/>' \ - '<span class="separator date"> - </span>' \ + '<span class="datagrid-range-separator"> - </span>' \ '<input class="datagrid-range-to" multiple type="text" name="report[created_at][]"/>' ) } From 350b6da11ae11210ced65223ab28863d2a90d62b Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 4 Nov 2024 12:02:10 +0100 Subject: [PATCH 021/157] Rename datagrid_table autogenerated CSS classes to match modern CSS modular frameworks --- app/assets/stylesheets/datagrid.sass | 18 +++---- app/views/datagrid/_order_for.html.erb | 6 +-- lib/datagrid/helper.rb | 2 +- lib/datagrid/renderer.rb | 2 +- spec/datagrid/helper_spec.rb | 70 +++++++++++++------------- 5 files changed, 46 insertions(+), 52 deletions(-) diff --git a/app/assets/stylesheets/datagrid.sass b/app/assets/stylesheets/datagrid.sass index 915ceaf..71e5b75 100644 --- a/app/assets/stylesheets/datagrid.sass +++ b/app/assets/stylesheets/datagrid.sass @@ -16,7 +16,7 @@ $dg-form-label: 150px zoom: 1 *display: inline -table.datagrid +table.datagrid-table background-color: transparent border-collapse: collapse max-width: 100% @@ -30,23 +30,17 @@ table.datagrid border: 1px solid #d6d6d6 padding: 5px 10px - .order + .datagrid-order a.asc, a.desc text-decoration: none font-weight: normal - &.ordered + .datagrid-order-active-asc, .datagrid-order-active-desc background-color: #fff7d5 - &.asc - a.asc - font-weight: bold - color: #d00 - - &.desc - a.desc - font-weight: bold - color: #d00 + a.datagird-order-control-asc, a.datagird-order-control-desc + font-weight: bold + color: #d00 .noresults text-align: center diff --git a/app/views/datagrid/_order_for.html.erb b/app/views/datagrid/_order_for.html.erb index 1545a8e..9960e00 100644 --- a/app/views/datagrid/_order_for.html.erb +++ b/app/views/datagrid/_order_for.html.erb @@ -1,10 +1,10 @@ -<div class="order"> +<div class="datagrid-order"> <%= link_to( I18n.t("datagrid.table.order.asc").html_safe, datagrid_order_path(grid, column, false), - class: "asc") %> + class: "datagrid-order-control-asc") %> <%= link_to( I18n.t("datagrid.table.order.desc").html_safe, datagrid_order_path(grid, column, true), - class: "desc") %> + class: "datagrid-order-control-desc") %> </div> diff --git a/lib/datagrid/helper.rb b/lib/datagrid/helper.rb index 925af9d..4f4361a 100644 --- a/lib/datagrid/helper.rb +++ b/lib/datagrid/helper.rb @@ -151,7 +151,7 @@ def datagrid_renderer def datagrid_column_classes(grid, column) order_class = if grid.ordered_by?(column) - ["ordered", grid.descending ? "desc" : "asc"] + [grid.descending ? "datagrid-order-active-desc" : "datagrid-order-active-asc"] end [column.name, order_class, column.options[:class]].compact.join(" ") end diff --git a/lib/datagrid/renderer.rb b/lib/datagrid/renderer.rb index d485241..1be59b9 100644 --- a/lib/datagrid/renderer.rb +++ b/lib/datagrid/renderer.rb @@ -36,7 +36,7 @@ def form_for(grid, options = {}) def table(grid, assets, **options) options[:html] ||= {} - options[:html][:class] ||= "datagrid #{@template.dom_class(grid)}" + options[:html][:class] ||= "datagrid-table #{@template.dom_class(grid)}" _render_partial("table", options[:partials], { diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 55617c5..bef7a42 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -42,7 +42,7 @@ datagrid_table = subject.datagrid_table(grid) expect(datagrid_table).to match_css_pattern( - "table.datagrid tr td.noresults" => 1 + "table.datagrid-table tr td.noresults" => 1 ) expect(datagrid_table).to include(I18n.t("datagrid.no_results")) end @@ -51,7 +51,7 @@ describe ".datagrid_table" do it "should have grid class as html class on table" do expect(subject.datagrid_table(grid)).to match_css_pattern( - "table.datagrid.simple_report" => 1 + "table.datagrid-table.simple_report" => 1 ) end it "should have namespaced grid class as html class on table" do @@ -63,19 +63,19 @@ class TestGrid end end expect(subject.datagrid_table(Ns23::TestGrid.new)).to match_css_pattern( - "table.datagrid.ns23_test_grid" => 1 + "table.datagrid-table.ns23_test_grid" => 1 ) end it "should return data table html" do datagrid_table = subject.datagrid_table(grid) expect(datagrid_table).to match_css_pattern({ - "table.datagrid tr th.group div.order" => 1, - "table.datagrid tr th.group" => /Group.*/, - "table.datagrid tr th.name div.order" => 1, - "table.datagrid tr th.name" => /Name.*/, - "table.datagrid tr td.group" => "Pop", - "table.datagrid tr td.name" => "Star" + "table.datagrid-table tr th.group div.datagrid-order" => 1, + "table.datagrid-table tr th.group" => /Group.*/, + "table.datagrid-table tr th.name div.datagrid-order" => 1, + "table.datagrid-table tr th.name" => /Name.*/, + "table.datagrid-table tr td.group" => "Pop", + "table.datagrid-table tr td.name" => "Star" }) end @@ -84,25 +84,25 @@ class TestGrid datagrid_table = subject.datagrid_table(grid, [entry]) expect(datagrid_table).to match_css_pattern({ - "table.datagrid tr th.group div.order" => 1, - "table.datagrid tr th.group" => /Group.*/, - "table.datagrid tr th.name div.order" => 1, - "table.datagrid tr th.name" => /Name.*/, - "table.datagrid tr td.group" => "Pop", - "table.datagrid tr td.name" => "Star" + "table.datagrid-table tr th.group div.datagrid-order" => 1, + "table.datagrid-table tr th.group" => /Group.*/, + "table.datagrid-table tr th.name div.datagrid-order" => 1, + "table.datagrid-table tr th.name" => /Name.*/, + "table.datagrid-table tr td.group" => "Pop", + "table.datagrid-table tr td.name" => "Star" }) end it "should support no order given" do - expect(subject.datagrid_table(grid, [entry], order: false)).to match_css_pattern("table.datagrid th .order" => 0) + expect(subject.datagrid_table(grid, [entry], order: false)).to match_css_pattern("table.datagrid-table th .datagrid-order" => 0) end it "should support columns option" do expect(subject.datagrid_table(grid, [entry], columns: [:name])).to match_css_pattern( - "table.datagrid th.name" => 1, - "table.datagrid td.name" => 1, - "table.datagrid th.group" => 0, - "table.datagrid td.group" => 0 + "table.datagrid-table th.name" => 1, + "table.datagrid-table td.name" => 1, + "table.datagrid-table th.group" => 0, + "table.datagrid-table td.group" => 0 ) end @@ -117,10 +117,10 @@ class TestGrid it "should output only given column names" do expect(subject.datagrid_table(grid, [entry])).to match_css_pattern( - "table.datagrid th.name" => 1, - "table.datagrid td.name" => 1, - "table.datagrid th.category" => 0, - "table.datagrid td.category" => 0 + "table.datagrid-table th.name" => 1, + "table.datagrid-table td.name" => 1, + "table.datagrid-table th.category" => 0, + "table.datagrid-table td.category" => 0 ) end end @@ -168,8 +168,8 @@ class TestGrid end it "should render table" do expect(subject.datagrid_table(grid)).to match_css_pattern( - "table.datagrid th.name" => 1, - "table.datagrid td.name" => 2 + "table.datagrid-table th.name" => 1, + "table.datagrid-table td.name" => 2 ) end end @@ -184,8 +184,8 @@ class TestGrid end it "should render table" do expect(subject.datagrid_table(grid)).to match_css_pattern( - "table.datagrid th.name" => 1, - "table.datagrid td.name" => 2 + "table.datagrid-table th.name" => 1, + "table.datagrid-table td.name" => 2 ) end end @@ -218,7 +218,7 @@ class TestGrid column(:name) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td.name.ordered.asc" => "Star" + "tr td.name.datagrid-order-active-asc" => "Star" ) end it "should add ordering classes to column" do @@ -241,7 +241,7 @@ class TestGrid column(:name) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td.name.ordered.desc" => "Star" + "tr td.name.datagrid-order-active-desc" => "Star" ) end @@ -458,9 +458,9 @@ class OrderedGrid end object = OrderedGrid.new(descending: true, order: :category) expect(subject.datagrid_order_for(object, object.column_by_name(:category))).to equal_to_dom(<<~HTML) - <div class="order"> - <a class="asc" href="/location?ordered_grid%5Bdescending%5D=false&ordered_grid%5Border%5D=category">↑</a> - <a class="desc" href="/location?ordered_grid%5Bdescending%5D=true&ordered_grid%5Border%5D=category">↓</a> + <div class="datagrid-order"> + <a class="datagrid-order-control-asc" href="/location?ordered_grid%5Bdescending%5D=false&ordered_grid%5Border%5D=category">↑</a> + <a class="datagrid-order-control-desc" href="/location?ordered_grid%5Bdescending%5D=true&ordered_grid%5Border%5D=category">↓</a> </div> HTML end @@ -665,8 +665,8 @@ def param_name end end expect(subject.datagrid_header(grid)).to equal_to_dom(<<~HTML) - <tr><th class="category ordered asc">Category<div class="order"> - <a class="asc" href="/location?grid%5Bdescending%5D=false&grid%5Border%5D=category">↑</a><a class="desc" href="/location?grid%5Bdescending%5D=true&grid%5Border%5D=category">↓</a> + <tr><th class="category datagrid-order-active-asc">Category<div class="datagrid-order"> + <a class="datagrid-order-control-asc" href="/location?grid%5Bdescending%5D=false&grid%5Border%5D=category">↑</a><a class="datagrid-order-control-desc" href="/location?grid%5Bdescending%5D=true&grid%5Border%5D=category">↓</a> </div> </th></tr> HTML From 589daaa31170da1d64269615561b664b07ebea42 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 4 Nov 2024 12:03:14 +0100 Subject: [PATCH 022/157] Rename .noresults .datagrid-noresults --- app/assets/stylesheets/datagrid.sass | 2 +- app/views/datagrid/_table.html.erb | 2 +- spec/datagrid/helper_spec.rb | 2 +- spec/support/test_partials/client/datagrid/_table.html.erb | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/datagrid.sass b/app/assets/stylesheets/datagrid.sass index 71e5b75..5f44b13 100644 --- a/app/assets/stylesheets/datagrid.sass +++ b/app/assets/stylesheets/datagrid.sass @@ -41,7 +41,7 @@ table.datagrid-table a.datagird-order-control-asc, a.datagird-order-control-desc font-weight: bold color: #d00 - .noresults + .datagrid-noresults text-align: center .datagrid-form diff --git a/app/views/datagrid/_table.html.erb b/app/views/datagrid/_table.html.erb index 8708c05..0031506 100644 --- a/app/views/datagrid/_table.html.erb +++ b/app/views/datagrid/_table.html.erb @@ -13,7 +13,7 @@ Local variables: <% if assets.any? %> <%= datagrid_rows(grid, assets, **options) %> <% else %> - <tr><td class="noresults" colspan="100%"><%= I18n.t('datagrid.no_results').html_safe %></td></tr> + <tr><td class="datagrid-noresults" colspan="100%"><%= I18n.t('datagrid.no_results').html_safe %></td></tr> <% end %> </tbody> <% end %> diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index bef7a42..dc7cb09 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -42,7 +42,7 @@ datagrid_table = subject.datagrid_table(grid) expect(datagrid_table).to match_css_pattern( - "table.datagrid-table tr td.noresults" => 1 + "table.datagrid-table tr td.datagrid-noresults" => 1 ) expect(datagrid_table).to include(I18n.t("datagrid.no_results")) end diff --git a/spec/support/test_partials/client/datagrid/_table.html.erb b/spec/support/test_partials/client/datagrid/_table.html.erb index 986ce52..22c46db 100644 --- a/spec/support/test_partials/client/datagrid/_table.html.erb +++ b/spec/support/test_partials/client/datagrid/_table.html.erb @@ -11,7 +11,7 @@ Local variables: </thead> <tbody> <% if assets.empty? %> - <tr><td class="noresults" colspan="100%"><%= I18n.t('datagrid.no_results').html_safe %></td></tr> + <tr><td class="datagrid-noresults" colspan="100%"><%= I18n.t('datagrid.no_results').html_safe %></td></tr> <% else %> <%= datagrid_rows(grid, assets, **options) %> <% end %> From 544c734593bc77730d023d0708ef75801875f7f1 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 4 Nov 2024 12:05:45 +0100 Subject: [PATCH 023/157] Cleanup css --- app/assets/stylesheets/datagrid.sass | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/app/assets/stylesheets/datagrid.sass b/app/assets/stylesheets/datagrid.sass index 5f44b13..6119b6f 100644 --- a/app/assets/stylesheets/datagrid.sass +++ b/app/assets/stylesheets/datagrid.sass @@ -30,19 +30,20 @@ table.datagrid-table border: 1px solid #d6d6d6 padding: 5px 10px - .datagrid-order - a.asc, a.desc - text-decoration: none - font-weight: normal - - .datagrid-order-active-asc, .datagrid-order-active-desc - background-color: #fff7d5 - - a.datagird-order-control-asc, a.datagird-order-control-desc - font-weight: bold - color: #d00 - .datagrid-noresults - text-align: center +.datagrid-order + a.asc, a.desc + text-decoration: none + font-weight: normal + +.datagrid-order-active-asc, .datagrid-order-active-desc + background-color: #fff7d5 + + a.datagird-order-control-asc, a.datagird-order-control-desc + font-weight: bold + color: #d00 + +.datagrid-noresults + text-align: center .datagrid-form background-color: #f0f0f0 From 6aa94896d91e2896645e8bb444a24a768f7974d1 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 4 Nov 2024 13:52:19 +0100 Subject: [PATCH 024/157] Use html5 input types by default --- lib/datagrid/filters/base_filter.rb | 3 +- lib/datagrid/filters/boolean_filter.rb | 4 +- lib/datagrid/filters/date_filter.rb | 2 + lib/datagrid/filters/date_time_filter.rb | 2 + lib/datagrid/filters/dynamic_filter.rb | 2 + lib/datagrid/filters/enum_filter.rb | 2 + .../filters/extended_boolean_filter.rb | 2 + lib/datagrid/filters/float_filter.rb | 2 + lib/datagrid/filters/integer_filter.rb | 2 + lib/datagrid/form_builder.rb | 21 +++-- spec/datagrid/form_builder_spec.rb | 79 +++++++++---------- 11 files changed, 72 insertions(+), 49 deletions(-) diff --git a/lib/datagrid/filters/base_filter.rb b/lib/datagrid/filters/base_filter.rb index eee49eb..57e5e09 100644 --- a/lib/datagrid/filters/base_filter.rb +++ b/lib/datagrid/filters/base_filter.rb @@ -11,7 +11,8 @@ class FilteringError < StandardError module Datagrid module Filters class BaseFilter - class_attribute :input_helper_name, instance_writer: false + class_attribute :default_input_options, instance_writer: false, default: {type: 'text'} + attr_accessor :grid_class, :options, :block, :name def initialize(grid_class, name, options = {}, &block) diff --git a/lib/datagrid/filters/boolean_filter.rb b/lib/datagrid/filters/boolean_filter.rb index 4248b7b..d54eea3 100644 --- a/lib/datagrid/filters/boolean_filter.rb +++ b/lib/datagrid/filters/boolean_filter.rb @@ -1,10 +1,12 @@ # frozen_string_literal: true require "datagrid/utils" -# @!visibility private + module Datagrid module Filters class BooleanFilter < Datagrid::Filters::BaseFilter + self.default_input_options = {type: 'checkbox' } + def parse(value) Datagrid::Utils.booleanize(value) end diff --git a/lib/datagrid/filters/date_filter.rb b/lib/datagrid/filters/date_filter.rb index 2a7d29d..3fe5428 100644 --- a/lib/datagrid/filters/date_filter.rb +++ b/lib/datagrid/filters/date_filter.rb @@ -7,6 +7,8 @@ module Filters class DateFilter < Datagrid::Filters::BaseFilter include Datagrid::Filters::RangedFilter + self.default_input_options = { type: 'date' } + def apply(grid_object, scope, value) value = value.begin&.beginning_of_day..value.end&.end_of_day if value.is_a?(Range) super diff --git a/lib/datagrid/filters/date_time_filter.rb b/lib/datagrid/filters/date_time_filter.rb index 0014eb1..37effa0 100644 --- a/lib/datagrid/filters/date_time_filter.rb +++ b/lib/datagrid/filters/date_time_filter.rb @@ -7,6 +7,8 @@ module Filters class DateTimeFilter < Datagrid::Filters::BaseFilter include Datagrid::Filters::RangedFilter + self.default_input_options = {type: 'datetime-local' } + def parse(value) Datagrid::Utils.parse_datetime(value) end diff --git a/lib/datagrid/filters/dynamic_filter.rb b/lib/datagrid/filters/dynamic_filter.rb index 636512c..c4e4e06 100644 --- a/lib/datagrid/filters/dynamic_filter.rb +++ b/lib/datagrid/filters/dynamic_filter.rb @@ -19,6 +19,8 @@ class DynamicFilter < Datagrid::Filters::BaseFilter ].freeze AVAILABLE_OPERATIONS = %w[= =~ >= <=].freeze + self.default_input_options = {} + def initialize(*) super options[:select] ||= default_select diff --git a/lib/datagrid/filters/enum_filter.rb b/lib/datagrid/filters/enum_filter.rb index 687fb1b..841a0ba 100644 --- a/lib/datagrid/filters/enum_filter.rb +++ b/lib/datagrid/filters/enum_filter.rb @@ -7,6 +7,8 @@ module Filters class EnumFilter < Datagrid::Filters::BaseFilter include Datagrid::Filters::SelectOptions + self.default_input_options = {type: 'select' } + def initialize(*args) super options[:multiple] = true if checkboxes? diff --git a/lib/datagrid/filters/extended_boolean_filter.rb b/lib/datagrid/filters/extended_boolean_filter.rb index 5cf418a..e2bbc6b 100644 --- a/lib/datagrid/filters/extended_boolean_filter.rb +++ b/lib/datagrid/filters/extended_boolean_filter.rb @@ -9,6 +9,8 @@ class ExtendedBooleanFilter < Datagrid::Filters::EnumFilter TRUTH_VALUES = [true, "true", "y", "yes"].freeze FALSE_VALUES = [false, "false", "n", "no"].freeze + self.default_input_options = {type: 'select' } + def initialize(report, attribute, options = {}, &block) options[:select] = -> { boolean_select } super diff --git a/lib/datagrid/filters/float_filter.rb b/lib/datagrid/filters/float_filter.rb index 6cc4aa9..0257746 100644 --- a/lib/datagrid/filters/float_filter.rb +++ b/lib/datagrid/filters/float_filter.rb @@ -6,6 +6,8 @@ module Filters class FloatFilter < Datagrid::Filters::BaseFilter include Datagrid::Filters::RangedFilter + self.default_input_options = {type: 'number', step: 'any' } + def parse(value) return nil if value.blank? diff --git a/lib/datagrid/filters/integer_filter.rb b/lib/datagrid/filters/integer_filter.rb index 6395b0b..fd64bb2 100644 --- a/lib/datagrid/filters/integer_filter.rb +++ b/lib/datagrid/filters/integer_filter.rb @@ -7,6 +7,8 @@ module Filters class IntegerFilter < Datagrid::Filters::BaseFilter include Datagrid::Filters::RangedFilter + self.default_input_options = {type: 'number', step: '1' } + def parse(value) return nil if value.blank? if defined?(ActiveRecord) && value.is_a?(ActiveRecord::Base) && diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 617d492..20a484f 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -30,9 +30,15 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) filter = datagrid_get_filter(attribute_or_filter) options = add_filter_options(filter, **options) type = options.delete(:type)&.to_sym - if options.key?(:value) && options[:value].nil? && %i[datetime-local date].include?(type) - # https://github.com/rails/rails/pull/53387 - options[:value] = "" + if %i[datetime-local date].include?(type) + if options.key?(:value) && options[:value].nil? && + # https://github.com/rails/rails/pull/53387 + options[:value] = "" + end + else + if options[:value] + options[:value] = filter.format(options[:value]) + end end case type when :"datetime-local" @@ -42,10 +48,11 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) when :textarea text_area filter.name, value: object.filter_value_as_string(filter), **options, &block when :checkbox - # raise options.inspect check_box filter.name, options, options.fetch(:value, 1) when :hidden hidden_field filter.name, **options + when :number + number_field filter.name, **options when :select select( filter.name, @@ -149,7 +156,7 @@ def datagrid_dynamic_filter(filter, options = {}) }, add_html_classes(options, "datagrid-dynamic-operation") ) - value_input = text_field(filter.name, **add_html_classes(options, "datagrid-dynamic-value"), value: value) + value_input = datagrid_filter_input(filter.name, **add_html_classes(options, "datagrid-dynamic-value"), value: value) [field_input, operation_input, value_input].join("\n").html_safe end @@ -181,7 +188,7 @@ def datagrid_range_filter(_type, filter, options = {}) def datagrid_range_filter_options(object, filter, type, options) type_method_map = { from: :first, to: :last } options = add_html_classes(options, "datagrid-range-#{type}") - options[:value] = filter.format(object[filter.name]&.public_send(type_method_map[type])) + options[:value] = object[filter.name]&.public_send(type_method_map[type]) # In case of datagrid ranged filter # from and to input will have same id if !options.key?(:id) @@ -229,7 +236,7 @@ def render_partial(name, locals) end def add_filter_options(filter, **options) - { **filter.input_options, **options } + { **filter.default_input_options, **filter.input_options, **options } end class Error < StandardError diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index b619e3b..81255d8 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -56,7 +56,7 @@ class MyTemplate end it { should equal_to_dom( - '<input type="text" name="report[group_id]" id="report_group_id"/>' + '<input type="number" step="1" name="report[group_id]" id="report_group_id"/>' ) } @@ -64,7 +64,7 @@ class MyTemplate let(:view_options) { { partials: "anything" } } it { should equal_to_dom( - '<input type="text" name="report[group_id]" id="report_group_id"/>' + '<input type="number" step="1" name="report[group_id]" id="report_group_id"/>' ) } end @@ -80,7 +80,7 @@ class MyTemplate end it { should equal_to_dom( - '<input type="text" name="report[created_at]" id="report_created_at"/>' + '<input type="date" name="report[created_at]" id="report_created_at"/>' ) } context "when special date format specified" do @@ -92,28 +92,28 @@ class MyTemplate end it { should equal_to_dom( - '<input value="01/02/2012" type="text" + '<input value="2012-01-02" type="date" name="report[created_at]" id="report_created_at"/>' ) } end end context "with input_options" do - context "type is date" do + context "date filter type is text" do let(:_filter) { :created_at } let(:_grid) do test_report do scope { Entry } - filter(:created_at, :date, input_options: { type: :date }) + filter(:created_at, :date, input_options: { type: 'text' }) end end it { should equal_to_dom( - '<input type="date" name="report[created_at]" id="report_created_at"/>' + '<input type="text" name="report[created_at]" id="report_created_at"/>' ) } end - context "type is textarea" do + context "string filter type is textarea" do let(:_filter) { :name } let(:_grid) do test_report do @@ -128,18 +128,18 @@ class MyTemplate } end - context "type is datetime-local" do + context "datetime filter type is text" do let(:_filter) { :created_at } let(:_grid) do test_report(created_at: Time.new(2024, 1, 1, 9, 25, 15)) do scope { Entry } - filter(:created_at, :datetime, input_options: { type: "datetime-local" }) + filter(:created_at, :datetime, input_options: { type: "text" }) end end it { should equal_to_dom( - '<input type="datetime-local" - value="2024-01-01T09:25:15" name="report[created_at]" id="report_created_at"/>' + '<input type="text" value="2024-01-01 09:25:15 +0100" + name="report[created_at]" id="report_created_at"/>' ) } @@ -149,14 +149,13 @@ class MyTemplate end it { should equal_to_dom( - '<input type="datetime-local" value="" - name="report[created_at]" id="report_created_at"/>' + '<input type="text" name="report[created_at]" id="report_created_at"/>' ) } end end - context "type is date" do + context "datetime filter type is date" do let(:_filter) { :created_at } let(:_grid) do test_report(created_at: Date.new(2024, 1, 1)) do @@ -187,10 +186,10 @@ class MyTemplate it { should equal_to_dom( '<input value="1" id="from_hello" class="datagrid-range-from" - multiple type="text" name="report[group_id][]"/>' \ + multiple type="number" step="1" name="report[group_id][]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2" id="to_hello" class="datagrid-range-to" - multiple type="text" name="report[group_id][]"/>' + multiple type="number" step="1" name="report[group_id][]"/>' ) } end @@ -199,10 +198,10 @@ class MyTemplate it { should equal_to_dom( '<input value="10" class="datagrid-range-from" - multiple type="text" name="report[group_id][]"/>' \ + multiple type="number" step="1" name="report[group_id][]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input class="datagrid-range-to" - multiple type="text" name="report[group_id][]"/>' + multiple type="number" step="1" name="report[group_id][]"/>' ) } it { should be_html_safe } @@ -211,9 +210,9 @@ class MyTemplate let(:_range) { [nil, 10] } it { should equal_to_dom( - '<input class="datagrid-range-from" multiple type="text" name="report[group_id][]"/>' \ + '<input class="datagrid-range-from" multiple type="number" step="1" name="report[group_id][]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ - '<input value="10" class="datagrid-range-to" multiple type="text" name="report[group_id][]"/>' + '<input value="10" class="datagrid-range-to" multiple type="number" step="1" name="report[group_id][]"/>' ) } it { should be_html_safe } @@ -223,9 +222,9 @@ class MyTemplate let(:_range) { 2..1 } it { should equal_to_dom( - '<input value="1" class="datagrid-range-from" multiple type="text" name="report[group_id][]"/>' \ + '<input value="1" class="datagrid-range-from" multiple type="number" step="1" name="report[group_id][]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ - '<input value="2" class="datagrid-range-to" multiple type="text" name="report[group_id][]"/>' + '<input value="2" class="datagrid-range-to" multiple type="number" step="1" name="report[group_id][]"/>' ) } end @@ -245,9 +244,9 @@ class MyTemplate let(:_range) { nil } it { should equal_to_dom( - '<input class="datagrid-range-from" multiple type="text" name="report[group_id][]"> + '<input class="datagrid-range-from" multiple type="number" step="1" name="report[group_id][]"> <span class="datagrid-range-separator"> - </span> - <input class="datagrid-range-to" multiple type="text" name="report[group_id][]">' + <input class="datagrid-range-to" multiple type="number" step="1" name="report[group_id][]">' ) } end @@ -265,10 +264,10 @@ class MyTemplate it { should equal_to_dom( '<input value="1.5" class="datagrid-range-from" - multiple type="text" name="report[rating][]"/>' \ + multiple type="number" step="any" name="report[rating][]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2.5" class="datagrid-range-to" - multiple type="text" name="report[rating][]"/>' + multiple type="number" step="any" name="report[rating][]"/>' ) } end @@ -285,9 +284,9 @@ class MyTemplate let(:_range) { ["2012-01-03", nil] } it { should equal_to_dom( - '<input value="2012-01-03" class="datagrid-range-from" multiple type="text" name="report[created_at][]"/>' \ + '<input value="2012-01-03" class="datagrid-range-from" multiple type="date" name="report[created_at][]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ - '<input class="datagrid-range-to" multiple type="text" name="report[created_at][]"/>' + '<input class="datagrid-range-to" multiple type="date" name="report[created_at][]" value=""/>' ) } it { should be_html_safe } @@ -301,11 +300,11 @@ class MyTemplate let(:_range) { ["2013/01/01", "2013/02/02"] } it { should equal_to_dom( - '<input value="01/01/2013" class="datagrid-range-from" - multiple type="text" name="report[created_at][]"/>' \ + '<input value="2013-01-01" class="datagrid-range-from" + multiple type="date" name="report[created_at][]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ - '<input value="02/02/2013" class="datagrid-range-to" - multiple type="text" name="report[created_at][]"/>' + '<input value="2013-02-02" class="datagrid-range-to" + multiple type="date" name="report[created_at][]"/>' ) } end @@ -314,10 +313,10 @@ class MyTemplate it { should equal_to_dom( '<input class="datagrid-range-from" - multiple type="text" name="report[created_at][]"/>' \ + multiple type="date" value="" name="report[created_at][]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2012-01-03" class="datagrid-range-to" - multiple type="text" name="report[created_at][]"/>' + multiple type="date" name="report[created_at][]"/>' ) } it { should be_html_safe } @@ -328,10 +327,10 @@ class MyTemplate it { should equal_to_dom( '<input value="2012-01-01" class="datagrid-range-from" - multiple type="text" name="report[created_at][]"/>' \ + multiple type="date" name="report[created_at][]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2012-01-02" class="datagrid-range-to" - multiple type="text" name="report[created_at][]"/>' + multiple type="date" name="report[created_at][]"/>' ) } end @@ -344,9 +343,9 @@ class MyTemplate let(:_range) { [nil, nil] } it { should equal_to_dom( - '<input class="datagrid-range-from" multiple type="text" name="report[created_at][]"/>' \ + '<input class="datagrid-range-from" multiple type="date" value="" name="report[created_at][]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ - '<input class="datagrid-range-to" multiple type="text" name="report[created_at][]"/>' + '<input class="datagrid-range-to" multiple type="date" value="" name="report[created_at][]"/>' ) } end @@ -557,7 +556,7 @@ class MyTemplate let(:_filter) { :group_id } it { should equal_to_dom( - '<input type="text" name="report[group_id]" id="report_group_id"/>' + '<input type="number" step="any" name="report[group_id]" id="report_group_id"/>' ) } end From e486c6b31706a8a53f0333bc397e39c2d45ac42c Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 4 Nov 2024 14:11:35 +0100 Subject: [PATCH 025/157] Rename several css classes --- app/assets/stylesheets/datagrid.sass | 6 +++--- app/views/datagrid/_table.html.erb | 2 +- lib/datagrid/filters/enum_filter.rb | 2 +- spec/datagrid/form_builder_spec.rb | 6 ------ spec/datagrid/helper_spec.rb | 2 +- spec/support/test_partials/client/datagrid/_table.html.erb | 2 +- 6 files changed, 7 insertions(+), 13 deletions(-) diff --git a/app/assets/stylesheets/datagrid.sass b/app/assets/stylesheets/datagrid.sass index 6119b6f..0f25722 100644 --- a/app/assets/stylesheets/datagrid.sass +++ b/app/assets/stylesheets/datagrid.sass @@ -31,7 +31,7 @@ table.datagrid-table padding: 5px 10px .datagrid-order - a.asc, a.desc + a.datagird-order-control-asc, a.datagird-order-control-desc text-decoration: none font-weight: normal @@ -42,7 +42,7 @@ table.datagrid-table font-weight: bold color: #d00 -.datagrid-noresults +.datagrid-no-results text-align: center .datagrid-form @@ -90,7 +90,7 @@ table.datagrid-table .datagrid-range-separator float: left margin: 6px 4px 0 - &.datagrid-checkboxes + &.datagrid-enum-checkboxes label float: none display: block diff --git a/app/views/datagrid/_table.html.erb b/app/views/datagrid/_table.html.erb index 0031506..e590d2c 100644 --- a/app/views/datagrid/_table.html.erb +++ b/app/views/datagrid/_table.html.erb @@ -13,7 +13,7 @@ Local variables: <% if assets.any? %> <%= datagrid_rows(grid, assets, **options) %> <% else %> - <tr><td class="datagrid-noresults" colspan="100%"><%= I18n.t('datagrid.no_results').html_safe %></td></tr> + <tr><td class="datagrid-no-results" colspan="100%"><%= I18n.t('datagrid.no_results').html_safe %></td></tr> <% end %> </tbody> <% end %> diff --git a/lib/datagrid/filters/enum_filter.rb b/lib/datagrid/filters/enum_filter.rb index 841a0ba..75817e0 100644 --- a/lib/datagrid/filters/enum_filter.rb +++ b/lib/datagrid/filters/enum_filter.rb @@ -23,7 +23,7 @@ def parse(value) def default_html_classes res = super - res.push("datagrid-checkboxes") if checkboxes? + res.push("datagrid-enum-checkboxes") if checkboxes? res end diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 81255d8..1162c05 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -20,12 +20,6 @@ class MyTemplate let(:view_options) { {} } describe ".datagrid_filter" do - it "should work for every filter type" do - Datagrid::Filters::FILTER_TYPES.each_value do |klass| - expect(Datagrid::FormBuilder.instance_methods.map(&:to_sym)).to include(klass.form_builder_helper_name) - end - end - subject do view.datagrid_filter(_filter, **_filter_options, &_filter_block) end diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index dc7cb09..31b956f 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -42,7 +42,7 @@ datagrid_table = subject.datagrid_table(grid) expect(datagrid_table).to match_css_pattern( - "table.datagrid-table tr td.datagrid-noresults" => 1 + "table.datagrid-table tr td.datagrid-no-results" => 1 ) expect(datagrid_table).to include(I18n.t("datagrid.no_results")) end diff --git a/spec/support/test_partials/client/datagrid/_table.html.erb b/spec/support/test_partials/client/datagrid/_table.html.erb index 22c46db..84ff466 100644 --- a/spec/support/test_partials/client/datagrid/_table.html.erb +++ b/spec/support/test_partials/client/datagrid/_table.html.erb @@ -11,7 +11,7 @@ Local variables: </thead> <tbody> <% if assets.empty? %> - <tr><td class="datagrid-noresults" colspan="100%"><%= I18n.t('datagrid.no_results').html_safe %></td></tr> + <tr><td class="datagrid-no-results" colspan="100%"><%= I18n.t('datagrid.no_results').html_safe %></td></tr> <% else %> <%= datagrid_rows(grid, assets, **options) %> <% end %> From 5ebe3e043d8a49a665696c507aa1961b2a4940c8 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 4 Nov 2024 15:45:14 +0100 Subject: [PATCH 026/157] Migration document prototype --- VERSION2.md | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 VERSION2.md diff --git a/VERSION2.md b/VERSION2.md new file mode 100644 index 0000000..fa0ac45 --- /dev/null +++ b/VERSION2.md @@ -0,0 +1,115 @@ +# Datagrid Version 2 + +Datagrid v1 was released Sep 19 2013 - more than 10 years ago. +A lot of new things had happened during this period and it is time. +It caused the library to be designed without support of those technologies +and implementing some of them would cause a breaking change. +And now it is time to indroduce them with Version 2. + +List of things introduces: + +1. Ruby infinite ranges for range filters. +1. Modern modular CSS classes. +1. HTML5 input types: number, date, datetime-local. +1. HTML5 input [names collision restriction](https://html.spec.whatwg.org/multipage/input.html#input-type-attr-summary) + +## Ruby Infinite Ranges + +## Modern CSS classes + +Built-in generated CSS classes renamed to match modern CSS naming conventions +and avoid collisions with other libraries: + +| Old Name | New Name | +|--------------|-------------------------------------| +| filter | datagrid-filter | +| from | datagrid-input-from | +| to | datagrid-input-to | +| noresults | datagrid-no-results | +| datagrid | datagrid-table | +| order | datagrid-order | +| a.asc | datagrid-order-control-asc | +| a.desc | datagrid-order-control-desc | +| ordered.asc | datagrid-order-active-asc | +| ordered.desc | datagrid-order-active-desc | +| field | datagrid-dynamic-field | +| operation | datagrid-dynamic-operation | +| value | datagrid-dynamic-value | +| separator | datgrid-range-separator | +| checkboxes | datagrid-enum-checkboxes | + +A few automatically generated classes were moved from `<input/>` to `<div class="datagrid-filter">` +to make sure they are editable through datagrid partials. + +### Example + +The difference in layout generation from v1 to v2 + +``` ruby +datagrid_form_for(@grid) +``` + +Version 1 layout: + +``` html +<form class="datagrid-form partial_default_grid" id="new_g" + action="/users" accept-charset="UTF-8" method="get"> + <input name="utf8" type="hidden" value="✓" autocomplete="off" /> + + <div class="datagrid-filter filter"> + <label for="g_id">Id</label> + <input class="id integer_filter from" multiple type="text" name="g[id][]" /> + <span class="separator integer"> - </span> + <input class="id integer_filter to" multiple type="text" name="g[id][]" /> + </div> + + <div class="datagrid-filter filter"> + <label for="g_group_id">Group</label> + <label class="group_id enum_filter checkboxes" for="g_group_id_1"> + <input id="g_group_id_1" type="checkbox" value="1" name="g[group_id][]" />1 + </label> + <label class="group_id enum_filter checkboxes" for="g_group_id_2"> + <input id="g_group_id_2" type="checkbox" value="2" name="g[group_id][]" />2 + </label> + </div> + + <div class="datagrid-actions"> + <input type="submit" name="commit" value="Search" + class="datagrid-submit" data-disable-with="Search" /> + <a class="datagrid-reset" href="/location">Reset</a> + </div> +</form> +``` + +Version 2 layout: + +TODO + +``` html +``` + +## HTML5 input types + +Version 1 generated `<input type="text"/>` for every filter type. +Version 2 uses the appropriate input type for each filter type: + +| Type | HTML Input Element | +|------------|--------------------------------------------| +| string | `<input type="text"/>` | +| boolean | `<input type="checkbox"/>` | +| date | `<input type="date"/>` | +| datetime | `<input type="datetime-local"/>` | +| enum | `<select>` | +| xboolean | `<select>` | +| float | `<input type="number" step="any"/>` | +| integer | `<input type="number" step="1"/>` | + +The default behavior can be changed back by using `input_options`: + +``` ruby +filter(:created_at, :date, range: true, input_options: {type: 'text'}) +filter(:created_at, :datetime, range: true, input_options: {type: 'text'}) +filter(:text, :string, input_options: {type: 'textarea'}) +``` + +## Names collision restriction From 76e3aa3658494adec4099d84e4981d6dd02bcd8c Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 4 Nov 2024 15:48:59 +0100 Subject: [PATCH 027/157] Remove automatically generated css classes from grid class --- lib/datagrid/renderer.rb | 4 ++-- spec/datagrid/helper_spec.rb | 18 +++--------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/lib/datagrid/renderer.rb b/lib/datagrid/renderer.rb index 1be59b9..f7c062d 100644 --- a/lib/datagrid/renderer.rb +++ b/lib/datagrid/renderer.rb @@ -29,14 +29,14 @@ def format_value(grid, column, asset) def form_for(grid, options = {}) options[:method] ||= :get options[:html] ||= {} - options[:html][:class] ||= "datagrid-form #{@template.dom_class(grid)}" + options[:html][:class] ||= "datagrid-form" options[:as] ||= grid.param_name _render_partial("form", options[:partials], { grid: grid, options: options }) end def table(grid, assets, **options) options[:html] ||= {} - options[:html][:class] ||= "datagrid-table #{@template.dom_class(grid)}" + options[:html][:class] ||= "datagrid-table" _render_partial("table", options[:partials], { diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 31b956f..fdb1431 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -51,19 +51,7 @@ describe ".datagrid_table" do it "should have grid class as html class on table" do expect(subject.datagrid_table(grid)).to match_css_pattern( - "table.datagrid-table.simple_report" => 1 - ) - end - it "should have namespaced grid class as html class on table" do - module ::Ns23 - class TestGrid - include Datagrid - scope { Entry } - column(:id) - end - end - expect(subject.datagrid_table(Ns23::TestGrid.new)).to match_css_pattern( - "table.datagrid-table.ns23_test_grid" => 1 + "table.datagrid-table" => 1 ) end it "should return data table html" do @@ -481,7 +469,7 @@ class FormForGrid end object = FormForGrid.new(category: "hello") expect(subject.datagrid_form_for(object, url: "/grid")).to match_css_pattern( - "form.datagrid-form.form_for_grid[action='/grid']" => 1, + "form.datagrid-form[action='/grid']" => 1, "form input[name=utf8]" => 1, "form .datagrid-filter label" => "Category", "form .datagrid-filter-category input[name='form_for_grid[category]'][value=hello]" => 1, @@ -498,7 +486,7 @@ class TestGrid end end expect(subject.datagrid_form_for(Ns22::TestGrid.new, url: "grid")).to match_css_pattern( - "form.datagrid-form.ns22_test_grid" => 1, + "form.datagrid-form" => 1, "form.datagrid-form label[for=ns22_test_grid_id]" => 1, "form.datagrid-form input#ns22_test_grid_id[name='ns22_test_grid[id]']" => 1 ) From 527f8d6f2bb82cdacd9a482c552d0655dff2284a Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 4 Nov 2024 16:07:40 +0100 Subject: [PATCH 028/157] Make datagrid-table datagrid-form classes explicitly set in views --- app/views/datagrid/_form.html.erb | 2 +- app/views/datagrid/_table.html.erb | 2 +- lib/datagrid/renderer.rb | 5 ----- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/app/views/datagrid/_form.html.erb b/app/views/datagrid/_form.html.erb index 06f0414..9648325 100644 --- a/app/views/datagrid/_form.html.erb +++ b/app/views/datagrid/_form.html.erb @@ -1,4 +1,4 @@ -<%= form_for grid, **options do |f| -%> +<%= form_for grid, html: {class: 'datagrid-form'}, **options do |f| -%> <% grid.filters.each do |filter| %> <div class="datagrid-filter <%= filter.default_html_classes.join(' ') %>"> <%= f.datagrid_label filter %> diff --git a/app/views/datagrid/_table.html.erb b/app/views/datagrid/_table.html.erb index e590d2c..dff7bef 100644 --- a/app/views/datagrid/_table.html.erb +++ b/app/views/datagrid/_table.html.erb @@ -5,7 +5,7 @@ Local variables: * options - passed options Hash %> <% if grid.html_columns(*options[:columns]).any? %> - <%= content_tag :table, options[:html] do %> + <%= content_tag :table, class: 'datagrid-table', **options.fetch(:html, {}) do %> <thead> <%= datagrid_header(grid, options) %> </thead> diff --git a/lib/datagrid/renderer.rb b/lib/datagrid/renderer.rb index f7c062d..23efd30 100644 --- a/lib/datagrid/renderer.rb +++ b/lib/datagrid/renderer.rb @@ -28,16 +28,11 @@ def format_value(grid, column, asset) def form_for(grid, options = {}) options[:method] ||= :get - options[:html] ||= {} - options[:html][:class] ||= "datagrid-form" options[:as] ||= grid.param_name _render_partial("form", options[:partials], { grid: grid, options: options }) end def table(grid, assets, **options) - options[:html] ||= {} - options[:html][:class] ||= "datagrid-table" - _render_partial("table", options[:partials], { grid: grid, From 874122c40c327340307b913209f6e72179dacea0 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 4 Nov 2024 19:52:20 +0100 Subject: [PATCH 029/157] Remove unnecessary html_safe calls --- app/views/datagrid/_form.html.erb | 4 ++-- app/views/datagrid/_order_for.html.erb | 4 ++-- app/views/datagrid/_table.html.erb | 4 ++-- lib/datagrid/filters/dynamic_filter.rb | 2 +- lib/datagrid/renderer.rb | 24 ++++++++++-------------- 5 files changed, 17 insertions(+), 21 deletions(-) diff --git a/app/views/datagrid/_form.html.erb b/app/views/datagrid/_form.html.erb index 9648325..84cf58e 100644 --- a/app/views/datagrid/_form.html.erb +++ b/app/views/datagrid/_form.html.erb @@ -6,7 +6,7 @@ </div> <% end %> <div class="datagrid-actions"> - <%= f.submit I18n.t("datagrid.form.search").html_safe, class: "datagrid-submit" %> - <%= link_to I18n.t('datagrid.form.reset').html_safe, url_for(grid.to_param => {}), class: "datagrid-reset" %> + <%= f.submit I18n.t("datagrid.form.search"), class: "datagrid-submit" %> + <%= link_to I18n.t('datagrid.form.reset'), url_for(grid.to_param => {}), class: "datagrid-reset" %> </div> <% end -%> diff --git a/app/views/datagrid/_order_for.html.erb b/app/views/datagrid/_order_for.html.erb index 9960e00..1c33c37 100644 --- a/app/views/datagrid/_order_for.html.erb +++ b/app/views/datagrid/_order_for.html.erb @@ -1,10 +1,10 @@ <div class="datagrid-order"> <%= link_to( - I18n.t("datagrid.table.order.asc").html_safe, + I18n.t("datagrid.table.order.asc"), datagrid_order_path(grid, column, false), class: "datagrid-order-control-asc") %> <%= link_to( - I18n.t("datagrid.table.order.desc").html_safe, + I18n.t("datagrid.table.order.desc"), datagrid_order_path(grid, column, true), class: "datagrid-order-control-desc") %> </div> diff --git a/app/views/datagrid/_table.html.erb b/app/views/datagrid/_table.html.erb index dff7bef..0b5ff24 100644 --- a/app/views/datagrid/_table.html.erb +++ b/app/views/datagrid/_table.html.erb @@ -13,10 +13,10 @@ Local variables: <% if assets.any? %> <%= datagrid_rows(grid, assets, **options) %> <% else %> - <tr><td class="datagrid-no-results" colspan="100%"><%= I18n.t('datagrid.no_results').html_safe %></td></tr> + <tr><td class="datagrid-no-results" colspan="100%"><%= I18n.t('datagrid.no_results') %></td></tr> <% end %> </tbody> <% end %> <% else -%> - <%= I18n.t("datagrid.table.no_columns").html_safe %> + <%= I18n.t("datagrid.table.no_columns") %> <% end %> diff --git a/lib/datagrid/filters/dynamic_filter.rb b/lib/datagrid/filters/dynamic_filter.rb index c4e4e06..5e08b95 100644 --- a/lib/datagrid/filters/dynamic_filter.rb +++ b/lib/datagrid/filters/dynamic_filter.rb @@ -81,7 +81,7 @@ def operations def operations_select operations.map do |operation| - [I18n.t(operation, scope: "datagrid.filters.dynamic.operations").html_safe, operation] + [I18n.t(operation, scope: "datagrid.filters.dynamic.operations"), operation] end end diff --git a/lib/datagrid/renderer.rb b/lib/datagrid/renderer.rb index 23efd30..30149ed 100644 --- a/lib/datagrid/renderer.rb +++ b/lib/datagrid/renderer.rb @@ -49,11 +49,11 @@ def header(grid, options = {}) end def rows(grid, assets = grid.assets, **options, &block) - result = assets.map do |asset| - row(grid, asset, **options, &block) - end.to_a.join - - _safe(result) + @template.safe_join( + assets.map do |asset| + row(grid, asset, **options, &block) + end.to_a + ) end def row(grid, asset, **options, &block) @@ -69,24 +69,20 @@ def order_for(grid, column, options = {}) def order_path(grid, column, descending, request) column = grid.column_by_name(column) - query = request ? request.query_parameters : {} + query = request&.query_parameters || {} ActionDispatch::Http::URL.path_for( - path: request ? request.path : "/", + path: request&.path || "/", params: query.merge(grid.query_params(order: column.name, descending: descending)) ) end private - def _safe(string) - string.respond_to?(:html_safe) ? string.html_safe : string - end - def _render_partial(partial_name, partials_path, locals = {}) @template.render({ - partial: File.join(partials_path || "datagrid", partial_name), - locals: locals - }) + partial: File.join(partials_path || "datagrid", partial_name), + locals: locals + }) end end From c9ec12446fbf72777f80e584a5cccb7fe1612729 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 4 Nov 2024 20:25:32 +0100 Subject: [PATCH 030/157] Fully removed column url option --- lib/datagrid/renderer.rb | 9 +-------- spec/datagrid/helper_spec.rb | 24 ++---------------------- 2 files changed, 3 insertions(+), 30 deletions(-) diff --git a/lib/datagrid/renderer.rb b/lib/datagrid/renderer.rb index 30149ed..8c62935 100644 --- a/lib/datagrid/renderer.rb +++ b/lib/datagrid/renderer.rb @@ -16,14 +16,7 @@ def initialize(template) def format_value(grid, column, asset) column = grid.column_by_name(column) if column.is_a?(String) || column.is_a?(Symbol) - value = grid.html_value(column, @template, asset) - - url = column.options[:url]&.call(asset) - if url - @template.link_to(value, url) - else - value - end + grid.html_value(column, @template, asset) end def form_for(grid, options = {}) diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index fdb1431..c8bb509 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -180,26 +180,6 @@ end describe ".datagrid_rows" do - it "should support urls" do - rp = test_report do - scope { Entry } - column(:name, url: lambda(&:name)) - end - expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td.name a[href=Star]" => "Star" - ) - end - - it "should support conditional urls" do - rp = test_report do - scope { Entry } - column(:name, url: ->(_model) { false }) - end - expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td.name" => "Star" - ) - end - it "should add ordering classes to column" do rp = test_report(order: :name) do scope { Entry } @@ -447,8 +427,8 @@ class OrderedGrid object = OrderedGrid.new(descending: true, order: :category) expect(subject.datagrid_order_for(object, object.column_by_name(:category))).to equal_to_dom(<<~HTML) <div class="datagrid-order"> - <a class="datagrid-order-control-asc" href="/location?ordered_grid%5Bdescending%5D=false&ordered_grid%5Border%5D=category">↑</a> - <a class="datagrid-order-control-desc" href="/location?ordered_grid%5Bdescending%5D=true&ordered_grid%5Border%5D=category">↓</a> + <a class="datagrid-order-control-asc" href="/location?ordered_grid%5Bdescending%5D=false&ordered_grid%5Border%5D=category">↑</a> + <a class="datagrid-order-control-desc" href="/location?ordered_grid%5Bdescending%5D=true&ordered_grid%5Border%5D=category">↓</a> </div> HTML end From 0c6b9cafbddbd0877fb62de1fca43000c3ad6ac1 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 4 Nov 2024 20:27:33 +0100 Subject: [PATCH 031/157] Remove composite filters completely --- lib/datagrid/filters.rb | 2 - lib/datagrid/filters/composite_filters.rb | 47 ------------ .../filters/composite_filters_spec.rb | 76 ------------------- 3 files changed, 125 deletions(-) delete mode 100644 lib/datagrid/filters/composite_filters.rb delete mode 100644 spec/datagrid/filters/composite_filters_spec.rb diff --git a/lib/datagrid/filters.rb b/lib/datagrid/filters.rb index 67f387b..69257a1 100644 --- a/lib/datagrid/filters.rb +++ b/lib/datagrid/filters.rb @@ -12,7 +12,6 @@ module Filters require "datagrid/filters/date_time_filter" require "datagrid/filters/default_filter" require "datagrid/filters/integer_filter" - require "datagrid/filters/composite_filters" require "datagrid/filters/string_filter" require "datagrid/filters/float_filter" require "datagrid/filters/dynamic_filter" @@ -39,7 +38,6 @@ def self.included(base) base.extend ClassMethods base.class_eval do include Datagrid::Core - include Datagrid::Filters::CompositeFilters class_attribute :filters_array, default: [] end end diff --git a/lib/datagrid/filters/composite_filters.rb b/lib/datagrid/filters/composite_filters.rb deleted file mode 100644 index 53cac78..0000000 --- a/lib/datagrid/filters/composite_filters.rb +++ /dev/null @@ -1,47 +0,0 @@ -# frozen_string_literal: true - -module Datagrid - module Filters - # @!visibility private - module CompositeFilters - def self.included(base) - base.extend ClassMethods - end - - # @!visibility private - module ClassMethods - def date_range_filters(field, from_options = {}, to_options = {}) - Utils.warn_once("date_range_filters is deprecated in favor of range option for date filter") - from_options = normalize_composite_filter_options(from_options, field) - to_options = normalize_composite_filter_options(to_options, field) - - filter(from_options[:name] || :"from_#{field.to_s.tr('.', '_')}", :date, - **from_options) do |date, scope, grid| - grid.driver.greater_equal(scope, field, date) - end - filter(to_options[:name] || :"to_#{field.to_s.tr('.', '_')}", :date, **to_options) do |date, scope, grid| - grid.driver.less_equal(scope, field, date) - end - end - - def integer_range_filters(field, from_options = {}, to_options = {}) - Utils.warn_once("integer_range_filters is deprecated in favor of range option for integer filter") - from_options = normalize_composite_filter_options(from_options, field) - to_options = normalize_composite_filter_options(to_options, field) - filter(from_options[:name] || :"from_#{field.to_s.tr('.', '_')}", :integer, - **from_options) do |value, scope, grid| - grid.driver.greater_equal(scope, field, value) - end - filter(to_options[:name] || :"to_#{field.to_s.tr('.', '_')}", :integer, **to_options) do |value, scope, grid| - grid.driver.less_equal(scope, field, value) - end - end - - def normalize_composite_filter_options(options, _field) - options = { name: options } if options.is_a?(String) || options.is_a?(Symbol) - options - end - end - end - end -end diff --git a/spec/datagrid/filters/composite_filters_spec.rb b/spec/datagrid/filters/composite_filters_spec.rb deleted file mode 100644 index 3a0e96c..0000000 --- a/spec/datagrid/filters/composite_filters_spec.rb +++ /dev/null @@ -1,76 +0,0 @@ -# frozen_string_literal: true - -require "spec_helper" - -describe Datagrid::Filters::CompositeFilters do - describe ".date_range_filters" do - it "should generate from date and to date filters" do - e1 = Entry.create!(shipping_date: 6.days.ago) - e2 = Entry.create!(shipping_date: 4.days.ago) - e3 = Entry.create!(shipping_date: 1.days.ago) - assets = test_report(from_shipping_date: 5.days.ago, to_shipping_date: 2.day.ago) do - scope { Entry } - silence_warnings do - date_range_filters(:shipping_date) - end - end.assets - - expect(assets).to include(e2) - expect(assets).not_to include(e1, e3) - end - - it "should support options" do - report = test_report do - silence_warnings do - date_range_filters(:shipping_date, { default: 10.days.ago.to_date }, { default: Date.today }) - end - end - expect(report.from_shipping_date).to eq(10.days.ago.to_date) - expect(report.to_shipping_date).to eq(Date.today) - end - it "should support table name in field" do - report = test_report do - silence_warnings do - date_range_filters("entries.shipping_date", { default: 10.days.ago.to_date }, { default: Date.today }) - end - end - expect(report.from_entries_shipping_date).to eq(10.days.ago.to_date) - expect(report.to_entries_shipping_date).to eq(Date.today) - end - end - - describe ".integer_range_filters" do - it "should generate from integer and to integer filters" do - e1 = Entry.create!(group_id: 1) - e2 = Entry.create!(group_id: 3) - e3 = Entry.create!(group_id: 5) - assets = test_report(from_group_id: 2, to_group_id: 4) do - scope { Entry } - silence_warnings do - integer_range_filters(:group_id) - end - end.assets - - expect(assets).to include(e2) - expect(assets).not_to include(e1, e3) - end - it "should support options" do - report = test_report do - silence_warnings do - integer_range_filters(:group_id, { default: 0 }, { default: 100 }) - end - end - expect(report.from_group_id).to eq(0) - expect(report.to_group_id).to eq(100) - end - it "should table name in field name" do - report = test_report do - silence_warnings do - integer_range_filters("entries.group_id", { default: 0 }, { default: 100 }) - end - end - expect(report.from_entries_group_id).to eq(0) - expect(report.to_entries_group_id).to eq(100) - end - end -end From a1a47a5e5b79bc3bc3c4c21d53f4dcc5c7c5c0a9 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Tue, 5 Nov 2024 10:07:07 +0100 Subject: [PATCH 032/157] Cleanup --- lib/datagrid.rb | 10 ++++++++++ lib/datagrid/active_model.rb | 12 +++++------- lib/datagrid/core.rb | 5 +---- lib/datagrid/filters.rb | 11 +++++------ 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/lib/datagrid.rb b/lib/datagrid.rb index 616d779..6955a3a 100644 --- a/lib/datagrid.rb +++ b/lib/datagrid.rb @@ -31,6 +31,16 @@ module Datagrid autoload :Engine + # extend ActiveSupport::Concern + + # included do + # include ::Datagrid::Core + # include ::Datagrid::ActiveModel + # include ::Datagrid::Filters + # include ::Datagrid::Columns + # include ::Datagrid::ColumnNamesAttribute + # include ::Datagrid::Ordering + # end # @!visibility private def self.included(base) base.class_eval do diff --git a/lib/datagrid/active_model.rb b/lib/datagrid/active_model.rb index f139ab0..bc77426 100644 --- a/lib/datagrid/active_model.rb +++ b/lib/datagrid/active_model.rb @@ -3,13 +3,11 @@ module Datagrid # Required to be ActiveModel compatible module ActiveModel - # @!visibility private - def self.included(base) - base.extend ClassMethods - base.class_eval do - require "active_model/naming" - extend ::ActiveModel::Naming - end + extend ActiveSupport::Concern + + included do + require "active_model/naming" + extend ::ActiveModel::Naming end module ClassMethods diff --git a/lib/datagrid/core.rb b/lib/datagrid/core.rb index 44df516..9c8386c 100644 --- a/lib/datagrid/core.rb +++ b/lib/datagrid/core.rb @@ -24,16 +24,13 @@ module ClassMethods def datagrid_attribute(name, &block) return if datagrid_attributes.include?(name) - block ||= lambda do |value| - value - end datagrid_attributes << name define_method name do instance_variable_get("@#{name}") end define_method :"#{name}=" do |value| - instance_variable_set("@#{name}", instance_exec(value, &block)) + instance_variable_set("@#{name}", block ? instance_exec(value, &block) : value) end end diff --git a/lib/datagrid/filters.rb b/lib/datagrid/filters.rb index 69257a1..b573e9f 100644 --- a/lib/datagrid/filters.rb +++ b/lib/datagrid/filters.rb @@ -33,13 +33,12 @@ module Filters # @!visibility private DEFAULT_FILTER_BLOCK = Object.new + extend ActiveSupport::Concern + # @!visibility private - def self.included(base) - base.extend ClassMethods - base.class_eval do - include Datagrid::Core - class_attribute :filters_array, default: [] - end + included do + include Datagrid::Core + class_attribute :filters_array, default: [] end # Grid class methods related to filters From 7b6e2b062b69ce71ed2bf684a9d3f6357ea7e2f4 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Tue, 5 Nov 2024 11:05:45 +0100 Subject: [PATCH 033/157] update upgrade guide --- VERSION2.md | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/VERSION2.md b/VERSION2.md index fa0ac45..86f8779 100644 --- a/VERSION2.md +++ b/VERSION2.md @@ -1,9 +1,9 @@ # Datagrid Version 2 Datagrid v1 was released Sep 19 2013 - more than 10 years ago. -A lot of new things had happened during this period and it is time. +A lot of new things had happened during this period. It caused the library to be designed without support of those technologies -and implementing some of them would cause a breaking change. +or their implementation to be suboptimal because of backward compatibility. And now it is time to indroduce them with Version 2. List of things introduces: @@ -12,8 +12,30 @@ List of things introduces: 1. Modern modular CSS classes. 1. HTML5 input types: number, date, datetime-local. 1. HTML5 input [names collision restriction](https://html.spec.whatwg.org/multipage/input.html#input-type-attr-summary) +1. Rails Engines: While supported, the library was not initially designed for it. -## Ruby Infinite Ranges +## Infinite Ranges for range filters + +Ruby supports infinite ranges now, +so there is no need to present infinite ranges as Hash or Array. +But it introduces a breaking changes to range filters in Datagrid: + +``` ruby +class UsersGrid + include Datagrid + + filter(:id, :integer, range: true) do |value, scope| + # V1 value: [1, nil] + # V2 value: 1..nil + scope.where(id: value) + end +end + +grid = UsersGrid.new +grid.id = [1, nil] +grid.id # V1: [1, nil] + # V2: (1..nil) +``` ## Modern CSS classes @@ -35,7 +57,7 @@ and avoid collisions with other libraries: | field | datagrid-dynamic-field | | operation | datagrid-dynamic-operation | | value | datagrid-dynamic-value | -| separator | datgrid-range-separator | +| separator | datagrid-range-separator | | checkboxes | datagrid-enum-checkboxes | A few automatically generated classes were moved from `<input/>` to `<div class="datagrid-filter">` @@ -108,7 +130,9 @@ The default behavior can be changed back by using `input_options`: ``` ruby filter(:created_at, :date, range: true, input_options: {type: 'text'}) -filter(:created_at, :datetime, range: true, input_options: {type: 'text'}) +filter(:salary, :integer, range: true, input_options: {type: 'text'}) + +# Rendered as <textarea/> tag: filter(:text, :string, input_options: {type: 'textarea'}) ``` From b3d4778287a9a4bb0362bee79bbf6f6be60cc56a Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Tue, 5 Nov 2024 11:49:06 +0100 Subject: [PATCH 034/157] Ability to assign range as {from: , to:} hash --- lib/datagrid/filters/ranged_filter.rb | 47 +++++++++++++++-------- spec/datagrid/filters/date_filter_spec.rb | 26 +++++++++++++ 2 files changed, 58 insertions(+), 15 deletions(-) diff --git a/lib/datagrid/filters/ranged_filter.rb b/lib/datagrid/filters/ranged_filter.rb index 9fa95d2..004afa7 100644 --- a/lib/datagrid/filters/ranged_filter.rb +++ b/lib/datagrid/filters/ranged_filter.rb @@ -11,11 +11,43 @@ def initialize(grid, name, options, &block) end def parse_values(value) + if value.is_a?(Hash) + value = parse_hash(value) + end result = super return result if !range? || result.nil? # Simulate single point range return [result, result] unless result.is_a?(Array) + parse_array(result) + end + + def range? + options[:range] + end + + def default_filter_where(scope, value) + if range? && value.is_a?(Array) + left, right = value + scope = driver.greater_equal(scope, name, left) if left + scope = driver.less_equal(scope, name, right) if right + scope + else + super + end + end + + protected + + def parse_hash(result) + if result[:from] || result[:to] + [result[:from], result[:to]] + else + nil + end + end + + def parse_array(result) case result.size when 0 nil @@ -34,21 +66,6 @@ def parse_values(value) raise ArgumentError, "Can not create a date range from array of more than two: #{result.inspect}" end end - - def range? - options[:range] - end - - def default_filter_where(scope, value) - if range? && value.is_a?(Array) - left, right = value - scope = driver.greater_equal(scope, name, left) if left - scope = driver.less_equal(scope, name, right) if right - scope - else - super - end - end end end end diff --git a/spec/datagrid/filters/date_filter_spec.rb b/spec/datagrid/filters/date_filter_spec.rb index 865b61d..8187b8b 100644 --- a/spec/datagrid/filters/date_filter_spec.rb +++ b/spec/datagrid/filters/date_filter_spec.rb @@ -31,6 +31,32 @@ expect(report.assets).not_to include(e2) end + it "supports hash argument" do + e1 = Entry.create!(created_at: 7.days.ago) + e2 = Entry.create!(created_at: 4.days.ago) + e3 = Entry.create!(created_at: 1.day.ago) + from = 5.days.ago + to = 3.days.ago + report = test_report(created_at: {from: , to:}) do + scope { Entry } + filter(:created_at, :date, range: true) + end + expect(report.created_at).to eq([from.to_date, to.to_date]) + expect(report.assets).not_to include(e1) + expect(report.assets).to include(e2) + expect(report.assets).not_to include(e3) + report.created_at = {} + expect(report.created_at).to eq(nil) + report.created_at = {from: nil, to: nil} + expect(report.created_at).to eq(nil) + report.created_at = {from: Date.today, to: nil} + expect(report.created_at).to eq([Date.today, nil]) + report.created_at = {from: nil, to: Date.today} + expect(report.created_at).to eq([nil, Date.today]) + report.created_at = {from: Time.now, to: Time.now} + expect(report.created_at).to eq([Date.today, Date.today]) + end + { active_record: Entry, mongoid: MongoidEntry, sequel: SequelEntry }.each do |orm, klass| describe "with orm #{orm}", orm => true do describe "date to timestamp conversion" do From 01e50e9ca8536fe72d21bd9e08c1a37b69d62a5e Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Wed, 6 Nov 2024 10:38:58 +0100 Subject: [PATCH 035/157] Use data attributes instead of CSS classes for column names --- VERSION2.md | 61 +++++++++++++++++++- app/views/datagrid/_head.html.erb | 2 +- app/views/datagrid/_row.html.erb | 2 +- lib/datagrid/columns/column.rb | 4 ++ lib/datagrid/helper.rb | 4 +- spec/datagrid/helper_spec.rb | 92 +++++++++++++++---------------- 6 files changed, 114 insertions(+), 51 deletions(-) diff --git a/VERSION2.md b/VERSION2.md index 86f8779..176c03b 100644 --- a/VERSION2.md +++ b/VERSION2.md @@ -13,6 +13,7 @@ List of things introduces: 1. HTML5 input types: number, date, datetime-local. 1. HTML5 input [names collision restriction](https://html.spec.whatwg.org/multipage/input.html#input-type-attr-summary) 1. Rails Engines: While supported, the library was not initially designed for it. +1. HTML5 data attributes ## Infinite Ranges for range filters @@ -37,7 +38,7 @@ grid.id # V1: [1, nil] # V2: (1..nil) ``` -## Modern CSS classes +## Modern CSS classes naming conventions Built-in generated CSS classes renamed to match modern CSS naming conventions and avoid collisions with other libraries: @@ -137,3 +138,61 @@ filter(:text, :string, input_options: {type: 'textarea'}) ``` ## Names collision restriction + +TODO + +## HTML5 data attributes + +It is more semantic and collision proof to use `data-*` attributes +instead of classes for meta information from backend. +Therefor built-in partials now generate data attributes by default +instead of classes for column names: + +Version 1: + +``` html +<tr> + <th class="name">Name</th> + <th class="category">Category</th> +</tr> +<tr> + <td class="name">John</th> + <td class="category">Worker</th> +</tr> +<tr> + <td class="name">Mike</th> + <td class="category">Manager</th> +</tr> +``` + +Version 2: + +``` html +<tr> + <th data-datagrid-column="name">Name</th> + <th data-datagrid-column="category">Category</th> +</tr> +<tr> + <td data-datagrid-column="name">John</th> + <td data-datagrid-column="category">Worker</th> +</tr> +<tr> + <td data-datagrid-column="name">Mike</th> + <td data-datagrid-column="category">Manager</th> +</tr> +``` + +If you still want to have an HTML class attached to a column use `class` column option: + +``` ruby +column(:name, class: 'column-name') +``` + +``` html +<th class="column-name" data-datagrid-column="name">Name</th> +... +<td class="column-name" data-datagrid-column="name">John</td> +``` + +If you want to change this behavior completely, +modify [built-in partials](https://github.com/bogdan/datagrid/wiki/Frontend#modifying-built-in-partials). diff --git a/app/views/datagrid/_head.html.erb b/app/views/datagrid/_head.html.erb index e939128..affccf4 100644 --- a/app/views/datagrid/_head.html.erb +++ b/app/views/datagrid/_head.html.erb @@ -1,6 +1,6 @@ <tr> <% grid.html_columns(*options[:columns]).each do |column| %> - <th class="<%= datagrid_column_classes(grid, column) %>"> + <th class="<%= datagrid_column_classes(grid, column) %>" data-datagrid-column="<%= column.name %>"> <%= column.header %> <%= datagrid_order_for(grid, column, options) if column.supports_order? && options[:order]%> </th> diff --git a/app/views/datagrid/_row.html.erb b/app/views/datagrid/_row.html.erb index f54d21c..b431ab7 100644 --- a/app/views/datagrid/_row.html.erb +++ b/app/views/datagrid/_row.html.erb @@ -1,5 +1,5 @@ <tr> <% grid.html_columns(*options[:columns]).each do |column| %> - <td class="<%= datagrid_column_classes(grid, column) %>"><%= datagrid_value(grid, column, asset) %></td> + <td class="<%= datagrid_column_classes(grid, column) %>" data-datagrid-column="<%= column.name %>"><%= datagrid_value(grid, column, asset) %></td> <% end %> </tr> diff --git a/lib/datagrid/columns/column.rb b/lib/datagrid/columns/column.rb index 2f15359..502295d 100644 --- a/lib/datagrid/columns/column.rb +++ b/lib/datagrid/columns/column.rb @@ -108,6 +108,10 @@ def mandatory? !!options[:mandatory] end + def html_class + options[:class] + end + def mandatory_explicitly_set? options.key?(:mandatory) end diff --git a/lib/datagrid/helper.rb b/lib/datagrid/helper.rb index 4f4361a..76a2551 100644 --- a/lib/datagrid/helper.rb +++ b/lib/datagrid/helper.rb @@ -151,9 +151,9 @@ def datagrid_renderer def datagrid_column_classes(grid, column) order_class = if grid.ordered_by?(column) - [grid.descending ? "datagrid-order-active-desc" : "datagrid-order-active-asc"] + grid.descending ? "datagrid-order-active-desc" : "datagrid-order-active-asc" end - [column.name, order_class, column.options[:class]].compact.join(" ") + [order_class, column.html_class].compact.join(" ") end end end diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index c8bb509..a38b8ff 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -58,12 +58,12 @@ datagrid_table = subject.datagrid_table(grid) expect(datagrid_table).to match_css_pattern({ - "table.datagrid-table tr th.group div.datagrid-order" => 1, - "table.datagrid-table tr th.group" => /Group.*/, - "table.datagrid-table tr th.name div.datagrid-order" => 1, - "table.datagrid-table tr th.name" => /Name.*/, - "table.datagrid-table tr td.group" => "Pop", - "table.datagrid-table tr td.name" => "Star" + "table.datagrid-table tr th[data-datagrid-column=group] div.datagrid-order" => 1, + "table.datagrid-table tr th[data-datagrid-column=group]" => /Group.*/, + "table.datagrid-table tr th[data-datagrid-column=name] div.datagrid-order" => 1, + "table.datagrid-table tr th[data-datagrid-column=name]" => /Name.*/, + "table.datagrid-table tr td[data-datagrid-column=group]" => "Pop", + "table.datagrid-table tr td[data-datagrid-column=name]" => "Star" }) end @@ -72,12 +72,12 @@ datagrid_table = subject.datagrid_table(grid, [entry]) expect(datagrid_table).to match_css_pattern({ - "table.datagrid-table tr th.group div.datagrid-order" => 1, - "table.datagrid-table tr th.group" => /Group.*/, - "table.datagrid-table tr th.name div.datagrid-order" => 1, - "table.datagrid-table tr th.name" => /Name.*/, - "table.datagrid-table tr td.group" => "Pop", - "table.datagrid-table tr td.name" => "Star" + "table.datagrid-table tr th[data-datagrid-column=group] div.datagrid-order" => 1, + "table.datagrid-table tr th[data-datagrid-column=group]" => /Group.*/, + "table.datagrid-table tr th[data-datagrid-column=name] div.datagrid-order" => 1, + "table.datagrid-table tr th[data-datagrid-column=name]" => /Name.*/, + "table.datagrid-table tr td[data-datagrid-column=group]" => "Pop", + "table.datagrid-table tr td[data-datagrid-column=name]" => "Star" }) end @@ -87,10 +87,10 @@ it "should support columns option" do expect(subject.datagrid_table(grid, [entry], columns: [:name])).to match_css_pattern( - "table.datagrid-table th.name" => 1, - "table.datagrid-table td.name" => 1, - "table.datagrid-table th.group" => 0, - "table.datagrid-table td.group" => 0 + "table.datagrid-table th[data-datagrid-column=name]" => 1, + "table.datagrid-table td[data-datagrid-column=name]" => 1, + "table.datagrid-table th[data-datagrid-column=group]" => 0, + "table.datagrid-table td[data-datagrid-column=group]" => 0 ) end @@ -105,10 +105,10 @@ it "should output only given column names" do expect(subject.datagrid_table(grid, [entry])).to match_css_pattern( - "table.datagrid-table th.name" => 1, - "table.datagrid-table td.name" => 1, - "table.datagrid-table th.category" => 0, - "table.datagrid-table td.category" => 0 + "table.datagrid-table th[data-datagrid-column=name]" => 1, + "table.datagrid-table td[data-datagrid-column=name]" => 1, + "table.datagrid-table th[data-datagrid-column=category]" => 0, + "table.datagrid-table td[data-datagrid-column=category]" => 0 ) end end @@ -156,8 +156,8 @@ end it "should render table" do expect(subject.datagrid_table(grid)).to match_css_pattern( - "table.datagrid-table th.name" => 1, - "table.datagrid-table td.name" => 2 + "table.datagrid-table th[data-datagrid-column=name]" => 1, + "table.datagrid-table td[data-datagrid-column=name]" => 2 ) end end @@ -172,8 +172,8 @@ end it "should render table" do expect(subject.datagrid_table(grid)).to match_css_pattern( - "table.datagrid-table th.name" => 1, - "table.datagrid-table td.name" => 2 + "table.datagrid-table th[data-datagrid-column=name]" => 1, + "table.datagrid-table td[data-datagrid-column=name]" => 2 ) end end @@ -186,7 +186,7 @@ column(:name) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td.name.datagrid-order-active-asc" => "Star" + "tr td[data-datagrid-column=name].datagrid-order-active-asc" => "Star" ) end it "should add ordering classes to column" do @@ -209,7 +209,7 @@ column(:name) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td.name.datagrid-order-active-desc" => "Star" + "tr td[data-datagrid-column=name].datagrid-order-active-desc" => "Star" ) end @@ -220,7 +220,7 @@ end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td.name" => "Star" + "tr td[data-datagrid-column=name]" => "Star" ) end @@ -232,7 +232,7 @@ end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td.name span" => "Star" + "tr td[data-datagrid-column=name] span" => "Star" ) end @@ -243,7 +243,7 @@ end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td.name" => "Star" + "tr td[data-datagrid-column=name]" => "Star" ) end @@ -256,7 +256,7 @@ end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td.name" => "Star" + "tr td[data-datagrid-column=name]" => "Star" ) end @@ -267,7 +267,7 @@ end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td.name" => "Star" + "tr td[data-datagrid-column=name]" => "Star" ) end @@ -277,7 +277,7 @@ column(:name, html: ->(data) { content_tag :h1, data }) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td.name h1" => "Star" + "tr td[data-datagrid-column=name] h1" => "Star" ) end @@ -289,7 +289,7 @@ end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td.name em" => "STAR" + "tr td[data-datagrid-column=name] em" => "STAR" ) end @@ -301,7 +301,7 @@ end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td.name span" => "Star-Entry" + "tr td[data-datagrid-column=name] span" => "Star-Entry" ) end @@ -313,7 +313,7 @@ }) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td.name h1" => "Star-star" + "tr td[data-datagrid-column=name] h1" => "Star-star" ) end @@ -325,7 +325,7 @@ }) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td.name h1" => "Star-star-Entry" + "tr td[data-datagrid-column=name] h1" => "Star-star-Entry" ) end @@ -339,7 +339,7 @@ end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td.name h1" => "STAR-Star" + "tr td[data-datagrid-column=name] h1" => "STAR-Star" ) end @@ -353,7 +353,7 @@ end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td.name h1" => "STAR-Star-Entry" + "tr td[data-datagrid-column=name] h1" => "STAR-Star-Entry" ) end @@ -364,10 +364,10 @@ column(:category) end expect(subject.datagrid_rows(rp, [entry], columns: [:name])).to match_css_pattern( - "tr td.name" => "Star" + "tr td[data-datagrid-column=name]" => "Star" ) expect(subject.datagrid_rows(rp, [entry], columns: [:name])).to match_css_pattern( - "tr td.category" => 0 + "tr td[data-datagrid-column=category]" => 0 ) end @@ -378,7 +378,7 @@ end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td.name.my_class" => "Star" + "tr td[data-datagrid-column=name].my_class" => "Star" ) end @@ -394,7 +394,7 @@ end it "should ignore them" do expect(subject.datagrid_rows(grid, [entry])).to match_css_pattern( - "td.name" => 1 + "td[data-datagrid-column=name]" => 1 ) end end @@ -402,7 +402,7 @@ it "should escape html" do entry.update!(name: "<div>hello</div>") expect(subject.datagrid_rows(grid, [entry], columns: [:name])).to equal_to_dom(<<-HTML) - <tr><td class="name"><div>hello</div></td></tr> + <tr><td class="" data-datagrid-column="name"><div>hello</div></td></tr> HTML end @@ -412,7 +412,7 @@ model.name.html_safe end expect(subject.datagrid_rows(grid, [entry], columns: [:safe_name])).to equal_to_dom(<<-HTML) - <tr><td class="safe_name"><div>hello</div></td></tr> + <tr><td class="" data-datagrid-column="safe_name"><div>hello</div></td></tr> HTML end end @@ -576,7 +576,7 @@ def param_name it "converts to string using columns option" do r = subject.datagrid_row(grid, entry, columns: [:name]).to_s - expect(r).to match_css_pattern("tr td.name") + expect(r).to match_css_pattern("tr td[data-datagrid-column=name]") expect(r).to_not match_css_pattern("tr td.category") end end @@ -633,7 +633,7 @@ def param_name end end expect(subject.datagrid_header(grid)).to equal_to_dom(<<~HTML) - <tr><th class="category datagrid-order-active-asc">Category<div class="datagrid-order"> + <tr><th class="datagrid-order-active-asc" data-datagrid-column="category">Category<div class="datagrid-order"> <a class="datagrid-order-control-asc" href="/location?grid%5Bdescending%5D=false&grid%5Border%5D=category">↑</a><a class="datagrid-order-control-desc" href="/location?grid%5Bdescending%5D=true&grid%5Border%5D=category">↓</a> </div> </th></tr> From f68ba6b2567878252997f6999369ffb9103773b8 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Wed, 6 Nov 2024 10:42:39 +0100 Subject: [PATCH 036/157] Cleanup --- .rubocop_todo.yml | 1021 --------------------------------------------- 1 file changed, 1021 deletions(-) delete mode 100644 .rubocop_todo.yml diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml deleted file mode 100644 index 88da75f..0000000 --- a/.rubocop_todo.yml +++ /dev/null @@ -1,1021 +0,0 @@ -# This configuration was generated by -# `rubocop --auto-gen-config` -# on 2024-11-03 18:32:09 UTC using RuboCop version 1.68.0. -# The point is for the user to remove these configuration records -# one by one as the offenses are removed from the code base. -# Note that changes in the inspected code, or installation of new -# versions of RuboCop, may require this file to be generated again. - -# Offense count: 6 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include. -# Include: **/*.gemfile, **/Gemfile, **/gems.rb -Bundler/OrderedGems: - Exclude: - - 'Gemfile' - - 'gemfiles/rails_6.1.gemfile' - - 'gemfiles/rails_7.0.gemfile' - - 'gemfiles/rails_7.1.gemfile' - - 'gemfiles/rails_7.2.gemfile' - -# Offense count: 3 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, IndentationWidth. -# SupportedStyles: with_first_argument, with_fixed_indentation -Layout/ArgumentAlignment: - Exclude: - - 'lib/datagrid/filters.rb' - - 'lib/datagrid/form_builder.rb' - -# Offense count: 5 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyleAlignWith. -# SupportedStylesAlignWith: either, start_of_block, start_of_line -Layout/BlockAlignment: - Exclude: - - 'spec/datagrid/drivers/mongo_mapper_spec.rb' - - 'spec/datagrid/filters/enum_filter_spec.rb' - -# Offense count: 35 -# This cop supports safe autocorrection (--autocorrect). -Layout/BlockEndNewline: - Exclude: - - 'spec/datagrid/form_builder_spec.rb' - - 'spec/datagrid/helper_spec.rb' - - 'spec/datagrid_spec.rb' - -# Offense count: 4 -# This cop supports safe autocorrection (--autocorrect). -Layout/ClosingHeredocIndentation: - Exclude: - - 'lib/datagrid/scaffold.rb' - - 'spec/datagrid/helper_spec.rb' - - 'spec/datagrid/scaffold_spec.rb' - -# Offense count: 40 -# This cop supports safe autocorrection (--autocorrect). -Layout/EmptyLineAfterGuardClause: - Exclude: - - 'lib/datagrid/columns.rb' - - 'lib/datagrid/columns/column.rb' - - 'lib/datagrid/drivers/active_record.rb' - - 'lib/datagrid/drivers/array.rb' - - 'lib/datagrid/drivers/mongo_mapper.rb' - - 'lib/datagrid/drivers/mongoid.rb' - - 'lib/datagrid/drivers/sequel.rb' - - 'lib/datagrid/filters.rb' - - 'lib/datagrid/filters/base_filter.rb' - - 'lib/datagrid/filters/dynamic_filter.rb' - - 'lib/datagrid/filters/enum_filter.rb' - - 'lib/datagrid/filters/float_filter.rb' - - 'lib/datagrid/filters/integer_filter.rb' - - 'lib/datagrid/ordering.rb' - - 'lib/datagrid/utils.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Layout/EmptyLineAfterMagicComment: - Exclude: - - 'spec/datagrid/form_builder_spec.rb' - -# Offense count: 14 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EmptyLineBetweenMethodDefs, EmptyLineBetweenClassDefs, EmptyLineBetweenModuleDefs, DefLikeMacros, AllowAdjacentOneLineDefs, NumberOfEmptyLines. -Layout/EmptyLineBetweenDefs: - Exclude: - - 'lib/datagrid/columns.rb' - - 'lib/datagrid/columns/column.rb' - - 'lib/datagrid/core.rb' - - 'lib/datagrid/filters/date_filter.rb' - - 'lib/datagrid/helper.rb' - - 'lib/datagrid/ordering.rb' - - 'spec/datagrid/columns_spec.rb' - - 'spec/support/active_record.rb' - - 'spec/support/matchers.rb' - - 'spec/support/sequel.rb' - -# Offense count: 60 -# This cop supports safe autocorrection (--autocorrect). -Layout/EmptyLines: - Enabled: false - -# Offense count: 6 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: around, only_before -Layout/EmptyLinesAroundAccessModifier: - Exclude: - - 'lib/datagrid/core.rb' - - 'lib/datagrid/drivers/abstract_driver.rb' - - 'lib/datagrid/form_builder.rb' - - 'lib/datagrid/renderer.rb' - - 'lib/datagrid/scaffold.rb' - - 'lib/datagrid/utils.rb' - -# Offense count: 2 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowAliasSyntax, AllowedMethods. -# AllowedMethods: alias_method, public, protected, private -Layout/EmptyLinesAroundAttributeAccessor: - Exclude: - - 'spec/datagrid/columns_spec.rb' - - 'spec/datagrid/filters_spec.rb' - -# Offense count: 96 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: empty_lines, no_empty_lines -Layout/EmptyLinesAroundBlockBody: - Enabled: false - -# Offense count: 37 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines, beginning_only, ending_only -Layout/EmptyLinesAroundClassBody: - Enabled: false - -# Offense count: 3 -# This cop supports safe autocorrection (--autocorrect). -Layout/EmptyLinesAroundMethodBody: - Exclude: - - 'lib/datagrid/columns/column.rb' - - 'lib/datagrid/filters/ranged_filter.rb' - - 'lib/datagrid/utils.rb' - -# Offense count: 16 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines -Layout/EmptyLinesAroundModuleBody: - Exclude: - - 'lib/datagrid.rb' - - 'lib/datagrid/columns.rb' - - 'lib/datagrid/configuration.rb' - - 'lib/datagrid/core.rb' - - 'lib/datagrid/filters.rb' - - 'lib/datagrid/filters/composite_filters.rb' - - 'lib/datagrid/filters/ranged_filter.rb' - - 'lib/datagrid/helper.rb' - - 'lib/datagrid/ordering.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyleAlignWith, Severity. -# SupportedStylesAlignWith: keyword, variable, start_of_line -Layout/EndAlignment: - Exclude: - - 'spec/datagrid/drivers/mongo_mapper_spec.rb' - -# Offense count: 16 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment. -Layout/ExtraSpacing: - Exclude: - - 'lib/datagrid/active_model.rb' - - 'lib/datagrid/columns.rb' - - 'lib/datagrid/drivers/active_record.rb' - - 'lib/datagrid/drivers/sequel.rb' - - 'lib/datagrid/filters/composite_filters.rb' - - 'lib/datagrid/ordering.rb' - - 'spec/datagrid/columns_spec.rb' - - 'spec/datagrid/filters/dynamic_filter_spec.rb' - - 'spec/datagrid/filters/enum_filter_spec.rb' - - 'spec/datagrid/ordering_spec.rb' - -# Offense count: 6 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: IndentationWidth. -# SupportedStyles: special_inside_parentheses, consistent, align_brackets -Layout/FirstArrayElementIndentation: - EnforcedStyle: consistent - -# Offense count: 16 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: IndentationWidth. -# SupportedStyles: special_inside_parentheses, consistent, align_braces -Layout/FirstHashElementIndentation: - EnforcedStyle: consistent - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. -# SupportedHashRocketStyles: key, separator, table -# SupportedColonStyles: key, separator, table -# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit -Layout/HashAlignment: - Exclude: - - 'spec/spec_helper.rb' - -# Offense count: 6 -# This cop supports safe autocorrection (--autocorrect). -Layout/HeredocIndentation: - Exclude: - - 'lib/datagrid/scaffold.rb' - - 'spec/datagrid/form_builder_spec.rb' - - 'spec/datagrid/helper_spec.rb' - -# Offense count: 4 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: normal, indented_internal_methods -Layout/IndentationConsistency: - Exclude: - - 'spec/datagrid/columns_spec.rb' - -# Offense count: 5 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: Width, AllowedPatterns. -Layout/IndentationWidth: - Exclude: - - 'spec/datagrid/drivers/mongo_mapper_spec.rb' - - 'spec/datagrid/helper_spec.rb' - -# Offense count: 11 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowDoxygenCommentStyle, AllowGemfileRubyComment, AllowRBSInlineAnnotation, AllowSteepAnnotation. -Layout/LeadingCommentSpace: - Exclude: - - 'lib/datagrid/drivers/mongo_mapper.rb' - - 'lib/datagrid/rspec.rb' - - 'spec/datagrid/filters/dynamic_filter_spec.rb' - - 'spec/spec_helper.rb' - - 'spec/support/active_record.rb' - - 'spec/support/mongoid.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Layout/LeadingEmptyLines: - Exclude: - - 'spec/support/simple_report.rb' - -# Offense count: 35 -# This cop supports safe autocorrection (--autocorrect). -Layout/MultilineBlockLayout: - Exclude: - - 'spec/datagrid/form_builder_spec.rb' - - 'spec/datagrid/helper_spec.rb' - - 'spec/datagrid_spec.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, IndentationWidth. -# SupportedStyles: aligned, indented -Layout/MultilineOperationIndentation: - Exclude: - - 'lib/datagrid/filters/integer_filter.rb' - -# Offense count: 36 -# This cop supports safe autocorrection (--autocorrect). -Layout/SpaceAfterComma: - Exclude: - - 'lib/datagrid/columns.rb' - - 'spec/datagrid/drivers/array_spec.rb' - - 'spec/datagrid/drivers/sequel_spec.rb' - - 'spec/datagrid/filters/date_filter_spec.rb' - - 'spec/datagrid/filters/date_time_filter_spec.rb' - - 'spec/datagrid/filters/enum_filter_spec.rb' - - 'spec/datagrid/filters/integer_filter_spec.rb' - - 'spec/datagrid/filters_spec.rb' - - 'spec/datagrid/form_builder_spec.rb' - - 'spec/datagrid/helper_spec.rb' - -# Offense count: 5 -# This cop supports safe autocorrection (--autocorrect). -Layout/SpaceAfterNot: - Exclude: - - 'lib/datagrid/columns/column.rb' - - 'lib/datagrid/drivers/active_record.rb' - - 'lib/datagrid/drivers/mongoid.rb' - - 'lib/datagrid/drivers/sequel.rb' - -# Offense count: 14 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowForAlignment, EnforcedStyleForExponentOperator, EnforcedStyleForRationalLiterals. -# SupportedStylesForExponentOperator: space, no_space -# SupportedStylesForRationalLiterals: space, no_space -Layout/SpaceAroundOperators: - Exclude: - - 'lib/datagrid/columns.rb' - - 'lib/datagrid/drivers/active_record.rb' - - 'lib/datagrid/drivers/mongo_mapper.rb' - - 'lib/datagrid/drivers/mongoid.rb' - - 'lib/datagrid/drivers/sequel.rb' - - 'spec/datagrid/drivers/array_spec.rb' - - 'spec/datagrid/drivers/mongo_mapper_spec.rb' - - 'spec/datagrid/drivers/mongoid_spec.rb' - - 'spec/datagrid/drivers/sequel_spec.rb' - - 'spec/datagrid/filters/date_time_filter_spec.rb' - - 'spec/datagrid/filters/enum_filter_spec.rb' - - 'spec/datagrid/filters/integer_filter_spec.rb' - - 'spec/spec_helper.rb' - -# Offense count: 3 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. -# SupportedStyles: space, no_space -# SupportedStylesForEmptyBraces: space, no_space -Layout/SpaceBeforeBlockBraces: - Exclude: - - 'lib/datagrid/filters.rb' - - 'spec/datagrid/filters/dynamic_filter_spec.rb' - - 'spec/datagrid/ordering_spec.rb' - -# Offense count: 5 -# This cop supports safe autocorrection (--autocorrect). -Layout/SpaceBeforeComma: - Exclude: - - 'lib/datagrid/drivers/mongoid.rb' - - 'lib/datagrid/filters.rb' - - 'lib/datagrid/form_builder.rb' - -# Offense count: 5 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowForAlignment. -Layout/SpaceBeforeFirstArg: - Exclude: - - 'lib/datagrid/active_model.rb' - - 'lib/datagrid/columns.rb' - - 'lib/datagrid/filters/composite_filters.rb' - - 'lib/datagrid/ordering.rb' - - 'spec/datagrid/columns_spec.rb' - -# Offense count: 16 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBrackets. -# SupportedStyles: space, no_space, compact -# SupportedStylesForEmptyBrackets: space, no_space -Layout/SpaceInsideArrayLiteralBrackets: - Exclude: - - 'lib/datagrid/drivers/mongoid.rb' - - 'lib/datagrid/filters/base_filter.rb' - - 'spec/datagrid/column_names_attribute_spec.rb' - - 'spec/datagrid/drivers/array_spec.rb' - - 'spec/datagrid/drivers/mongo_mapper_spec.rb' - - 'spec/datagrid/drivers/mongoid_spec.rb' - - 'spec/datagrid/drivers/sequel_spec.rb' - -# Offense count: 425 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters. -# SupportedStyles: space, no_space -# SupportedStylesForEmptyBraces: space, no_space -Layout/SpaceInsideBlockBraces: - Enabled: false - -# Offense count: 162 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. -# SupportedStyles: space, no_space, compact -# SupportedStylesForEmptyBraces: space, no_space -Layout/SpaceInsideHashLiteralBraces: - Enabled: false - -# Offense count: 18 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: space, compact, no_space -Layout/SpaceInsideParens: - Exclude: - - 'lib/datagrid/form_builder.rb' - - 'lib/datagrid/ordering.rb' - - 'spec/datagrid/filters/enum_filter_spec.rb' - - 'spec/datagrid/filters/integer_filter_spec.rb' - - 'spec/datagrid/filters/string_filter_spec.rb' - - 'spec/datagrid/filters_spec.rb' - - 'spec/datagrid/form_builder_spec.rb' - - 'spec/datagrid/helper_spec.rb' - -# Offense count: 15 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: final_newline, final_blank_line -Layout/TrailingEmptyLines: - Exclude: - - 'Rakefile' - - 'datagrid.gemspec' - - 'lib/datagrid.rb' - - 'lib/datagrid/column_names_attribute.rb' - - 'lib/datagrid/drivers/mongoid.rb' - - 'lib/datagrid/filters/base_filter.rb' - - 'lib/datagrid/filters/date_filter.rb' - - 'lib/datagrid/filters/date_time_filter.rb' - - 'lib/datagrid/filters/integer_filter.rb' - - 'lib/datagrid/helper.rb' - - 'spec/datagrid/helper_spec.rb' - - 'spec/support/configuration.rb' - - 'spec/support/mongoid.rb' - - 'spec/support/sequel.rb' - - 'spec/support/simple_report.rb' - -# Offense count: 4 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowInHeredoc. -Layout/TrailingWhitespace: - Exclude: - - 'spec/datagrid/columns/column_spec.rb' - - 'spec/datagrid/filters/base_filter_spec.rb' - - 'spec/datagrid/filters/float_filter_spec.rb' - - 'spec/datagrid/utils_spec.rb' - -# Offense count: 4 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: AllowSafeAssignment. -Lint/AssignmentInCondition: - Exclude: - - 'lib/datagrid/columns/column.rb' - - 'lib/datagrid/filters/base_filter.rb' - - 'lib/datagrid/form_builder.rb' - - 'lib/datagrid/renderer.rb' - -# Offense count: 31 -# Configuration parameters: AllowedMethods. -# AllowedMethods: enums -Lint/ConstantDefinitionInBlock: - Exclude: - - 'spec/datagrid/active_model_spec.rb' - - 'spec/datagrid/columns/column_spec.rb' - - 'spec/datagrid/columns_spec.rb' - - 'spec/datagrid/core_spec.rb' - - 'spec/datagrid/drivers/array_spec.rb' - - 'spec/datagrid/drivers/sequel_spec.rb' - - 'spec/datagrid/filters/enum_filter_spec.rb' - - 'spec/datagrid/filters_spec.rb' - - 'spec/datagrid/helper_spec.rb' - - 'spec/datagrid/ordering_spec.rb' - - 'spec/support/active_record.rb' - -# Offense count: 1 -# This cop supports unsafe autocorrection (--autocorrect-all). -Lint/NonDeterministicRequireOrder: - Exclude: - - 'spec/spec_helper.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Lint/RedundantStringCoercion: - Exclude: - - 'lib/datagrid/form_builder.rb' - -# Offense count: 6 -# Configuration parameters: AllowComments, AllowNil. -Lint/SuppressedException: - Exclude: - - 'lib/datagrid/active_model.rb' - - 'lib/datagrid/utils.rb' - - 'spec/spec_helper.rb' - -# Offense count: 8 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AutoCorrect, IgnoreEmptyBlocks, AllowUnusedKeywordArguments. -Lint/UnusedBlockArgument: - Exclude: - - 'lib/datagrid/filters/extended_boolean_filter.rb' - - 'spec/datagrid/columns_spec.rb' - - 'spec/datagrid/drivers/active_record_spec.rb' - - 'spec/datagrid/form_builder_spec.rb' - - 'spec/datagrid/helper_spec.rb' - - 'spec/datagrid/ordering_spec.rb' - -# Offense count: 20 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AutoCorrect, AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods. -Lint/UnusedMethodArgument: - Exclude: - - 'lib/datagrid/columns.rb' - - 'lib/datagrid/drivers/array.rb' - - 'lib/datagrid/drivers/mongo_mapper.rb' - - 'lib/datagrid/drivers/mongoid.rb' - - 'lib/datagrid/filters/base_filter.rb' - - 'lib/datagrid/filters/composite_filters.rb' - - 'lib/datagrid/form_builder.rb' - - 'spec/support/i18n_helpers.rb' - -# Offense count: 3 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: AutoCorrect. -Lint/UselessMethodDefinition: - Exclude: - - 'lib/datagrid/core.rb' - - 'lib/datagrid/drivers/sequel.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AutoCorrect, CheckForMethodsWithNoSideEffects. -Lint/Void: - Exclude: - - 'spec/support/matchers.rb' - -# Offense count: 14 -# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. -Metrics/AbcSize: - Max: 39 - -# Offense count: 64 -# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. -# AllowedMethods: refine -Metrics/BlockLength: - Max: 606 - -# Offense count: 5 -# Configuration parameters: CountComments, CountAsOne. -Metrics/ClassLength: - Max: 146 - -# Offense count: 10 -# Configuration parameters: AllowedMethods, AllowedPatterns. -Metrics/CyclomaticComplexity: - Max: 14 - -# Offense count: 32 -# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. -Metrics/MethodLength: - Max: 34 - -# Offense count: 3 -# Configuration parameters: CountComments, CountAsOne. -Metrics/ModuleLength: - Max: 193 - -# Offense count: 10 -# Configuration parameters: AllowedMethods, AllowedPatterns. -Metrics/PerceivedComplexity: - Max: 14 - -# Offense count: 9 -# Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros. -# NamePrefix: is_, has_, have_ -# ForbiddenPrefixes: is_, has_, have_ -# AllowedMethods: is_a? -# MethodDefinitionMacros: define_method, define_singleton_method -Naming/PredicateName: - Exclude: - - 'spec/**/*' - - 'lib/datagrid/drivers/abstract_driver.rb' - - 'lib/datagrid/drivers/active_record.rb' - - 'lib/datagrid/drivers/array.rb' - - 'lib/datagrid/drivers/mongo_mapper.rb' - - 'lib/datagrid/drivers/mongoid.rb' - - 'lib/datagrid/drivers/sequel.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: prefer_alias, prefer_alias_method -Style/Alias: - Exclude: - - 'lib/datagrid/ordering.rb' - -# Offense count: 1 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: always, conditionals -Style/AndOr: - Exclude: - - 'spec/support/matchers.rb' - -# Offense count: 28 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods. -# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces -# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object -# FunctionalMethods: let, let!, subject, watch -# AllowedMethods: lambda, proc, it -Style/BlockDelimiters: - Exclude: - - 'spec/datagrid/columns_spec.rb' - - 'spec/datagrid/core_spec.rb' - - 'spec/datagrid/drivers/mongo_mapper_spec.rb' - - 'spec/datagrid/drivers/mongoid_spec.rb' - - 'spec/datagrid/drivers/sequel_spec.rb' - - 'spec/datagrid/filters/dynamic_filter_spec.rb' - - 'spec/datagrid/filters_spec.rb' - - 'spec/datagrid/form_builder_spec.rb' - - 'spec/datagrid/helper_spec.rb' - - 'spec/datagrid/ordering_spec.rb' - - 'spec/datagrid_spec.rb' - -# Offense count: 3 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowOnConstant, AllowOnSelfClass. -Style/CaseEquality: - Exclude: - - 'lib/datagrid/filters/select_options.rb' - -# Offense count: 2 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: MinBranchesCount. -Style/CaseLikeIf: - Exclude: - - 'lib/datagrid/form_builder.rb' - - 'spec/support/matchers.rb' - -# Offense count: 16 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: nested, compact -Style/ClassAndModuleChildren: - Exclude: - - 'lib/datagrid/columns/column.rb' - - 'lib/datagrid/filters/base_filter.rb' - - 'lib/datagrid/filters/boolean_filter.rb' - - 'lib/datagrid/filters/date_filter.rb' - - 'lib/datagrid/filters/date_time_filter.rb' - - 'lib/datagrid/filters/default_filter.rb' - - 'lib/datagrid/filters/dynamic_filter.rb' - - 'lib/datagrid/filters/enum_filter.rb' - - 'lib/datagrid/filters/extended_boolean_filter.rb' - - 'lib/datagrid/filters/float_filter.rb' - - 'lib/datagrid/filters/integer_filter.rb' - - 'lib/datagrid/filters/ranged_filter.rb' - - 'lib/datagrid/filters/select_options.rb' - - 'lib/datagrid/filters/string_filter.rb' - - 'lib/datagrid/scaffold.rb' - -# Offense count: 2 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: Keywords, RequireColon. -# Keywords: TODO, FIXME, OPTIMIZE, HACK, REVIEW, NOTE -Style/CommentAnnotation: - Exclude: - - 'lib/datagrid/drivers/mongo_mapper.rb' - - 'spec/spec_helper.rb' - -# Offense count: 25 -# Configuration parameters: AllowedConstants. -Style/Documentation: - Enabled: false - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AutoCorrect, EnforcedStyle, AllowComments. -# SupportedStyles: empty, nil, both -Style/EmptyElse: - Exclude: - - 'lib/datagrid/ordering.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Style/EmptyLiteral: - Exclude: - - 'spec/datagrid/drivers/array_spec.rb' - -# Offense count: 2 -# This cop supports safe autocorrection (--autocorrect). -Style/Encoding: - Exclude: - - 'Rakefile' - - 'spec/datagrid/form_builder_spec.rb' - -# Offense count: 3 -# This cop supports safe autocorrection (--autocorrect). -Style/ExpandPathArguments: - Exclude: - - 'lib/datagrid.rb' - - 'spec/spec_helper.rb' - -# Offense count: 2 -# This cop supports safe autocorrection (--autocorrect). -Style/ExplicitBlockArgument: - Exclude: - - 'lib/datagrid/drivers/mongo_mapper.rb' - - 'lib/datagrid/drivers/mongoid.rb' - -# Offense count: 82 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: always, always_true, never -Style/FrozenStringLiteralComment: - Enabled: false - -# Offense count: 3 -# Configuration parameters: AllowedVariables. -Style/GlobalVars: - Exclude: - - 'spec/datagrid/filters_spec.rb' - -# Offense count: 9 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: MinBodyLength, AllowConsecutiveConditionals. -Style/GuardClause: - Exclude: - - 'lib/datagrid/core.rb' - - 'lib/datagrid/drivers/abstract_driver.rb' - - 'lib/datagrid/filters/dynamic_filter.rb' - - 'lib/datagrid/filters/ranged_filter.rb' - - 'lib/datagrid/filters/select_options.rb' - - 'lib/datagrid/form_builder.rb' - - 'lib/datagrid/ordering.rb' - - 'spec/support/matchers.rb' - -# Offense count: 1 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: AllowedReceivers. -# AllowedReceivers: Thread.current -Style/HashEachMethods: - Exclude: - - 'spec/datagrid/form_builder_spec.rb' - -# Offense count: 226 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, EnforcedShorthandSyntax, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols. -# SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys -# SupportedShorthandSyntax: always, never, either, consistent, either_consistent -Style/HashSyntax: - Enabled: false - -# Offense count: 2 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowIfModifier. -Style/IfInsideElse: - Exclude: - - 'lib/datagrid/column_names_attribute.rb' - - 'lib/datagrid/ordering.rb' - -# Offense count: 45 -# This cop supports safe autocorrection (--autocorrect). -Style/IfUnlessModifier: - Enabled: false - -# Offense count: 6 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: line_count_dependent, lambda, literal -Style/Lambda: - Exclude: - - 'spec/datagrid/helper_spec.rb' - - 'spec/support/simple_report.rb' - -# Offense count: 20 -# This cop supports unsafe autocorrection (--autocorrect-all). -Style/LineEndConcatenation: - Exclude: - - 'spec/datagrid/form_builder_spec.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowedMethods, AllowedPatterns. -Style/MethodCallWithoutArgsParentheses: - Exclude: - - 'spec/datagrid/form_builder_spec.rb' - -# Offense count: 2 -Style/MissingRespondToMissing: - Exclude: - - 'lib/datagrid/columns.rb' - - 'lib/datagrid/renderer.rb' - -# Offense count: 2 -# This cop supports safe autocorrection (--autocorrect). -Style/MultilineTernaryOperator: - Exclude: - - 'lib/datagrid/drivers/active_record.rb' - - 'lib/datagrid/filters/select_options.rb' - -# Offense count: 14 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: literals, strict -Style/MutableConstant: - Exclude: - - 'lib/datagrid/drivers/abstract_driver.rb' - - 'lib/datagrid/filters.rb' - - 'lib/datagrid/filters/dynamic_filter.rb' - - 'lib/datagrid/filters/extended_boolean_filter.rb' - - 'lib/datagrid/utils.rb' - - 'lib/datagrid/version.rb' - -# Offense count: 2 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: both, prefix, postfix -Style/NegatedIf: - Exclude: - - 'spec/support/matchers.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Style/NestedTernaryOperator: - Exclude: - - 'lib/datagrid/helper.rb' - -# Offense count: 20 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedOctalStyle. -# SupportedOctalStyles: zero_with_o, zero_only -Style/NumericLiteralPrefix: - Exclude: - - 'spec/datagrid/filters/date_filter_spec.rb' - - 'spec/datagrid/filters/date_time_filter_spec.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: Strict, AllowedNumbers, AllowedPatterns. -Style/NumericLiterals: - MinDigits: 6 - -# Offense count: 4 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns. -# SupportedStyles: predicate, comparison -Style/NumericPredicate: - Exclude: - - 'spec/**/*' - - 'lib/datagrid/columns.rb' - - 'lib/datagrid/utils.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Style/ParallelAssignment: - Exclude: - - 'lib/datagrid/utils.rb' - -# Offense count: 6 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: PreferredDelimiters. -Style/PercentLiteralDelimiters: - Exclude: - - 'lib/datagrid/filters/dynamic_filter.rb' - - 'spec/datagrid/columns_spec.rb' - - 'spec/datagrid/form_builder_spec.rb' - -# Offense count: 7 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: short, verbose -Style/PreferredHashMethods: - Exclude: - - 'lib/datagrid/columns/column.rb' - - 'lib/datagrid/filters/base_filter.rb' - - 'lib/datagrid/filters/dynamic_filter.rb' - - 'lib/datagrid/filters/select_options.rb' - - 'lib/datagrid/form_builder.rb' - - 'lib/datagrid/renderer.rb' - -# Offense count: 4 -# This cop supports safe autocorrection (--autocorrect). -Style/RedundantBegin: - Exclude: - - 'lib/datagrid/utils.rb' - - 'spec/support/configuration.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowMultipleReturnValues. -Style/RedundantReturn: - Exclude: - - 'lib/datagrid/drivers/mongoid.rb' - -# Offense count: 38 -# This cop supports safe autocorrection (--autocorrect). -Style/RedundantSelf: - Exclude: - - 'lib/datagrid/active_model.rb' - - 'lib/datagrid/columns.rb' - - 'lib/datagrid/columns/column.rb' - - 'lib/datagrid/core.rb' - - 'lib/datagrid/drivers/abstract_driver.rb' - - 'lib/datagrid/filters.rb' - - 'lib/datagrid/filters/base_filter.rb' - - 'lib/datagrid/filters/enum_filter.rb' - - 'lib/datagrid/filters/select_options.rb' - - 'lib/datagrid/form_builder.rb' - - 'lib/datagrid/ordering.rb' - - 'spec/datagrid/helper_spec.rb' - - 'spec/support/simple_report.rb' - -# Offense count: 2 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, AllowInnerSlashes. -# SupportedStyles: slashes, percent_r, mixed -Style/RegexpLiteral: - Exclude: - - 'lib/datagrid/scaffold.rb' - -# Offense count: 4 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength. -# AllowedMethods: present?, blank?, presence, try, try! -Style/SafeNavigation: - Exclude: - - 'lib/datagrid/column_names_attribute.rb' - - 'lib/datagrid/filters/base_filter.rb' - - 'lib/datagrid/filters/string_filter.rb' - - 'lib/datagrid/renderer.rb' - -# Offense count: 4 -# This cop supports safe autocorrection (--autocorrect). -Style/StderrPuts: - Exclude: - - 'Rakefile' - - 'spec/spec_helper.rb' - -# Offense count: 17 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: Mode. -Style/StringConcatenation: - Exclude: - - 'lib/datagrid/scaffold.rb' - - 'lib/tasks/datagrid_tasks.rake' - - 'spec/datagrid/form_builder_spec.rb' - -# Offense count: 1090 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. -# SupportedStyles: single_quotes, double_quotes -Style/StringLiterals: - Enabled: false - -# Offense count: 1 -# This cop supports unsafe autocorrection (--autocorrect-all). -Style/StructInheritance: - Exclude: - - 'spec/datagrid/drivers/array_spec.rb' - -# Offense count: 20 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: MinSize. -# SupportedStyles: percent, brackets -Style/SymbolArray: - EnforcedStyle: brackets - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Style/SymbolLiteral: - Exclude: - - 'spec/datagrid/columns_spec.rb' - -# Offense count: 6 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: AllowMethodsWithArguments, AllowedMethods, AllowedPatterns, AllowComments. -# AllowedMethods: define_method -Style/SymbolProc: - Exclude: - - 'lib/datagrid/column_names_attribute.rb' - - 'spec/datagrid/filters/enum_filter_spec.rb' - - 'spec/datagrid/helper_spec.rb' - - 'spec/support/simple_report.rb' - -# Offense count: 9 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyleForMultiline. -# SupportedStylesForMultiline: comma, consistent_comma, no_comma -Style/TrailingCommaInArguments: - Exclude: - - 'lib/datagrid/column_names_attribute.rb' - - 'lib/datagrid/form_builder.rb' - - 'spec/datagrid/drivers/active_record_spec.rb' - - 'spec/datagrid/helper_spec.rb' - -# Offense count: 6 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyleForMultiline. -# SupportedStylesForMultiline: comma, consistent_comma, no_comma -Style/TrailingCommaInArrayLiteral: - Exclude: - - 'datagrid.gemspec' - - 'lib/datagrid/drivers/mongoid.rb' - - 'lib/datagrid/filters/dynamic_filter.rb' - - 'spec/datagrid/drivers/array_spec.rb' - - 'spec/datagrid/helper_spec.rb' - - 'spec/spec_helper.rb' - -# Offense count: 6 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyleForMultiline. -# SupportedStylesForMultiline: comma, consistent_comma, no_comma -Style/TrailingCommaInHashLiteral: - Exclude: - - 'datagrid.gemspec' - - 'lib/datagrid/drivers/mongoid.rb' - - 'lib/datagrid/form_builder.rb' - - 'lib/datagrid/scaffold.rb' - - 'spec/datagrid/filters_spec.rb' - -# Offense count: 31 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, MinSize, WordRegex. -# SupportedStyles: percent, brackets -Style/WordArray: - Exclude: - - 'spec/datagrid/column_names_attribute_spec.rb' - - 'spec/datagrid/columns_spec.rb' - - 'spec/datagrid/core_spec.rb' - - 'spec/datagrid/drivers/array_spec.rb' - - 'spec/datagrid/drivers/mongo_mapper_spec.rb' - - 'spec/datagrid/drivers/mongoid_spec.rb' - - 'spec/datagrid/drivers/sequel_spec.rb' - - 'spec/datagrid/filters/date_filter_spec.rb' - - 'spec/datagrid/filters/extended_boolean_filter_spec.rb' - - 'spec/datagrid/filters/string_filter_spec.rb' - - 'spec/datagrid/filters_spec.rb' - - 'spec/datagrid/form_builder_spec.rb' - - 'spec/datagrid/helper_spec.rb' - - 'spec/support/simple_report.rb' - -# Offense count: 36 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns. -# URISchemes: http, https -Layout/LineLength: - Max: 250 From bcfdd94ee37d60c1b37a4aa08c3ae907baaf126a Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Wed, 6 Nov 2024 10:50:47 +0100 Subject: [PATCH 037/157] V2 guide --- VERSION2.md | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 1 deletion(-) diff --git a/VERSION2.md b/VERSION2.md index 176c03b..d076475 100644 --- a/VERSION2.md +++ b/VERSION2.md @@ -195,4 +195,130 @@ column(:name, class: 'column-name') ``` If you want to change this behavior completely, -modify [built-in partials](https://github.com/bogdan/datagrid/wiki/Frontend#modifying-built-in-partials). +modify [built-in partials](https://github.com/bogdan/datagrid/wiki/Frontend#modifying-built-in-partials) + +## All changes in built-in partials + +Version 2 built-in partials are trying to expose +as much UI as possible for user modification. + +Here is a complete diff for built-in partials between V1 and V2: + +TODO update + +``` diff +diff --git a/app/views/datagrid/_enum_checkboxes.html.erb b/app/views/datagrid/_enum_checkboxes.html.erb +index 9f48319..f114c17 100644 +--- a/app/views/datagrid/_enum_checkboxes.html.erb ++++ b/app/views/datagrid/_enum_checkboxes.html.erb +@@ -4,8 +4,8 @@ You can add indent if whitespace doesn't matter for you + %> + <%- elements.each do |value, text, checked| -%> + <%- id = [form.object_name, filter.name, value].join('_').underscore -%> +-<%= form.label filter.name, options.merge(for: id) do -%> +-<%= form.check_box(filter.name, {multiple: true, id: id, checked: checked, include_hidden: false}, value.to_s, nil) -%> ++<%= form.datagrid_label(filter.name, **options, for: id) do -%> ++<%= form.datagrid_filter_input(filter.name, type: :checkbox, multiple: true, id: id, checked: checked, include_hidden: false, value: value.to_s) -%> + <%= text -%> + <%- end -%> + <%- end -%> +diff --git a/app/views/datagrid/_form.html.erb b/app/views/datagrid/_form.html.erb +index 7e175c1..84cf58e 100644 +--- a/app/views/datagrid/_form.html.erb ++++ b/app/views/datagrid/_form.html.erb +@@ -1,12 +1,12 @@ +-<%= form_for grid, options do |f| -%> ++<%= form_for grid, html: {class: 'datagrid-form'}, **options do |f| -%> + <% grid.filters.each do |filter| %> +- <div class="datagrid-filter filter"> ++ <div class="datagrid-filter <%= filter.default_html_classes.join(' ') %>"> + <%= f.datagrid_label filter %> + <%= f.datagrid_filter filter %> + </div> + <% end %> + <div class="datagrid-actions"> +- <%= f.submit I18n.t("datagrid.form.search").html_safe, class: "datagrid-submit" %> +- <%= link_to I18n.t('datagrid.form.reset').html_safe, url_for(grid.to_param => {}), class: "datagrid-reset" %> ++ <%= f.submit I18n.t("datagrid.form.search"), class: "datagrid-submit" %> ++ <%= link_to I18n.t('datagrid.form.reset'), url_for(grid.to_param => {}), class: "datagrid-reset" %> + </div> + <% end -%> +diff --git a/app/views/datagrid/_head.html.erb b/app/views/datagrid/_head.html.erb +index e939128..affccf4 100644 +--- a/app/views/datagrid/_head.html.erb ++++ b/app/views/datagrid/_head.html.erb +@@ -1,6 +1,6 @@ + <tr> + <% grid.html_columns(*options[:columns]).each do |column| %> +- <th class="<%= datagrid_column_classes(grid, column) %>"> ++ <th class="<%= datagrid_column_classes(grid, column) %>" data-datagrid-column="<%= column.name %>"> + <%= column.header %> + <%= datagrid_order_for(grid, column, options) if column.supports_order? && options[:order]%> + </th> +diff --git a/app/views/datagrid/_order_for.html.erb b/app/views/datagrid/_order_for.html.erb +index 1545a8e..1c33c37 100644 +--- a/app/views/datagrid/_order_for.html.erb ++++ b/app/views/datagrid/_order_for.html.erb +@@ -1,10 +1,10 @@ +-<div class="order"> ++<div class="datagrid-order"> + <%= link_to( +- I18n.t("datagrid.table.order.asc").html_safe, ++ I18n.t("datagrid.table.order.asc"), + datagrid_order_path(grid, column, false), +- class: "asc") %> ++ class: "datagrid-order-control-asc") %> + <%= link_to( +- I18n.t("datagrid.table.order.desc").html_safe, ++ I18n.t("datagrid.table.order.desc"), + datagrid_order_path(grid, column, true), +- class: "desc") %> ++ class: "datagrid-order-control-desc") %> + </div> +diff --git a/app/views/datagrid/_range_filter.html.erb b/app/views/datagrid/_range_filter.html.erb +index 7a8a123..1b90dc8 100644 +--- a/app/views/datagrid/_range_filter.html.erb ++++ b/app/views/datagrid/_range_filter.html.erb +@@ -1,3 +1,3 @@ + <%= form.datagrid_filter_input(filter, **from_options) %> +-<span class="separator <%= filter.type %>"><%= I18n.t('datagrid.filters.range.separator') %></span> ++<span class="datagrid-range-separator"><%= I18n.t('datagrid.filters.range.separator') %></span> + <%= form.datagrid_filter_input(filter, **to_options) %> +diff --git a/app/views/datagrid/_row.html.erb b/app/views/datagrid/_row.html.erb +index f54d21c..b431ab7 100644 +--- a/app/views/datagrid/_row.html.erb ++++ b/app/views/datagrid/_row.html.erb +@@ -1,5 +1,5 @@ + <tr> + <% grid.html_columns(*options[:columns]).each do |column| %> +- <td class="<%= datagrid_column_classes(grid, column) %>"><%= datagrid_value(grid, column, asset) %></td> ++ <td class="<%= datagrid_column_classes(grid, column) %>" data-datagrid-column="<%= column.name %>"><%= datagrid_value(grid, column, asset) %></td> + <% end %> + </tr> +diff --git a/app/views/datagrid/_table.html.erb b/app/views/datagrid/_table.html.erb +index 8708c05..0b5ff24 100644 +--- a/app/views/datagrid/_table.html.erb ++++ b/app/views/datagrid/_table.html.erb +@@ -5,7 +5,7 @@ Local variables: + * options - passed options Hash + %> + <% if grid.html_columns(*options[:columns]).any? %> +- <%= content_tag :table, options[:html] do %> ++ <%= content_tag :table, class: 'datagrid-table', **options.fetch(:html, {}) do %> + <thead> + <%= datagrid_header(grid, options) %> + </thead> +@@ -13,10 +13,10 @@ Local variables: + <% if assets.any? %> + <%= datagrid_rows(grid, assets, **options) %> + <% else %> +- <tr><td class="noresults" colspan="100%"><%= I18n.t('datagrid.no_results').html_safe %></td></tr> ++ <tr><td class="datagrid-no-results" colspan="100%"><%= I18n.t('datagrid.no_results') %></td></tr> + <% end %> + </tbody> + <% end %> + <% else -%> +- <%= I18n.t("datagrid.table.no_columns").html_safe %> ++ <%= I18n.t("datagrid.table.no_columns") %> + <% end %> +``` From 47f491d02247f2e2011e77b31012f0c201cb72fc Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Wed, 6 Nov 2024 14:42:50 +0100 Subject: [PATCH 038/157] Introduce Datagrid::Base --- Readme.markdown | 4 +-- VERSION2.md | 16 ++++++++-- lib/datagrid.rb | 38 ++-------------------- lib/datagrid/base.rb | 39 +++++++++++++++++++++++ lib/datagrid/core.rb | 20 ++++++------ lib/datagrid/scaffold.rb | 2 +- spec/datagrid/columns/column_spec.rb | 3 +- spec/datagrid/columns_spec.rb | 15 +++------ spec/datagrid/core_spec.rb | 9 ++---- spec/datagrid/drivers/array_spec.rb | 6 ++-- spec/datagrid/drivers/sequel_spec.rb | 3 +- spec/datagrid/filters/enum_filter_spec.rb | 3 +- spec/datagrid/filters_spec.rb | 15 +++------ spec/datagrid/helper_spec.rb | 15 +++------ spec/datagrid/ordering_spec.rb | 3 +- spec/datagrid_spec.rb | 12 +++++++ spec/support/mongoid.rb | 3 +- spec/support/sequel.rb | 4 +-- spec/support/simple_report.rb | 7 ++-- templates/base.rb.erb | 6 +--- 20 files changed, 107 insertions(+), 116 deletions(-) create mode 100644 lib/datagrid/base.rb diff --git a/Readme.markdown b/Readme.markdown index 5d565a4..98a9f80 100644 --- a/Readme.markdown +++ b/Readme.markdown @@ -47,9 +47,7 @@ including admin panels, analytics and data representation: In order to create a grid: ``` ruby -class UsersGrid - - include Datagrid +class UsersGrid < Datagrid::Base scope do User.includes(:group) diff --git a/VERSION2.md b/VERSION2.md index d076475..019f575 100644 --- a/VERSION2.md +++ b/VERSION2.md @@ -14,6 +14,7 @@ List of things introduces: 1. HTML5 input [names collision restriction](https://html.spec.whatwg.org/multipage/input.html#input-type-attr-summary) 1. Rails Engines: While supported, the library was not initially designed for it. 1. HTML5 data attributes +1. Inherit `Datagrid::Base` instead of `include Datagrid` ## Infinite Ranges for range filters @@ -22,9 +23,7 @@ so there is no need to present infinite ranges as Hash or Array. But it introduces a breaking changes to range filters in Datagrid: ``` ruby -class UsersGrid - include Datagrid - +class UsersGrid < Datagrid::Base filter(:id, :integer, range: true) do |value, scope| # V1 value: [1, nil] # V2 value: 1..nil @@ -322,3 +321,14 @@ index 8708c05..0b5ff24 100644 + <%= I18n.t("datagrid.table.no_columns") %> <% end %> ``` + +## Inherit Datagrid::Base + +`include Datagrid` causes method name space to be clamsy. +Version 2 introduces a difference between the class +that needs to be inherited and high level namespace (just like most gems do): + +``` ruby +class ApplicationGrid < Datagrid::Base +end +``` diff --git a/lib/datagrid.rb b/lib/datagrid.rb index 6955a3a..80ec058 100644 --- a/lib/datagrid.rb +++ b/lib/datagrid.rb @@ -4,45 +4,12 @@ require "datagrid/configuration" require "datagrid/engine" -# Main datagrid module that needs to be included in grid class -# -# @example -# class UsersGrid -# include Datagrid -# scope { User } -# column(:id) -# column(:name) -# end +# @main README.md module Datagrid - extend ActiveSupport::Autoload - autoload :Core - autoload :ActiveModel - autoload :Filters - autoload :Columns - autoload :ColumnNamesAttribute - autoload :Ordering - autoload :Configuration - - autoload :Helper - autoload :FormBuilder - - autoload :Renderer - - autoload :Engine - - # extend ActiveSupport::Concern - - # included do - # include ::Datagrid::Core - # include ::Datagrid::ActiveModel - # include ::Datagrid::Filters - # include ::Datagrid::Columns - # include ::Datagrid::ColumnNamesAttribute - # include ::Datagrid::Ordering - # end # @!visibility private def self.included(base) + Utils.warn_once("Including Datagrid is deprecated. Inherit Datagrid::Base instead.") base.class_eval do include ::Datagrid::Core include ::Datagrid::ActiveModel @@ -58,5 +25,6 @@ class ArgumentError < ::ArgumentError; end class ColumnUnavailableError < StandardError; end end +require 'datagrid/base' require "datagrid/scaffold" I18n.load_path << File.expand_path("datagrid/locale/en.yml", __dir__) diff --git a/lib/datagrid/base.rb b/lib/datagrid/base.rb new file mode 100644 index 0000000..6d86f97 --- /dev/null +++ b/lib/datagrid/base.rb @@ -0,0 +1,39 @@ +module Datagrid + extend ActiveSupport::Autoload + + autoload :Core + autoload :ActiveModel + autoload :Filters + autoload :Columns + autoload :ColumnNamesAttribute + autoload :Ordering + autoload :Configuration + + autoload :Helper + autoload :FormBuilder + + autoload :Renderer + + autoload :Engine + + # Main datagrid class allowing to define columns and filters on your objects + # + # @example + # class UsersGrid < Datagrid::Base + # scope { User } + # + # filter(:id, :integer) + # filter(:name, :string) + # + # column(:id) + # column(:name) + # end + class Base + include ::Datagrid::Core + include ::Datagrid::ActiveModel + include ::Datagrid::Filters + include ::Datagrid::Columns + include ::Datagrid::ColumnNamesAttribute + include ::Datagrid::Ordering + end +end diff --git a/lib/datagrid/core.rb b/lib/datagrid/core.rb index 9c8386c..1578cbc 100644 --- a/lib/datagrid/core.rb +++ b/lib/datagrid/core.rb @@ -34,7 +34,8 @@ def datagrid_attribute(name, &block) end end - # @return [void] Defines a scope at class level + # Defines a relation scope of database models to be filtered + # @return [void] # @example # scope { User } # scope { Project.where(deleted: false) } @@ -106,13 +107,15 @@ def dynamic(&block) end end - protected - + # @!visibility private def check_scope_defined!(message = nil) message ||= "#{self}.scope is not defined" raise(Datagrid::ConfigurationError, message) unless scope_value end + protected + + # @!visibility private def inherited(child_class) super child_class.datagrid_attributes = datagrid_attributes.clone @@ -133,7 +136,7 @@ def initialize(attributes = nil, &block) scope(&block) end - # @return [Hash<Symbol, Object>] grid attributes including filter values and ordering values + # @return [{Symbol => Object}] grid attributes including filter values and ordering values def attributes result = {} datagrid_attributes.each do |name| @@ -143,7 +146,7 @@ def attributes end # Updates datagrid attributes with a passed hash argument - # @param attributes [Hash<Symbol, Object>] + # @param attributes [{Symbol => Object}] # @example # grid = MyGrid.new # grid.attributes = {first_name: 'John', last_name: 'Smith'} @@ -217,7 +220,7 @@ def scope(&block) # @!visibility private def original_scope - check_scope_defined! + self.class.check_scope_defined! scope_value.call end @@ -236,11 +239,6 @@ def driver self.class.driver end - # @!visibility private - def check_scope_defined!(message = nil) - self.class.send :check_scope_defined!, message - end - # @return [String] a datagrid attributes and their values in inspection form def inspect attrs = attributes.map do |key, value| diff --git a/lib/datagrid/scaffold.rb b/lib/datagrid/scaffold.rb index b1faa50..84cccb4 100644 --- a/lib/datagrid/scaffold.rb +++ b/lib/datagrid/scaffold.rb @@ -74,7 +74,7 @@ def pagination_helper_code end def base_grid_file - "app/grids/base_grid.rb" + "app/grids/application_grid.rb" end def grid_route_name diff --git a/spec/datagrid/columns/column_spec.rb b/spec/datagrid/columns/column_spec.rb index a2fe70e..12bc2b1 100644 --- a/spec/datagrid/columns/column_spec.rb +++ b/spec/datagrid/columns/column_spec.rb @@ -5,8 +5,7 @@ describe Datagrid::Columns::Column do describe ".inspect" do subject do - class ColumnInspectTest - include Datagrid + class ColumnInspectTest < Datagrid::Base scope { Entry } column(:id, header: "ID") end diff --git a/spec/datagrid/columns_spec.rb b/spec/datagrid/columns_spec.rb index 9fdb23e..4b83f48 100644 --- a/spec/datagrid/columns_spec.rb +++ b/spec/datagrid/columns_spec.rb @@ -68,8 +68,7 @@ describe "translations" do module ::Ns45 - class TranslatedReport - include Datagrid + class TranslatedReport < Datagrid::Base scope { Entry } column(:name) end @@ -81,8 +80,7 @@ class TranslatedReport end it "translates column-header without namespace" do - class Report27 - include Datagrid + class Report27 < Datagrid::Base scope { Entry } column(:name) end @@ -93,8 +91,7 @@ class Report27 end it "translates column-header in using defaults namespace" do - class Report27 - include Datagrid + class Report27 < Datagrid::Base scope { Entry } column(:name) end @@ -188,8 +185,7 @@ class Report27 end it "should inherit columns correctly" do - parent = Class.new do - include Datagrid + parent = Class.new(Datagrid::Base) do scope { Entry } column(:name) end @@ -613,8 +609,7 @@ def capitalized_name describe "#data_hash" do it "works" do pending - class DataHashGrid - include Datagrid + class DataHashGrid < Datagrid::Base scope { Entry } column(:name, order: true) end diff --git a/spec/datagrid/core_spec.rb b/spec/datagrid/core_spec.rb index ca14b37..4874b68 100644 --- a/spec/datagrid/core_spec.rb +++ b/spec/datagrid/core_spec.rb @@ -26,8 +26,7 @@ before { 2.times { Entry.create } } let(:report_class) do - class ScopeTestReport - include Datagrid + class ScopeTestReport < Datagrid::Base scope { Entry.order("id desc") } end ScopeTestReport @@ -99,8 +98,7 @@ class TestGrid < ScopeTestReport describe "#inspect" do it "should show all attribute values" do - class InspectTest - include Datagrid + class InspectTest < Datagrid::Base scope { Entry } filter(:created_at, :date, range: true) column(:name) @@ -114,8 +112,7 @@ class InspectTest end describe "#==" do - class EqualTest - include Datagrid + class EqualTest < Datagrid::Base scope { Entry } filter(:created_at, :date) column(:name) diff --git a/spec/datagrid/drivers/array_spec.rb b/spec/datagrid/drivers/array_spec.rb index 5fdaa2c..daf3663 100644 --- a/spec/datagrid/drivers/array_spec.rb +++ b/spec/datagrid/drivers/array_spec.rb @@ -12,9 +12,8 @@ end describe "api" do - class ArrayGrid + class ArrayGrid < Datagrid::Base User = Struct.new(:name, :age) - include Datagrid scope do [] end @@ -102,8 +101,7 @@ class ArrayGrid end describe "array of hashes" do - class HashGrid - include Datagrid + class HashGrid < Datagrid::Base scope do [{ name: "Bogdan", age: 30 }, { name: "Brad", age: 32 }] end diff --git a/spec/datagrid/drivers/sequel_spec.rb b/spec/datagrid/drivers/sequel_spec.rb index e95165b..5b79963 100644 --- a/spec/datagrid/drivers/sequel_spec.rb +++ b/spec/datagrid/drivers/sequel_spec.rb @@ -33,8 +33,7 @@ end it "supports pagination" do - class PaginationTest - include Datagrid + class PaginationTest < Datagrid::Base scope { SequelEntry } end grid = PaginationTest.new do |scope| diff --git a/spec/datagrid/filters/enum_filter_spec.rb b/spec/datagrid/filters/enum_filter_spec.rb index 6ea8ec7..bc61a96 100644 --- a/spec/datagrid/filters/enum_filter_spec.rb +++ b/spec/datagrid/filters/enum_filter_spec.rb @@ -29,8 +29,7 @@ end it "should initialize select option only on instanciation" do - class ReportWithLazySelect - include Datagrid + class ReportWithLazySelect < Datagrid::Base scope { Entry } filter(:group_id, :enum, select: proc { raise "hello" }) end diff --git a/spec/datagrid/filters_spec.rb b/spec/datagrid/filters_spec.rb index afd239c..16d126e 100644 --- a/spec/datagrid/filters_spec.rb +++ b/spec/datagrid/filters_spec.rb @@ -45,8 +45,7 @@ it "should initialize when report Scope table not exists" do class ModelWithoutTable < ActiveRecord::Base; end expect(ModelWithoutTable).not_to be_table_exists - class TheReport - include Datagrid + class TheReport < Datagrid::Base scope { ModelWithoutTable } @@ -57,8 +56,7 @@ class TheReport end it "should support inheritence" do - parent = Class.new do - include Datagrid + parent = Class.new(Datagrid::Base) do scope { Entry } filter(:name) end @@ -195,8 +193,7 @@ def check_performed(value, result, **options) describe "tranlations" do module ::Ns46 - class TranslatedReport - include Datagrid + class TranslatedReport < Datagrid::Base scope { Entry } filter(:name) end @@ -262,8 +259,7 @@ class InheritedReport < TranslatedReport describe "#inspect" do it "should list all fitlers with types" do module ::NsInspect - class TestGrid - include Datagrid + class TestGrid < Datagrid::Base scope { Entry } filter(:id, :integer) filter(:name, :string) @@ -277,8 +273,7 @@ class TestGrid end it "dislays no filters" do - class TestGrid8728 - include Datagrid + class TestGrid8728 < Datagrid::Base scope { Entry } end diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index a38b8ff..8b1f00b 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -419,8 +419,7 @@ describe ".datagrid_order_for" do it "should render ordering layout" do - class OrderedGrid - include Datagrid + class OrderedGrid < Datagrid::Base scope { Entry } column(:category) end @@ -442,8 +441,7 @@ class OrderedGrid expect(rendered_form).to include "Namespaced form partial." end it "should render form and filter inputs" do - class FormForGrid - include Datagrid + class FormForGrid < Datagrid::Base scope { Entry } filter(:category) end @@ -459,8 +457,7 @@ class FormForGrid end it "should support html classes for grid class with namespace" do module ::Ns22 - class TestGrid - include Datagrid + class TestGrid < Datagrid::Base scope { Entry } filter(:id) end @@ -473,8 +470,7 @@ class TestGrid end it "should have overridable param_name method" do - class ParamNameGrid81 - include Datagrid + class ParamNameGrid81 < Datagrid::Base scope { Entry } filter(:id) def param_name @@ -487,8 +483,7 @@ def param_name end it "takes default partials if custom doesn't exist" do - class PartialDefaultGrid - include Datagrid + class PartialDefaultGrid < Datagrid::Base scope { Entry } filter(:id, :integer, range: true) filter(:group_id, :enum, multiple: true, checkboxes: true, select: [1, 2]) diff --git a/spec/datagrid/ordering_spec.rb b/spec/datagrid/ordering_spec.rb index 028a448..a6306d3 100644 --- a/spec/datagrid/ordering_spec.rb +++ b/spec/datagrid/ordering_spec.rb @@ -102,8 +102,7 @@ end it "should work correctly with inherited classes" do - class OrderInheritenceBase - include Datagrid + class OrderInheritenceBase < Datagrid::Base scope { Entry } end diff --git a/spec/datagrid_spec.rb b/spec/datagrid_spec.rb index 074ca2c..f3fdea6 100644 --- a/spec/datagrid_spec.rb +++ b/spec/datagrid_spec.rb @@ -90,4 +90,16 @@ end end end + + it "deprecates inclucsion of Datagrid module" do + silence_warnings do + class DeprecatedInclusion + include Datagrid + scope { Entry } + column(:name) + end + end + grid = DeprecatedInclusion.new + expect(grid.data).to eq([["Name"], ["Star"]]) + end end diff --git a/spec/support/mongoid.rb b/spec/support/mongoid.rb index 878a20c..1fa6ec8 100644 --- a/spec/support/mongoid.rb +++ b/spec/support/mongoid.rb @@ -16,8 +16,7 @@ class MongoidEntry field :shipping_date, type: Time end -class MongoidGrid - include ::Datagrid +class MongoidGrid < Datagrid::Base scope do MongoidEntry diff --git a/spec/support/sequel.rb b/spec/support/sequel.rb index 77da337..d0492a9 100644 --- a/spec/support/sequel.rb +++ b/spec/support/sequel.rb @@ -20,9 +20,7 @@ class SequelEntry < Sequel::Model end -class SequelGrid - include ::Datagrid - +class SequelGrid < Datagrid::Base scope do SequelEntry end diff --git a/spec/support/simple_report.rb b/spec/support/simple_report.rb index ed5afab..7b5bfeb 100644 --- a/spec/support/simple_report.rb +++ b/spec/support/simple_report.rb @@ -6,9 +6,8 @@ def test_report(attributes = {}, &block) end def test_report_class(&block) - Class.new.tap do |klass| + Class.new(Datagrid::Base).tap do |klass| klass.class_eval do - include Datagrid def self.name "TestGrid" end @@ -17,9 +16,7 @@ def self.name end end -class SimpleReport - include Datagrid - +class SimpleReport < Datagrid::Base scope do ::Entry.includes(:group).order("entries.created_at") end diff --git a/templates/base.rb.erb b/templates/base.rb.erb index ed4281c..cde6316 100644 --- a/templates/base.rb.erb +++ b/templates/base.rb.erb @@ -1,7 +1,4 @@ -class BaseGrid - - include Datagrid - +class BaseGrid < Datagrid::Base self.default_column_options = { # Uncomment to disable the default order # order: false, @@ -41,5 +38,4 @@ class BaseGrid value ? "Yes" : "No" end end - end From debfd76cfa6cadaeba611ceccad43165d2757181 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Wed, 6 Nov 2024 14:44:13 +0100 Subject: [PATCH 039/157] Rename BaseGrid to ApplicationGrid --- VERSION2.md | 27 +++++++++++++++++++++++++++ lib/datagrid/scaffold.rb | 4 ++++ templates/base.rb.erb | 2 +- templates/grid.rb.erb | 2 +- 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/VERSION2.md b/VERSION2.md index 019f575..94b5589 100644 --- a/VERSION2.md +++ b/VERSION2.md @@ -15,6 +15,7 @@ List of things introduces: 1. Rails Engines: While supported, the library was not initially designed for it. 1. HTML5 data attributes 1. Inherit `Datagrid::Base` instead of `include Datagrid` +1. `ApplicationGrid` is now recommended name instead of `BaseGrid` ## Infinite Ranges for range filters @@ -332,3 +333,29 @@ that needs to be inherited and high level namespace (just like most gems do): class ApplicationGrid < Datagrid::Base end ``` + +## ApplicationGrid base class + +Previously recommended base class `BaseGrid` is incosistent +with Rails naming conventionsa. +It was renamed to `ApplicationGrid` instead: + +``` ruby +# app/grids/application_grid.rb +class ApplicationGrid < Datagrid::Base + def self.timestamp_column(name, *args, &block) + column(name, *args) do |model| + value = block ? block.call(model) : model.public_send(name) + value&.strftime("%Y-%m-%d") + end + end +end + +# app/grids/users_grid.rb +class UsersGrid < ApplicationGrid + scope { User } + + column(:name) + timestamp_column(:created_at) +end +``` diff --git a/lib/datagrid/scaffold.rb b/lib/datagrid/scaffold.rb index 84cccb4..b016c57 100644 --- a/lib/datagrid/scaffold.rb +++ b/lib/datagrid/scaffold.rb @@ -44,6 +44,10 @@ def grid_class_name "#{file_name.camelize.pluralize}Grid" end + def grid_base_class + file_exists?('app/grids/base_grid.rb') ? 'BaseGrid' : 'ApplicationGrid' + end + def grid_controller_class_name "#{controller_class_name.camelize}Controller" end diff --git a/templates/base.rb.erb b/templates/base.rb.erb index cde6316..c5e5801 100644 --- a/templates/base.rb.erb +++ b/templates/base.rb.erb @@ -1,4 +1,4 @@ -class BaseGrid < Datagrid::Base +class ApplicationGrid < Datagrid::Base self.default_column_options = { # Uncomment to disable the default order # order: false, diff --git a/templates/grid.rb.erb b/templates/grid.rb.erb index 2dfa87a..76b3e7d 100644 --- a/templates/grid.rb.erb +++ b/templates/grid.rb.erb @@ -1,4 +1,4 @@ -class <%= grid_class_name %> < BaseGrid +class <%= grid_class_name %> < <%= grid_base_class %> scope do <%= grid_model_name %> From 9279b7e945647f86e1afd959de0add8ab0080f05 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Wed, 6 Nov 2024 17:11:24 +0100 Subject: [PATCH 040/157] Use data-* attributes distinguish filters --- VERSION2.md | 37 ++++++++++++++++++++++++----- app/views/datagrid/_form.html.erb | 6 ++++- lib/datagrid/filters/base_filter.rb | 7 ++---- lib/datagrid/filters/enum_filter.rb | 10 ++------ lib/datagrid/form_builder.rb | 2 +- spec/datagrid/helper_spec.rb | 10 ++++---- 6 files changed, 46 insertions(+), 26 deletions(-) diff --git a/VERSION2.md b/VERSION2.md index 94b5589..ea2ab1e 100644 --- a/VERSION2.md +++ b/VERSION2.md @@ -1,21 +1,24 @@ # Datagrid Version 2 Datagrid v1 was released Sep 19 2013 - more than 10 years ago. -A lot of new things had happened during this period. +A lot of changes in best practices and available technology +had happened during this period. It caused the library to be designed without support of those technologies or their implementation to be suboptimal because of backward compatibility. -And now it is time to indroduce them with Version 2. +Version 2 addresses all that evolution. List of things introduces: 1. Ruby infinite ranges for range filters. 1. Modern modular CSS classes. 1. HTML5 input types: number, date, datetime-local. -1. HTML5 input [names collision restriction](https://html.spec.whatwg.org/multipage/input.html#input-type-attr-summary) -1. Rails Engines: While supported, the library was not initially designed for it. +1. HTML5 [input names collision restriction](https://html.spec.whatwg.org/multipage/input.html#input-type-attr-summary) +1. Native Rails Engines: + while supported, the library was not initially designed for it. 1. HTML5 data attributes 1. Inherit `Datagrid::Base` instead of `include Datagrid` 1. `ApplicationGrid` is now recommended name instead of `BaseGrid` +1. Remove SASS dependency ## Infinite Ranges for range filters @@ -61,8 +64,6 @@ and avoid collisions with other libraries: | separator | datagrid-range-separator | | checkboxes | datagrid-enum-checkboxes | -A few automatically generated classes were moved from `<input/>` to `<div class="datagrid-filter">` -to make sure they are editable through datagrid partials. ### Example @@ -148,6 +149,30 @@ instead of classes for meta information from backend. Therefor built-in partials now generate data attributes by default instead of classes for column names: +### Filters + +``` html +<div class="datagrid-filter filter"> + <label for="form_for_grid_category">Category</label> + <input class="category default_filter" type="text" name="form_for_grid[category]" id="form_for_grid_category" /> +</div> +``` + +Version 2: + +``` html +<div class="datagrid-filter" + data-datagrid-filter="category" + data-datagrid-filter-type="string" + data-datagrid-filter-checkboxes="false" +> + <label for="form_for_grid_category">Category</label> + <input type="text" name="form_for_grid[category]" id="form_for_grid_category" /> +</div> +``` + +### Columns + Version 1: ``` html diff --git a/app/views/datagrid/_form.html.erb b/app/views/datagrid/_form.html.erb index 84cf58e..88a39f9 100644 --- a/app/views/datagrid/_form.html.erb +++ b/app/views/datagrid/_form.html.erb @@ -1,6 +1,10 @@ <%= form_for grid, html: {class: 'datagrid-form'}, **options do |f| -%> <% grid.filters.each do |filter| %> - <div class="datagrid-filter <%= filter.default_html_classes.join(' ') %>"> + <div class="datagrid-filter" + data-datagrid-filter="<%= filter.name %>" + data-datagrid-filter-type="<%= filter.type %>" + data-datagrid-filter-checkboxes="<%= filter.enum_checkboxes? %>" + > <%= f.datagrid_label filter %> <%= f.datagrid_filter filter %> </div> diff --git a/lib/datagrid/filters/base_filter.rb b/lib/datagrid/filters/base_filter.rb index 57e5e09..7d373aa 100644 --- a/lib/datagrid/filters/base_filter.rb +++ b/lib/datagrid/filters/base_filter.rb @@ -144,11 +144,8 @@ def enabled?(grid) ::Datagrid::Utils.process_availability(grid, options[:if], options[:unless]) end - def default_html_classes - [ - "datagrid-filter-#{name}", - "datagrid-filter-type-#{type}", - ] + def enum_checkboxes? + false end protected diff --git a/lib/datagrid/filters/enum_filter.rb b/lib/datagrid/filters/enum_filter.rb index 75817e0..4133d07 100644 --- a/lib/datagrid/filters/enum_filter.rb +++ b/lib/datagrid/filters/enum_filter.rb @@ -11,7 +11,7 @@ class EnumFilter < Datagrid::Filters::BaseFilter def initialize(*args) super - options[:multiple] = true if checkboxes? + options[:multiple] = true if enum_checkboxes? raise Datagrid::ConfigurationError, ":select option not specified" unless options[:select] end @@ -21,17 +21,11 @@ def parse(value) value end - def default_html_classes - res = super - res.push("datagrid-enum-checkboxes") if checkboxes? - res - end - def strict options[:strict] end - def checkboxes? + def enum_checkboxes? options[:checkboxes] end end diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 20a484f..05ae48b 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -94,7 +94,7 @@ def datagrid_default_filter(filter, options = {}) end def datagrid_enum_filter(filter, options = {}, &block) - if filter.checkboxes? + if filter.enum_checkboxes? elements = object.select_options(filter).map do |element| text, value = @template.send(:option_text_and_value, element) checked = enum_checkbox_checked?(filter, value) diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 8b1f00b..8cb24fd 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -443,16 +443,16 @@ class OrderedGrid < Datagrid::Base it "should render form and filter inputs" do class FormForGrid < Datagrid::Base scope { Entry } - filter(:category) + filter(:category, :string) end object = FormForGrid.new(category: "hello") expect(subject.datagrid_form_for(object, url: "/grid")).to match_css_pattern( "form.datagrid-form[action='/grid']" => 1, "form input[name=utf8]" => 1, - "form .datagrid-filter label" => "Category", - "form .datagrid-filter-category input[name='form_for_grid[category]'][value=hello]" => 1, - "form input[name=commit][value=Search]" => 1, - "form a.datagrid-reset[href='/location']" => 1 + "form .datagrid-filter[data-datagrid-filter=category][data-datagrid-filter-type=string] label" => "Category", + "form .datagrid-filter input[name='form_for_grid[category]'][value=hello]" => 1, + "form .datagrid-actions input[name=commit][value=Search]" => 1, + "form .datagrid-actions a.datagrid-reset[href='/location']" => 1 ) end it "should support html classes for grid class with namespace" do From 9f0ce55d5e9d41fb2f1ae74311c0017ac5c80e6e Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Wed, 6 Nov 2024 17:55:24 +0100 Subject: [PATCH 041/157] Use Range for RangedFilter value --- VERSION2.md | 12 ++-- lib/datagrid/filters/ranged_filter.rb | 62 ++++++++++--------- lib/datagrid/form_builder.rb | 3 +- spec/datagrid/core_spec.rb | 2 +- spec/datagrid/filters/date_filter_spec.rb | 16 ++--- .../datagrid/filters/date_time_filter_spec.rb | 8 +-- spec/datagrid/filters/integer_filter_spec.rb | 6 +- 7 files changed, 59 insertions(+), 50 deletions(-) diff --git a/VERSION2.md b/VERSION2.md index ea2ab1e..ef9f45d 100644 --- a/VERSION2.md +++ b/VERSION2.md @@ -12,12 +12,13 @@ List of things introduces: 1. Ruby infinite ranges for range filters. 1. Modern modular CSS classes. 1. HTML5 input types: number, date, datetime-local. -1. HTML5 [input names collision restriction](https://html.spec.whatwg.org/multipage/input.html#input-type-attr-summary) +1. Use Hash instead of Array for multiparameters attirubtes + to avoid [input names collision restriction](https://html.spec.whatwg.org/multipage/input.html#input-type-attr-summary) 1. Native Rails Engines: while supported, the library was not initially designed for it. 1. HTML5 data attributes 1. Inherit `Datagrid::Base` instead of `include Datagrid` -1. `ApplicationGrid` is now recommended name instead of `BaseGrid` +1. `ApplicationGrid` is recommended base class instead of `BaseGrid` 1. Remove SASS dependency ## Infinite Ranges for range filters @@ -64,7 +65,6 @@ and avoid collisions with other libraries: | separator | datagrid-range-separator | | checkboxes | datagrid-enum-checkboxes | - ### Example The difference in layout generation from v1 to v2 @@ -154,7 +154,8 @@ instead of classes for column names: ``` html <div class="datagrid-filter filter"> <label for="form_for_grid_category">Category</label> - <input class="category default_filter" type="text" name="form_for_grid[category]" id="form_for_grid_category" /> + <input class="category default_filter" type="text" + name="form_for_grid[category]" id="form_for_grid_category" /> </div> ``` @@ -167,7 +168,8 @@ Version 2: data-datagrid-filter-checkboxes="false" > <label for="form_for_grid_category">Category</label> - <input type="text" name="form_for_grid[category]" id="form_for_grid_category" /> + <input type="text" + name="form_for_grid[category]" id="form_for_grid_category" /> </div> ``` diff --git a/lib/datagrid/filters/ranged_filter.rb b/lib/datagrid/filters/ranged_filter.rb index 004afa7..03c9174 100644 --- a/lib/datagrid/filters/ranged_filter.rb +++ b/lib/datagrid/filters/ranged_filter.rb @@ -7,19 +7,24 @@ def initialize(grid, name, options, &block) super return unless range? - options[:multiple] = true + options[:multiple] = false end def parse_values(value) - if value.is_a?(Hash) - value = parse_hash(value) + unless range? + return super + end + case value + when Hash + parse_hash(value) + when Array + parse_array(value) + when Range + to_range(value.begin, value.end) + else + result = super + to_range(result, result) end - result = super - return result if !range? || result.nil? - # Simulate single point range - return [result, result] unless result.is_a?(Array) - - parse_array(result) end def range? @@ -27,10 +32,9 @@ def range? end def default_filter_where(scope, value) - if range? && value.is_a?(Array) - left, right = value - scope = driver.greater_equal(scope, name, left) if left - scope = driver.less_equal(scope, name, right) if right + if range? && value.is_a?(Range) + scope = driver.greater_equal(scope, name, value.begin) if value.begin + scope = driver.less_equal(scope, name, value.end) if value.end scope else super @@ -40,28 +44,30 @@ def default_filter_where(scope, value) protected def parse_hash(result) - if result[:from] || result[:to] - [result[:from], result[:to]] - else - nil + to_range(result[:from], result[:to]) + end + + def to_range(from, to) + from = parse(from) + to = parse(to) + return nil unless to || from + + # If wrong range is given - reverse it to be always valid + if from && to && from > to + from, to = to, from end + from..to end def parse_array(result) + first = result.first + last = result.last + case result.size when 0 nil - when 1 - result.first - when 2 - if result.first && result.last && result.first > result.last - # If wrong range is given - reverse it to be always valid - result.reverse - elsif !result.first && !result.last - nil - else - result - end + when 1,2 + to_range(first, last) else raise ArgumentError, "Can not create a date range from array of more than two: #{result.inspect}" end diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 05ae48b..4893dab 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -186,8 +186,9 @@ def datagrid_range_filter(_type, filter, options = {}) end def datagrid_range_filter_options(object, filter, type, options) - type_method_map = { from: :first, to: :last } + type_method_map = { from: :begin, to: :end } options = add_html_classes(options, "datagrid-range-#{type}") + options[:multiple] = true options[:value] = object[filter.name]&.public_send(type_method_map[type]) # In case of datagrid ranged filter # from and to input will have same id diff --git a/spec/datagrid/core_spec.rb b/spec/datagrid/core_spec.rb index 4874b68..41fa720 100644 --- a/spec/datagrid/core_spec.rb +++ b/spec/datagrid/core_spec.rb @@ -106,7 +106,7 @@ class InspectTest < Datagrid::Base grid = InspectTest.new(created_at: %w[2014-01-01 2014-08-05], descending: true, order: "name") expect(grid.inspect).to eq( - "#<InspectTest order: :name, descending: true, created_at: [Wed, 01 Jan 2014, Tue, 05 Aug 2014]>" + "#<InspectTest order: :name, descending: true, created_at: Wed, 01 Jan 2014..Tue, 05 Aug 2014>" ) end end diff --git a/spec/datagrid/filters/date_filter_spec.rb b/spec/datagrid/filters/date_filter_spec.rb index 8187b8b..9d09a52 100644 --- a/spec/datagrid/filters/date_filter_spec.rb +++ b/spec/datagrid/filters/date_filter_spec.rb @@ -41,7 +41,7 @@ scope { Entry } filter(:created_at, :date, range: true) end - expect(report.created_at).to eq([from.to_date, to.to_date]) + expect(report.created_at).to eq(from.to_date..to.to_date) expect(report.assets).not_to include(e1) expect(report.assets).to include(e2) expect(report.assets).not_to include(e3) @@ -50,11 +50,11 @@ report.created_at = {from: nil, to: nil} expect(report.created_at).to eq(nil) report.created_at = {from: Date.today, to: nil} - expect(report.created_at).to eq([Date.today, nil]) + expect(report.created_at).to eq(Date.today..nil) report.created_at = {from: nil, to: Date.today} - expect(report.created_at).to eq([nil, Date.today]) + expect(report.created_at).to eq(nil..Date.today) report.created_at = {from: Time.now, to: Time.now} - expect(report.created_at).to eq([Date.today, Date.today]) + expect(report.created_at).to eq(Date.today..Date.today) end { active_record: Entry, mongoid: MongoidEntry, sequel: SequelEntry }.each do |orm, klass| @@ -154,7 +154,7 @@ def entry_dated(date) scope { Entry } filter(:created_at, :date, range: true) end - expect(report.created_at).to eq([range.last.to_date, range.first.to_date]) + expect(report.created_at).to eq(range.last.to_date..range.first.to_date) expect(report.assets).to include(e1) expect(report.assets).to include(e2) expect(report.assets).to include(e3) @@ -166,7 +166,7 @@ def entry_dated(date) report = test_report(created_at: date) do scope { Entry } filter(:created_at, :date, range: true) do |value| - where("created_at >= ?", value) + where(created_at: value) end end expect(report.assets).not_to include(Entry.create!(created_at: time - 1.day)) @@ -202,14 +202,14 @@ def entry_dated(date) scope { Entry } filter(:created_at, :date, range: true) end - expect(report.created_at).to eq([Date.new(2012, 0o1, 0o1), Date.new(2013, 0o1, 0o1)]) + expect(report.created_at).to eq(Date.new(2012, 0o1, 0o1)..Date.new(2013, 0o1, 0o1)) end it "should automatically reverse Array if first more than last" do report = test_report(created_at: %w[2013-01-01 2012-01-01]) do scope { Entry } filter(:created_at, :date, range: true) end - expect(report.created_at).to eq([Date.new(2012, 0o1, 0o1), Date.new(2013, 0o1, 0o1)]) + expect(report.created_at).to eq(Date.new(2012, 0o1, 0o1)..Date.new(2013, 0o1, 0o1)) end it "should nullify blank range" do diff --git a/spec/datagrid/filters/date_time_filter_spec.rb b/spec/datagrid/filters/date_time_filter_spec.rb index b0d1627..b518b10 100644 --- a/spec/datagrid/filters/date_time_filter_spec.rb +++ b/spec/datagrid/filters/date_time_filter_spec.rb @@ -121,17 +121,17 @@ def entry_dated(date) scope { Entry } filter(:created_at, :datetime, range: true) end - expect(report.created_at).to eq([range.last, range.first]) + expect(report.created_at).to eq(range.last..range.first) expect(report.assets).to include(e1) expect(report.assets).to include(e2) expect(report.assets).to include(e3) end it "should support block" do - report = test_report(created_at: Time.now) do + report = test_report(created_at: Time.now..) do scope { Entry } filter(:created_at, :datetime, range: true) do |value| - where("created_at >= ?", value) + where(created_at: value) end end expect(report.assets).not_to include(Entry.create!(created_at: 1.day.ago)) @@ -167,6 +167,6 @@ def entry_dated(date) scope { Entry } filter(:created_at, :datetime, range: true) end - expect(report.created_at).to eq([Time.new(2012, 0o1, 0o1, 1, 0), Time.new(2013, 0o1, 0o1, 1, 0)]) + expect(report.created_at).to eq(Time.new(2012, 0o1, 0o1, 1, 0)..Time.new(2013, 0o1, 0o1, 1, 0)) end end diff --git a/spec/datagrid/filters/integer_filter_spec.rb b/spec/datagrid/filters/integer_filter_spec.rb index fb6f5d7..7cb937d 100644 --- a/spec/datagrid/filters/integer_filter_spec.rb +++ b/spec/datagrid/filters/integer_filter_spec.rb @@ -73,7 +73,7 @@ scope { Entry } filter(:group_id, :integer, range: true) end - expect(report.group_id).to eq([1, 7]) + expect(report.group_id).to eq(1..7) expect(report.assets).to include(entry7) expect(report.assets).to include(entry4) expect(report.assets).to include(entry1) @@ -95,7 +95,7 @@ scope { Entry.joins(:group) } filter(:rating, :integer, range: true) end - expect(report.rating).to eq([4, nil]) + expect(report.rating).to eq(4..nil) expect(report.assets).not_to include(Entry.create!(group: Group.create!(rating: 3))) expect(report.assets).to include(Entry.create!(group: Group.create!(rating: 5))) end @@ -105,7 +105,7 @@ scope { Entry } filter(:group_id, :integer, multiple: true) end - expect(report.group_id).to eq([1, 2]) + expect(report.group_id).to eq([1,2]) expect(report.assets).to include(entry1) expect(report.assets).to include(entry2) expect(report.assets).not_to include(entry3) From 68c2340d02a9ca885e6e3f5df6fd2dcf36184284 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Wed, 6 Nov 2024 20:30:35 +0100 Subject: [PATCH 042/157] Change range inputs from array to [from] [to] hash --- VERSION2.md | 10 ++++-- lib/datagrid/filters/ranged_filter.rb | 2 +- lib/datagrid/form_builder.rb | 1 + spec/datagrid/form_builder_spec.rb | 44 +++++++++++++-------------- 4 files changed, 31 insertions(+), 26 deletions(-) diff --git a/VERSION2.md b/VERSION2.md index ef9f45d..88221c3 100644 --- a/VERSION2.md +++ b/VERSION2.md @@ -133,7 +133,11 @@ The default behavior can be changed back by using `input_options`: ``` ruby filter(:created_at, :date, range: true, input_options: {type: 'text'}) filter(:salary, :integer, range: true, input_options: {type: 'text'}) +``` + +Additionally, textarea inputs are now supported this way: +``` ruby # Rendered as <textarea/> tag: filter(:text, :string, input_options: {type: 'textarea'}) ``` @@ -212,13 +216,13 @@ Version 2: If you still want to have an HTML class attached to a column use `class` column option: ``` ruby -column(:name, class: 'column-name') +column(:name, class: 'short-column') ``` ``` html -<th class="column-name" data-datagrid-column="name">Name</th> +<th class="short-column" data-datagrid-column="name">Name</th> ... -<td class="column-name" data-datagrid-column="name">John</td> +<td class="short-column" data-datagrid-column="name">John</td> ``` If you want to change this behavior completely, diff --git a/lib/datagrid/filters/ranged_filter.rb b/lib/datagrid/filters/ranged_filter.rb index 03c9174..1e0c105 100644 --- a/lib/datagrid/filters/ranged_filter.rb +++ b/lib/datagrid/filters/ranged_filter.rb @@ -69,7 +69,7 @@ def parse_array(result) when 1,2 to_range(first, last) else - raise ArgumentError, "Can not create a date range from array of more than two: #{result.inspect}" + raise ArgumentError, "Can not create a range from array of more than two elements" end end end diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 4893dab..95b47ad 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -190,6 +190,7 @@ def datagrid_range_filter_options(object, filter, type, options) options = add_html_classes(options, "datagrid-range-#{type}") options[:multiple] = true options[:value] = object[filter.name]&.public_send(type_method_map[type]) + options[:name] = @template.field_name(object_name, filter.name, type) # In case of datagrid ranged filter # from and to input will have same id if !options.key?(:id) diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 1162c05..15314fa 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -180,10 +180,10 @@ class MyTemplate it { should equal_to_dom( '<input value="1" id="from_hello" class="datagrid-range-from" - multiple type="number" step="1" name="report[group_id][]"/>' \ + multiple type="number" step="1" name="report[group_id][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2" id="to_hello" class="datagrid-range-to" - multiple type="number" step="1" name="report[group_id][]"/>' + multiple type="number" step="1" name="report[group_id][to]"/>' ) } end @@ -192,10 +192,10 @@ class MyTemplate it { should equal_to_dom( '<input value="10" class="datagrid-range-from" - multiple type="number" step="1" name="report[group_id][]"/>' \ + multiple type="number" step="1" name="report[group_id][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input class="datagrid-range-to" - multiple type="number" step="1" name="report[group_id][]"/>' + multiple type="number" step="1" name="report[group_id][to]"/>' ) } it { should be_html_safe } @@ -204,9 +204,9 @@ class MyTemplate let(:_range) { [nil, 10] } it { should equal_to_dom( - '<input class="datagrid-range-from" multiple type="number" step="1" name="report[group_id][]"/>' \ + '<input class="datagrid-range-from" multiple type="number" step="1" name="report[group_id][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ - '<input value="10" class="datagrid-range-to" multiple type="number" step="1" name="report[group_id][]"/>' + '<input value="10" class="datagrid-range-to" multiple type="number" step="1" name="report[group_id][to]"/>' ) } it { should be_html_safe } @@ -216,9 +216,9 @@ class MyTemplate let(:_range) { 2..1 } it { should equal_to_dom( - '<input value="1" class="datagrid-range-from" multiple type="number" step="1" name="report[group_id][]"/>' \ + '<input value="1" class="datagrid-range-from" multiple type="number" step="1" name="report[group_id][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ - '<input value="2" class="datagrid-range-to" multiple type="number" step="1" name="report[group_id][]"/>' + '<input value="2" class="datagrid-range-to" multiple type="number" step="1" name="report[group_id][to]"/>' ) } end @@ -238,9 +238,9 @@ class MyTemplate let(:_range) { nil } it { should equal_to_dom( - '<input class="datagrid-range-from" multiple type="number" step="1" name="report[group_id][]"> + '<input class="datagrid-range-from" multiple type="number" step="1" name="report[group_id][from]"> <span class="datagrid-range-separator"> - </span> - <input class="datagrid-range-to" multiple type="number" step="1" name="report[group_id][]">' + <input class="datagrid-range-to" multiple type="number" step="1" name="report[group_id][to]">' ) } end @@ -258,10 +258,10 @@ class MyTemplate it { should equal_to_dom( '<input value="1.5" class="datagrid-range-from" - multiple type="number" step="any" name="report[rating][]"/>' \ + multiple type="number" step="any" name="report[rating][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2.5" class="datagrid-range-to" - multiple type="number" step="any" name="report[rating][]"/>' + multiple type="number" step="any" name="report[rating][to]"/>' ) } end @@ -278,9 +278,9 @@ class MyTemplate let(:_range) { ["2012-01-03", nil] } it { should equal_to_dom( - '<input value="2012-01-03" class="datagrid-range-from" multiple type="date" name="report[created_at][]"/>' \ + '<input value="2012-01-03" class="datagrid-range-from" multiple type="date" name="report[created_at][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ - '<input class="datagrid-range-to" multiple type="date" name="report[created_at][]" value=""/>' + '<input class="datagrid-range-to" multiple type="date" name="report[created_at][to]" value=""/>' ) } it { should be_html_safe } @@ -295,10 +295,10 @@ class MyTemplate it { should equal_to_dom( '<input value="2013-01-01" class="datagrid-range-from" - multiple type="date" name="report[created_at][]"/>' \ + multiple type="date" name="report[created_at][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2013-02-02" class="datagrid-range-to" - multiple type="date" name="report[created_at][]"/>' + multiple type="date" name="report[created_at][to]"/>' ) } end @@ -307,10 +307,10 @@ class MyTemplate it { should equal_to_dom( '<input class="datagrid-range-from" - multiple type="date" value="" name="report[created_at][]"/>' \ + multiple type="date" value="" name="report[created_at][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2012-01-03" class="datagrid-range-to" - multiple type="date" name="report[created_at][]"/>' + multiple type="date" name="report[created_at][to]"/>' ) } it { should be_html_safe } @@ -321,10 +321,10 @@ class MyTemplate it { should equal_to_dom( '<input value="2012-01-01" class="datagrid-range-from" - multiple type="date" name="report[created_at][]"/>' \ + multiple type="date" name="report[created_at][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2012-01-02" class="datagrid-range-to" - multiple type="date" name="report[created_at][]"/>' + multiple type="date" name="report[created_at][to]"/>' ) } end @@ -337,9 +337,9 @@ class MyTemplate let(:_range) { [nil, nil] } it { should equal_to_dom( - '<input class="datagrid-range-from" multiple type="date" value="" name="report[created_at][]"/>' \ + '<input class="datagrid-range-from" multiple type="date" value="" name="report[created_at][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ - '<input class="datagrid-range-to" multiple type="date" value="" name="report[created_at][]"/>' + '<input class="datagrid-range-to" multiple type="date" value="" name="report[created_at][to]"/>' ) } end From 252e069d70303c797b557533b756aae5eb229577 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Wed, 6 Nov 2024 22:13:39 +0100 Subject: [PATCH 043/157] Dynamic filter rework to use Hash instead of Array --- VERSION2.md | 51 +++++++++++++++++++- lib/datagrid/filters/dynamic_filter.rb | 41 ++++++++++++++-- spec/datagrid/filters/dynamic_filter_spec.rb | 32 +++++++----- spec/datagrid/form_builder_spec.rb | 16 ++++-- 4 files changed, 116 insertions(+), 24 deletions(-) diff --git a/VERSION2.md b/VERSION2.md index 88221c3..ecc5db3 100644 --- a/VERSION2.md +++ b/VERSION2.md @@ -144,7 +144,56 @@ filter(:text, :string, input_options: {type: 'textarea'}) ## Names collision restriction -TODO +HTML5 prohibits multiple inputs to have the same name. +This is contradicts to Rails parameters convention that serializes multiple inputs with same name into array: + +``` html +Date From: +<input type="number" name="grid[members_count][]" value="1"/> +Date To: +<input type="number" name="grid[members_count][]" value="5"/> +``` + +Serialized to: + +``` ruby +{grid: {members_count: ['1', '5']}} +``` + +V1 had used this convention for `range: true` and `dynamic` filter type. +Now, they are using the following convention instead: + +``` html +Date From: +<input type="number" name="grid[members_count][from]" value="1"/> +Date To: +<input type="number" name="grid[members_count][to]" value="5"/> +``` + +`Grid#members_count` will automatically typecast a hash +into appropriate `Range` on assignment: + +``` ruby +grid.members_count = {from: 1, to: 5} +grid.members_count # => 1..5 +``` + +The old convention would still work +to ensure smooth transition to new version: + +``` ruby +grid.members_count = [3, 7] +grid.members_count # => 3..7 +``` + +However, the `f.datagrid_filter :members_count` +will always generate from/to inputs instead: + +``` html +<input value="3" type="number" step="1" name="grid[members_count][from]"/> +<span class="datagrid-range-separator"> - </span> +<input value="7" type="number" step="1" name="grid[members_count][to]"/> +``` ## HTML5 data attributes diff --git a/lib/datagrid/filters/dynamic_filter.rb b/lib/datagrid/filters/dynamic_filter.rb index 5e08b95..77c6507 100644 --- a/lib/datagrid/filters/dynamic_filter.rb +++ b/lib/datagrid/filters/dynamic_filter.rb @@ -31,18 +31,22 @@ def initialize(*) end def parse_values(filter) - field, operation, value = filter - [field, operation, type_cast(field, value)] + if filter.is_a?(Array) + field, operation, value = filter + filter = { field:, operation:, value: type_cast(field, value)} + end + filter ? FilterValue.new(filter) : nil end def unapplicable_value?(filter) - _, _, value = filter - super(value) + super(filter&.value) end def default_filter_where(scope, filter) - field, operation, value = filter + field = filter.field + operation = filter.operation + value = filter.value date_conversion = value.is_a?(Date) && driver.is_timestamp?(scope, field) return scope if field.blank? || operation.blank? @@ -122,6 +126,33 @@ def type_cast(field, value) def column_type(field) grid_class.driver.normalized_column_type(grid_class.scope, field) end + + class FilterValue < Hash + def initialize(object = nil) + super() + update(object) if object + end + + def field + self[:field] + end + + def operation + self[:operation] + end + + def value + self[:value] + end + + def to_ary + to_a + end + + def to_a + [field, operation, value] + end + end end end end diff --git a/spec/datagrid/filters/dynamic_filter_spec.rb b/spec/datagrid/filters/dynamic_filter_spec.rb index 149a461..0c4a6cb 100644 --- a/spec/datagrid/filters/dynamic_filter_spec.rb +++ b/spec/datagrid/filters/dynamic_filter_spec.rb @@ -62,22 +62,26 @@ it "should nullify incorrect value for integer" do report.condition = [:group_id, "<=", "aa"] - expect(report.condition).to eq([:group_id, "<=", nil]) + expect(report.condition).to eq( + {field: :group_id, operation: "<=", value: nil} + ) end it "should nullify incorrect value for date" do report.condition = [:shipping_date, "<=", "aa"] - expect(report.condition).to eq([:shipping_date, "<=", nil]) + expect(report.condition).to eq({ + field: :shipping_date, operation: "<=", value: nil + }) end it "should nullify incorrect value for datetime" do report.condition = [:created_at, "<=", "aa"] - expect(report.condition).to eq([:created_at, "<=", nil]) + expect(report.condition).to eq({field: :created_at, operation: "<=", value: nil}) end it "should support date comparation operation by timestamp column" do report.condition = [:created_at, "<=", "1986-08-05"] - expect(report.condition).to eq([:created_at, "<=", Date.parse("1986-08-05")]) + expect(report.condition).to eq({field: :created_at, operation: "<=", value: Date.parse("1986-08-05")}) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-04 01:01:01"))) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 23:59:59"))) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 00:00:00"))) @@ -87,7 +91,7 @@ it "should support date = operation by timestamp column" do report.condition = [:created_at, "=", "1986-08-05"] - expect(report.condition).to eq([:created_at, "=", Date.parse("1986-08-05")]) + expect(report.condition).to eq({field: :created_at, operation: "=", value: Date.parse("1986-08-05")}) expect(report.assets).not_to include(Entry.create!(created_at: Time.parse("1986-08-04 23:59:59"))) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 23:59:59"))) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 00:00:01"))) @@ -98,7 +102,7 @@ it "should support date =~ operation by timestamp column" do report.condition = [:created_at, "=~", "1986-08-05"] - expect(report.condition).to eq([:created_at, "=~", Date.parse("1986-08-05")]) + expect(report.condition).to eq({field: :created_at, operation: "=~", value: Date.parse("1986-08-05")}) expect(report.assets).not_to include(Entry.create!(created_at: Time.parse("1986-08-04 23:59:59"))) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 23:59:59"))) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 00:00:01"))) @@ -123,8 +127,10 @@ it "should support allow_nil and allow_blank options" do grid = test_report do scope { Entry } - filter(:condition, :dynamic, allow_nil: true, allow_blank: true, - operations: [">=", "<="]) do |(field, operation, value), scope| + filter( + :condition, :dynamic, allow_nil: true, allow_blank: true, + operations: [">=", "<="] + ) do |(field, operation, value), scope| if value.blank? scope.where(disabled: false) else @@ -133,8 +139,8 @@ end end - expect(grid.assets).to_not include(Entry.create!(disabled: true)) - expect(grid.assets).to include(Entry.create!(disabled: false)) + # expect(grid.assets).to_not include(Entry.create!(disabled: true)) + # expect(grid.assets).to include(Entry.create!(disabled: false)) grid.condition = [:group_id, ">=", 3] expect(grid.assets).to include(Entry.create!(disabled: true, group_id: 4)) @@ -148,9 +154,9 @@ scope { Entry } filter( :condition, :dynamic, operations: ["=", "!="] - ) do |(field, operation, value), scope| - if operation == "!=" - scope.where("#{field} != ?", value) + ) do |filter, scope| + if filter.operation == "!=" + scope.where("#{filter.field} != ?", filter.value) else default_filter end diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 15314fa..e7cb6b2 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -671,13 +671,19 @@ class MyTemplate end let(:expected_html) do <<-HTML - <select class="datagrid-dynamic-field" name="report[condition][]" id="report_condition"><option selected value="id">id</option> - <option value="name">name</option></select><select class="datagrid-dynamic-operation" name="report[condition][]" id="report_condition"><option value="=">=</option> - <option value="=~">≈</option> - <option selected value=">=">≥</option> - <option value="<=">≤</option></select><input class="datagrid-dynamic-value" name="report[condition][]" value="1" type="text" id="report_condition"> + <select class="datagrid-dynamic-field" name="report[condition][]" id="report_condition"> + <option selected value="id">id</option> + <option value="name">name</option> + </select> + <select class="datagrid-dynamic-operation" name="report[condition][]" id="report_condition"> + <option value="=">=</option> + <option value="=~">≈</option> + <option selected value=">=">≥</option> + <option value="<=">≤</option></select> + <input value="1" name="report[condition][]" class="datagrid-dynamic-value" type="text" id="report_condition"/> HTML end + it { should equal_to_dom(expected_html) } end From 67baa57435a50826588703266cfa9b13a60a7cc0 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Thu, 7 Nov 2024 11:07:41 +0100 Subject: [PATCH 044/157] Remove multiple attribute from range filters --- lib/datagrid/form_builder.rb | 2 -- spec/datagrid/form_builder_spec.rb | 44 +++++++++++++++--------------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 95b47ad..9b6c859 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -174,7 +174,6 @@ def dynamic_filter_select(name, variants, select_options, html_options) def datagrid_range_filter(_type, filter, options = {}) if filter.range? - options = options.merge(multiple: true) from_options = datagrid_range_filter_options(object, filter, :from, options) to_options = datagrid_range_filter_options(object, filter, :to, options) render_partial "range_filter", { @@ -188,7 +187,6 @@ def datagrid_range_filter(_type, filter, options = {}) def datagrid_range_filter_options(object, filter, type, options) type_method_map = { from: :begin, to: :end } options = add_html_classes(options, "datagrid-range-#{type}") - options[:multiple] = true options[:value] = object[filter.name]&.public_send(type_method_map[type]) options[:name] = @template.field_name(object_name, filter.name, type) # In case of datagrid ranged filter diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index e7cb6b2..5379fe8 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -180,10 +180,10 @@ class MyTemplate it { should equal_to_dom( '<input value="1" id="from_hello" class="datagrid-range-from" - multiple type="number" step="1" name="report[group_id][from]"/>' \ + type="number" step="1" name="report[group_id][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2" id="to_hello" class="datagrid-range-to" - multiple type="number" step="1" name="report[group_id][to]"/>' + type="number" step="1" name="report[group_id][to]"/>' ) } end @@ -192,10 +192,10 @@ class MyTemplate it { should equal_to_dom( '<input value="10" class="datagrid-range-from" - multiple type="number" step="1" name="report[group_id][from]"/>' \ + type="number" step="1" name="report[group_id][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input class="datagrid-range-to" - multiple type="number" step="1" name="report[group_id][to]"/>' + type="number" step="1" name="report[group_id][to]"/>' ) } it { should be_html_safe } @@ -204,9 +204,9 @@ class MyTemplate let(:_range) { [nil, 10] } it { should equal_to_dom( - '<input class="datagrid-range-from" multiple type="number" step="1" name="report[group_id][from]"/>' \ + '<input class="datagrid-range-from" type="number" step="1" name="report[group_id][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ - '<input value="10" class="datagrid-range-to" multiple type="number" step="1" name="report[group_id][to]"/>' + '<input value="10" class="datagrid-range-to" type="number" step="1" name="report[group_id][to]"/>' ) } it { should be_html_safe } @@ -216,9 +216,9 @@ class MyTemplate let(:_range) { 2..1 } it { should equal_to_dom( - '<input value="1" class="datagrid-range-from" multiple type="number" step="1" name="report[group_id][from]"/>' \ + '<input value="1" class="datagrid-range-from" type="number" step="1" name="report[group_id][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ - '<input value="2" class="datagrid-range-to" multiple type="number" step="1" name="report[group_id][to]"/>' + '<input value="2" class="datagrid-range-to" type="number" step="1" name="report[group_id][to]"/>' ) } end @@ -238,9 +238,9 @@ class MyTemplate let(:_range) { nil } it { should equal_to_dom( - '<input class="datagrid-range-from" multiple type="number" step="1" name="report[group_id][from]"> + '<input class="datagrid-range-from" type="number" step="1" name="report[group_id][from]"> <span class="datagrid-range-separator"> - </span> - <input class="datagrid-range-to" multiple type="number" step="1" name="report[group_id][to]">' + <input class="datagrid-range-to" type="number" step="1" name="report[group_id][to]">' ) } end @@ -258,10 +258,10 @@ class MyTemplate it { should equal_to_dom( '<input value="1.5" class="datagrid-range-from" - multiple type="number" step="any" name="report[rating][from]"/>' \ + type="number" step="any" name="report[rating][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2.5" class="datagrid-range-to" - multiple type="number" step="any" name="report[rating][to]"/>' + type="number" step="any" name="report[rating][to]"/>' ) } end @@ -278,9 +278,9 @@ class MyTemplate let(:_range) { ["2012-01-03", nil] } it { should equal_to_dom( - '<input value="2012-01-03" class="datagrid-range-from" multiple type="date" name="report[created_at][from]"/>' \ + '<input value="2012-01-03" class="datagrid-range-from" type="date" name="report[created_at][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ - '<input class="datagrid-range-to" multiple type="date" name="report[created_at][to]" value=""/>' + '<input class="datagrid-range-to" type="date" name="report[created_at][to]" value=""/>' ) } it { should be_html_safe } @@ -295,10 +295,10 @@ class MyTemplate it { should equal_to_dom( '<input value="2013-01-01" class="datagrid-range-from" - multiple type="date" name="report[created_at][from]"/>' \ + type="date" name="report[created_at][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2013-02-02" class="datagrid-range-to" - multiple type="date" name="report[created_at][to]"/>' + type="date" name="report[created_at][to]"/>' ) } end @@ -307,10 +307,10 @@ class MyTemplate it { should equal_to_dom( '<input class="datagrid-range-from" - multiple type="date" value="" name="report[created_at][from]"/>' \ + type="date" value="" name="report[created_at][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2012-01-03" class="datagrid-range-to" - multiple type="date" name="report[created_at][to]"/>' + type="date" name="report[created_at][to]"/>' ) } it { should be_html_safe } @@ -321,10 +321,10 @@ class MyTemplate it { should equal_to_dom( '<input value="2012-01-01" class="datagrid-range-from" - multiple type="date" name="report[created_at][from]"/>' \ + type="date" name="report[created_at][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2012-01-02" class="datagrid-range-to" - multiple type="date" name="report[created_at][to]"/>' + type="date" name="report[created_at][to]"/>' ) } end @@ -337,9 +337,9 @@ class MyTemplate let(:_range) { [nil, nil] } it { should equal_to_dom( - '<input class="datagrid-range-from" multiple type="date" value="" name="report[created_at][from]"/>' \ + '<input class="datagrid-range-from" type="date" value="" name="report[created_at][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ - '<input class="datagrid-range-to" multiple type="date" value="" name="report[created_at][to]"/>' + '<input class="datagrid-range-to" type="date" value="" name="report[created_at][to]"/>' ) } end From 6856b5320eb7e58e225f98be18f49d930fff8f7d Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Thu, 7 Nov 2024 13:48:12 +0100 Subject: [PATCH 045/157] Ability to serialize/deserialize ranged filters --- lib/datagrid/filters/ranged_filter.rb | 19 ++++--- .../datagrid/filters/date_time_filter_spec.rb | 27 ++++++++++ spec/datagrid/filters/integer_filter_spec.rb | 50 ++++++++++++++----- 3 files changed, 75 insertions(+), 21 deletions(-) diff --git a/lib/datagrid/filters/ranged_filter.rb b/lib/datagrid/filters/ranged_filter.rb index 1e0c105..abe73de 100644 --- a/lib/datagrid/filters/ranged_filter.rb +++ b/lib/datagrid/filters/ranged_filter.rb @@ -3,18 +3,21 @@ module Datagrid module Filters module RangedFilter - def initialize(grid, name, options, &block) - super - return unless range? - - options[:multiple] = false - end + SERIALIZED_RANGE = /\A(.*)\.{2,3}(.*)\z/ def parse_values(value) unless range? return super end case value + when String + if value == '..' || value == '...' + nil + elsif match = value.match(SERIALIZED_RANGE) + to_range(match.captures[0], match.captures[1], value.include?('...')) + else + super + end when Hash parse_hash(value) when Array @@ -47,7 +50,7 @@ def parse_hash(result) to_range(result[:from], result[:to]) end - def to_range(from, to) + def to_range(from, to, exclusive = false) from = parse(from) to = parse(to) return nil unless to || from @@ -56,7 +59,7 @@ def to_range(from, to) if from && to && from > to from, to = to, from end - from..to + exclusive ? from...to : from..to end def parse_array(result) diff --git a/spec/datagrid/filters/date_time_filter_spec.rb b/spec/datagrid/filters/date_time_filter_spec.rb index b518b10..c3d99c9 100644 --- a/spec/datagrid/filters/date_time_filter_spec.rb +++ b/spec/datagrid/filters/date_time_filter_spec.rb @@ -169,4 +169,31 @@ def entry_dated(date) end expect(report.created_at).to eq(Time.new(2012, 0o1, 0o1, 1, 0)..Time.new(2013, 0o1, 0o1, 1, 0)) end + + it "supports serialized range value" do + from = Time.parse("2013-01-01 01:00") + to = Time.parse("2013-01-02 02:00") + report = test_report do + scope { Entry } + filter(:created_at, :datetime, range: true) + end + + report.created_at = (from..to).as_json + expect(report.created_at).to eq(from..to) + + report.created_at = (from..).as_json + expect(report.created_at).to eq(from..) + + report.created_at = (..to).as_json + expect(report.created_at).to eq(..to) + + report.created_at = (from...to).as_json + expect(report.created_at).to eq(from...to) + + report.created_at = (nil..nil).as_json + expect(report.created_at).to eq(nil) + + report.created_at = (nil...nil).as_json + expect(report.created_at).to eq(nil) + end end diff --git a/spec/datagrid/filters/integer_filter_spec.rb b/spec/datagrid/filters/integer_filter_spec.rb index 7cb937d..9ea1183 100644 --- a/spec/datagrid/filters/integer_filter_spec.rb +++ b/spec/datagrid/filters/integer_filter_spec.rb @@ -33,9 +33,7 @@ scope { Entry } filter(:group_id, :integer, range: true) end - expect(report.assets).not_to include(entry7) - expect(report.assets).to include(entry4) - expect(report.assets).not_to include(entry1) + expect(report.group_id).to eq(3..5) end it "should support minimum integer argument" do @@ -43,9 +41,7 @@ scope { Entry } filter(:group_id, :integer, range: true) end - expect(report.assets).not_to include(entry1) - expect(report.assets).not_to include(entry4) - expect(report.assets).to include(entry7) + expect(report.group_id).to eq(5..) end it "should support maximum integer argument" do @@ -53,9 +49,7 @@ scope { Entry } filter(:group_id, :integer, range: true) end - expect(report.assets).to include(entry1) - expect(report.assets).to include(entry4) - expect(report.assets).not_to include(entry7) + expect(report.group_id).to eq(..5) end it "should find something in one integer interval" do @@ -68,15 +62,20 @@ expect(report.assets).not_to include(entry1) end - it "should support invalid range" do + it "supports range inversion" do report = test_report(group_id: (7..1)) do scope { Entry } filter(:group_id, :integer, range: true) end expect(report.group_id).to eq(1..7) - expect(report.assets).to include(entry7) - expect(report.assets).to include(entry4) - expect(report.assets).to include(entry1) + end + + it "converts infinite range to nil" do + report = test_report(group_id: (nil..nil)) do + scope { Entry } + filter(:group_id, :integer, range: true) + end + expect(report.group_id).to eq(nil) end it "should support block" do @@ -146,4 +145,29 @@ expect(report.group_id).to eq(group.id) end + + it "supports serialized range value" do + report = test_report do + scope { Entry } + filter(:group_id, :integer, range: true) + end + + report.group_id = (1..5).as_json + expect(report.group_id).to eq(1..5) + + report.group_id = (1..).as_json + expect(report.group_id).to eq(1..) + + report.group_id = (..5).as_json + expect(report.group_id).to eq(..5) + + report.group_id = (1...5).as_json + expect(report.group_id).to eq(1...5) + + report.group_id = (nil..nil).as_json + expect(report.group_id).to eq(nil) + + report.group_id = (nil...nil).as_json + expect(report.group_id).to eq(nil) + end end From 329f32d04e75ce365656bef9d1bc5bf1209b4c9c Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Thu, 7 Nov 2024 13:57:37 +0100 Subject: [PATCH 046/157] Use hash instead of array when generating dynamic filter inputs --- lib/datagrid/form_builder.rb | 15 ++++++++++----- spec/datagrid/form_builder_spec.rb | 22 +++++++++++----------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 9b6c859..865ab96 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -131,10 +131,8 @@ def datagrid_integer_filter(filter, options = {}) end def datagrid_dynamic_filter(filter, options = {}) - input_name = "#{object_name}[#{filter.name}][]" field, operation, value = object.filter_value(filter) options = add_filter_options(filter, **options) - options = options.merge(name: input_name) field_input = dynamic_filter_select( filter.name, object.select_options(filter) || [], @@ -144,7 +142,8 @@ def datagrid_dynamic_filter(filter, options = {}) include_hidden: false, selected: field }, - add_html_classes(options, "datagrid-dynamic-field") + **add_html_classes(options, "datagrid-dynamic-field"), + name: @template.field_name(object_name, filter.name, 'field') ) operation_input = dynamic_filter_select( filter.name, filter.operations_select, @@ -154,9 +153,15 @@ def datagrid_dynamic_filter(filter, options = {}) prompt: false, selected: operation }, - add_html_classes(options, "datagrid-dynamic-operation") + **add_html_classes(options, "datagrid-dynamic-operation"), + name: @template.field_name(object_name, filter.name, 'operation') + ) + value_input = datagrid_filter_input( + filter.name, + **add_html_classes(options, "datagrid-dynamic-value"), + value: value, + name: @template.field_name(object_name, filter.name, 'value') ) - value_input = datagrid_filter_input(filter.name, **add_html_classes(options, "datagrid-dynamic-value"), value: value) [field_input, operation_input, value_input].join("\n").html_safe end diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 5379fe8..27db321 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -647,7 +647,7 @@ class MyTemplate context "with no options" do let(:expected_html) do <<-HTML - <select class="datagrid-dynamic-field" name="report[condition][]" id="report_condition"><option value="id">Id</option> + <select class="datagrid-dynamic-field" name="report[condition][field]" id="report_condition"><option value="id">Id</option> <option value="group_id">Group</option> <option value="name">Name</option> <option value="category">Category</option> @@ -657,10 +657,10 @@ class MyTemplate <option value="confirmed">Confirmed</option> <option value="shipping_date">Shipping date</option> <option value="created_at">Created at</option> - <option value="updated_at">Updated at</option></select><select class="datagrid-dynamic-operation" name="report[condition][]" id="report_condition"><option value="=">=</option> + <option value="updated_at">Updated at</option></select><select class="datagrid-dynamic-operation" name="report[condition][operation]" id="report_condition"><option value="=">=</option> <option value="=~">≈</option> <option value=">=">≥</option> - <option value="<=">≤</option></select><input class="datagrid-dynamic-value" name="report[condition][]" type="text" id="report_condition"> + <option value="<=">≤</option></select><input class="datagrid-dynamic-value" name="report[condition][value]" type="text" id="report_condition"> HTML end it { should equal_to_dom(expected_html) } @@ -671,16 +671,16 @@ class MyTemplate end let(:expected_html) do <<-HTML - <select class="datagrid-dynamic-field" name="report[condition][]" id="report_condition"> + <select class="datagrid-dynamic-field" name="report[condition][field]" id="report_condition"> <option selected value="id">id</option> <option value="name">name</option> </select> - <select class="datagrid-dynamic-operation" name="report[condition][]" id="report_condition"> + <select class="datagrid-dynamic-operation" name="report[condition][operation]" id="report_condition"> <option value="=">=</option> <option value="=~">≈</option> <option selected value=">=">≥</option> <option value="<=">≤</option></select> - <input value="1" name="report[condition][]" class="datagrid-dynamic-value" type="text" id="report_condition"/> + <input value="1" name="report[condition][value]" class="datagrid-dynamic-value" type="text" id="report_condition"/> HTML end @@ -693,8 +693,8 @@ class MyTemplate end let(:expected_html) do <<-HTML - <select class="datagrid-dynamic-field" name="report[condition][]" id="report_condition"><option value="id">id</option><option value="name">name</option></select><select class="datagrid-dynamic-operation" name="report[condition][]" id="report_condition"><option value=">=">≥</option> - <option value="<=">≤</option></select><input class="datagrid-dynamic-value" name="report[condition][]" type="text" id="report_condition"> + <select class="datagrid-dynamic-field" name="report[condition][field]" id="report_condition"><option value="id">id</option><option value="name">name</option></select><select class="datagrid-dynamic-operation" name="report[condition][operation]" id="report_condition"><option value=">=">≥</option> + <option value="<=">≤</option></select><input class="datagrid-dynamic-value" name="report[condition][value]" type="text" id="report_condition"> HTML end it { should equal_to_dom(expected_html) } @@ -706,8 +706,8 @@ class MyTemplate end let(:expected_html) do <<-HTML - <input class="datagrid-dynamic-field" name="report[condition][]" value="id" autocomplete="off" type="hidden" id="report_condition"><select class="datagrid-dynamic-operation" name="report[condition][]" id="report_condition"><option value=">=">≥</option> - <option value="<=">≤</option></select><input class="datagrid-dynamic-value" name="report[condition][]" type="text" id="report_condition"> + <input class="datagrid-dynamic-field" name="report[condition][field]" value="id" autocomplete="off" type="hidden" id="report_condition"><select class="datagrid-dynamic-operation" name="report[condition][operation]" id="report_condition"><option value=">=">≥</option> + <option value="<=">≤</option></select><input class="datagrid-dynamic-value" name="report[condition][value]" type="text" id="report_condition"> HTML end it { should equal_to_dom(expected_html) } @@ -718,7 +718,7 @@ class MyTemplate end let(:expected_html) do <<-HTML - <select class="datagrid-dynamic-field" name="report[condition][]" id="report_condition"><option value="id">id</option><option value="name">name</option></select><input class="datagrid-dynamic-operation" name="report[condition][]" value="=" autocomplete="off" type="hidden" id="report_condition"><input class="datagrid-dynamic-value" name="report[condition][]" type="text" id="report_condition"> + <select class="datagrid-dynamic-field" name="report[condition][field]" id="report_condition"><option value="id">id</option><option value="name">name</option></select><input class="datagrid-dynamic-operation" name="report[condition][operation]" value="=" autocomplete="off" type="hidden" id="report_condition"><input class="datagrid-dynamic-value" name="report[condition][value]" type="text" id="report_condition"> HTML end it { should equal_to_dom(expected_html) } From 113536fa813681fac3b9c2da51e680eb17974b69 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Thu, 7 Nov 2024 16:59:29 +0100 Subject: [PATCH 047/157] Update migration guide --- VERSION2.md | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/VERSION2.md b/VERSION2.md index ecc5db3..563721e 100644 --- a/VERSION2.md +++ b/VERSION2.md @@ -42,6 +42,31 @@ grid.id # V1: [1, nil] # V2: (1..nil) ``` +Version 2 makes an effort to make the transition as smooth as possible to you: + +* Old Array format will be converted to new Range format +* Serialization/Deserialization of Range is help correctly + +``` ruby +grid.id = 1..5 +grid.id # => 1..5 + +grid.id = "1..5" +grid.id # => 1..5 + +grid.id = [nil, 5] +grid.id # => ..5 + +grid.id = nil..nil +grid id # => nil + +grid.id = 3..7 +# Simulate serialization/deserialization when interacting with +# jobs queue or database storage +grid = UsersGrid.new(ActiveSupport::JSON.load(grid.attributes.to_json)) +grid.id # => 3..7 +``` + ## Modern CSS classes naming conventions Built-in generated CSS classes renamed to match modern CSS naming conventions @@ -67,7 +92,7 @@ and avoid collisions with other libraries: ### Example -The difference in layout generation from v1 to v2 +The difference in layout generation from v1 to v2. ``` ruby datagrid_form_for(@grid) From ab79ed9101b3dffc5298d0dd7e935aeb8c8624df Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 8 Nov 2024 10:38:10 +0100 Subject: [PATCH 048/157] Remove SASS --- VERSION2.md | 105 ++++++------ app/assets/stylesheets/datagrid.css | 171 +++++++++++++++++++ app/assets/stylesheets/datagrid.sass | 130 -------------- app/views/datagrid/_enum_checkboxes.html.erb | 4 +- app/views/datagrid/_form.html.erb | 5 +- app/views/datagrid/_head.html.erb | 2 +- app/views/datagrid/_row.html.erb | 2 +- lib/datagrid/core.rb | 8 +- spec/datagrid/core_spec.rb | 24 ++- spec/datagrid/form_builder_spec.rb | 18 +- spec/datagrid/helper_spec.rb | 94 +++++----- 11 files changed, 315 insertions(+), 248 deletions(-) create mode 100644 app/assets/stylesheets/datagrid.css delete mode 100644 app/assets/stylesheets/datagrid.sass diff --git a/VERSION2.md b/VERSION2.md index 563721e..326c041 100644 --- a/VERSION2.md +++ b/VERSION2.md @@ -241,9 +241,8 @@ Version 2: ``` html <div class="datagrid-filter" - data-datagrid-filter="category" - data-datagrid-filter-type="string" - data-datagrid-filter-checkboxes="false" + data-filter="category" + data-type="string" > <label for="form_for_grid_category">Category</label> <input type="text" @@ -274,16 +273,16 @@ Version 2: ``` html <tr> - <th data-datagrid-column="name">Name</th> - <th data-datagrid-column="category">Category</th> + <th data-column="name">Name</th> + <th data-column="category">Category</th> </tr> <tr> - <td data-datagrid-column="name">John</th> - <td data-datagrid-column="category">Worker</th> + <td data-column="name">John</th> + <td data-column="category">Worker</th> </tr> <tr> - <td data-datagrid-column="name">Mike</th> - <td data-datagrid-column="category">Manager</th> + <td data-column="name">Mike</th> + <td data-column="category">Manager</th> </tr> ``` @@ -294,14 +293,51 @@ column(:name, class: 'short-column') ``` ``` html -<th class="short-column" data-datagrid-column="name">Name</th> +<th class="short-column" data-column="name">Name</th> ... -<td class="short-column" data-datagrid-column="name">John</td> +<td class="short-column" data-column="name">John</td> ``` If you want to change this behavior completely, modify [built-in partials](https://github.com/bogdan/datagrid/wiki/Frontend#modifying-built-in-partials) +## Inherit Datagrid::Base + +`include Datagrid` causes method name space to be clamsy. +Version 2 introduces a difference between the class +that needs to be inherited and high level namespace (just like most gems do): + +``` ruby +class ApplicationGrid < Datagrid::Base +end +``` + +## ApplicationGrid base class + +Previously recommended base class `BaseGrid` is incosistent +with Rails naming conventionsa. +It was renamed to `ApplicationGrid` instead: + +``` ruby +# app/grids/application_grid.rb +class ApplicationGrid < Datagrid::Base + def self.timestamp_column(name, *args, &block) + column(name, *args) do |model| + value = block ? block.call(model) : model.public_send(name) + value&.strftime("%Y-%m-%d") + end + end +end + +# app/grids/users_grid.rb +class UsersGrid < ApplicationGrid + scope { User } + + column(:name) + timestamp_column(:created_at) +end +``` + ## All changes in built-in partials Version 2 built-in partials are trying to expose @@ -328,15 +364,19 @@ index 9f48319..f114c17 100644 <%- end -%> <%- end -%> diff --git a/app/views/datagrid/_form.html.erb b/app/views/datagrid/_form.html.erb -index 7e175c1..84cf58e 100644 +index 7e175c1..88a39f9 100644 --- a/app/views/datagrid/_form.html.erb +++ b/app/views/datagrid/_form.html.erb -@@ -1,12 +1,12 @@ +@@ -1,12 +1,16 @@ -<%= form_for grid, options do |f| -%> +<%= form_for grid, html: {class: 'datagrid-form'}, **options do |f| -%> <% grid.filters.each do |filter| %> - <div class="datagrid-filter filter"> -+ <div class="datagrid-filter <%= filter.default_html_classes.join(' ') %>"> ++ <div class="datagrid-filter" ++ data-datagrid-filter="<%= filter.name %>" ++ data-type="<%= filter.type %>" ++ data-datagrid-filter-checkboxes="<%= filter.enum_checkboxes? %>" ++ > <%= f.datagrid_label filter %> <%= f.datagrid_filter filter %> </div> @@ -427,40 +467,3 @@ index 8708c05..0b5ff24 100644 + <%= I18n.t("datagrid.table.no_columns") %> <% end %> ``` - -## Inherit Datagrid::Base - -`include Datagrid` causes method name space to be clamsy. -Version 2 introduces a difference between the class -that needs to be inherited and high level namespace (just like most gems do): - -``` ruby -class ApplicationGrid < Datagrid::Base -end -``` - -## ApplicationGrid base class - -Previously recommended base class `BaseGrid` is incosistent -with Rails naming conventionsa. -It was renamed to `ApplicationGrid` instead: - -``` ruby -# app/grids/application_grid.rb -class ApplicationGrid < Datagrid::Base - def self.timestamp_column(name, *args, &block) - column(name, *args) do |model| - value = block ? block.call(model) : model.public_send(name) - value&.strftime("%Y-%m-%d") - end - end -end - -# app/grids/users_grid.rb -class UsersGrid < ApplicationGrid - scope { User } - - column(:name) - timestamp_column(:created_at) -end -``` diff --git a/app/assets/stylesheets/datagrid.css b/app/assets/stylesheets/datagrid.css new file mode 100644 index 0000000..fee4ee5 --- /dev/null +++ b/app/assets/stylesheets/datagrid.css @@ -0,0 +1,171 @@ +table.datagrid-table { + background-color: transparent; + border-collapse: collapse; + max-width: 100%; +} + +table.datagrid-table th { + background-color: #eee; + text-align: left; +} + +table.datagrid-table td, +table.datagrid-table th { + border: 1px solid #d6d6d6; + padding: 5px 10px; +} + +.datagrid-order-control-asc, +.datagrid-order-control-desc { + text-decoration: none; + font-weight: normal; +} + +.datagrid-order-active-asc, +.datagrid-order-active-desc { + background-color: #fff7d5; +} + +.datagrid-order-active-asc a.datagrid-order-control-asc, +.datagrid-order-active-desc a.datagrid-order-control-desc { + font-weight: bold; + color: #d00; +} + +.datagrid-no-results { + text-align: center; +} + +.datagrid-form { + background-color: #f0f0f0; + border-radius: 5px; + padding: 20px; +} + +.datagrid-filter { + margin: 10px; +} + +.datagrid-filter::before, +.datagrid-filter::after { + content: ''; + display: table; +} + +.datagrid-filter::after { + clear: both; +} + +.datagrid-filter label { + width: 150px; + float: left; +} + +.datagrid-filter a { + float: left; +} + +.datagrid-filter input { + border: 2px solid #ccc; + border-radius: 4px; + float: left; + padding: 5px 12px; + width: 300px; +} + +.datagrid-filter input.datagrid-range-from, +.datagrid-filter input.datagrid-range-to { + width: 83px; +} + +.datagrid-filter select { + float: left; + width: 300px +} + +.datagrid-filter select[multiple] { + border: 2px solid #ccc; + border-radius: 5px; + height: 100px; +} + +.datagrid-filter .datagrid-dynamic-field { + width: 178px; +} + +.datagrid-filter .datagrid-dynamic-operation { + margin-left: 7px; + width: 50px; +} + +.datagrid-filter .datagrid-dynamic-value { + margin: 10px 0 0 150px; + clear: both; +} + +.datagrid-filter .datagrid-range-separator { + float: left; + margin: 6px 4px 0; +} + +.datagrid-enum-checkboxes { + float: left; +} + +.datagrid-enum-checkboxes label { + display: block; + float: none; + width: 100%; +} + +input.datagrid-range-from, input.datagrid-range-to { + width: 144px !important +} + +select.datagrid-dynamic-field { + width: 242px +} + +.datagrid-enum-checkboxes input { + margin: 7px; + float: none; + width: auto; +} + +.datagrid-actions { + padding-left: calc(150px + 10px); +} + +.datagrid-actions input[type='submit'] { + background-color: #555; + border: none; + border-radius: 5px; + color: white; + cursor: pointer; + font-size: 14px; + font-weight: bold; + line-height: normal; + padding: 7px 15px; + vertical-align: middle; + display: inline-block; + zoom: 1; + *display: inline; +} + +.datagrid-actions input[type='submit']:hover, +.datagrid-actions input[type='submit']:focus { + background-color: #333; +} + +.datagrid-actions input[type='submit']:active { + background-color: #000; +} + +.datagrid-actions > a { + font-size: 14px; + padding: 7px 15px; + vertical-align: middle; + display: inline-block; + zoom: 1; + *display: inline; +} diff --git a/app/assets/stylesheets/datagrid.sass b/app/assets/stylesheets/datagrid.sass deleted file mode 100644 index 0f25722..0000000 --- a/app/assets/stylesheets/datagrid.sass +++ /dev/null @@ -1,130 +0,0 @@ -$dg-form-label: 150px - -= clearfix - *zoom: 1 - - &:before, - &:after - display: table - content: '' - - &:after - clear: both - -=inline-block - display: inline-block - zoom: 1 - *display: inline - -table.datagrid-table - background-color: transparent - border-collapse: collapse - max-width: 100% - - th - background-color: #eee - text-align: left - - td, - th - border: 1px solid #d6d6d6 - padding: 5px 10px - -.datagrid-order - a.datagird-order-control-asc, a.datagird-order-control-desc - text-decoration: none - font-weight: normal - -.datagrid-order-active-asc, .datagrid-order-active-desc - background-color: #fff7d5 - - a.datagird-order-control-asc, a.datagird-order-control-desc - font-weight: bold - color: #d00 - -.datagrid-no-results - text-align: center - -.datagrid-form - background-color: #f0f0f0 - border-radius: 5px - padding: 20px - -.datagrid-filter - margin: 10px - +clearfix - - label - width: $dg-form-label - float: left - a - float: left - - input - border: 2px solid #ccc - border-radius: 4px - float: left - padding: 5px 12px - width: 207px - - &.datagrid-range-from, &.datagrid-range-to - width: 83px - - select - float: left - width: 235px - - &[multiple] - border: 2px solid #ccc - border-radius: 5px - height: 100px - .datagrid-dynamic-field - width: 178px - .datagrid-dynamic-operation - margin-left: 7px - width: 50px - .datagrid-dynamic-value - margin: 10px 0 0 $dg-form-label - clear: both - - .datagrid-range-separator - float: left - margin: 6px 4px 0 - &.datagrid-enum-checkboxes - label - float: none - display: block - width: 100% - margin-left: 150px - input - margin: 7px - - -.datagrid-actions - padding-left: $dg-form-label + 10 - - input[type='submit'] - background-color: #555 - border: none - border-radius: 5px - color: white - cursor: pointer - font-size: 14px - font-weight: bold - line-height: normal - padding: 7px 15px - vertical-align: middle - +inline-block - - &:hover, - &:focus - background-color: #333 - - &:active - background-color: #000 - - > a - font-size: 14px - padding: 7px 15px - vertical-align: middle - +inline-block diff --git a/app/views/datagrid/_enum_checkboxes.html.erb b/app/views/datagrid/_enum_checkboxes.html.erb index f114c17..2d46139 100644 --- a/app/views/datagrid/_enum_checkboxes.html.erb +++ b/app/views/datagrid/_enum_checkboxes.html.erb @@ -2,10 +2,12 @@ Indent in this file may cause extra space to appear. You can add indent if whitespace doesn't matter for you %> +<div class="datagrid-enum-checkboxes"> <%- elements.each do |value, text, checked| -%> <%- id = [form.object_name, filter.name, value].join('_').underscore -%> -<%= form.datagrid_label(filter.name, **options, for: id) do -%> +<%= form.datagrid_label(filter.name, **options, for: id, class: 'datagrid-enum-checkbox-label') do -%> <%= form.datagrid_filter_input(filter.name, type: :checkbox, multiple: true, id: id, checked: checked, include_hidden: false, value: value.to_s) -%> <%= text -%> <%- end -%> <%- end -%> +</div> diff --git a/app/views/datagrid/_form.html.erb b/app/views/datagrid/_form.html.erb index 88a39f9..bd66d9f 100644 --- a/app/views/datagrid/_form.html.erb +++ b/app/views/datagrid/_form.html.erb @@ -1,9 +1,8 @@ <%= form_for grid, html: {class: 'datagrid-form'}, **options do |f| -%> <% grid.filters.each do |filter| %> <div class="datagrid-filter" - data-datagrid-filter="<%= filter.name %>" - data-datagrid-filter-type="<%= filter.type %>" - data-datagrid-filter-checkboxes="<%= filter.enum_checkboxes? %>" + data-filter="<%= filter.name %>" + data-type="<%= filter.type %>" > <%= f.datagrid_label filter %> <%= f.datagrid_filter filter %> diff --git a/app/views/datagrid/_head.html.erb b/app/views/datagrid/_head.html.erb index affccf4..c3264bb 100644 --- a/app/views/datagrid/_head.html.erb +++ b/app/views/datagrid/_head.html.erb @@ -1,6 +1,6 @@ <tr> <% grid.html_columns(*options[:columns]).each do |column| %> - <th class="<%= datagrid_column_classes(grid, column) %>" data-datagrid-column="<%= column.name %>"> + <th class="<%= datagrid_column_classes(grid, column) %>" data-column="<%= column.name %>"> <%= column.header %> <%= datagrid_order_for(grid, column, options) if column.supports_order? && options[:order]%> </th> diff --git a/app/views/datagrid/_row.html.erb b/app/views/datagrid/_row.html.erb index b431ab7..20f3ffb 100644 --- a/app/views/datagrid/_row.html.erb +++ b/app/views/datagrid/_row.html.erb @@ -1,5 +1,5 @@ <tr> <% grid.html_columns(*options[:columns]).each do |column| %> - <td class="<%= datagrid_column_classes(grid, column) %>" data-datagrid-column="<%= column.name %>"><%= datagrid_value(grid, column, asset) %></td> + <td class="<%= datagrid_column_classes(grid, column) %>" data-column="<%= column.name %>"><%= datagrid_value(grid, column, asset) %></td> <% end %> </tr> diff --git a/lib/datagrid/core.rb b/lib/datagrid/core.rb index 1578cbc..1a167c9 100644 --- a/lib/datagrid/core.rb +++ b/lib/datagrid/core.rb @@ -261,7 +261,13 @@ def reset protected def sanitize_for_mass_assignment(attributes) - forbidden_attributes_protection ? super : attributes + if forbidden_attributes_protection + super + elsif defined?(ActionController::Parameters) && attributes.is_a?(ActionController::Parameters) + attributes.permit!.to_h + else + attributes + end end end end diff --git a/spec/datagrid/core_spec.rb b/spec/datagrid/core_spec.rb index 41fa720..c2ff630 100644 --- a/spec/datagrid/core_spec.rb +++ b/spec/datagrid/core_spec.rb @@ -206,13 +206,14 @@ class EqualTest < Datagrid::Base end it "permites all attributes by default" do - expect do - test_report(params) do - scope { Entry } - filter(:name) - end - end.to_not raise_error + grid = test_report(params) do + scope { Entry } + filter(:name) + end + + expect(grid.name).to eq('one') end + it "doesn't permit attributes when forbidden_attributes_protection is set" do expect do test_report(params) do @@ -222,6 +223,7 @@ class EqualTest < Datagrid::Base end end.to raise_error(ActiveModel::ForbiddenAttributesError) end + it "permits attributes when forbidden_attributes_protection is set and attributes are permitted" do expect do test_report(params.permit!) do @@ -231,6 +233,16 @@ class EqualTest < Datagrid::Base end end.to_not raise_error end + + it "supports hash attribute assignment" do + grid = test_report( + ActionController::Parameters.new(group_id: {from: 1, to:2}) + ) do + scope { Entry } + filter(:group_id, :integer, range: true) + end + expect(grid.group_id).to eq(1..2) + end end describe ".query_param" do diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 27db321..5b64bb5 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -439,18 +439,20 @@ class MyTemplate let(:_category_filter_options) { { checkboxes: true } } it { should equal_to_dom( - ' -<label for="report_category_first"> + <<-HTML +<div class="datagrid-enum-checkboxes"> +<label for="report_category_first" class="datagrid-enum-checkbox-label"> <input type="checkbox" id="report_category_first" value="first" name="report[category][]" /> first </label> -<label for="report_category_second"> +<label for="report_category_second" class="datagrid-enum-checkbox-label"> <input type="checkbox" id="report_category_second" value="second" name="report[category][]" /> second </label> -' +</div> + HTML ) } @@ -611,18 +613,20 @@ class MyTemplate let(:_filter) { :column_names } let(:expected_html) do <<~DOM - <label for="report_column_names_id"> + <div class="datagrid-enum-checkboxes"> + <label for="report_column_names_id" class="datagrid-enum-checkbox-label"> <input id="report_column_names_id" type="checkbox" value="id" checked name="report[column_names][]"> Id </label> - <label for="report_column_names_name"> + <label for="report_column_names_name" class="datagrid-enum-checkbox-label"> <input id="report_column_names_name" type="checkbox" value="name" checked name="report[column_names][]"/> Name </label> - <label for="report_column_names_category"> + <label for="report_column_names_category" class="datagrid-enum-checkbox-label"> <input id="report_column_names_category" type="checkbox" value="category" name="report[column_names][]"> Category </label> + </div> DOM end diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 8cb24fd..46f4498 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -58,12 +58,12 @@ datagrid_table = subject.datagrid_table(grid) expect(datagrid_table).to match_css_pattern({ - "table.datagrid-table tr th[data-datagrid-column=group] div.datagrid-order" => 1, - "table.datagrid-table tr th[data-datagrid-column=group]" => /Group.*/, - "table.datagrid-table tr th[data-datagrid-column=name] div.datagrid-order" => 1, - "table.datagrid-table tr th[data-datagrid-column=name]" => /Name.*/, - "table.datagrid-table tr td[data-datagrid-column=group]" => "Pop", - "table.datagrid-table tr td[data-datagrid-column=name]" => "Star" + "table.datagrid-table tr th[data-column=group] div.datagrid-order" => 1, + "table.datagrid-table tr th[data-column=group]" => /Group.*/, + "table.datagrid-table tr th[data-column=name] div.datagrid-order" => 1, + "table.datagrid-table tr th[data-column=name]" => /Name.*/, + "table.datagrid-table tr td[data-column=group]" => "Pop", + "table.datagrid-table tr td[data-column=name]" => "Star" }) end @@ -72,12 +72,12 @@ datagrid_table = subject.datagrid_table(grid, [entry]) expect(datagrid_table).to match_css_pattern({ - "table.datagrid-table tr th[data-datagrid-column=group] div.datagrid-order" => 1, - "table.datagrid-table tr th[data-datagrid-column=group]" => /Group.*/, - "table.datagrid-table tr th[data-datagrid-column=name] div.datagrid-order" => 1, - "table.datagrid-table tr th[data-datagrid-column=name]" => /Name.*/, - "table.datagrid-table tr td[data-datagrid-column=group]" => "Pop", - "table.datagrid-table tr td[data-datagrid-column=name]" => "Star" + "table.datagrid-table tr th[data-column=group] div.datagrid-order" => 1, + "table.datagrid-table tr th[data-column=group]" => /Group.*/, + "table.datagrid-table tr th[data-column=name] div.datagrid-order" => 1, + "table.datagrid-table tr th[data-column=name]" => /Name.*/, + "table.datagrid-table tr td[data-column=group]" => "Pop", + "table.datagrid-table tr td[data-column=name]" => "Star" }) end @@ -87,10 +87,10 @@ it "should support columns option" do expect(subject.datagrid_table(grid, [entry], columns: [:name])).to match_css_pattern( - "table.datagrid-table th[data-datagrid-column=name]" => 1, - "table.datagrid-table td[data-datagrid-column=name]" => 1, - "table.datagrid-table th[data-datagrid-column=group]" => 0, - "table.datagrid-table td[data-datagrid-column=group]" => 0 + "table.datagrid-table th[data-column=name]" => 1, + "table.datagrid-table td[data-column=name]" => 1, + "table.datagrid-table th[data-column=group]" => 0, + "table.datagrid-table td[data-column=group]" => 0 ) end @@ -105,10 +105,10 @@ it "should output only given column names" do expect(subject.datagrid_table(grid, [entry])).to match_css_pattern( - "table.datagrid-table th[data-datagrid-column=name]" => 1, - "table.datagrid-table td[data-datagrid-column=name]" => 1, - "table.datagrid-table th[data-datagrid-column=category]" => 0, - "table.datagrid-table td[data-datagrid-column=category]" => 0 + "table.datagrid-table th[data-column=name]" => 1, + "table.datagrid-table td[data-column=name]" => 1, + "table.datagrid-table th[data-column=category]" => 0, + "table.datagrid-table td[data-column=category]" => 0 ) end end @@ -156,8 +156,8 @@ end it "should render table" do expect(subject.datagrid_table(grid)).to match_css_pattern( - "table.datagrid-table th[data-datagrid-column=name]" => 1, - "table.datagrid-table td[data-datagrid-column=name]" => 2 + "table.datagrid-table th[data-column=name]" => 1, + "table.datagrid-table td[data-column=name]" => 2 ) end end @@ -172,8 +172,8 @@ end it "should render table" do expect(subject.datagrid_table(grid)).to match_css_pattern( - "table.datagrid-table th[data-datagrid-column=name]" => 1, - "table.datagrid-table td[data-datagrid-column=name]" => 2 + "table.datagrid-table th[data-column=name]" => 1, + "table.datagrid-table td[data-column=name]" => 2 ) end end @@ -186,7 +186,7 @@ column(:name) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-datagrid-column=name].datagrid-order-active-asc" => "Star" + "tr td[data-column=name].datagrid-order-active-asc" => "Star" ) end it "should add ordering classes to column" do @@ -209,7 +209,7 @@ column(:name) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-datagrid-column=name].datagrid-order-active-desc" => "Star" + "tr td[data-column=name].datagrid-order-active-desc" => "Star" ) end @@ -220,7 +220,7 @@ end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-datagrid-column=name]" => "Star" + "tr td[data-column=name]" => "Star" ) end @@ -232,7 +232,7 @@ end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-datagrid-column=name] span" => "Star" + "tr td[data-column=name] span" => "Star" ) end @@ -243,7 +243,7 @@ end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-datagrid-column=name]" => "Star" + "tr td[data-column=name]" => "Star" ) end @@ -256,7 +256,7 @@ end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-datagrid-column=name]" => "Star" + "tr td[data-column=name]" => "Star" ) end @@ -267,7 +267,7 @@ end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-datagrid-column=name]" => "Star" + "tr td[data-column=name]" => "Star" ) end @@ -277,7 +277,7 @@ column(:name, html: ->(data) { content_tag :h1, data }) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-datagrid-column=name] h1" => "Star" + "tr td[data-column=name] h1" => "Star" ) end @@ -289,7 +289,7 @@ end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-datagrid-column=name] em" => "STAR" + "tr td[data-column=name] em" => "STAR" ) end @@ -301,7 +301,7 @@ end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-datagrid-column=name] span" => "Star-Entry" + "tr td[data-column=name] span" => "Star-Entry" ) end @@ -313,7 +313,7 @@ }) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-datagrid-column=name] h1" => "Star-star" + "tr td[data-column=name] h1" => "Star-star" ) end @@ -325,7 +325,7 @@ }) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-datagrid-column=name] h1" => "Star-star-Entry" + "tr td[data-column=name] h1" => "Star-star-Entry" ) end @@ -339,7 +339,7 @@ end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-datagrid-column=name] h1" => "STAR-Star" + "tr td[data-column=name] h1" => "STAR-Star" ) end @@ -353,7 +353,7 @@ end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-datagrid-column=name] h1" => "STAR-Star-Entry" + "tr td[data-column=name] h1" => "STAR-Star-Entry" ) end @@ -364,10 +364,10 @@ column(:category) end expect(subject.datagrid_rows(rp, [entry], columns: [:name])).to match_css_pattern( - "tr td[data-datagrid-column=name]" => "Star" + "tr td[data-column=name]" => "Star" ) expect(subject.datagrid_rows(rp, [entry], columns: [:name])).to match_css_pattern( - "tr td[data-datagrid-column=category]" => 0 + "tr td[data-column=category]" => 0 ) end @@ -378,7 +378,7 @@ end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-datagrid-column=name].my_class" => "Star" + "tr td[data-column=name].my_class" => "Star" ) end @@ -394,7 +394,7 @@ end it "should ignore them" do expect(subject.datagrid_rows(grid, [entry])).to match_css_pattern( - "td[data-datagrid-column=name]" => 1 + "td[data-column=name]" => 1 ) end end @@ -402,7 +402,7 @@ it "should escape html" do entry.update!(name: "<div>hello</div>") expect(subject.datagrid_rows(grid, [entry], columns: [:name])).to equal_to_dom(<<-HTML) - <tr><td class="" data-datagrid-column="name"><div>hello</div></td></tr> + <tr><td class="" data-column="name"><div>hello</div></td></tr> HTML end @@ -412,7 +412,7 @@ model.name.html_safe end expect(subject.datagrid_rows(grid, [entry], columns: [:safe_name])).to equal_to_dom(<<-HTML) - <tr><td class="" data-datagrid-column="safe_name"><div>hello</div></td></tr> + <tr><td class="" data-column="safe_name"><div>hello</div></td></tr> HTML end end @@ -449,7 +449,7 @@ class FormForGrid < Datagrid::Base expect(subject.datagrid_form_for(object, url: "/grid")).to match_css_pattern( "form.datagrid-form[action='/grid']" => 1, "form input[name=utf8]" => 1, - "form .datagrid-filter[data-datagrid-filter=category][data-datagrid-filter-type=string] label" => "Category", + "form .datagrid-filter[data-filter=category][data-type=string] label" => "Category", "form .datagrid-filter input[name='form_for_grid[category]'][value=hello]" => 1, "form .datagrid-actions input[name=commit][value=Search]" => 1, "form .datagrid-actions a.datagrid-reset[href='/location']" => 1 @@ -571,7 +571,7 @@ def param_name it "converts to string using columns option" do r = subject.datagrid_row(grid, entry, columns: [:name]).to_s - expect(r).to match_css_pattern("tr td[data-datagrid-column=name]") + expect(r).to match_css_pattern("tr td[data-column=name]") expect(r).to_not match_css_pattern("tr td.category") end end @@ -628,7 +628,7 @@ def param_name end end expect(subject.datagrid_header(grid)).to equal_to_dom(<<~HTML) - <tr><th class="datagrid-order-active-asc" data-datagrid-column="category">Category<div class="datagrid-order"> + <tr><th class="datagrid-order-active-asc" data-column="category">Category<div class="datagrid-order"> <a class="datagrid-order-control-asc" href="/location?grid%5Bdescending%5D=false&grid%5Border%5D=category">↑</a><a class="datagrid-order-control-desc" href="/location?grid%5Bdescending%5D=true&grid%5Border%5D=category">↓</a> </div> </th></tr> From ded516d5eba7e5876aa65bc95198d97a60d7a2b1 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 8 Nov 2024 10:44:33 +0100 Subject: [PATCH 049/157] Make range input classes editable in partials --- app/views/datagrid/_range_filter.html.erb | 4 ++-- lib/datagrid/form_builder.rb | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/views/datagrid/_range_filter.html.erb b/app/views/datagrid/_range_filter.html.erb index 1b90dc8..3b8ca85 100644 --- a/app/views/datagrid/_range_filter.html.erb +++ b/app/views/datagrid/_range_filter.html.erb @@ -1,3 +1,3 @@ -<%= form.datagrid_filter_input(filter, **from_options) %> +<%= form.datagrid_filter_input(filter, class: 'datagrid-range-from', **from_options) %> <span class="datagrid-range-separator"><%= I18n.t('datagrid.filters.range.separator') %></span> -<%= form.datagrid_filter_input(filter, **to_options) %> +<%= form.datagrid_filter_input(filter, class: 'datagrid-range-to', **to_options) %> diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 865ab96..e58c623 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -179,8 +179,8 @@ def dynamic_filter_select(name, variants, select_options, html_options) def datagrid_range_filter(_type, filter, options = {}) if filter.range? - from_options = datagrid_range_filter_options(object, filter, :from, options) - to_options = datagrid_range_filter_options(object, filter, :to, options) + from_options = datagrid_range_filter_options(object, filter, :from, **options) + to_options = datagrid_range_filter_options(object, filter, :to, **options) render_partial "range_filter", { from_options: from_options, to_options: to_options, filter: filter, form: self } @@ -189,9 +189,9 @@ def datagrid_range_filter(_type, filter, options = {}) end end - def datagrid_range_filter_options(object, filter, type, options) + def datagrid_range_filter_options(object, filter, type, **options) type_method_map = { from: :begin, to: :end } - options = add_html_classes(options, "datagrid-range-#{type}") + # options = add_html_classes(options, "datagrid-range-#{type}") options[:value] = object[filter.name]&.public_send(type_method_map[type]) options[:name] = @template.field_name(object_name, filter.name, type) # In case of datagrid ranged filter From 54a9a77815dabcc9989e46e1a2ff43b7379c1c5e Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 8 Nov 2024 10:58:35 +0100 Subject: [PATCH 050/157] Expose datagrid-range-from/to classes in partials --- app/views/datagrid/_form.html.erb | 5 +---- lib/datagrid/form_builder.rb | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/app/views/datagrid/_form.html.erb b/app/views/datagrid/_form.html.erb index bd66d9f..9b41ff2 100644 --- a/app/views/datagrid/_form.html.erb +++ b/app/views/datagrid/_form.html.erb @@ -1,9 +1,6 @@ <%= form_for grid, html: {class: 'datagrid-form'}, **options do |f| -%> <% grid.filters.each do |filter| %> - <div class="datagrid-filter" - data-filter="<%= filter.name %>" - data-type="<%= filter.type %>" - > + <div class="datagrid-filter" data-filter="<%= filter.name %>" data-type="<%= filter.type %>"> <%= f.datagrid_label filter %> <%= f.datagrid_filter filter %> </div> diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index e58c623..1af46df 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -191,7 +191,6 @@ def datagrid_range_filter(_type, filter, options = {}) def datagrid_range_filter_options(object, filter, type, **options) type_method_map = { from: :begin, to: :end } - # options = add_html_classes(options, "datagrid-range-#{type}") options[:value] = object[filter.name]&.public_send(type_method_map[type]) options[:name] = @template.field_name(object_name, filter.name, type) # In case of datagrid ranged filter From 4f5fd526967d3d5d3d58e572733635cdc142617c Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 8 Nov 2024 12:05:46 +0100 Subject: [PATCH 051/157] Prettify CSS --- app/assets/stylesheets/datagrid.css | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/app/assets/stylesheets/datagrid.css b/app/assets/stylesheets/datagrid.css index fee4ee5..5201d17 100644 --- a/app/assets/stylesheets/datagrid.css +++ b/app/assets/stylesheets/datagrid.css @@ -7,6 +7,7 @@ table.datagrid-table { table.datagrid-table th { background-color: #eee; text-align: left; + vertical-align: top; } table.datagrid-table td, @@ -61,10 +62,6 @@ table.datagrid-table th { float: left; } -.datagrid-filter a { - float: left; -} - .datagrid-filter input { border: 2px solid #ccc; border-radius: 4px; @@ -73,9 +70,8 @@ table.datagrid-table th { width: 300px; } -.datagrid-filter input.datagrid-range-from, -.datagrid-filter input.datagrid-range-to { - width: 83px; +input.datagrid-range-from, input.datagrid-range-to { + width: 144px; } .datagrid-filter select { @@ -89,21 +85,17 @@ table.datagrid-table th { height: 100px; } -.datagrid-filter .datagrid-dynamic-field { - width: 178px; -} - -.datagrid-filter .datagrid-dynamic-operation { +select.datagrid-dynamic-operation { margin-left: 7px; width: 50px; } -.datagrid-filter .datagrid-dynamic-value { +.datagrid-dynamic-value { margin: 10px 0 0 150px; clear: both; } -.datagrid-filter .datagrid-range-separator { +.datagrid-range-separator { float: left; margin: 6px 4px 0; } @@ -118,9 +110,6 @@ table.datagrid-table th { width: 100%; } -input.datagrid-range-from, input.datagrid-range-to { - width: 144px !important -} select.datagrid-dynamic-field { width: 242px From f19c191ee4e58a41052fb2e48bee28777b93631c Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 8 Nov 2024 12:09:42 +0100 Subject: [PATCH 052/157] Prettify CSS --- app/assets/stylesheets/datagrid.css | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/app/assets/stylesheets/datagrid.css b/app/assets/stylesheets/datagrid.css index 5201d17..7083c37 100644 --- a/app/assets/stylesheets/datagrid.css +++ b/app/assets/stylesheets/datagrid.css @@ -1,3 +1,5 @@ +/* Table */ + table.datagrid-table { background-color: transparent; border-collapse: collapse; @@ -37,6 +39,8 @@ table.datagrid-table th { text-align: center; } +/* Form */ + .datagrid-form { background-color: #f0f0f0; border-radius: 5px; @@ -104,13 +108,6 @@ select.datagrid-dynamic-operation { float: left; } -.datagrid-enum-checkboxes label { - display: block; - float: none; - width: 100%; -} - - select.datagrid-dynamic-field { width: 242px } @@ -121,11 +118,17 @@ select.datagrid-dynamic-field { width: auto; } +.datagrid-enum-checkboxes label { + display: block; + float: none; + width: 100%; +} + .datagrid-actions { padding-left: calc(150px + 10px); } -.datagrid-actions input[type='submit'] { +.datagrid-submit { background-color: #555; border: none; border-radius: 5px; @@ -141,16 +144,16 @@ select.datagrid-dynamic-field { *display: inline; } -.datagrid-actions input[type='submit']:hover, -.datagrid-actions input[type='submit']:focus { +.datagrid-submit:hover, +.datagrid-submit:focus { background-color: #333; } -.datagrid-actions input[type='submit']:active { +.datagrid-submit:active { background-color: #000; } -.datagrid-actions > a { +.datagrid-reset { font-size: 14px; padding: 7px 15px; vertical-align: middle; From 47369af8ff1ff84092806e952c2cd0da3a6ae6f2 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 8 Nov 2024 12:23:15 +0100 Subject: [PATCH 053/157] Fully support pagy in scaffold generator --- lib/datagrid/scaffold.rb | 37 +++++++++++++++++++++++++++++++++---- templates/index.html.erb | 4 ++-- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/lib/datagrid/scaffold.rb b/lib/datagrid/scaffold.rb index b016c57..a14b381 100644 --- a/lib/datagrid/scaffold.rb +++ b/lib/datagrid/scaffold.rb @@ -21,7 +21,7 @@ def create_scaffold end template "index.html.erb", view_file route(generate_routing_namespace("resources :#{grid_controller_short_name}")) - gem "kaminari" unless defined?(::Kaminari) || defined?(::WillPaginate) + gem "kaminari" unless defined?(::Kaminari) || defined?(::WillPaginate) || defined?(::Pagy) in_root do { "css" => " *= require datagrid", @@ -71,12 +71,22 @@ def grid_param_name def pagination_helper_code if defined?(::WillPaginate) "will_paginate(@grid.assets)" + elsif defined?(::Pagy) + "pagy_nav(@pagy)" else # Kaminari is default "paginate(@grid.assets)" end end + def table_helper_code + if defined?(::Pagy) + "datagrid_table @grid, @records" + else + "datagrid_table @grid" + end + end + def base_grid_file "app/grids/application_grid.rb" end @@ -88,9 +98,7 @@ def grid_route_name def index_action indent(<<~RUBY) def index - @grid = #{grid_class_name}.new(grid_params) do |scope| - scope.page(params[:page]) - end +#{index_body} end protected @@ -101,6 +109,27 @@ def grid_params RUBY end + def index_body + + if defined?(::Pagy) + <<~RUBY + def index + @grid = #{grid_class_name}.new(grid_params) + @pagy, @assets = pagy(@grid.assets) + end + RUBY + else + <<~RUBY + def index + @grid = #{grid_class_name}.new(grid_params) do |scope| + scope.page(params[:page]) + end + end + RUBY + end + + end + protected def generate_routing_namespace(code) diff --git a/templates/index.html.erb b/templates/index.html.erb index 9ef276d..105b49f 100644 --- a/templates/index.html.erb +++ b/templates/index.html.erb @@ -1,5 +1,5 @@ -<%%= datagrid_form_for @grid, method: :get, url: <%= grid_route_name %> %> +<%%= datagrid_form_for @grid, url: <%= grid_route_name %> %> <%%= <%=pagination_helper_code%> %> -<%%= datagrid_table @grid %> +<%%= <%=table_helper_code%> %> <%%= <%=pagination_helper_code%> %> From 83d875f78c5c61679d29c6a30414b8fdb9baf792 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 8 Nov 2024 13:29:17 +0100 Subject: [PATCH 054/157] Improve scaffold --- lib/datagrid/filters.rb | 4 ++- lib/datagrid/scaffold.rb | 66 ++++++++++++++++++---------------- spec/datagrid/scaffold_spec.rb | 8 +++-- templates/base.rb.erb | 6 ++++ 4 files changed, 50 insertions(+), 34 deletions(-) diff --git a/lib/datagrid/filters.rb b/lib/datagrid/filters.rb index b573e9f..de15078 100644 --- a/lib/datagrid/filters.rb +++ b/lib/datagrid/filters.rb @@ -144,7 +144,9 @@ def filters_inspection def initialize(...) self.filters_array = self.class.filters_array.clone filters_array.each do |filter| - self[filter.name] = filter.default(self) + if value = filter.default(self) + self[filter.name] = value + end end super end diff --git a/lib/datagrid/scaffold.rb b/lib/datagrid/scaffold.rb index a14b381..9fae2a0 100644 --- a/lib/datagrid/scaffold.rb +++ b/lib/datagrid/scaffold.rb @@ -9,7 +9,7 @@ class Scaffold < Rails::Generators::NamedBase include Rails::Generators::ResourceHelpers check_class_collision suffix: "Grid" - source_root File.expand_path("/Users/bogdan/makabu/my/datagrid/lib/datagrid/scaffold.rb/../../../templates") + source_root File.expand_path("#{__FILE__}/../../../templates") def create_scaffold template "base.rb.erb", base_grid_file unless file_exists?(base_grid_file) @@ -17,9 +17,9 @@ def create_scaffold if file_exists?(grid_controller_file) inject_into_file grid_controller_file, index_action, after: /class .*#{grid_controller_class_name}.*\n/ else - template "controller.rb.erb", grid_controller_file + create_file grid_controller_file, controller_code end - template "index.html.erb", view_file + create_file view_file, view_code route(generate_routing_namespace("resources :#{grid_controller_short_name}")) gem "kaminari" unless defined?(::Kaminari) || defined?(::WillPaginate) || defined?(::Pagy) in_root do @@ -95,39 +95,45 @@ def grid_route_name "#{controller_class_name.underscore.gsub('/', '_')}_path" end - def index_action - indent(<<~RUBY) - def index -#{index_body} - end - - protected - - def grid_params - params.fetch(:#{grid_param_name}, {}).permit! - end - RUBY - end - - def index_body - + def index_code if defined?(::Pagy) - <<~RUBY - def index - @grid = #{grid_class_name}.new(grid_params) - @pagy, @assets = pagy(@grid.assets) - end + <<-RUBY + @grid = #{grid_class_name}.new(grid_params) + @pagy, @assets = pagy(@grid.assets) RUBY else - <<~RUBY - def index - @grid = #{grid_class_name}.new(grid_params) do |scope| - scope.page(params[:page]) - end - end + <<-RUBY + @grid = #{grid_class_name}.new(grid_params) do |scope| + scope.page(params[:page]) + end RUBY end + end + + def controller_code + <<~RUBY +class #{grid_controller_class_name} < ApplicationController + def index +#{index_code.rstrip} + end + + protected + + def grid_params + params.fetch(:#{grid_param_name}, {}).permit! + end +end +RUBY + end + + def view_code + indent(<<~ERB) +<%= datagrid_form_for @grid, url: #{grid_route_name} %> +<%= #{pagination_helper_code} %> +<%= #{table_helper_code} %> +<%= #{pagination_helper_code} %> +ERB end protected diff --git a/spec/datagrid/scaffold_spec.rb b/spec/datagrid/scaffold_spec.rb index 6c1bd16..3e37561 100644 --- a/spec/datagrid/scaffold_spec.rb +++ b/spec/datagrid/scaffold_spec.rb @@ -24,9 +24,10 @@ end end - describe ".index_action" do + describe ".controller_code" do it "works" do - expect(subject.index_action).to eq(<<-RUBY) + expect(subject.controller_code).to eq(<<-RUBY) +class UsersController < ApplicationController def index @grid = UsersGrid.new(grid_params) do |scope| scope.page(params[:page]) @@ -38,7 +39,8 @@ def index def grid_params params.fetch(:users_grid, {}).permit! end - RUBY +end +RUBY end end end diff --git a/templates/base.rb.erb b/templates/base.rb.erb index c5e5801..f580d0c 100644 --- a/templates/base.rb.erb +++ b/templates/base.rb.erb @@ -38,4 +38,10 @@ class ApplicationGrid < Datagrid::Base value ? "Yes" : "No" end end + + # Uncomment to shorten URL query string for all grids. + # May cause collisions if multiple grids are used on the same page. + # def param_name + # 'grid' + # end end From 755c21cbebec2a027b793813c2eacdefa7d89e8d Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 8 Nov 2024 14:11:30 +0100 Subject: [PATCH 055/157] Fix dynamic filter when assigned a hash with string keys --- lib/datagrid/filters/dynamic_filter.rb | 93 +++++++++++--------- spec/datagrid/filters/dynamic_filter_spec.rb | 24 +++-- 2 files changed, 71 insertions(+), 46 deletions(-) diff --git a/lib/datagrid/filters/dynamic_filter.rb b/lib/datagrid/filters/dynamic_filter.rb index 77c6507..febb8f6 100644 --- a/lib/datagrid/filters/dynamic_filter.rb +++ b/lib/datagrid/filters/dynamic_filter.rb @@ -31,12 +31,7 @@ def initialize(*) end def parse_values(filter) - - if filter.is_a?(Array) - field, operation, value = filter - filter = { field:, operation:, value: type_cast(field, value)} - end - filter ? FilterValue.new(filter) : nil + filter ? FilterValue.new(grid_class, filter) : nil end def unapplicable_value?(filter) @@ -101,48 +96,39 @@ def default_select } end - def type_cast(field, value) - type = column_type(field) - return nil if value.blank? - - case type - when :string - value.to_s - when :integer - value.is_a?(Numeric) || value =~ /^\d/ ? value.to_i : nil - when :float - value.is_a?(Numeric) || value =~ /^\d/ ? value.to_f : nil - when :date, :timestamp - Datagrid::Utils.parse_date(value) - when :boolean - Datagrid::Utils.booleanize(value) - when nil - value - else - raise NotImplementedError, "unknown column type: #{type.inspect}" - end - end - def column_type(field) grid_class.driver.normalized_column_type(grid_class.scope, field) end - class FilterValue < Hash - def initialize(object = nil) - super() - update(object) if object - end + class FilterValue + attr_accessor :field, :operation, :value - def field - self[:field] - end + def initialize(grid_class, object = nil) + super() - def operation - self[:operation] + case object + when Hash + object = object.symbolize_keys + self.field = object[:field] + self.operation = object[:operation] + self.value = object[:value] + when Array + self.field = object[0] + self.operation = object[1] + self.value = object[2] + else + raise ArgumentError, object.inspect + end + if grid_class + type = grid_class.driver.normalized_column_type( + grid_class.scope, field + ) + self.value = type_cast(type, value) + end end - def value - self[:value] + def inspect + {field: field, operation: operation, value: value} end def to_ary @@ -152,6 +138,33 @@ def to_ary def to_a [field, operation, value] end + + def to_h + {field: field, operation: operation, value: value} + end + + protected + + def type_cast(type, value) + return nil if value.blank? + + case type + when :string + value.to_s + when :integer + value.is_a?(Numeric) || value =~ /^\d/ ? value.to_i : nil + when :float + value.is_a?(Numeric) || value =~ /^\d/ ? value.to_f : nil + when :date, :timestamp + Datagrid::Utils.parse_date(value) + when :boolean + Datagrid::Utils.booleanize(value) + when nil + value + else + raise NotImplementedError, "unknown column type: #{type.inspect}" + end + end end end end diff --git a/spec/datagrid/filters/dynamic_filter_spec.rb b/spec/datagrid/filters/dynamic_filter_spec.rb index 0c4a6cb..f373f08 100644 --- a/spec/datagrid/filters/dynamic_filter_spec.rb +++ b/spec/datagrid/filters/dynamic_filter_spec.rb @@ -62,26 +62,26 @@ it "should nullify incorrect value for integer" do report.condition = [:group_id, "<=", "aa"] - expect(report.condition).to eq( + expect(report.condition.to_h).to eq( {field: :group_id, operation: "<=", value: nil} ) end it "should nullify incorrect value for date" do report.condition = [:shipping_date, "<=", "aa"] - expect(report.condition).to eq({ + expect(report.condition.to_h).to eq({ field: :shipping_date, operation: "<=", value: nil }) end it "should nullify incorrect value for datetime" do report.condition = [:created_at, "<=", "aa"] - expect(report.condition).to eq({field: :created_at, operation: "<=", value: nil}) + expect(report.condition.to_h).to eq({field: :created_at, operation: "<=", value: nil}) end it "should support date comparation operation by timestamp column" do report.condition = [:created_at, "<=", "1986-08-05"] - expect(report.condition).to eq({field: :created_at, operation: "<=", value: Date.parse("1986-08-05")}) + expect(report.condition.to_h).to eq({field: :created_at, operation: "<=", value: Date.parse("1986-08-05")}) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-04 01:01:01"))) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 23:59:59"))) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 00:00:00"))) @@ -91,7 +91,7 @@ it "should support date = operation by timestamp column" do report.condition = [:created_at, "=", "1986-08-05"] - expect(report.condition).to eq({field: :created_at, operation: "=", value: Date.parse("1986-08-05")}) + expect(report.condition.to_h).to eq({field: :created_at, operation: "=", value: Date.parse("1986-08-05")}) expect(report.assets).not_to include(Entry.create!(created_at: Time.parse("1986-08-04 23:59:59"))) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 23:59:59"))) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 00:00:01"))) @@ -102,7 +102,7 @@ it "should support date =~ operation by timestamp column" do report.condition = [:created_at, "=~", "1986-08-05"] - expect(report.condition).to eq({field: :created_at, operation: "=~", value: Date.parse("1986-08-05")}) + expect(report.condition.to_h).to eq({field: :created_at, operation: "=~", value: Date.parse("1986-08-05")}) expect(report.assets).not_to include(Entry.create!(created_at: Time.parse("1986-08-04 23:59:59"))) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 23:59:59"))) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 00:00:01"))) @@ -179,4 +179,16 @@ report.assets end.to raise_error(Datagrid::FilteringError) end + + it "supports assignment of string keys hash" do + report.condition = { + field: "shipping_date", + operation: "<>", + value: "1996-08-05", + }.stringify_keys + + expect(report.condition.to_h).to eq({ + field: 'shipping_date', operation: '<>', value: Date.parse('1996-08-05') + }) + end end From ed1ad9a1920aad6b213c06ae94bf75860f068233 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 8 Nov 2024 19:10:38 +0100 Subject: [PATCH 056/157] Extract views diff to separated file --- VERSION2.md => version-2/Readme.markdown | 126 +---------------------- version-2/views.diff | 120 +++++++++++++++++++++ 2 files changed, 122 insertions(+), 124 deletions(-) rename VERSION2.md => version-2/Readme.markdown (63%) create mode 100644 version-2/views.diff diff --git a/VERSION2.md b/version-2/Readme.markdown similarity index 63% rename from VERSION2.md rename to version-2/Readme.markdown index 326c041..d9522fe 100644 --- a/VERSION2.md +++ b/version-2/Readme.markdown @@ -343,127 +343,5 @@ end Version 2 built-in partials are trying to expose as much UI as possible for user modification. -Here is a complete diff for built-in partials between V1 and V2: - -TODO update - -``` diff -diff --git a/app/views/datagrid/_enum_checkboxes.html.erb b/app/views/datagrid/_enum_checkboxes.html.erb -index 9f48319..f114c17 100644 ---- a/app/views/datagrid/_enum_checkboxes.html.erb -+++ b/app/views/datagrid/_enum_checkboxes.html.erb -@@ -4,8 +4,8 @@ You can add indent if whitespace doesn't matter for you - %> - <%- elements.each do |value, text, checked| -%> - <%- id = [form.object_name, filter.name, value].join('_').underscore -%> --<%= form.label filter.name, options.merge(for: id) do -%> --<%= form.check_box(filter.name, {multiple: true, id: id, checked: checked, include_hidden: false}, value.to_s, nil) -%> -+<%= form.datagrid_label(filter.name, **options, for: id) do -%> -+<%= form.datagrid_filter_input(filter.name, type: :checkbox, multiple: true, id: id, checked: checked, include_hidden: false, value: value.to_s) -%> - <%= text -%> - <%- end -%> - <%- end -%> -diff --git a/app/views/datagrid/_form.html.erb b/app/views/datagrid/_form.html.erb -index 7e175c1..88a39f9 100644 ---- a/app/views/datagrid/_form.html.erb -+++ b/app/views/datagrid/_form.html.erb -@@ -1,12 +1,16 @@ --<%= form_for grid, options do |f| -%> -+<%= form_for grid, html: {class: 'datagrid-form'}, **options do |f| -%> - <% grid.filters.each do |filter| %> -- <div class="datagrid-filter filter"> -+ <div class="datagrid-filter" -+ data-datagrid-filter="<%= filter.name %>" -+ data-type="<%= filter.type %>" -+ data-datagrid-filter-checkboxes="<%= filter.enum_checkboxes? %>" -+ > - <%= f.datagrid_label filter %> - <%= f.datagrid_filter filter %> - </div> - <% end %> - <div class="datagrid-actions"> -- <%= f.submit I18n.t("datagrid.form.search").html_safe, class: "datagrid-submit" %> -- <%= link_to I18n.t('datagrid.form.reset').html_safe, url_for(grid.to_param => {}), class: "datagrid-reset" %> -+ <%= f.submit I18n.t("datagrid.form.search"), class: "datagrid-submit" %> -+ <%= link_to I18n.t('datagrid.form.reset'), url_for(grid.to_param => {}), class: "datagrid-reset" %> - </div> - <% end -%> -diff --git a/app/views/datagrid/_head.html.erb b/app/views/datagrid/_head.html.erb -index e939128..affccf4 100644 ---- a/app/views/datagrid/_head.html.erb -+++ b/app/views/datagrid/_head.html.erb -@@ -1,6 +1,6 @@ - <tr> - <% grid.html_columns(*options[:columns]).each do |column| %> -- <th class="<%= datagrid_column_classes(grid, column) %>"> -+ <th class="<%= datagrid_column_classes(grid, column) %>" data-datagrid-column="<%= column.name %>"> - <%= column.header %> - <%= datagrid_order_for(grid, column, options) if column.supports_order? && options[:order]%> - </th> -diff --git a/app/views/datagrid/_order_for.html.erb b/app/views/datagrid/_order_for.html.erb -index 1545a8e..1c33c37 100644 ---- a/app/views/datagrid/_order_for.html.erb -+++ b/app/views/datagrid/_order_for.html.erb -@@ -1,10 +1,10 @@ --<div class="order"> -+<div class="datagrid-order"> - <%= link_to( -- I18n.t("datagrid.table.order.asc").html_safe, -+ I18n.t("datagrid.table.order.asc"), - datagrid_order_path(grid, column, false), -- class: "asc") %> -+ class: "datagrid-order-control-asc") %> - <%= link_to( -- I18n.t("datagrid.table.order.desc").html_safe, -+ I18n.t("datagrid.table.order.desc"), - datagrid_order_path(grid, column, true), -- class: "desc") %> -+ class: "datagrid-order-control-desc") %> - </div> -diff --git a/app/views/datagrid/_range_filter.html.erb b/app/views/datagrid/_range_filter.html.erb -index 7a8a123..1b90dc8 100644 ---- a/app/views/datagrid/_range_filter.html.erb -+++ b/app/views/datagrid/_range_filter.html.erb -@@ -1,3 +1,3 @@ - <%= form.datagrid_filter_input(filter, **from_options) %> --<span class="separator <%= filter.type %>"><%= I18n.t('datagrid.filters.range.separator') %></span> -+<span class="datagrid-range-separator"><%= I18n.t('datagrid.filters.range.separator') %></span> - <%= form.datagrid_filter_input(filter, **to_options) %> -diff --git a/app/views/datagrid/_row.html.erb b/app/views/datagrid/_row.html.erb -index f54d21c..b431ab7 100644 ---- a/app/views/datagrid/_row.html.erb -+++ b/app/views/datagrid/_row.html.erb -@@ -1,5 +1,5 @@ - <tr> - <% grid.html_columns(*options[:columns]).each do |column| %> -- <td class="<%= datagrid_column_classes(grid, column) %>"><%= datagrid_value(grid, column, asset) %></td> -+ <td class="<%= datagrid_column_classes(grid, column) %>" data-datagrid-column="<%= column.name %>"><%= datagrid_value(grid, column, asset) %></td> - <% end %> - </tr> -diff --git a/app/views/datagrid/_table.html.erb b/app/views/datagrid/_table.html.erb -index 8708c05..0b5ff24 100644 ---- a/app/views/datagrid/_table.html.erb -+++ b/app/views/datagrid/_table.html.erb -@@ -5,7 +5,7 @@ Local variables: - * options - passed options Hash - %> - <% if grid.html_columns(*options[:columns]).any? %> -- <%= content_tag :table, options[:html] do %> -+ <%= content_tag :table, class: 'datagrid-table', **options.fetch(:html, {}) do %> - <thead> - <%= datagrid_header(grid, options) %> - </thead> -@@ -13,10 +13,10 @@ Local variables: - <% if assets.any? %> - <%= datagrid_rows(grid, assets, **options) %> - <% else %> -- <tr><td class="noresults" colspan="100%"><%= I18n.t('datagrid.no_results').html_safe %></td></tr> -+ <tr><td class="datagrid-no-results" colspan="100%"><%= I18n.t('datagrid.no_results') %></td></tr> - <% end %> - </tbody> - <% end %> - <% else -%> -- <%= I18n.t("datagrid.table.no_columns").html_safe %> -+ <%= I18n.t("datagrid.table.no_columns") %> - <% end %> -``` +Here is a complete [diff for built-in partials between V1 and V2](./views.diff) + diff --git a/version-2/views.diff b/version-2/views.diff new file mode 100644 index 0000000..ed70538 --- /dev/null +++ b/version-2/views.diff @@ -0,0 +1,120 @@ +diff --git a/app/views/datagrid/_enum_checkboxes.html.erb b/app/views/datagrid/_enum_checkboxes.html.erb +index 9f48319..2d46139 100644 +--- a/app/views/datagrid/_enum_checkboxes.html.erb ++++ b/app/views/datagrid/_enum_checkboxes.html.erb +@@ -2,10 +2,12 @@ + Indent in this file may cause extra space to appear. + You can add indent if whitespace doesn't matter for you + %> ++<div class="datagrid-enum-checkboxes"> + <%- elements.each do |value, text, checked| -%> + <%- id = [form.object_name, filter.name, value].join('_').underscore -%> +-<%= form.label filter.name, options.merge(for: id) do -%> +-<%= form.check_box(filter.name, {multiple: true, id: id, checked: checked, include_hidden: false}, value.to_s, nil) -%> ++<%= form.datagrid_label(filter.name, **options, for: id, class: 'datagrid-enum-checkbox-label') do -%> ++<%= form.datagrid_filter_input(filter.name, type: :checkbox, multiple: true, id: id, checked: checked, include_hidden: false, value: value.to_s) -%> + <%= text -%> + <%- end -%> + <%- end -%> ++</div> +diff --git a/app/views/datagrid/_form.html.erb b/app/views/datagrid/_form.html.erb +index 7e175c1..9b41ff2 100644 +--- a/app/views/datagrid/_form.html.erb ++++ b/app/views/datagrid/_form.html.erb +@@ -1,12 +1,12 @@ +-<%= form_for grid, options do |f| -%> ++<%= form_for grid, html: {class: 'datagrid-form'}, **options do |f| -%> + <% grid.filters.each do |filter| %> +- <div class="datagrid-filter filter"> ++ <div class="datagrid-filter" data-filter="<%= filter.name %>" data-type="<%= filter.type %>"> + <%= f.datagrid_label filter %> + <%= f.datagrid_filter filter %> + </div> + <% end %> + <div class="datagrid-actions"> +- <%= f.submit I18n.t("datagrid.form.search").html_safe, class: "datagrid-submit" %> +- <%= link_to I18n.t('datagrid.form.reset').html_safe, url_for(grid.to_param => {}), class: "datagrid-reset" %> ++ <%= f.submit I18n.t("datagrid.form.search"), class: "datagrid-submit" %> ++ <%= link_to I18n.t('datagrid.form.reset'), url_for(grid.to_param => {}), class: "datagrid-reset" %> + </div> + <% end -%> +diff --git a/app/views/datagrid/_head.html.erb b/app/views/datagrid/_head.html.erb +index e939128..c3264bb 100644 +--- a/app/views/datagrid/_head.html.erb ++++ b/app/views/datagrid/_head.html.erb +@@ -1,6 +1,6 @@ + <tr> + <% grid.html_columns(*options[:columns]).each do |column| %> +- <th class="<%= datagrid_column_classes(grid, column) %>"> ++ <th class="<%= datagrid_column_classes(grid, column) %>" data-column="<%= column.name %>"> + <%= column.header %> + <%= datagrid_order_for(grid, column, options) if column.supports_order? && options[:order]%> + </th> +diff --git a/app/views/datagrid/_order_for.html.erb b/app/views/datagrid/_order_for.html.erb +index 1545a8e..1c33c37 100644 +--- a/app/views/datagrid/_order_for.html.erb ++++ b/app/views/datagrid/_order_for.html.erb +@@ -1,10 +1,10 @@ +-<div class="order"> ++<div class="datagrid-order"> + <%= link_to( +- I18n.t("datagrid.table.order.asc").html_safe, ++ I18n.t("datagrid.table.order.asc"), + datagrid_order_path(grid, column, false), +- class: "asc") %> ++ class: "datagrid-order-control-asc") %> + <%= link_to( +- I18n.t("datagrid.table.order.desc").html_safe, ++ I18n.t("datagrid.table.order.desc"), + datagrid_order_path(grid, column, true), +- class: "desc") %> ++ class: "datagrid-order-control-desc") %> + </div> +diff --git a/app/views/datagrid/_range_filter.html.erb b/app/views/datagrid/_range_filter.html.erb +index 7a8a123..3b8ca85 100644 +--- a/app/views/datagrid/_range_filter.html.erb ++++ b/app/views/datagrid/_range_filter.html.erb +@@ -1,3 +1,3 @@ +-<%= form.datagrid_filter_input(filter, **from_options) %> +-<span class="separator <%= filter.type %>"><%= I18n.t('datagrid.filters.range.separator') %></span> +-<%= form.datagrid_filter_input(filter, **to_options) %> ++<%= form.datagrid_filter_input(filter, class: 'datagrid-range-from', **from_options) %> ++<span class="datagrid-range-separator"><%= I18n.t('datagrid.filters.range.separator') %></span> ++<%= form.datagrid_filter_input(filter, class: 'datagrid-range-to', **to_options) %> +diff --git a/app/views/datagrid/_row.html.erb b/app/views/datagrid/_row.html.erb +index f54d21c..20f3ffb 100644 +--- a/app/views/datagrid/_row.html.erb ++++ b/app/views/datagrid/_row.html.erb +@@ -1,5 +1,5 @@ + <tr> + <% grid.html_columns(*options[:columns]).each do |column| %> +- <td class="<%= datagrid_column_classes(grid, column) %>"><%= datagrid_value(grid, column, asset) %></td> ++ <td class="<%= datagrid_column_classes(grid, column) %>" data-column="<%= column.name %>"><%= datagrid_value(grid, column, asset) %></td> + <% end %> + </tr> +diff --git a/app/views/datagrid/_table.html.erb b/app/views/datagrid/_table.html.erb +index 8708c05..0b5ff24 100644 +--- a/app/views/datagrid/_table.html.erb ++++ b/app/views/datagrid/_table.html.erb +@@ -5,7 +5,7 @@ Local variables: + * options - passed options Hash + %> + <% if grid.html_columns(*options[:columns]).any? %> +- <%= content_tag :table, options[:html] do %> ++ <%= content_tag :table, class: 'datagrid-table', **options.fetch(:html, {}) do %> + <thead> + <%= datagrid_header(grid, options) %> + </thead> +@@ -13,10 +13,10 @@ Local variables: + <% if assets.any? %> + <%= datagrid_rows(grid, assets, **options) %> + <% else %> +- <tr><td class="noresults" colspan="100%"><%= I18n.t('datagrid.no_results').html_safe %></td></tr> ++ <tr><td class="datagrid-no-results" colspan="100%"><%= I18n.t('datagrid.no_results') %></td></tr> + <% end %> + </tbody> + <% end %> + <% else -%> +- <%= I18n.t("datagrid.table.no_columns").html_safe %> ++ <%= I18n.t("datagrid.table.no_columns") %> + <% end %> From 1a0fcbd7bcb36bad1de25268bac1cc88eac5a543 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sat, 9 Nov 2024 10:05:26 +0100 Subject: [PATCH 057/157] Form versions --- version-2/form-v1.html | 26 ++++++++++++++++++++++++++ version-2/form-v2.html | 27 +++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 version-2/form-v1.html create mode 100644 version-2/form-v2.html diff --git a/version-2/form-v1.html b/version-2/form-v1.html new file mode 100644 index 0000000..5e8241a --- /dev/null +++ b/version-2/form-v1.html @@ -0,0 +1,26 @@ +<form class="datagrid-form partial_default_grid" id="new_g" action="/users" accept-charset="UTF-8" method="get"> + <input name="utf8" type="hidden" value="✓" autocomplete="off" /> + + <div class="datagrid-filter filter"> + <label for="g_id">Id</label> + <input class="id integer_filter from" multiple type="text" name="g[id][]" /> + <span class="separator integer"> - </span> + <input class="id integer_filter to" multiple type="text" name="g[id][]" /> + </div> + + <div class="datagrid-filter filter"> + <label for="g_group_id">Group</label> + <label class="group_id enum_filter checkboxes" for="g_group_id_1"> + <input id="g_group_id_1" type="checkbox" value="1" name="g[group_id][]" />1 + </label> + <label class="group_id enum_filter checkboxes" for="g_group_id_2"> + <input id="g_group_id_2" type="checkbox" value="2" name="g[group_id][]" />2 + </label> + </div> + + <div class="datagrid-actions"> + <input type="submit" name="commit" value="Search" + class="datagrid-submit" data-disable-with="Search" /> + <a class="datagrid-reset" href="/location">Reset</a> + </div> +</form> diff --git a/version-2/form-v2.html b/version-2/form-v2.html new file mode 100644 index 0000000..03a40a3 --- /dev/null +++ b/version-2/form-v2.html @@ -0,0 +1,27 @@ +<form class="datagrid-form" id="new_g" action="/users" accept-charset="UTF-8" method="get"> + <input name="utf8" type="hidden" value="✓" autocomplete="off" /> + + <div class="datagrid-filter" data-filter="id" data-type="integer"> + <label for="g_id">Id</label> + <input step="1" class="datagrid-range-from" name="g[id][from]" type="number" /> + <span class="datagrid-range-separator"> - </span> + <input step="1" class="datagrid-range-to" name="g[id][to]" type="number" /> + </div> + + <div class="datagrid-filter" data-filter="group_id" data-type="enum"> + <label for="g_group_id">Group</label> + <div class="datagrid-enum-checkboxes"> + <label class="datagrid-enum-checkbox-label" for="g_group_id_1"> + <input id="g_group_id_1" value="1" type="checkbox" name="g[group_id][]" />1 + </label> + <label class="datagrid-enum-checkbox-label" for="g_group_id_2"> + <input id="g_group_id_2" type="checkbox" value="2" name="g[group_id][]" />2 + </label> + </div> + </div> + <div class="datagrid-actions"> + <input type="submit" name="commit" value="Search" + class="datagrid-submit" data-disable-with="Search" /> + <a class="datagrid-reset" href="/location">Reset</a> + </div> +</form> From c4414258dbc166d171ebb25c4be292e4d3c55a42 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sat, 9 Nov 2024 10:05:39 +0100 Subject: [PATCH 058/157] Check order with direction --- lib/datagrid/ordering.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/datagrid/ordering.rb b/lib/datagrid/ordering.rb index 963d7c4..695a812 100644 --- a/lib/datagrid/ordering.rb +++ b/lib/datagrid/ordering.rb @@ -52,9 +52,11 @@ def order_column end # @param column [String, Datagrid::Columns::Column] + # @param desc [nil, Boolean] confirm order direction as well if specified # @return [Boolean] true if given grid is ordered by given column. - def ordered_by?(column) - order_column == column_by_name(column) + def ordered_by?(column, desc = nil) + order_column == column_by_name(column) && + (desc.nil? || (desc ? descending? : !descending?)) end private From f1ee16160faa319126adc34f1fe35c177a3989f0 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sat, 9 Nov 2024 11:41:54 +0100 Subject: [PATCH 059/157] Lint --- .rubocop.yml | 15 ++ datagrid.gemspec | 6 +- lib/datagrid.rb | 3 +- lib/datagrid/base.rb | 2 + lib/datagrid/column_names_attribute.rb | 2 +- lib/datagrid/columns.rb | 14 +- lib/datagrid/drivers/active_record.rb | 2 +- lib/datagrid/drivers/mongoid.rb | 2 +- lib/datagrid/drivers/sequel.rb | 2 +- lib/datagrid/filters.rb | 6 +- lib/datagrid/filters/base_filter.rb | 6 +- lib/datagrid/filters/boolean_filter.rb | 2 +- lib/datagrid/filters/date_filter.rb | 2 +- lib/datagrid/filters/date_time_filter.rb | 2 +- lib/datagrid/filters/dynamic_filter.rb | 28 ++-- lib/datagrid/filters/enum_filter.rb | 2 +- .../filters/extended_boolean_filter.rb | 2 +- lib/datagrid/filters/float_filter.rb | 2 +- lib/datagrid/filters/integer_filter.rb | 2 +- lib/datagrid/filters/ranged_filter.rb | 19 ++- lib/datagrid/form_builder.rb | 28 ++-- lib/datagrid/ordering.rb | 2 +- lib/datagrid/renderer.rb | 28 ++-- lib/datagrid/scaffold.rb | 40 +++--- spec/datagrid/columns_spec.rb | 24 ++-- spec/datagrid/core_spec.rb | 6 +- spec/datagrid/drivers/active_record_spec.rb | 10 +- spec/datagrid/drivers/mongo_mapper_spec.rb | 6 +- spec/datagrid/drivers/mongoid_spec.rb | 6 +- spec/datagrid/drivers/sequel_spec.rb | 6 +- spec/datagrid/filters/date_filter_spec.rb | 10 +- spec/datagrid/filters/dynamic_filter_spec.rb | 20 +-- spec/datagrid/filters/integer_filter_spec.rb | 2 +- spec/datagrid/filters_spec.rb | 5 +- spec/datagrid/form_builder_spec.rb | 134 +++++++++--------- spec/datagrid/helper_spec.rb | 113 +++++++-------- spec/datagrid/scaffold_spec.rb | 30 ++-- spec/datagrid_spec.rb | 4 +- spec/spec_helper.rb | 40 +++--- spec/support/mongoid.rb | 1 - 40 files changed, 323 insertions(+), 313 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 4421b7b..8ff7392 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -2,6 +2,21 @@ AllCops: NewCops: enable Style/StringLiterals: EnforcedStyle: double_quotes +Style/TrailingCommaInArguments: + EnforcedStyleForMultiline: consistent_comma +Style/TrailingCommaInArrayLiteral: + EnforcedStyleForMultiline: consistent_comma +Style/TrailingCommaInHashLiteral: + EnforcedStyleForMultiline: consistent_comma +Style/RegexpLiteral: + EnforcedStyle: percent_r +Layout/FirstHashElementIndentation: + EnforcedStyle: consistent +Layout/FirstArrayElementIndentation: + EnforcedStyle: consistent +Layout/ArgumentAlignment: + EnforcedStyle: with_fixed_indentation + Metrics/BlockLength: Enabled: false Metrics/MethodLength: diff --git a/datagrid.gemspec b/datagrid.gemspec index 49add80..a5e48e3 100644 --- a/datagrid.gemspec +++ b/datagrid.gemspec @@ -12,13 +12,13 @@ Gem::Specification.new do |s| s.email = "agresso@gmail.com" s.extra_rdoc_files = [ "LICENSE.txt", - "Readme.markdown" + "Readme.markdown", ] s.files = [ "LICENSE.txt", "CHANGELOG.md", "Readme.markdown", - "datagrid.gemspec" + "datagrid.gemspec", ] s.files += `git ls-files | grep -E '^(app|lib|templates)'`.split("\n") s.homepage = "https://github.com/bogdan/datagrid" @@ -30,7 +30,7 @@ Gem::Specification.new do |s| "documentation_uri" => "#{s.homepage}/wiki", "changelog_uri" => "#{s.homepage}/blob/master/CHANGELOG.md", "source_code_uri" => s.homepage, - "rubygems_mfa_required" => "true" + "rubygems_mfa_required" => "true", } s.add_dependency "railties", ">= 6.1" diff --git a/lib/datagrid.rb b/lib/datagrid.rb index 80ec058..a63a21b 100644 --- a/lib/datagrid.rb +++ b/lib/datagrid.rb @@ -6,7 +6,6 @@ # @main README.md module Datagrid - # @!visibility private def self.included(base) Utils.warn_once("Including Datagrid is deprecated. Inherit Datagrid::Base instead.") @@ -25,6 +24,6 @@ class ArgumentError < ::ArgumentError; end class ColumnUnavailableError < StandardError; end end -require 'datagrid/base' +require "datagrid/base" require "datagrid/scaffold" I18n.load_path << File.expand_path("datagrid/locale/en.yml", __dir__) diff --git a/lib/datagrid/base.rb b/lib/datagrid/base.rb index 6d86f97..f904d16 100644 --- a/lib/datagrid/base.rb +++ b/lib/datagrid/base.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Datagrid extend ActiveSupport::Autoload diff --git a/lib/datagrid/column_names_attribute.rb b/lib/datagrid/column_names_attribute.rb index 48041ae..7cb5ef1 100644 --- a/lib/datagrid/column_names_attribute.rb +++ b/lib/datagrid/column_names_attribute.rb @@ -33,7 +33,7 @@ def column_names_filter(**options) select: :optional_columns_select, multiple: true, dummy: true, - **options + **options, ) end end diff --git a/lib/datagrid/columns.rb b/lib/datagrid/columns.rb index 360cd0f..dca4638 100644 --- a/lib/datagrid/columns.rb +++ b/lib/datagrid/columns.rb @@ -201,8 +201,8 @@ def find_column_by_name(columns, name) def assets append_column_preload( driver.append_column_queries( - super, columns.select(&:query) - ) + super, columns.select(&:query), + ), ) end @@ -277,7 +277,7 @@ def to_csv(*column_names, **options) CSV.generate( headers: header(*column_names), write_headers: true, - **options + **options, ) do |csv| each_with_batches do |asset| csv << row_for(asset, *column_names) @@ -294,7 +294,7 @@ def to_csv(*column_names, **options) # grid.columns(:id, :category) # => id and category column def columns(*column_names, data: false, html: false) self.class.filter_columns( - columns_array, *column_names, data: data, html: html + columns_array, *column_names, data: data, html: html, ).select do |column| column.enabled?(self) end @@ -480,9 +480,9 @@ def cache_key(asset) end rescue NotImplementedError raise Datagrid::ConfigurationError, - <<~MSG - #{self} is setup to use cache. But there was appropriate cache key found for #{asset.inspect}. - MSG + <<~MSG + #{self} is setup to use cache. But there was appropriate cache key found for #{asset.inspect}. + MSG end def map_with_batches(&block) diff --git a/lib/datagrid/drivers/active_record.rb b/lib/datagrid/drivers/active_record.rb index 64f5949..282dccd 100644 --- a/lib/datagrid/drivers/active_record.rb +++ b/lib/datagrid/drivers/active_record.rb @@ -98,7 +98,7 @@ def normalized_column_type(scope, field) %i[float decimal] => :float, [:date] => :date, %i[datetime timestamp] => :timestamp, - [:boolean] => :boolean + [:boolean] => :boolean, }.each do |keys, value| return value if keys.include?(builtin_type) end diff --git a/lib/datagrid/drivers/mongoid.rb b/lib/datagrid/drivers/mongoid.rb index e75b674..25c97fa 100644 --- a/lib/datagrid/drivers/mongoid.rb +++ b/lib/datagrid/drivers/mongoid.rb @@ -73,7 +73,7 @@ def normalized_column_type(scope, field) [Float] => :float, - [Integer] => :integer + [Integer] => :integer, }.each do |keys, value| return value if keys.include?(type) end diff --git a/lib/datagrid/drivers/sequel.rb b/lib/datagrid/drivers/sequel.rb index a84766e..20ea28b 100644 --- a/lib/datagrid/drivers/sequel.rb +++ b/lib/datagrid/drivers/sequel.rb @@ -67,7 +67,7 @@ def normalized_column_type(scope, field) %i[float decimal] => :float, [:date] => :date, [:datetime] => :timestamp, - [:boolean] => :boolean + [:boolean] => :boolean, }.each do |keys, value| return value if keys.include?(type) end diff --git a/lib/datagrid/filters.rb b/lib/datagrid/filters.rb index de15078..6ed0047 100644 --- a/lib/datagrid/filters.rb +++ b/lib/datagrid/filters.rb @@ -27,7 +27,7 @@ module Filters integer: Filters::IntegerFilter, enum: Filters::EnumFilter, float: Filters::FloatFilter, - dynamic: Filters::DynamicFilter + dynamic: Filters::DynamicFilter, }.freeze # @!visibility private @@ -144,7 +144,7 @@ def filters_inspection def initialize(...) self.filters_array = self.class.filters_array.clone filters_array.each do |filter| - if value = filter.default(self) + if (value = filter.default(self)) self[filter.name] = value end end @@ -219,7 +219,7 @@ def find_select_filter(filter) type = FILTER_TYPES.invert[filter.class].inspect raise( ::Datagrid::ArgumentError, - "#{self.class.name}##{filter.name} with type #{type} can not have select options" + "#{self.class.name}##{filter.name} with type #{type} can not have select options", ) end filter diff --git a/lib/datagrid/filters/base_filter.rb b/lib/datagrid/filters/base_filter.rb index 7d373aa..69e7854 100644 --- a/lib/datagrid/filters/base_filter.rb +++ b/lib/datagrid/filters/base_filter.rb @@ -11,7 +11,7 @@ class FilteringError < StandardError module Datagrid module Filters class BaseFilter - class_attribute :default_input_options, instance_writer: false, default: {type: 'text'} + class_attribute :default_input_options, instance_writer: false, default: { type: "text" } attr_accessor :grid_class, :options, :block, :name @@ -41,7 +41,7 @@ def apply(grid_object, scope, value) unless grid_object.driver.match?(result) raise( Datagrid::FilteringError, - "Filter #{name.inspect} unapplicable: result no longer match #{grid_object.driver.class}." + "Filter #{name.inspect} unapplicable: result no longer match #{grid_object.driver.class}.", ) end @@ -57,7 +57,7 @@ def parse_values(value) end elsif value.is_a?(Array) raise Datagrid::ArgumentError, - "#{grid_class}##{name} filter can not accept Array argument. Use :multiple option." + "#{grid_class}##{name} filter can not accept Array argument. Use :multiple option." else parse(value) end diff --git a/lib/datagrid/filters/boolean_filter.rb b/lib/datagrid/filters/boolean_filter.rb index d54eea3..72b6d15 100644 --- a/lib/datagrid/filters/boolean_filter.rb +++ b/lib/datagrid/filters/boolean_filter.rb @@ -5,7 +5,7 @@ module Datagrid module Filters class BooleanFilter < Datagrid::Filters::BaseFilter - self.default_input_options = {type: 'checkbox' } + self.default_input_options = { type: "checkbox" } def parse(value) Datagrid::Utils.booleanize(value) diff --git a/lib/datagrid/filters/date_filter.rb b/lib/datagrid/filters/date_filter.rb index 3fe5428..44bd0c5 100644 --- a/lib/datagrid/filters/date_filter.rb +++ b/lib/datagrid/filters/date_filter.rb @@ -7,7 +7,7 @@ module Filters class DateFilter < Datagrid::Filters::BaseFilter include Datagrid::Filters::RangedFilter - self.default_input_options = { type: 'date' } + self.default_input_options = { type: "date" } def apply(grid_object, scope, value) value = value.begin&.beginning_of_day..value.end&.end_of_day if value.is_a?(Range) diff --git a/lib/datagrid/filters/date_time_filter.rb b/lib/datagrid/filters/date_time_filter.rb index 37effa0..09d2bed 100644 --- a/lib/datagrid/filters/date_time_filter.rb +++ b/lib/datagrid/filters/date_time_filter.rb @@ -7,7 +7,7 @@ module Filters class DateTimeFilter < Datagrid::Filters::BaseFilter include Datagrid::Filters::RangedFilter - self.default_input_options = {type: 'datetime-local' } + self.default_input_options = { type: "datetime-local" } def parse(value) Datagrid::Utils.parse_datetime(value) diff --git a/lib/datagrid/filters/dynamic_filter.rb b/lib/datagrid/filters/dynamic_filter.rb index febb8f6..c9bb9be 100644 --- a/lib/datagrid/filters/dynamic_filter.rb +++ b/lib/datagrid/filters/dynamic_filter.rb @@ -15,7 +15,7 @@ class DynamicFilter < Datagrid::Filters::BaseFilter EQUAL_OPERATION, LIKE_OPERATION, MORE_EQUAL_OPERATION, - LESS_EQUAL_OPERATION + LESS_EQUAL_OPERATION, ].freeze AVAILABLE_OPERATIONS = %w[= =~ >= <=].freeze @@ -48,7 +48,7 @@ def default_filter_where(scope, filter) unless operations.include?(operation) raise Datagrid::FilteringError, - "Unknown operation: #{operation.inspect}. Available operations: #{operations.join(' ')}" + "Unknown operation: #{operation.inspect}. Available operations: #{operations.join(' ')}" end case operation @@ -70,7 +70,7 @@ def default_filter_where(scope, filter) driver.less_equal(scope, field, value) else raise Datagrid::FilteringError, - "Unknown operation: #{operation.inspect}. Use filter block argument to implement operation" + "Unknown operation: #{operation.inspect}. Use filter block argument to implement operation" end end @@ -91,7 +91,7 @@ def default_select grid.driver.column_names(grid.scope).map do |name| # Mongodb/Rails problem: # '_id'.humanize returns '' - [name.gsub(/^_/, "").humanize.strip, name] + [name.gsub(%r{^_}, "").humanize.strip, name] end } end @@ -119,16 +119,16 @@ def initialize(grid_class, object = nil) else raise ArgumentError, object.inspect end - if grid_class - type = grid_class.driver.normalized_column_type( - grid_class.scope, field - ) - self.value = type_cast(type, value) - end + return unless grid_class + + type = grid_class.driver.normalized_column_type( + grid_class.scope, field, + ) + self.value = type_cast(type, value) end def inspect - {field: field, operation: operation, value: value} + { field: field, operation: operation, value: value } end def to_ary @@ -140,7 +140,7 @@ def to_a end def to_h - {field: field, operation: operation, value: value} + { field: field, operation: operation, value: value } end protected @@ -152,9 +152,9 @@ def type_cast(type, value) when :string value.to_s when :integer - value.is_a?(Numeric) || value =~ /^\d/ ? value.to_i : nil + value.is_a?(Numeric) || value =~ %r{^\d} ? value.to_i : nil when :float - value.is_a?(Numeric) || value =~ /^\d/ ? value.to_f : nil + value.is_a?(Numeric) || value =~ %r{^\d} ? value.to_f : nil when :date, :timestamp Datagrid::Utils.parse_date(value) when :boolean diff --git a/lib/datagrid/filters/enum_filter.rb b/lib/datagrid/filters/enum_filter.rb index 4133d07..7cacacb 100644 --- a/lib/datagrid/filters/enum_filter.rb +++ b/lib/datagrid/filters/enum_filter.rb @@ -7,7 +7,7 @@ module Filters class EnumFilter < Datagrid::Filters::BaseFilter include Datagrid::Filters::SelectOptions - self.default_input_options = {type: 'select' } + self.default_input_options = { type: "select" } def initialize(*args) super diff --git a/lib/datagrid/filters/extended_boolean_filter.rb b/lib/datagrid/filters/extended_boolean_filter.rb index e2bbc6b..b8a9b29 100644 --- a/lib/datagrid/filters/extended_boolean_filter.rb +++ b/lib/datagrid/filters/extended_boolean_filter.rb @@ -9,7 +9,7 @@ class ExtendedBooleanFilter < Datagrid::Filters::EnumFilter TRUTH_VALUES = [true, "true", "y", "yes"].freeze FALSE_VALUES = [false, "false", "n", "no"].freeze - self.default_input_options = {type: 'select' } + self.default_input_options = { type: "select" } def initialize(report, attribute, options = {}, &block) options[:select] = -> { boolean_select } diff --git a/lib/datagrid/filters/float_filter.rb b/lib/datagrid/filters/float_filter.rb index 0257746..4cafa9f 100644 --- a/lib/datagrid/filters/float_filter.rb +++ b/lib/datagrid/filters/float_filter.rb @@ -6,7 +6,7 @@ module Filters class FloatFilter < Datagrid::Filters::BaseFilter include Datagrid::Filters::RangedFilter - self.default_input_options = {type: 'number', step: 'any' } + self.default_input_options = { type: "number", step: "any" } def parse(value) return nil if value.blank? diff --git a/lib/datagrid/filters/integer_filter.rb b/lib/datagrid/filters/integer_filter.rb index fd64bb2..3029df6 100644 --- a/lib/datagrid/filters/integer_filter.rb +++ b/lib/datagrid/filters/integer_filter.rb @@ -7,7 +7,7 @@ module Filters class IntegerFilter < Datagrid::Filters::BaseFilter include Datagrid::Filters::RangedFilter - self.default_input_options = {type: 'number', step: '1' } + self.default_input_options = { type: "number", step: "1" } def parse(value) return nil if value.blank? diff --git a/lib/datagrid/filters/ranged_filter.rb b/lib/datagrid/filters/ranged_filter.rb index abe73de..a18cb18 100644 --- a/lib/datagrid/filters/ranged_filter.rb +++ b/lib/datagrid/filters/ranged_filter.rb @@ -3,18 +3,17 @@ module Datagrid module Filters module RangedFilter - SERIALIZED_RANGE = /\A(.*)\.{2,3}(.*)\z/ + SERIALIZED_RANGE = %r{\A(.*)\.{2,3}(.*)\z}.freeze def parse_values(value) - unless range? - return super - end + return super unless range? + case value when String - if value == '..' || value == '...' + if ["..", "..."].include?(value) nil - elsif match = value.match(SERIALIZED_RANGE) - to_range(match.captures[0], match.captures[1], value.include?('...')) + elsif (match = value.match(SERIALIZED_RANGE)) + to_range(match.captures[0], match.captures[1], value.include?("...")) else super end @@ -56,9 +55,7 @@ def to_range(from, to, exclusive = false) return nil unless to || from # If wrong range is given - reverse it to be always valid - if from && to && from > to - from, to = to, from - end + from, to = to, from if from && to && from > to exclusive ? from...to : from..to end @@ -69,7 +66,7 @@ def parse_array(result) case result.size when 0 nil - when 1,2 + when 1, 2 to_range(first, last) else raise ArgumentError, "Can not create a range from array of more than two elements" diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 1af46df..34a921a 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -32,13 +32,11 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) type = options.delete(:type)&.to_sym if %i[datetime-local date].include?(type) if options.key?(:value) && options[:value].nil? && - # https://github.com/rails/rails/pull/53387 - options[:value] = "" - end - else - if options[:value] - options[:value] = filter.format(options[:value]) + # https://github.com/rails/rails/pull/53387 + (options[:value] = "") end + elsif options[:value] + options[:value] = filter.format(options[:value]) end case type when :"datetime-local" @@ -60,7 +58,7 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) { include_blank: filter.include_blank, prompt: filter.prompt, - include_hidden: false + include_hidden: false, }, multiple: filter.multiple?, **options, @@ -106,8 +104,8 @@ def datagrid_enum_filter(filter, options = {}, &block) elements: elements, form: self, filter: filter, - options: options - } + options: options, + }, ) else datagrid_filter_input(filter, **options, type: :select, &block) @@ -140,10 +138,10 @@ def datagrid_dynamic_filter(filter, options = {}) include_blank: filter.include_blank, prompt: filter.prompt, include_hidden: false, - selected: field + selected: field, }, **add_html_classes(options, "datagrid-dynamic-field"), - name: @template.field_name(object_name, filter.name, 'field') + name: @template.field_name(object_name, filter.name, "field"), ) operation_input = dynamic_filter_select( filter.name, filter.operations_select, @@ -151,16 +149,16 @@ def datagrid_dynamic_filter(filter, options = {}) include_blank: false, include_hidden: false, prompt: false, - selected: operation + selected: operation, }, **add_html_classes(options, "datagrid-dynamic-operation"), - name: @template.field_name(object_name, filter.name, 'operation') + name: @template.field_name(object_name, filter.name, "operation"), ) value_input = datagrid_filter_input( filter.name, **add_html_classes(options, "datagrid-dynamic-value"), value: value, - name: @template.field_name(object_name, filter.name, 'value') + name: @template.field_name(object_name, filter.name, "value"), ) [field_input, operation_input, value_input].join("\n").html_safe end @@ -182,7 +180,7 @@ def datagrid_range_filter(_type, filter, options = {}) from_options = datagrid_range_filter_options(object, filter, :from, **options) to_options = datagrid_range_filter_options(object, filter, :to, **options) render_partial "range_filter", { - from_options: from_options, to_options: to_options, filter: filter, form: self + from_options: from_options, to_options: to_options, filter: filter, form: self, } else datagrid_filter_input(filter, **options) diff --git a/lib/datagrid/ordering.rb b/lib/datagrid/ordering.rb index 695a812..8b8ebc2 100644 --- a/lib/datagrid/ordering.rb +++ b/lib/datagrid/ordering.rb @@ -110,7 +110,7 @@ def reverse_order(assets) driver.reverse_order(assets) rescue NotImplementedError self.class.order_unsupported(order_column.name, - "Your ORM do not support reverse order: please specify :order_desc option manually") + "Your ORM do not support reverse order: please specify :order_desc option manually",) end def apply_block_order(assets, order) diff --git a/lib/datagrid/renderer.rb b/lib/datagrid/renderer.rb index 8c62935..2253b01 100644 --- a/lib/datagrid/renderer.rb +++ b/lib/datagrid/renderer.rb @@ -27,25 +27,25 @@ def form_for(grid, options = {}) def table(grid, assets, **options) _render_partial("table", options[:partials], - { - grid: grid, - options: options, - assets: assets - }) + { + grid: grid, + options: options, + assets: assets, + },) end def header(grid, options = {}) options[:order] = true unless options.key?(:order) _render_partial("head", options[:partials], - { grid: grid, options: options }) + { grid: grid, options: options },) end def rows(grid, assets = grid.assets, **options, &block) @template.safe_join( assets.map do |asset| row(grid, asset, **options, &block) - end.to_a + end.to_a, ) end @@ -57,7 +57,7 @@ def row(grid, asset, **options, &block) def order_for(grid, column, options = {}) _render_partial("order_for", options[:partials], - { grid: grid, column: column }) + { grid: grid, column: column },) end def order_path(grid, column, descending, request) @@ -65,7 +65,7 @@ def order_path(grid, column, descending, request) query = request&.query_parameters || {} ActionDispatch::Http::URL.path_for( path: request&.path || "/", - params: query.merge(grid.query_params(order: column.name, descending: descending)) + params: query.merge(grid.query_params(order: column.name, descending: descending)), ) end @@ -74,7 +74,7 @@ def order_path(grid, column, descending, request) def _render_partial(partial_name, partials_path, locals = {}) @template.render({ partial: File.join(partials_path || "datagrid", partial_name), - locals: locals + locals: locals, }) end end @@ -118,10 +118,10 @@ def each(&block) def to_s @renderer.send(:_render_partial, "row", options[:partials], { - grid: grid, - options: options, - asset: asset - }) + grid: grid, + options: options, + asset: asset, + },) end protected diff --git a/lib/datagrid/scaffold.rb b/lib/datagrid/scaffold.rb index 9fae2a0..d0f69a0 100644 --- a/lib/datagrid/scaffold.rb +++ b/lib/datagrid/scaffold.rb @@ -15,7 +15,7 @@ def create_scaffold template "base.rb.erb", base_grid_file unless file_exists?(base_grid_file) template "grid.rb.erb", "app/grids/#{grid_class_name.underscore}.rb" if file_exists?(grid_controller_file) - inject_into_file grid_controller_file, index_action, after: /class .*#{grid_controller_class_name}.*\n/ + inject_into_file grid_controller_file, index_action, after: %r{class .*#{grid_controller_class_name}.*\n} else create_file grid_controller_file, controller_code end @@ -26,11 +26,11 @@ def create_scaffold { "css" => " *= require datagrid", "css.sass" => " *= require datagrid", - "css.scss" => " *= require datagrid" + "css.scss" => " *= require datagrid", }.each do |extension, string| file = "app/assets/stylesheets/application.#{extension}" if file_exists?(file) - inject_into_file file, "#{string}\n", { before: /.*require_self/ } # before all + inject_into_file file, "#{string}\n", { before: %r{.*require_self} } # before all end end end @@ -45,7 +45,7 @@ def grid_class_name end def grid_base_class - file_exists?('app/grids/base_grid.rb') ? 'BaseGrid' : 'ApplicationGrid' + file_exists?("app/grids/base_grid.rb") ? "BaseGrid" : "ApplicationGrid" end def grid_controller_class_name @@ -72,7 +72,7 @@ def pagination_helper_code if defined?(::WillPaginate) "will_paginate(@grid.assets)" elsif defined?(::Pagy) - "pagy_nav(@pagy)" + "pagy_nav(@pagy)" else # Kaminari is default "paginate(@grid.assets)" @@ -112,28 +112,28 @@ def index_code def controller_code <<~RUBY -class #{grid_controller_class_name} < ApplicationController - def index -#{index_code.rstrip} - end + class #{grid_controller_class_name} < ApplicationController + def index + #{index_code.rstrip} + end - protected + protected - def grid_params - params.fetch(:#{grid_param_name}, {}).permit! - end -end -RUBY + def grid_params + params.fetch(:#{grid_param_name}, {}).permit! + end + end + RUBY end def view_code indent(<<~ERB) -<%= datagrid_form_for @grid, url: #{grid_route_name} %> + <%= datagrid_form_for @grid, url: #{grid_route_name} %> -<%= #{pagination_helper_code} %> -<%= #{table_helper_code} %> -<%= #{pagination_helper_code} %> -ERB + <%= #{pagination_helper_code} %> + <%= #{table_helper_code} %> + <%= #{pagination_helper_code} %> + ERB end protected diff --git a/spec/datagrid/columns_spec.rb b/spec/datagrid/columns_spec.rb index 4b83f48..3e313f0 100644 --- a/spec/datagrid/columns_spec.rb +++ b/spec/datagrid/columns_spec.rb @@ -19,7 +19,7 @@ category: "first", access_level: "admin", pet: "rottweiler", - shipping_date: Date.new(2013, 8, 1) + shipping_date: Date.new(2013, 8, 1), ) end @@ -126,9 +126,9 @@ class Report27 < Datagrid::Base it "should generate table data" do expect(subject.data).to eq([ - subject.header, - subject.row_for(entry) - ]) + subject.header, + subject.row_for(entry), + ]) end it "supports dynamic header" do @@ -142,17 +142,17 @@ class Report27 < Datagrid::Base it "should generate hash for given asset" do expect(subject.hash_for(entry)).to eq({ - group: "Pop", - name: "Star", - access_level: "admin", - pet: "ROTTWEILER", - shipping_date: date - }) + group: "Pop", + name: "Star", + access_level: "admin", + pet: "ROTTWEILER", + shipping_date: date, + }) end it "should support csv export" do expect(subject.to_csv).to eq( - "Shipping date,Group,Name,Access level,Pet\n#{date},Pop,Star,admin,ROTTWEILER\n" + "Shipping date,Group,Name,Access level,Pet\n#{date},Pop,Star,admin,ROTTWEILER\n", ) end @@ -162,7 +162,7 @@ class Report27 < Datagrid::Base it "should support csv export options" do expect(subject.to_csv(col_sep: ";")).to eq( - "Shipping date;Group;Name;Access level;Pet\n#{date};Pop;Star;admin;ROTTWEILER\n" + "Shipping date;Group;Name;Access level;Pet\n#{date};Pop;Star;admin;ROTTWEILER\n", ) end end diff --git a/spec/datagrid/core_spec.rb b/spec/datagrid/core_spec.rb index c2ff630..f7cea42 100644 --- a/spec/datagrid/core_spec.rb +++ b/spec/datagrid/core_spec.rb @@ -106,7 +106,7 @@ class InspectTest < Datagrid::Base grid = InspectTest.new(created_at: %w[2014-01-01 2014-08-05], descending: true, order: "name") expect(grid.inspect).to eq( - "#<InspectTest order: :name, descending: true, created_at: Wed, 01 Jan 2014..Tue, 05 Aug 2014>" + "#<InspectTest order: :name, descending: true, created_at: Wed, 01 Jan 2014..Tue, 05 Aug 2014>", ) end end @@ -211,7 +211,7 @@ class EqualTest < Datagrid::Base filter(:name) end - expect(grid.name).to eq('one') + expect(grid.name).to eq("one") end it "doesn't permit attributes when forbidden_attributes_protection is set" do @@ -236,7 +236,7 @@ class EqualTest < Datagrid::Base it "supports hash attribute assignment" do grid = test_report( - ActionController::Parameters.new(group_id: {from: 1, to:2}) + ActionController::Parameters.new(group_id: { from: 1, to: 2 }), ) do scope { Entry } filter(:group_id, :integer, range: true) diff --git a/spec/datagrid/drivers/active_record_spec.rb b/spec/datagrid/drivers/active_record_spec.rb index fbc6c06..1dd671a 100644 --- a/spec/datagrid/drivers/active_record_spec.rb +++ b/spec/datagrid/drivers/active_record_spec.rb @@ -19,8 +19,8 @@ it "should support append_column_queries" do scope = subject.append_column_queries(Entry.where({}), - [Datagrid::Columns::Column.new(test_report_class, :sum_group_id, - "sum(entries.group_id)")]) + [Datagrid::Columns::Column.new(test_report_class, :sum_group_id, + "sum(entries.group_id)",)],) expect(scope.to_sql.strip).to eq('SELECT "entries".*, sum(entries.group_id) AS sum_group_id FROM "entries"') end @@ -49,18 +49,18 @@ end it "includes object created in proper range" do expect(subject).to include( - Entry.create!(group: Group.create!(created_at: 7.days.ago)) + Entry.create!(group: Group.create!(created_at: 7.days.ago)), ) end it "excludes object created before the range" do expect(subject).to_not include( - Entry.create!(created_at: 7.days.ago, group: Group.create!(created_at: 11.days.ago)) + Entry.create!(created_at: 7.days.ago, group: Group.create!(created_at: 11.days.ago)), ) end it "excludes object created after the range" do expect(subject).to_not include( - Entry.create!(created_at: 7.days.ago, group: Group.create!(created_at: 4.days.ago)) + Entry.create!(created_at: 7.days.ago, group: Group.create!(created_at: 4.days.ago)), ) end end diff --git a/spec/datagrid/drivers/mongo_mapper_spec.rb b/spec/datagrid/drivers/mongo_mapper_spec.rb index 2deec97..750f02d 100644 --- a/spec/datagrid/drivers/mongo_mapper_spec.rb +++ b/spec/datagrid/drivers/mongo_mapper_spec.rb @@ -15,7 +15,7 @@ describe "api" do subject do MongoMapperGrid.new( - defined?(_attributes) ? _attributes : {} + defined?(_attributes) ? _attributes : {}, ) end @@ -23,14 +23,14 @@ MongoMapperEntry.create!( group_id: 2, name: "Main First", - disabled: false + disabled: false, ) end let!(:second) do MongoMapperEntry.create!( group_id: 3, name: "Main Second", - disabled: true + disabled: true, ) end diff --git a/spec/datagrid/drivers/mongoid_spec.rb b/spec/datagrid/drivers/mongoid_spec.rb index 1f9646e..d68958d 100644 --- a/spec/datagrid/drivers/mongoid_spec.rb +++ b/spec/datagrid/drivers/mongoid_spec.rb @@ -13,7 +13,7 @@ describe "api" do subject do MongoidGrid.new( - defined?(_attributes) ? _attributes : {} + defined?(_attributes) ? _attributes : {}, ) end @@ -21,14 +21,14 @@ MongoidEntry.create!( group_id: 2, name: "Main First", - disabled: false + disabled: false, ) end let!(:second) do MongoidEntry.create!( group_id: 3, name: "Main Second", - disabled: true + disabled: true, ) end diff --git a/spec/datagrid/drivers/sequel_spec.rb b/spec/datagrid/drivers/sequel_spec.rb index 5b79963..93c0636 100644 --- a/spec/datagrid/drivers/sequel_spec.rb +++ b/spec/datagrid/drivers/sequel_spec.rb @@ -13,7 +13,7 @@ describe "api" do subject do SequelGrid.new( - defined?(_attributes) ? _attributes : {} + defined?(_attributes) ? _attributes : {}, ) end @@ -21,14 +21,14 @@ SequelEntry.create( group_id: 2, name: "Main First", - disabled: false + disabled: false, ) end let!(:second) do SequelEntry.create( group_id: 3, name: "Main Second", - disabled: true + disabled: true, ) end diff --git a/spec/datagrid/filters/date_filter_spec.rb b/spec/datagrid/filters/date_filter_spec.rb index 9d09a52..3aa08c9 100644 --- a/spec/datagrid/filters/date_filter_spec.rb +++ b/spec/datagrid/filters/date_filter_spec.rb @@ -37,7 +37,7 @@ e3 = Entry.create!(created_at: 1.day.ago) from = 5.days.ago to = 3.days.ago - report = test_report(created_at: {from: , to:}) do + report = test_report(created_at: { from: from, to: to }) do scope { Entry } filter(:created_at, :date, range: true) end @@ -47,13 +47,13 @@ expect(report.assets).not_to include(e3) report.created_at = {} expect(report.created_at).to eq(nil) - report.created_at = {from: nil, to: nil} + report.created_at = { from: nil, to: nil } expect(report.created_at).to eq(nil) - report.created_at = {from: Date.today, to: nil} + report.created_at = { from: Date.today, to: nil } expect(report.created_at).to eq(Date.today..nil) - report.created_at = {from: nil, to: Date.today} + report.created_at = { from: nil, to: Date.today } expect(report.created_at).to eq(nil..Date.today) - report.created_at = {from: Time.now, to: Time.now} + report.created_at = { from: Time.now, to: Time.now } expect(report.created_at).to eq(Date.today..Date.today) end diff --git a/spec/datagrid/filters/dynamic_filter_spec.rb b/spec/datagrid/filters/dynamic_filter_spec.rb index f373f08..eae16f6 100644 --- a/spec/datagrid/filters/dynamic_filter_spec.rb +++ b/spec/datagrid/filters/dynamic_filter_spec.rb @@ -63,25 +63,25 @@ it "should nullify incorrect value for integer" do report.condition = [:group_id, "<=", "aa"] expect(report.condition.to_h).to eq( - {field: :group_id, operation: "<=", value: nil} + { field: :group_id, operation: "<=", value: nil }, ) end it "should nullify incorrect value for date" do report.condition = [:shipping_date, "<=", "aa"] expect(report.condition.to_h).to eq({ - field: :shipping_date, operation: "<=", value: nil + field: :shipping_date, operation: "<=", value: nil, }) end it "should nullify incorrect value for datetime" do report.condition = [:created_at, "<=", "aa"] - expect(report.condition.to_h).to eq({field: :created_at, operation: "<=", value: nil}) + expect(report.condition.to_h).to eq({ field: :created_at, operation: "<=", value: nil }) end it "should support date comparation operation by timestamp column" do report.condition = [:created_at, "<=", "1986-08-05"] - expect(report.condition.to_h).to eq({field: :created_at, operation: "<=", value: Date.parse("1986-08-05")}) + expect(report.condition.to_h).to eq({ field: :created_at, operation: "<=", value: Date.parse("1986-08-05") }) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-04 01:01:01"))) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 23:59:59"))) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 00:00:00"))) @@ -91,7 +91,7 @@ it "should support date = operation by timestamp column" do report.condition = [:created_at, "=", "1986-08-05"] - expect(report.condition.to_h).to eq({field: :created_at, operation: "=", value: Date.parse("1986-08-05")}) + expect(report.condition.to_h).to eq({ field: :created_at, operation: "=", value: Date.parse("1986-08-05") }) expect(report.assets).not_to include(Entry.create!(created_at: Time.parse("1986-08-04 23:59:59"))) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 23:59:59"))) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 00:00:01"))) @@ -102,7 +102,7 @@ it "should support date =~ operation by timestamp column" do report.condition = [:created_at, "=~", "1986-08-05"] - expect(report.condition.to_h).to eq({field: :created_at, operation: "=~", value: Date.parse("1986-08-05")}) + expect(report.condition.to_h).to eq({ field: :created_at, operation: "=~", value: Date.parse("1986-08-05") }) expect(report.assets).not_to include(Entry.create!(created_at: Time.parse("1986-08-04 23:59:59"))) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 23:59:59"))) expect(report.assets).to include(Entry.create!(created_at: Time.parse("1986-08-05 00:00:01"))) @@ -129,7 +129,7 @@ scope { Entry } filter( :condition, :dynamic, allow_nil: true, allow_blank: true, - operations: [">=", "<="] + operations: [">=", "<="], ) do |(field, operation, value), scope| if value.blank? scope.where(disabled: false) @@ -153,7 +153,7 @@ grid = test_report do scope { Entry } filter( - :condition, :dynamic, operations: ["=", "!="] + :condition, :dynamic, operations: ["=", "!="], ) do |filter, scope| if filter.operation == "!=" scope.where("#{filter.field} != ?", filter.value) @@ -181,14 +181,14 @@ end it "supports assignment of string keys hash" do - report.condition = { + report.condition = { field: "shipping_date", operation: "<>", value: "1996-08-05", }.stringify_keys expect(report.condition.to_h).to eq({ - field: 'shipping_date', operation: '<>', value: Date.parse('1996-08-05') + field: "shipping_date", operation: "<>", value: Date.parse("1996-08-05"), }) end end diff --git a/spec/datagrid/filters/integer_filter_spec.rb b/spec/datagrid/filters/integer_filter_spec.rb index 9ea1183..913249d 100644 --- a/spec/datagrid/filters/integer_filter_spec.rb +++ b/spec/datagrid/filters/integer_filter_spec.rb @@ -104,7 +104,7 @@ scope { Entry } filter(:group_id, :integer, multiple: true) end - expect(report.group_id).to eq([1,2]) + expect(report.group_id).to eq([1, 2]) expect(report.assets).to include(entry1) expect(report.assets).to include(entry2) expect(report.assets).not_to include(entry3) diff --git a/spec/datagrid/filters_spec.rb b/spec/datagrid/filters_spec.rb index 16d126e..457c75f 100644 --- a/spec/datagrid/filters_spec.rb +++ b/spec/datagrid/filters_spec.rb @@ -46,7 +46,6 @@ class ModelWithoutTable < ActiveRecord::Base; end expect(ModelWithoutTable).not_to be_table_exists class TheReport < Datagrid::Base - scope { ModelWithoutTable } filter(:name) @@ -229,7 +228,7 @@ class InheritedReport < TranslatedReport filters = { id: [1, 2], name: [["a", 1], ["b", 2]], - category: { a: 1, b: 2 } + category: { a: 1, b: 2 }, } grid = test_report do scope { Entry } @@ -268,7 +267,7 @@ class TestGrid < Datagrid::Base end expect(NsInspect::TestGrid.inspect).to eq( - "NsInspect::TestGrid(id: integer, name: string, current_user: default)" + "NsInspect::TestGrid(id: integer, name: string, current_user: default)", ) end diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 5b64bb5..e8bfee9 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -36,7 +36,7 @@ class MyTemplate let(:_filter) { :name } it { should equal_to_dom( - '<input type="text" name="report[name]" id="report_name"/>' + '<input type="text" name="report[name]" id="report_name"/>', ) } end @@ -50,7 +50,7 @@ class MyTemplate end it { should equal_to_dom( - '<input type="number" step="1" name="report[group_id]" id="report_group_id"/>' + '<input type="number" step="1" name="report[group_id]" id="report_group_id"/>', ) } @@ -58,7 +58,7 @@ class MyTemplate let(:view_options) { { partials: "anything" } } it { should equal_to_dom( - '<input type="number" step="1" name="report[group_id]" id="report_group_id"/>' + '<input type="number" step="1" name="report[group_id]" id="report_group_id"/>', ) } end @@ -74,7 +74,7 @@ class MyTemplate end it { should equal_to_dom( - '<input type="date" name="report[created_at]" id="report_created_at"/>' + '<input type="date" name="report[created_at]" id="report_created_at"/>', ) } context "when special date format specified" do @@ -87,7 +87,7 @@ class MyTemplate it { should equal_to_dom( '<input value="2012-01-02" type="date" - name="report[created_at]" id="report_created_at"/>' + name="report[created_at]" id="report_created_at"/>', ) } end @@ -98,12 +98,12 @@ class MyTemplate let(:_grid) do test_report do scope { Entry } - filter(:created_at, :date, input_options: { type: 'text' }) + filter(:created_at, :date, input_options: { type: "text" }) end end it { should equal_to_dom( - '<input type="text" name="report[created_at]" id="report_created_at"/>' + '<input type="text" name="report[created_at]" id="report_created_at"/>', ) } end @@ -117,7 +117,7 @@ class MyTemplate end it { should equal_to_dom( - '<textarea name="report[name]" id="report_name"/>' + '<textarea name="report[name]" id="report_name"/>', ) } end @@ -133,7 +133,7 @@ class MyTemplate it { should equal_to_dom( '<input type="text" value="2024-01-01 09:25:15 +0100" - name="report[created_at]" id="report_created_at"/>' + name="report[created_at]" id="report_created_at"/>', ) } @@ -143,7 +143,7 @@ class MyTemplate end it { should equal_to_dom( - '<input type="text" name="report[created_at]" id="report_created_at"/>' + '<input type="text" name="report[created_at]" id="report_created_at"/>', ) } end @@ -160,7 +160,7 @@ class MyTemplate it { should equal_to_dom( '<input type="date" value="2024-01-01" - name="report[created_at]" id="report_created_at"/>' + name="report[created_at]" id="report_created_at"/>', ) } end @@ -183,7 +183,7 @@ class MyTemplate type="number" step="1" name="report[group_id][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2" id="to_hello" class="datagrid-range-to" - type="number" step="1" name="report[group_id][to]"/>' + type="number" step="1" name="report[group_id][to]"/>', ) } end @@ -195,7 +195,7 @@ class MyTemplate type="number" step="1" name="report[group_id][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input class="datagrid-range-to" - type="number" step="1" name="report[group_id][to]"/>' + type="number" step="1" name="report[group_id][to]"/>', ) } it { should be_html_safe } @@ -206,7 +206,7 @@ class MyTemplate should equal_to_dom( '<input class="datagrid-range-from" type="number" step="1" name="report[group_id][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ - '<input value="10" class="datagrid-range-to" type="number" step="1" name="report[group_id][to]"/>' + '<input value="10" class="datagrid-range-to" type="number" step="1" name="report[group_id][to]"/>', ) } it { should be_html_safe } @@ -218,7 +218,7 @@ class MyTemplate should equal_to_dom( '<input value="1" class="datagrid-range-from" type="number" step="1" name="report[group_id][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ - '<input value="2" class="datagrid-range-to" type="number" step="1" name="report[group_id][to]"/>' + '<input value="2" class="datagrid-range-to" type="number" step="1" name="report[group_id][to]"/>', ) } end @@ -228,7 +228,7 @@ class MyTemplate let(:_range) { nil } it { should equal_to_dom( - "custom_range_partial" + "custom_range_partial", ) } end @@ -240,7 +240,7 @@ class MyTemplate should equal_to_dom( '<input class="datagrid-range-from" type="number" step="1" name="report[group_id][from]"> <span class="datagrid-range-separator"> - </span> - <input class="datagrid-range-to" type="number" step="1" name="report[group_id][to]">' + <input class="datagrid-range-to" type="number" step="1" name="report[group_id][to]">', ) } end @@ -261,7 +261,7 @@ class MyTemplate type="number" step="any" name="report[rating][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2.5" class="datagrid-range-to" - type="number" step="any" name="report[rating][to]"/>' + type="number" step="any" name="report[rating][to]"/>', ) } end @@ -280,7 +280,7 @@ class MyTemplate should equal_to_dom( '<input value="2012-01-03" class="datagrid-range-from" type="date" name="report[created_at][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ - '<input class="datagrid-range-to" type="date" name="report[created_at][to]" value=""/>' + '<input class="datagrid-range-to" type="date" name="report[created_at][to]" value=""/>', ) } it { should be_html_safe } @@ -298,7 +298,7 @@ class MyTemplate type="date" name="report[created_at][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2013-02-02" class="datagrid-range-to" - type="date" name="report[created_at][to]"/>' + type="date" name="report[created_at][to]"/>', ) } end @@ -310,7 +310,7 @@ class MyTemplate type="date" value="" name="report[created_at][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2012-01-03" class="datagrid-range-to" - type="date" name="report[created_at][to]"/>' + type="date" name="report[created_at][to]"/>', ) } it { should be_html_safe } @@ -324,7 +324,7 @@ class MyTemplate type="date" name="report[created_at][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2012-01-02" class="datagrid-range-to" - type="date" name="report[created_at][to]"/>' + type="date" name="report[created_at][to]"/>', ) } end @@ -339,7 +339,7 @@ class MyTemplate should equal_to_dom( '<input class="datagrid-range-from" type="date" value="" name="report[created_at][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ - '<input class="datagrid-range-to" type="date" value="" name="report[created_at][to]"/>' + '<input class="datagrid-range-to" type="date" value="" name="report[created_at][to]"/>', ) } end @@ -359,7 +359,7 @@ class MyTemplate %(<select name="report[category]" id="report_category"> <option value="" label=" "></option> <option value="first">first</option> - <option value="second">second</option></select>) + <option value="second">second</option></select>), ) } @@ -373,7 +373,7 @@ class MyTemplate should equal_to_dom( %(<select name="report[category]" id="report_category"> <option value="" label=" "></option> - <option value="block_value">block option</option></select>) + <option value="block_value">block option</option></select>), ) } end @@ -386,7 +386,7 @@ class MyTemplate %(<select name="report[category]" id="report_category"> <option value="" label=" "></option> <option selected value="first">first</option> - <option value="second">second</option></select>) + <option value="second">second</option></select>), ) } end @@ -396,7 +396,7 @@ class MyTemplate should equal_to_dom( '<select name="report[category]" id="report_category"> <option value="first">first</option> - <option value="second">second</option></select>' + <option value="second">second</option></select>', ) } end @@ -407,7 +407,7 @@ class MyTemplate '<select name="report[category]" id="report_category"> <option value="">Choose plz</option> <option value="first">first</option> - <option value="second">second</option></select>' + <option value="second">second</option></select>', ) } end @@ -419,7 +419,7 @@ class MyTemplate '<select name="report[category]" id="report_category"> <option value="">My Prompt</option> <option value="first">first</option> - <option value="second">second</option></select>' + <option value="second">second</option></select>', ) } end @@ -431,7 +431,7 @@ class MyTemplate '<select class="custom-class" name="report[category]" id="report_category"> <option value="" label=" "></option> <option value="first">first</option> - <option value="second">second</option></select>' + <option value="second">second</option></select>', ) } end @@ -439,19 +439,19 @@ class MyTemplate let(:_category_filter_options) { { checkboxes: true } } it { should equal_to_dom( - <<-HTML -<div class="datagrid-enum-checkboxes"> -<label for="report_category_first" class="datagrid-enum-checkbox-label"> -<input type="checkbox" id="report_category_first" - value="first" name="report[category][]" /> -first -</label> -<label for="report_category_second" class="datagrid-enum-checkbox-label"> -<input type="checkbox" id="report_category_second" - value="second" name="report[category][]" /> -second -</label> -</div> + <<~HTML, + <div class="datagrid-enum-checkboxes"> + <label for="report_category_first" class="datagrid-enum-checkbox-label"> + <input type="checkbox" id="report_category_first" + value="first" name="report[category][]" /> + first + </label> + <label for="report_category_second" class="datagrid-enum-checkbox-label"> + <input type="checkbox" id="report_category_second" + value="second" name="report[category][]" /> + second + </label> + </div> HTML ) } @@ -476,7 +476,7 @@ class MyTemplate # hidden is important when default is set to true %(<input name="report[disabled]" type="hidden" value="0" autocomplete="off"> <input type="checkbox" value="1" - checked name="report[disabled]" id="report_disabled">) + checked name="report[disabled]" id="report_disabled">), ) } end @@ -493,7 +493,7 @@ class MyTemplate %(<select name="report[disabled]" id="report_disabled"> <option value="" label=" "></option> <option value="YES">Yes</option> - <option value="NO">No</option></select>) + <option value="NO">No</option></select>), ) } end @@ -521,7 +521,7 @@ class MyTemplate it { should equal_to_dom( - '<input value="one,two" type="text" name="report[name]" id="report_name">' + '<input value="one,two" type="text" name="report[name]" id="report_name">', ) } end @@ -535,7 +535,7 @@ class MyTemplate :name, :enum, include_blank: false, multiple: false, - select: [] + select: [], ) end end @@ -552,7 +552,7 @@ class MyTemplate let(:_filter) { :group_id } it { should equal_to_dom( - '<input type="number" step="any" name="report[group_id]" id="report_group_id"/>' + '<input type="number" step="any" name="report[group_id]" id="report_group_id"/>', ) } end @@ -613,20 +613,20 @@ class MyTemplate let(:_filter) { :column_names } let(:expected_html) do <<~DOM - <div class="datagrid-enum-checkboxes"> - <label for="report_column_names_id" class="datagrid-enum-checkbox-label"> - <input id="report_column_names_id" type="checkbox" value="id" checked name="report[column_names][]"> - Id - </label> - <label for="report_column_names_name" class="datagrid-enum-checkbox-label"> - <input id="report_column_names_name" type="checkbox" value="name" checked name="report[column_names][]"/> - Name - </label> - <label for="report_column_names_category" class="datagrid-enum-checkbox-label"> - <input id="report_column_names_category" type="checkbox" value="category" name="report[column_names][]"> - Category - </label> - </div> + <div class="datagrid-enum-checkboxes"> + <label for="report_column_names_id" class="datagrid-enum-checkbox-label"> + <input id="report_column_names_id" type="checkbox" value="id" checked name="report[column_names][]"> + Id + </label> + <label for="report_column_names_name" class="datagrid-enum-checkbox-label"> + <input id="report_column_names_name" type="checkbox" value="name" checked name="report[column_names][]"/> + Name + </label> + <label for="report_column_names_category" class="datagrid-enum-checkbox-label"> + <input id="report_column_names_category" type="checkbox" value="category" name="report[column_names][]"> + Category + </label> + </div> DOM end @@ -740,27 +740,27 @@ class MyTemplate end it "should generate label for filter" do expect(view.datagrid_label(:created_at)).to equal_to_dom( - '<label class="js-date-selector" for="report_created_at">Created at</label>' + '<label class="js-date-selector" for="report_created_at">Created at</label>', ) end it "should generate label for filter" do expect(view.datagrid_label(:name)).to equal_to_dom( - '<label for="report_name">Name</label>' + '<label for="report_name">Name</label>', ) end it "should pass options through to the helper" do expect(view.datagrid_label(:name, class: "foo")).to equal_to_dom( - '<label class="foo" for="report_name">Name</label>' + '<label class="foo" for="report_name">Name</label>', ) end it "should support block" do expect(view.datagrid_label(:name, class: "foo") { "The Name" }).to equal_to_dom( - '<label class="foo" for="report_name">The Name</label>' + '<label class="foo" for="report_name">The Name</label>', ) end it "should support explicit label" do expect(view.datagrid_label(:name, "The Name")).to equal_to_dom( - '<label for="report_name">The Name</label>' + '<label for="report_name">The Name</label>', ) end end diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 46f4498..771e2fa 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -25,7 +25,7 @@ let(:group) { Group.create!(name: "Pop") } let!(:entry) do Entry.create!( - group: group, name: "Star", disabled: false, confirmed: false, category: "first" + group: group, name: "Star", disabled: false, confirmed: false, category: "first", ) end let(:grid) { SimpleReport.new } @@ -42,7 +42,7 @@ datagrid_table = subject.datagrid_table(grid) expect(datagrid_table).to match_css_pattern( - "table.datagrid-table tr td.datagrid-no-results" => 1 + "table.datagrid-table tr td.datagrid-no-results" => 1, ) expect(datagrid_table).to include(I18n.t("datagrid.no_results")) end @@ -51,20 +51,20 @@ describe ".datagrid_table" do it "should have grid class as html class on table" do expect(subject.datagrid_table(grid)).to match_css_pattern( - "table.datagrid-table" => 1 + "table.datagrid-table" => 1, ) end it "should return data table html" do datagrid_table = subject.datagrid_table(grid) expect(datagrid_table).to match_css_pattern({ - "table.datagrid-table tr th[data-column=group] div.datagrid-order" => 1, - "table.datagrid-table tr th[data-column=group]" => /Group.*/, - "table.datagrid-table tr th[data-column=name] div.datagrid-order" => 1, - "table.datagrid-table tr th[data-column=name]" => /Name.*/, - "table.datagrid-table tr td[data-column=group]" => "Pop", - "table.datagrid-table tr td[data-column=name]" => "Star" - }) + "table.datagrid-table tr th[data-column=group] div.datagrid-order" => 1, + "table.datagrid-table tr th[data-column=group]" => %r{Group.*}, + "table.datagrid-table tr th[data-column=name] div.datagrid-order" => 1, + "table.datagrid-table tr th[data-column=name]" => %r{Name.*}, + "table.datagrid-table tr td[data-column=group]" => "Pop", + "table.datagrid-table tr td[data-column=name]" => "Star", + }) end it "should support giving assets explicitly" do @@ -72,17 +72,18 @@ datagrid_table = subject.datagrid_table(grid, [entry]) expect(datagrid_table).to match_css_pattern({ - "table.datagrid-table tr th[data-column=group] div.datagrid-order" => 1, - "table.datagrid-table tr th[data-column=group]" => /Group.*/, - "table.datagrid-table tr th[data-column=name] div.datagrid-order" => 1, - "table.datagrid-table tr th[data-column=name]" => /Name.*/, - "table.datagrid-table tr td[data-column=group]" => "Pop", - "table.datagrid-table tr td[data-column=name]" => "Star" - }) + "table.datagrid-table tr th[data-column=group] div.datagrid-order" => 1, + "table.datagrid-table tr th[data-column=group]" => %r{Group.*}, + "table.datagrid-table tr th[data-column=name] div.datagrid-order" => 1, + "table.datagrid-table tr th[data-column=name]" => %r{Name.*}, + "table.datagrid-table tr td[data-column=group]" => "Pop", + "table.datagrid-table tr td[data-column=name]" => "Star", + }) end it "should support no order given" do - expect(subject.datagrid_table(grid, [entry], order: false)).to match_css_pattern("table.datagrid-table th .datagrid-order" => 0) + expect(subject.datagrid_table(grid, [entry], + order: false,)).to match_css_pattern("table.datagrid-table th .datagrid-order" => 0) end it "should support columns option" do @@ -90,7 +91,7 @@ "table.datagrid-table th[data-column=name]" => 1, "table.datagrid-table td[data-column=name]" => 1, "table.datagrid-table th[data-column=group]" => 0, - "table.datagrid-table td[data-column=group]" => 0 + "table.datagrid-table td[data-column=group]" => 0, ) end @@ -108,7 +109,7 @@ "table.datagrid-table th[data-column=name]" => 1, "table.datagrid-table td[data-column=name]" => 1, "table.datagrid-table th[data-column=category]" => 0, - "table.datagrid-table td[data-column=category]" => 0 + "table.datagrid-table td[data-column=category]" => 0, ) end end @@ -136,7 +137,7 @@ it "renders namespaced table partial" do rendered_partial = subject.datagrid_table( - grid, [entry], partials: "client/datagrid" + grid, [entry], partials: "client/datagrid", ) expect(rendered_partial).to include "Namespaced table partial." expect(rendered_partial).to include "Namespaced row partial." @@ -157,7 +158,7 @@ it "should render table" do expect(subject.datagrid_table(grid)).to match_css_pattern( "table.datagrid-table th[data-column=name]" => 1, - "table.datagrid-table td[data-column=name]" => 2 + "table.datagrid-table td[data-column=name]" => 2, ) end end @@ -173,7 +174,7 @@ it "should render table" do expect(subject.datagrid_table(grid)).to match_css_pattern( "table.datagrid-table th[data-column=name]" => 1, - "table.datagrid-table td[data-column=name]" => 2 + "table.datagrid-table td[data-column=name]" => 2, ) end end @@ -186,7 +187,7 @@ column(:name) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-column=name].datagrid-order-active-asc" => "Star" + "tr td[data-column=name].datagrid-order-active-asc" => "Star", ) end it "should add ordering classes to column" do @@ -197,9 +198,9 @@ expect( subject.datagrid_rows(rp) do |row| subject.content_tag(:strong, row.name) - end + end, ).to match_css_pattern( - "strong" => "Star" + "strong" => "Star", ) end @@ -209,7 +210,7 @@ column(:name) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-column=name].datagrid-order-active-desc" => "Star" + "tr td[data-column=name].datagrid-order-active-desc" => "Star", ) end @@ -220,7 +221,7 @@ end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-column=name]" => "Star" + "tr td[data-column=name]" => "Star", ) end @@ -232,7 +233,7 @@ end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-column=name] span" => "Star" + "tr td[data-column=name] span" => "Star", ) end @@ -243,7 +244,7 @@ end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-column=name]" => "Star" + "tr td[data-column=name]" => "Star", ) end @@ -256,7 +257,7 @@ end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-column=name]" => "Star" + "tr td[data-column=name]" => "Star", ) end @@ -267,7 +268,7 @@ end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-column=name]" => "Star" + "tr td[data-column=name]" => "Star", ) end @@ -277,7 +278,7 @@ column(:name, html: ->(data) { content_tag :h1, data }) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-column=name] h1" => "Star" + "tr td[data-column=name] h1" => "Star", ) end @@ -289,7 +290,7 @@ end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-column=name] em" => "STAR" + "tr td[data-column=name] em" => "STAR", ) end @@ -301,7 +302,7 @@ end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-column=name] span" => "Star-Entry" + "tr td[data-column=name] span" => "Star-Entry", ) end @@ -310,10 +311,10 @@ scope { Entry } column(:name, html: lambda { |data, model| content_tag :h1, "#{data}-#{model.name.downcase}" - }) + },) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-column=name] h1" => "Star-star" + "tr td[data-column=name] h1" => "Star-star", ) end @@ -322,10 +323,10 @@ scope { Entry } column(:name, html: lambda { |data, model, grid| content_tag :h1, "#{data}-#{model.name.downcase}-#{grid.assets.klass}" - }) + },) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-column=name] h1" => "Star-star-Entry" + "tr td[data-column=name] h1" => "Star-star-Entry", ) end @@ -334,12 +335,12 @@ scope { Entry } column(:name, html: lambda { |data, model| content_tag :h1, "#{data}-#{model.name}" - }) do + },) do name.upcase end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-column=name] h1" => "STAR-Star" + "tr td[data-column=name] h1" => "STAR-Star", ) end @@ -348,12 +349,12 @@ scope { Entry } column(:name, html: lambda { |data, model, grid| content_tag :h1, "#{data}-#{model.name}-#{grid.assets.klass}" - }) do + },) do name.upcase end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-column=name] h1" => "STAR-Star-Entry" + "tr td[data-column=name] h1" => "STAR-Star-Entry", ) end @@ -364,10 +365,10 @@ column(:category) end expect(subject.datagrid_rows(rp, [entry], columns: [:name])).to match_css_pattern( - "tr td[data-column=name]" => "Star" + "tr td[data-column=name]" => "Star", ) expect(subject.datagrid_rows(rp, [entry], columns: [:name])).to match_css_pattern( - "tr td[data-column=category]" => 0 + "tr td[data-column=category]" => 0, ) end @@ -378,7 +379,7 @@ end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-column=name].my_class" => "Star" + "tr td[data-column=name].my_class" => "Star", ) end @@ -394,7 +395,7 @@ end it "should ignore them" do expect(subject.datagrid_rows(grid, [entry])).to match_css_pattern( - "td[data-column=name]" => 1 + "td[data-column=name]" => 1, ) end end @@ -435,9 +436,9 @@ class OrderedGrid < Datagrid::Base describe ".datagrid_form_for" do it "returns namespaced partial if partials options is passed" do rendered_form = subject.datagrid_form_for(grid, { - url: "", - partials: "client/datagrid" - }) + url: "", + partials: "client/datagrid", + },) expect(rendered_form).to include "Namespaced form partial." end it "should render form and filter inputs" do @@ -452,7 +453,7 @@ class FormForGrid < Datagrid::Base "form .datagrid-filter[data-filter=category][data-type=string] label" => "Category", "form .datagrid-filter input[name='form_for_grid[category]'][value=hello]" => 1, "form .datagrid-actions input[name=commit][value=Search]" => 1, - "form .datagrid-actions a.datagrid-reset[href='/location']" => 1 + "form .datagrid-actions a.datagrid-reset[href='/location']" => 1, ) end it "should support html classes for grid class with namespace" do @@ -465,7 +466,7 @@ class TestGrid < Datagrid::Base expect(subject.datagrid_form_for(Ns22::TestGrid.new, url: "grid")).to match_css_pattern( "form.datagrid-form" => 1, "form.datagrid-form label[for=ns22_test_grid_id]" => 1, - "form.datagrid-form input#ns22_test_grid_id[name='ns22_test_grid[id]']" => 1 + "form.datagrid-form input#ns22_test_grid_id[name='ns22_test_grid[id]']" => 1, ) end @@ -478,7 +479,7 @@ def param_name end end expect(subject.datagrid_form_for(ParamNameGrid81.new, url: "/grid")).to match_css_pattern( - "form.datagrid-form input[name='g[id]']" => 1 + "form.datagrid-form input[name='g[id]']" => 1, ) end @@ -492,9 +493,9 @@ def param_name end end rendered_form = subject.datagrid_form_for(PartialDefaultGrid.new, { - url: "", - partials: "custom_form" - }) + url: "", + partials: "custom_form", + },) expect(rendered_form).to include "form_partial_test" end end diff --git a/spec/datagrid/scaffold_spec.rb b/spec/datagrid/scaffold_spec.rb index 3e37561..0fcf45e 100644 --- a/spec/datagrid/scaffold_spec.rb +++ b/spec/datagrid/scaffold_spec.rb @@ -26,21 +26,21 @@ describe ".controller_code" do it "works" do - expect(subject.controller_code).to eq(<<-RUBY) -class UsersController < ApplicationController - def index - @grid = UsersGrid.new(grid_params) do |scope| - scope.page(params[:page]) - end - end - - protected - - def grid_params - params.fetch(:users_grid, {}).permit! - end -end -RUBY + expect(subject.controller_code).to eq(<<~RUBY) + class UsersController < ApplicationController + def index + @grid = UsersGrid.new(grid_params) do |scope| + scope.page(params[:page]) + end + end + + protected + + def grid_params + params.fetch(:users_grid, {}).permit! + end + end + RUBY end end end diff --git a/spec/datagrid_spec.rb b/spec/datagrid_spec.rb index f3fdea6..881cb57 100644 --- a/spec/datagrid_spec.rb +++ b/spec/datagrid_spec.rb @@ -16,13 +16,13 @@ name: "Star", category: "first", disabled: false, - confirmed: false + confirmed: false, ) end let!(:entry) do Entry.create!( - group: group, name: "Star", disabled: false, confirmed: false, category: "first" + group: group, name: "Star", disabled: false, confirmed: false, category: "first", ) end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b8cb418..63df808 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -39,23 +39,23 @@ class DatagridTest < Rails::Application else begin Mongoid.load_configuration({ - "clients" => - { - "default" => - { - "hosts" => ["localhost:27017"], - "database" => "datagrid_mongoid", - options: { - max_read_retries: 0, - retry_reads: false, - connect_timeout: 2, - wait_queue_timeout: 2, - server_selection_timeout: 2, - socket_timeout: 1 - } - } - } - }) + "clients" => + { + "default" => + { + "hosts" => ["localhost:27017"], + "database" => "datagrid_mongoid", + options: { + max_read_retries: 0, + retry_reads: false, + connect_timeout: 2, + wait_queue_timeout: 2, + server_selection_timeout: 2, + socket_timeout: 1, + }, + }, + }, + }) Mongoid.client(:default).collections # check mongo connection @@ -94,9 +94,9 @@ class DatagridTest < Rails::Application def action_view_template context = ActionView::LookupContext.new([ - File.expand_path("../app/views", __dir__), - File.expand_path("support/test_partials", __dir__) - ], {}) + File.expand_path("../app/views", __dir__), + File.expand_path("support/test_partials", __dir__), + ], {},) Datagrid::Engine.extend_modules template = ActionView::Base.with_empty_template_cache.new(context, {}, ActionController::Base.new) allow(template).to receive(:protect_against_forgery?).and_return(false) diff --git a/spec/support/mongoid.rb b/spec/support/mongoid.rb index 1fa6ec8..68625a4 100644 --- a/spec/support/mongoid.rb +++ b/spec/support/mongoid.rb @@ -17,7 +17,6 @@ class MongoidEntry end class MongoidGrid < Datagrid::Base - scope do MongoidEntry end From 4c91827542657d88fbc984e78a4683ff2548ce08 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sat, 9 Nov 2024 12:28:27 +0100 Subject: [PATCH 060/157] Rework class attribute as method --- lib/datagrid/filters/base_filter.rb | 6 ++++-- lib/datagrid/filters/boolean_filter.rb | 4 +++- lib/datagrid/filters/date_filter.rb | 4 +++- lib/datagrid/filters/date_time_filter.rb | 4 +++- lib/datagrid/filters/dynamic_filter.rb | 6 ++++-- lib/datagrid/filters/enum_filter.rb | 6 ++++-- lib/datagrid/filters/extended_boolean_filter.rb | 6 ++++-- lib/datagrid/filters/float_filter.rb | 4 +++- lib/datagrid/filters/integer_filter.rb | 4 +++- 9 files changed, 31 insertions(+), 13 deletions(-) diff --git a/lib/datagrid/filters/base_filter.rb b/lib/datagrid/filters/base_filter.rb index 69e7854..262aed5 100644 --- a/lib/datagrid/filters/base_filter.rb +++ b/lib/datagrid/filters/base_filter.rb @@ -11,8 +11,6 @@ class FilteringError < StandardError module Datagrid module Filters class BaseFilter - class_attribute :default_input_options, instance_writer: false, default: { type: "text" } - attr_accessor :grid_class, :options, :block, :name def initialize(grid_class, name, options = {}, &block) @@ -26,6 +24,10 @@ def parse(value) raise NotImplementedError, "#parse(value) suppose to be overwritten" end + def default_input_options + { type: "text" } + end + def unapplicable_value?(value) value.nil? ? !allow_nil? : value.blank? && !allow_blank? end diff --git a/lib/datagrid/filters/boolean_filter.rb b/lib/datagrid/filters/boolean_filter.rb index 72b6d15..6c16209 100644 --- a/lib/datagrid/filters/boolean_filter.rb +++ b/lib/datagrid/filters/boolean_filter.rb @@ -5,7 +5,9 @@ module Datagrid module Filters class BooleanFilter < Datagrid::Filters::BaseFilter - self.default_input_options = { type: "checkbox" } + def default_input_options + { **super, type: "checkbox" } + end def parse(value) Datagrid::Utils.booleanize(value) diff --git a/lib/datagrid/filters/date_filter.rb b/lib/datagrid/filters/date_filter.rb index 44bd0c5..9793698 100644 --- a/lib/datagrid/filters/date_filter.rb +++ b/lib/datagrid/filters/date_filter.rb @@ -7,7 +7,9 @@ module Filters class DateFilter < Datagrid::Filters::BaseFilter include Datagrid::Filters::RangedFilter - self.default_input_options = { type: "date" } + def default_input_options + { **super, type: "date" } + end def apply(grid_object, scope, value) value = value.begin&.beginning_of_day..value.end&.end_of_day if value.is_a?(Range) diff --git a/lib/datagrid/filters/date_time_filter.rb b/lib/datagrid/filters/date_time_filter.rb index 09d2bed..55e4e44 100644 --- a/lib/datagrid/filters/date_time_filter.rb +++ b/lib/datagrid/filters/date_time_filter.rb @@ -7,7 +7,9 @@ module Filters class DateTimeFilter < Datagrid::Filters::BaseFilter include Datagrid::Filters::RangedFilter - self.default_input_options = { type: "datetime-local" } + def default_input_options + { **super, type: "datetime-local" } + end def parse(value) Datagrid::Utils.parse_datetime(value) diff --git a/lib/datagrid/filters/dynamic_filter.rb b/lib/datagrid/filters/dynamic_filter.rb index c9bb9be..8ac9d2e 100644 --- a/lib/datagrid/filters/dynamic_filter.rb +++ b/lib/datagrid/filters/dynamic_filter.rb @@ -19,8 +19,6 @@ class DynamicFilter < Datagrid::Filters::BaseFilter ].freeze AVAILABLE_OPERATIONS = %w[= =~ >= <=].freeze - self.default_input_options = {} - def initialize(*) super options[:select] ||= default_select @@ -30,6 +28,10 @@ def initialize(*) options[:include_blank] = false end + def default_input_options + {**super, type: nil} + end + def parse_values(filter) filter ? FilterValue.new(grid_class, filter) : nil end diff --git a/lib/datagrid/filters/enum_filter.rb b/lib/datagrid/filters/enum_filter.rb index 7cacacb..faf7bd4 100644 --- a/lib/datagrid/filters/enum_filter.rb +++ b/lib/datagrid/filters/enum_filter.rb @@ -7,8 +7,6 @@ module Filters class EnumFilter < Datagrid::Filters::BaseFilter include Datagrid::Filters::SelectOptions - self.default_input_options = { type: "select" } - def initialize(*args) super options[:multiple] = true if enum_checkboxes? @@ -21,6 +19,10 @@ def parse(value) value end + def default_input_options + { **super, type: "select" } + end + def strict options[:strict] end diff --git a/lib/datagrid/filters/extended_boolean_filter.rb b/lib/datagrid/filters/extended_boolean_filter.rb index b8a9b29..ad8efa8 100644 --- a/lib/datagrid/filters/extended_boolean_filter.rb +++ b/lib/datagrid/filters/extended_boolean_filter.rb @@ -9,8 +9,6 @@ class ExtendedBooleanFilter < Datagrid::Filters::EnumFilter TRUTH_VALUES = [true, "true", "y", "yes"].freeze FALSE_VALUES = [false, "false", "n", "no"].freeze - self.default_input_options = { type: "select" } - def initialize(report, attribute, options = {}, &block) options[:select] = -> { boolean_select } super @@ -21,6 +19,10 @@ def execute(value, scope, grid_object) super end + def default_input_options + { **super, type: "select" } + end + def parse(value) value = value.downcase if value.is_a?(String) case value diff --git a/lib/datagrid/filters/float_filter.rb b/lib/datagrid/filters/float_filter.rb index 4cafa9f..2c9b164 100644 --- a/lib/datagrid/filters/float_filter.rb +++ b/lib/datagrid/filters/float_filter.rb @@ -6,7 +6,9 @@ module Filters class FloatFilter < Datagrid::Filters::BaseFilter include Datagrid::Filters::RangedFilter - self.default_input_options = { type: "number", step: "any" } + def default_input_options + { **super, type: "number", step: "any" } + end def parse(value) return nil if value.blank? diff --git a/lib/datagrid/filters/integer_filter.rb b/lib/datagrid/filters/integer_filter.rb index 3029df6..79ff5f8 100644 --- a/lib/datagrid/filters/integer_filter.rb +++ b/lib/datagrid/filters/integer_filter.rb @@ -7,7 +7,9 @@ module Filters class IntegerFilter < Datagrid::Filters::BaseFilter include Datagrid::Filters::RangedFilter - self.default_input_options = { type: "number", step: "1" } + def default_input_options + { **super, type: "number", step: "1" } + end def parse(value) return nil if value.blank? From efd092eaf8a2c4d026e2359930f1929b706303f1 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sat, 9 Nov 2024 12:50:12 +0100 Subject: [PATCH 061/157] Simplify enum checkboxes partial --- app/views/datagrid/_enum_checkboxes.html.erb | 2 +- lib/datagrid/filters/enum_filter.rb | 7 ++++++- lib/datagrid/form_builder.rb | 8 ++++++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/app/views/datagrid/_enum_checkboxes.html.erb b/app/views/datagrid/_enum_checkboxes.html.erb index 2d46139..f225cc6 100644 --- a/app/views/datagrid/_enum_checkboxes.html.erb +++ b/app/views/datagrid/_enum_checkboxes.html.erb @@ -6,7 +6,7 @@ You can add indent if whitespace doesn't matter for you <%- elements.each do |value, text, checked| -%> <%- id = [form.object_name, filter.name, value].join('_').underscore -%> <%= form.datagrid_label(filter.name, **options, for: id, class: 'datagrid-enum-checkbox-label') do -%> -<%= form.datagrid_filter_input(filter.name, type: :checkbox, multiple: true, id: id, checked: checked, include_hidden: false, value: value.to_s) -%> +<%= form.datagrid_filter_input(filter.name, id: id, value: value) -%> <%= text -%> <%- end -%> <%- end -%> diff --git a/lib/datagrid/filters/enum_filter.rb b/lib/datagrid/filters/enum_filter.rb index faf7bd4..0c9e15e 100644 --- a/lib/datagrid/filters/enum_filter.rb +++ b/lib/datagrid/filters/enum_filter.rb @@ -20,7 +20,12 @@ def parse(value) end def default_input_options - { **super, type: "select" } + { + **super, + type: enum_checkboxes? ? "checkbox" : "select", + multiple: multiple?, + include_hidden: enum_checkboxes? ? false : nil, + } end def strict diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 34a921a..a53b79a 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -46,7 +46,11 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) when :textarea text_area filter.name, value: object.filter_value_as_string(filter), **options, &block when :checkbox - check_box filter.name, options, options.fetch(:value, 1) + value = options.fetch(:value, 1).to_s + if filter.enum_checkboxes? && enum_checkbox_checked?(filter, value) + options = {checked: true, **options} + end + check_box filter.name, options, value when :hidden hidden_field filter.name, **options when :number @@ -113,7 +117,7 @@ def datagrid_enum_filter(filter, options = {}, &block) end def enum_checkbox_checked?(filter, option_value) - current_value = object.public_send(filter.name) + current_value = object.filter_value(filter) if current_value.respond_to?(:include?) # Typecast everything to string # to remove difference between String and Symbol From d6695cfb5160819423d67fa784ac11039b2e0eeb Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sat, 9 Nov 2024 19:21:57 +0100 Subject: [PATCH 062/157] Rework a test --- spec/datagrid/helper_spec.rb | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 771e2fa..c900e31 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -447,14 +447,19 @@ class FormForGrid < Datagrid::Base filter(:category, :string) end object = FormForGrid.new(category: "hello") - expect(subject.datagrid_form_for(object, url: "/grid")).to match_css_pattern( - "form.datagrid-form[action='/grid']" => 1, - "form input[name=utf8]" => 1, - "form .datagrid-filter[data-filter=category][data-type=string] label" => "Category", - "form .datagrid-filter input[name='form_for_grid[category]'][value=hello]" => 1, - "form .datagrid-actions input[name=commit][value=Search]" => 1, - "form .datagrid-actions a.datagrid-reset[href='/location']" => 1, - ) + expect(subject.datagrid_form_for(object, url: "/grid")).to equal_to_dom(<<~HTML) + <form class="datagrid-form" id="new_form_for_grid" action="/grid" accept-charset="UTF-8" method="get"> + <input name="utf8" type="hidden" value="✓" autocomplete="off" /> + <div class="datagrid-filter" data-filter="category" data-type="string"> + <label for="form_for_grid_category">Category</label> + <input value="hello" type="text" name="form_for_grid[category]" id="form_for_grid_category" /> + </div> + <div class="datagrid-actions"> + <input type="submit" name="commit" value="Search" class="datagrid-submit" data-disable-with="Search" /> + <a class="datagrid-reset" href="/location">Reset</a> + </div> +</form> + HTML end it "should support html classes for grid class with namespace" do module ::Ns22 From b273387e59e30903a33dfc51b8d9d1bfa0d9ad62 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sat, 9 Nov 2024 21:55:18 +0100 Subject: [PATCH 063/157] Migrate from form_for to form_with --- app/views/datagrid/_form.html.erb | 2 +- lib/datagrid/filters.rb | 4 +- lib/datagrid/helper.rb | 22 ++++- lib/datagrid/renderer.rb | 14 ++- lib/datagrid/scaffold.rb | 2 +- spec/datagrid/form_builder_spec.rb | 9 +- spec/datagrid/helper_spec.rb | 87 ++++++++++++++++++- .../client/datagrid/_form.html.erb | 2 +- .../test_partials/custom_form/_form.html.erb | 2 +- templates/index.html.erb | 2 +- version-2/Readme.markdown | 30 ++++++- version-2/views.diff | 4 +- 12 files changed, 162 insertions(+), 18 deletions(-) diff --git a/app/views/datagrid/_form.html.erb b/app/views/datagrid/_form.html.erb index 9b41ff2..fc4f4ae 100644 --- a/app/views/datagrid/_form.html.erb +++ b/app/views/datagrid/_form.html.erb @@ -1,4 +1,4 @@ -<%= form_for grid, html: {class: 'datagrid-form'}, **options do |f| -%> +<%= form_with model: grid, html: {class: 'datagrid-form'}, scope: grid.param_name, method: :get, **options do |f| %> <% grid.filters.each do |filter| %> <div class="datagrid-filter" data-filter="<%= filter.name %>" data-type="<%= filter.type %>"> <%= f.datagrid_label filter %> diff --git a/lib/datagrid/filters.rb b/lib/datagrid/filters.rb index 6ed0047..c5fee88 100644 --- a/lib/datagrid/filters.rb +++ b/lib/datagrid/filters.rb @@ -83,9 +83,9 @@ def filter_by_name(attribute) # * <tt>:allow_nil</tt> - determines if the value can be nil # * <tt>:allow_blank</tt> - determines if the value can be blank # * <tt>:before</tt> - determines the position of this filter, - # by adding it before the filter passed here (when using datagrid_form_for helper) + # by adding it before the filter passed here (when using datagrid_form_with helper) # * <tt>:after</tt> - determines the position of this filter, - # by adding it after the filter passed here (when using datagrid_form_for helper) + # by adding it after the filter passed here (when using datagrid_form_with helper) # * <tt>:dummy</tt> - if true, this filter will not be applied automatically # and will be just displayed in form. In case you may want to apply it manually. # * <tt>:if</tt> - specify the condition when the filter can be dislayed and used. diff --git a/lib/datagrid/helper.rb b/lib/datagrid/helper.rb index 76a2551..a7496db 100644 --- a/lib/datagrid/helper.rb +++ b/lib/datagrid/helper.rb @@ -97,16 +97,36 @@ def datagrid_order_for(grid, column, options = {}) datagrid_renderer.order_for(grid, column, options) end - # Renders HTML for for grid with all filters inputs and lables defined in it + # Renders HTML for grid with all filters inputs and labels defined in it + # + # Supported options: + # + # * <tt>:partials</tt> - Path for form partial lookup. + # Default: 'datagrid' results in using `app/views/datagrid/` partials. + # Example: 'datagrid_admin' results in using `app/views/datagrid_admin` partials. + # * <tt>:model</tt> - Datagrid object to be rendedred. + # * All options supported by Rails <tt>form_with</tt> helper + # @param grid [Datagrid] grid object + # @return [String] form HTML tag markup + def datagrid_form_with(**options) + if block_given? + raise ArgumentError, 'datagrid_form_with block argument is invalid. Use form_with instead.' + end + datagrid_renderer.form_with(**options) + end + + # Renders HTML for grid with all filters inputs and labels defined in it # # Supported options: # # * <tt>:partials</tt> - Path for form partial lookup. # Default: 'datagrid'. # * All options supported by Rails <tt>form_for</tt> helper + # @deprecated Use {#datagrid_form_with} instead. # @param grid [Datagrid] grid object # @return [String] form HTML tag markup def datagrid_form_for(grid, options = {}) + Datagrid::Utils.warn_once("datagrid_form_for is deprecated if favor of datagrid_form_with.") datagrid_renderer.form_for(grid, options) end diff --git a/lib/datagrid/renderer.rb b/lib/datagrid/renderer.rb index 2253b01..be9ca2e 100644 --- a/lib/datagrid/renderer.rb +++ b/lib/datagrid/renderer.rb @@ -25,13 +25,23 @@ def form_for(grid, options = {}) _render_partial("form", options[:partials], { grid: grid, options: options }) end + def form_with(**options) + grid = options[:model] + if grid&.filters&.empty? + raise ArgumentError, "Grid has no available filters" + end + _render_partial("form", options[:partials], { grid: options[:model], options: options }) + end + def table(grid, assets, **options) - _render_partial("table", options[:partials], + _render_partial( + "table", options[:partials], { grid: grid, options: options, assets: assets, - },) + }, + ) end def header(grid, options = {}) diff --git a/lib/datagrid/scaffold.rb b/lib/datagrid/scaffold.rb index d0f69a0..6f8a310 100644 --- a/lib/datagrid/scaffold.rb +++ b/lib/datagrid/scaffold.rb @@ -128,7 +128,7 @@ def grid_params def view_code indent(<<~ERB) - <%= datagrid_form_for @grid, url: #{grid_route_name} %> + <%= datagrid_form_with model: @grid, url: #{grid_route_name} %> <%= #{pagination_helper_code} %> <%= #{table_helper_code} %> diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index e8bfee9..cfc5dfe 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -16,7 +16,14 @@ class MyTemplate action_view_template end - let(:view) { ActionView::Helpers::FormBuilder.new(:report, _grid, template, view_options) } + let(:view) do + ActionView::Helpers::FormBuilder.new( + :report, _grid, template, + skip_default_ids: false, + **view_options, + ) + end + let(:view_options) { {} } describe ".datagrid_filter" do diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index c900e31..566b7b6 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -20,6 +20,8 @@ allow(subject).to receive(:url_for) do |options| options.is_a?(String) ? options : ["/location", options.to_param.presence].compact.join("?") end + # Rails default since 5.x + ActionView::Helpers::FormHelper.form_with_generates_ids = true end let(:group) { Group.create!(name: "Pop") } @@ -433,7 +435,14 @@ class OrderedGrid < Datagrid::Base HTML end end + describe ".datagrid_form_for" do + around(:each) do |e| + silence_warnings do + e.run + end + end + it "returns namespaced partial if partials options is passed" do rendered_form = subject.datagrid_form_for(grid, { url: "", @@ -448,7 +457,7 @@ class FormForGrid < Datagrid::Base end object = FormForGrid.new(category: "hello") expect(subject.datagrid_form_for(object, url: "/grid")).to equal_to_dom(<<~HTML) - <form class="datagrid-form" id="new_form_for_grid" action="/grid" accept-charset="UTF-8" method="get"> + <form class="datagrid-form" action="/grid" accept-charset="UTF-8" data-remote="true" method="get"> <input name="utf8" type="hidden" value="✓" autocomplete="off" /> <div class="datagrid-filter" data-filter="category" data-type="string"> <label for="form_for_grid_category">Category</label> @@ -505,6 +514,82 @@ def param_name end end + + describe ".datagrid_form_with" do + it "returns namespaced partial if partials options is passed" do + rendered_form = subject.datagrid_form_with( + model: grid, + url: "", + partials: "client/datagrid", + ) + expect(rendered_form).to include "Namespaced form partial." + end + it "should render form and filter inputs" do + class FormWithGrid < Datagrid::Base + scope { Entry } + filter(:category, :string) + end + object = FormWithGrid.new(category: "hello") + expect(subject.datagrid_form_with(model: object, url: "/grid")).to equal_to_dom(<<~HTML) + <form class="datagrid-form" action="/grid" accept-charset="UTF-8" data-remote="true" method="get"> + <input name="utf8" type="hidden" value="✓" autocomplete="off" /> + <div class="datagrid-filter" data-filter="category" data-type="string"> + <label for="form_with_grid_category">Category</label> + <input value="hello" type="text" name="form_with_grid[category]" id="form_with_grid_category" /> + </div> + <div class="datagrid-actions"> + <input type="submit" name="commit" value="Search" class="datagrid-submit" data-disable-with="Search" /> + <a class="datagrid-reset" href="/location">Reset</a> + </div> +</form> + HTML + end + it "should support html classes for grid class with namespace" do + module ::Ns23 + class TestGrid < Datagrid::Base + scope { Entry } + filter(:id) + end + end + expect(subject.datagrid_form_with(model: Ns23::TestGrid.new, url: "grid")).to match_css_pattern( + "form.datagrid-form" => 1, + "form.datagrid-form label[for=ns23_test_grid_id]" => 1, + "form.datagrid-form input#ns23_test_grid_id[name='ns23_test_grid[id]']" => 1, + ) + end + + it "should have overridable param_name method" do + class ParamNameGrid82 < Datagrid::Base + scope { Entry } + filter(:id) + def param_name + "g" + end + end + expect(subject.datagrid_form_with(model: ParamNameGrid82.new, url: "/grid")).to match_css_pattern( + "form.datagrid-form input[name='g[id]']" => 1, + ) + end + + it "takes default partials if custom doesn't exist" do + class PartialDefaultGrid < Datagrid::Base + scope { Entry } + filter(:id, :integer, range: true) + filter(:group_id, :enum, multiple: true, checkboxes: true, select: [1, 2]) + def param_name + "g" + end + end + rendered_form = subject.datagrid_form_with( + model: PartialDefaultGrid.new, + url: "", + partials: "custom_form", + ) + expect(rendered_form).to include "form_partial_test" + end + end + + describe ".datagrid_row" do let(:grid) do test_report do diff --git a/spec/support/test_partials/client/datagrid/_form.html.erb b/spec/support/test_partials/client/datagrid/_form.html.erb index 29835a1..8a1f5a8 100644 --- a/spec/support/test_partials/client/datagrid/_form.html.erb +++ b/spec/support/test_partials/client/datagrid/_form.html.erb @@ -1,4 +1,4 @@ -<%= form_for grid, options do |f| -%> +<%= form_with model: grid, method: :get, **options do |f| -%> <p>Namespaced form partial.</p> <% grid.filters.each do |filter| %> <div class="datagrid-filter filter"> diff --git a/spec/support/test_partials/custom_form/_form.html.erb b/spec/support/test_partials/custom_form/_form.html.erb index 8b5351e..15077d2 100644 --- a/spec/support/test_partials/custom_form/_form.html.erb +++ b/spec/support/test_partials/custom_form/_form.html.erb @@ -1,4 +1,4 @@ -<%= form_for grid, options do |f| -%> +<%= form_with model: grid, method: :get, **options do |f| -%> <p>form_partial_test</p> <% grid.filters.each do |filter| %> <%= f.datagrid_label filter %> diff --git a/templates/index.html.erb b/templates/index.html.erb index 105b49f..133754b 100644 --- a/templates/index.html.erb +++ b/templates/index.html.erb @@ -1,4 +1,4 @@ -<%%= datagrid_form_for @grid, url: <%= grid_route_name %> %> +<%%= datagrid_form_with model: @grid, url: <%= grid_route_name %> %> <%%= <%=pagination_helper_code%> %> <%%= <%=table_helper_code%> %> diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index d9522fe..7bdc956 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -9,18 +9,34 @@ Version 2 addresses all that evolution. List of things introduces: +1. Use `form_with` instead of `form_for`. 1. Ruby infinite ranges for range filters. 1. Modern modular CSS classes. 1. HTML5 input types: number, date, datetime-local. -1. Use Hash instead of Array for multiparameters attirubtes - to avoid [input names collision restriction](https://html.spec.whatwg.org/multipage/input.html#input-type-attr-summary) -1. Native Rails Engines: - while supported, the library was not initially designed for it. +1. Use Hash instead of Array for multiparameter attirubtes. +1. Native Rails Engines. + * while supported, the library was not initially designed for it. 1. HTML5 data attributes 1. Inherit `Datagrid::Base` instead of `include Datagrid` 1. `ApplicationGrid` is recommended base class instead of `BaseGrid` 1. Remove SASS dependency +## Use form\_with + +Rails [deprecates form\_for in favor of form\_with](https://guides.rubyonrails.org/form_helpers.html#using-form-tag-and-form-for). + +`datagrid_form_for` is now depreacted if favor of `datagrid_form_with`. +However, `datagrid_form_for` would also use Rails `form_with` because they share the same view partial. + +TODO: update the wiki + +``` ruby +# V1 +datagrid_form_for(@users_grid, url: users_path) +# V2 +datagrid_form_with(model: @users_grid, url: users_path) +``` + ## Infinite Ranges for range filters Ruby supports infinite ranges now, @@ -345,3 +361,9 @@ as much UI as possible for user modification. Here is a complete [diff for built-in partials between V1 and V2](./views.diff) +## Remove SASS dependency + +SASS is no longer a default choice when starting a rails project. +Version 2 makes it more flexible by avoiding the dependency on any particular CSS framework. + +Inspect [a new built-in CSS file](../app/assets/datagrid.css). diff --git a/version-2/views.diff b/version-2/views.diff index ed70538..fc4123b 100644 --- a/version-2/views.diff +++ b/version-2/views.diff @@ -1,5 +1,5 @@ diff --git a/app/views/datagrid/_enum_checkboxes.html.erb b/app/views/datagrid/_enum_checkboxes.html.erb -index 9f48319..2d46139 100644 +index 9f48319..f225cc6 100644 --- a/app/views/datagrid/_enum_checkboxes.html.erb +++ b/app/views/datagrid/_enum_checkboxes.html.erb @@ -2,10 +2,12 @@ @@ -12,7 +12,7 @@ index 9f48319..2d46139 100644 -<%= form.label filter.name, options.merge(for: id) do -%> -<%= form.check_box(filter.name, {multiple: true, id: id, checked: checked, include_hidden: false}, value.to_s, nil) -%> +<%= form.datagrid_label(filter.name, **options, for: id, class: 'datagrid-enum-checkbox-label') do -%> -+<%= form.datagrid_filter_input(filter.name, type: :checkbox, multiple: true, id: id, checked: checked, include_hidden: false, value: value.to_s) -%> ++<%= form.datagrid_filter_input(filter.name, id: id, value: value) -%> <%= text -%> <%- end -%> <%- end -%> From 77017a7025fc838f37ac1bbe38aa295770a7e4ff Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sat, 9 Nov 2024 21:57:10 +0100 Subject: [PATCH 064/157] Update views diff --- version-2/views.diff | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version-2/views.diff b/version-2/views.diff index fc4123b..e0a83c4 100644 --- a/version-2/views.diff +++ b/version-2/views.diff @@ -18,12 +18,12 @@ index 9f48319..f225cc6 100644 <%- end -%> +</div> diff --git a/app/views/datagrid/_form.html.erb b/app/views/datagrid/_form.html.erb -index 7e175c1..9b41ff2 100644 +index 7e175c1..fc4f4ae 100644 --- a/app/views/datagrid/_form.html.erb +++ b/app/views/datagrid/_form.html.erb @@ -1,12 +1,12 @@ -<%= form_for grid, options do |f| -%> -+<%= form_for grid, html: {class: 'datagrid-form'}, **options do |f| -%> ++<%= form_with model: grid, html: {class: 'datagrid-form'}, scope: grid.param_name, method: :get, **options do |f| %> <% grid.filters.each do |filter| %> - <div class="datagrid-filter filter"> + <div class="datagrid-filter" data-filter="<%= filter.name %>" data-type="<%= filter.type %>"> From cbcb8517fa94ebeb0bd7db6cc41029bfd3254b4d Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 10 Nov 2024 09:17:21 +0100 Subject: [PATCH 065/157] Support rails from 7.0 and ruby from 3.1 --- .github/workflows/ci.yml | 10 +++++----- Gemfile | 2 +- datagrid.gemspec | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b235eb6..247a5aa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,11 +8,11 @@ jobs: fail-fast: false matrix: # To keep matrix size down, only test highest and lowest rubies. - ruby: ["2.7", "3.3"] - rails: ["6.1", "7.0", "7.1", "7.2"] - exclude: - - ruby: "2.7" - rails: "7.2" + ruby: ["3.1", "3.3"] + rails: ["7.0", "7.1", "7.2", "8.0"] + # exclude: + # - ruby: "2.7" + # rails: "7.2" name: Ruby ${{ matrix.ruby }}, Rails ${{ matrix.rails }} runs-on: ubuntu-latest env: diff --git a/Gemfile b/Gemfile index c0c942e..55d01f1 100644 --- a/Gemfile +++ b/Gemfile @@ -16,6 +16,7 @@ group :development do gem "rspec" gem "sequel" gem "sqlite3", "~> 1.7.0" + gem "rubocop", "~> 1.68" group :mongo do gem "bson" @@ -23,4 +24,3 @@ group :development do end end -gem "rubocop", "~> 1.68", group: :development diff --git a/datagrid.gemspec b/datagrid.gemspec index a5e48e3..1e9444c 100644 --- a/datagrid.gemspec +++ b/datagrid.gemspec @@ -33,5 +33,5 @@ Gem::Specification.new do |s| "rubygems_mfa_required" => "true", } - s.add_dependency "railties", ">= 6.1" + s.add_dependency "railties", ">= 7.0" end From 296cc487df2743252119d7f7a9c512dd1d873730 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 10 Nov 2024 09:19:44 +0100 Subject: [PATCH 066/157] Fix build --- spec/spec_helper.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 63df808..617d4ab 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -20,7 +20,6 @@ require "mongoid" require "datagrid" -require "debug" require "rspec" require "logger" From 9673a83858c0cd32f6adbe012353b5a12402c016 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 10 Nov 2024 09:37:16 +0100 Subject: [PATCH 067/157] Support TimeWithZone as an argument of datetime filter --- lib/datagrid/utils.rb | 3 +++ spec/datagrid/form_builder_spec.rb | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/datagrid/utils.rb b/lib/datagrid/utils.rb index 43152ce..56a85a7 100644 --- a/lib/datagrid/utils.rb +++ b/lib/datagrid/utils.rb @@ -93,6 +93,9 @@ def parse_date(value) def parse_datetime(value) return nil if value.blank? return value if value.is_a?(Range) + if defined?(ActiveSupport::TimeWithZone) && value.is_a?(ActiveSupport::TimeWithZone) + return value + end if value.is_a?(String) Array(Datagrid.configuration.datetime_formats).each do |format| diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index cfc5dfe..edc871f 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -132,14 +132,17 @@ class MyTemplate context "datetime filter type is text" do let(:_filter) { :created_at } let(:_grid) do - test_report(created_at: Time.new(2024, 1, 1, 9, 25, 15)) do + created_at = ActiveSupport::TimeZone['UTC'].local( + 2024, 1, 1, 9, 25, 15 + ) + test_report(created_at: ) do scope { Entry } filter(:created_at, :datetime, input_options: { type: "text" }) end end it { should equal_to_dom( - '<input type="text" value="2024-01-01 09:25:15 +0100" + '<input type="text" value="2024-01-01 09:25:15 UTC" name="report[created_at]" id="report_created_at"/>', ) } From 30b89a8f2b440a7f54256a29efe74d7f6fd47e70 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 10 Nov 2024 09:37:44 +0100 Subject: [PATCH 068/157] Support ruby 3.0 --- .github/workflows/ci.yml | 2 +- datagrid.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 247a5aa..f0304cc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ jobs: fail-fast: false matrix: # To keep matrix size down, only test highest and lowest rubies. - ruby: ["3.1", "3.3"] + ruby: ["3.0", "3.3"] rails: ["7.0", "7.1", "7.2", "8.0"] # exclude: # - ruby: "2.7" diff --git a/datagrid.gemspec b/datagrid.gemspec index 1e9444c..e6904a7 100644 --- a/datagrid.gemspec +++ b/datagrid.gemspec @@ -23,7 +23,7 @@ Gem::Specification.new do |s| s.files += `git ls-files | grep -E '^(app|lib|templates)'`.split("\n") s.homepage = "https://github.com/bogdan/datagrid" s.licenses = ["MIT"] - s.required_ruby_version = Gem::Requirement.new(">= 2.7") + s.required_ruby_version = Gem::Requirement.new(">= 3.0") s.metadata = { "homepage_uri" => s.homepage, "bug_tracker_uri" => "#{s.homepage}/issues", From 9c1ad90211d5a49d08f241b71247bce522317b62 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 10 Nov 2024 09:40:00 +0100 Subject: [PATCH 069/157] Fix ruby 3.0 --- spec/datagrid/form_builder_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index edc871f..6279457 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -135,7 +135,7 @@ class MyTemplate created_at = ActiveSupport::TimeZone['UTC'].local( 2024, 1, 1, 9, 25, 15 ) - test_report(created_at: ) do + test_report(created_at: created_at) do scope { Entry } filter(:created_at, :datetime, input_options: { type: "text" }) end From ade8780f839a5f0ea1a5ef53776cd926e533bed1 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 10 Nov 2024 09:40:44 +0100 Subject: [PATCH 070/157] Rails 8 gemfile --- gemfiles/rails_8.0.gemfile | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 gemfiles/rails_8.0.gemfile diff --git a/gemfiles/rails_8.0.gemfile b/gemfiles/rails_8.0.gemfile new file mode 100644 index 0000000..c18e1a6 --- /dev/null +++ b/gemfiles/rails_8.0.gemfile @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +# This file was generated by Appraisal + +source "https://rubygems.org" + +group :development do + gem "appraisal" + gem "bump" + gem "csv" + gem "nokogiri" + gem "pry-byebug" + gem "rails", "~> 8.0.0" + gem "rspec" + gem "sequel" + gem "sqlite3", "~> 2.0.0" + + group :mongo do + gem "bson" + gem "mongoid", github: "mongodb/mongoid" + end +end + +gemspec path: "../" From b66723834cf8a80be7d27566574965dfd8be4749 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 10 Nov 2024 09:43:26 +0100 Subject: [PATCH 071/157] Fix build ruby 3.0 rails 7.2 8.0 --- .github/workflows/ci.yml | 8 +++++--- gemfiles/rails_8.0.gemfile | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f0304cc..0913239 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,9 +10,11 @@ jobs: # To keep matrix size down, only test highest and lowest rubies. ruby: ["3.0", "3.3"] rails: ["7.0", "7.1", "7.2", "8.0"] - # exclude: - # - ruby: "2.7" - # rails: "7.2" + exclude: + - ruby: "3.0" + rails: "7.2" + - ruby: "3.0" + rails: "8.0" name: Ruby ${{ matrix.ruby }}, Rails ${{ matrix.rails }} runs-on: ubuntu-latest env: diff --git a/gemfiles/rails_8.0.gemfile b/gemfiles/rails_8.0.gemfile index c18e1a6..5185cba 100644 --- a/gemfiles/rails_8.0.gemfile +++ b/gemfiles/rails_8.0.gemfile @@ -13,7 +13,7 @@ group :development do gem "rails", "~> 8.0.0" gem "rspec" gem "sequel" - gem "sqlite3", "~> 2.0.0" + gem "sqlite3", "~> 2.1.0" group :mongo do gem "bson" From bcde3151c76ebda55585eb770bed3dbd17a2c3e5 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 10 Nov 2024 09:54:58 +0100 Subject: [PATCH 072/157] Cleanup --- spec/datagrid/filters/date_filter_spec.rb | 13 ++++--------- spec/datagrid/filters/dynamic_filter_spec.rb | 4 ++-- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/spec/datagrid/filters/date_filter_spec.rb b/spec/datagrid/filters/date_filter_spec.rb index 3aa08c9..72fa450 100644 --- a/spec/datagrid/filters/date_filter_spec.rb +++ b/spec/datagrid/filters/date_filter_spec.rb @@ -32,19 +32,14 @@ end it "supports hash argument" do - e1 = Entry.create!(created_at: 7.days.ago) - e2 = Entry.create!(created_at: 4.days.ago) - e3 = Entry.create!(created_at: 1.day.ago) - from = 5.days.ago - to = 3.days.ago - report = test_report(created_at: { from: from, to: to }) do + report = test_report do scope { Entry } filter(:created_at, :date, range: true) end + from = 5.days.ago + to = 3.days.ago + report.created_at = { from: from, to: to } expect(report.created_at).to eq(from.to_date..to.to_date) - expect(report.assets).not_to include(e1) - expect(report.assets).to include(e2) - expect(report.assets).not_to include(e3) report.created_at = {} expect(report.created_at).to eq(nil) report.created_at = { from: nil, to: nil } diff --git a/spec/datagrid/filters/dynamic_filter_spec.rb b/spec/datagrid/filters/dynamic_filter_spec.rb index eae16f6..c658ff8 100644 --- a/spec/datagrid/filters/dynamic_filter_spec.rb +++ b/spec/datagrid/filters/dynamic_filter_spec.rb @@ -139,8 +139,8 @@ end end - # expect(grid.assets).to_not include(Entry.create!(disabled: true)) - # expect(grid.assets).to include(Entry.create!(disabled: false)) + expect(grid.assets).to_not include(Entry.create!(disabled: true)) + expect(grid.assets).to include(Entry.create!(disabled: false)) grid.condition = [:group_id, ">=", 3] expect(grid.assets).to include(Entry.create!(disabled: true, group_id: 4)) From 0a2077bad4681bf93b3e4641a772705e8af23818 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 10 Nov 2024 11:42:12 +0100 Subject: [PATCH 073/157] Expose datagrid-order-active-asc/desc classes --- app/views/datagrid/_head.html.erb | 16 ++++++++++++---- app/views/datagrid/_row.html.erb | 13 ++++++++++++- lib/datagrid/helper.rb | 14 ++++++++++---- spec/datagrid/helper_spec.rb | 18 ++++++++++++++++++ .../client/datagrid/_head.html.erb | 4 ++-- .../client/datagrid/_row.html.erb | 2 +- 6 files changed, 55 insertions(+), 12 deletions(-) diff --git a/app/views/datagrid/_head.html.erb b/app/views/datagrid/_head.html.erb index c3264bb..a1bbd51 100644 --- a/app/views/datagrid/_head.html.erb +++ b/app/views/datagrid/_head.html.erb @@ -1,8 +1,16 @@ <tr> <% grid.html_columns(*options[:columns]).each do |column| %> - <th class="<%= datagrid_column_classes(grid, column) %>" data-column="<%= column.name %>"> - <%= column.header %> - <%= datagrid_order_for(grid, column, options) if column.supports_order? && options[:order]%> - </th> + <%= content_tag( + :th, + safe_join([column.header, datagrid_order_for(grid, column, **options)]), + class: { + # Adding html clases based on condition + # Consider maintaining consistency with datagrid/rows partial + "datagrid-order-active-asc": grid.ordered_by?(column, false), + "datagrid-order-active-desc": grid.ordered_by?(column ,true), + column.html_class => column.html_class.present?, + }, + "data-column": column.name + ) %> <% end %> </tr> diff --git a/app/views/datagrid/_row.html.erb b/app/views/datagrid/_row.html.erb index 20f3ffb..340aea6 100644 --- a/app/views/datagrid/_row.html.erb +++ b/app/views/datagrid/_row.html.erb @@ -1,5 +1,16 @@ <tr> <% grid.html_columns(*options[:columns]).each do |column| %> - <td class="<%= datagrid_column_classes(grid, column) %>" data-column="<%= column.name %>"><%= datagrid_value(grid, column, asset) %></td> + <%= content_tag( + :td, + datagrid_value(grid, column, asset), + class: { + # Adding html clases based on condition + # Consider maintaining consistency with datagrid/head partial + "datagrid-order-active-asc": grid.ordered_by?(column, false), + "datagrid-order-active-desc": grid.ordered_by?(column ,true), + column.html_class => column.html_class.present?, + }, + "data-column": column.name + ) %> <% end %> </tr> diff --git a/lib/datagrid/helper.rb b/lib/datagrid/helper.rb index a7496db..d55b8e6 100644 --- a/lib/datagrid/helper.rb +++ b/lib/datagrid/helper.rb @@ -93,8 +93,9 @@ def datagrid_rows(grid, assets = grid.assets, **options, &block) # # * <tt>:partials</tt> - Path for partials lookup. # Default: 'datagrid'. - def datagrid_order_for(grid, column, options = {}) - datagrid_renderer.order_for(grid, column, options) + def datagrid_order_for(grid, column, order: true, **options) + return "" unless column.supports_order? && order + datagrid_renderer.order_for(grid, column, **options) end # Renders HTML for grid with all filters inputs and labels defined in it @@ -170,10 +171,15 @@ def datagrid_renderer end def datagrid_column_classes(grid, column) + Datagrid::Utils.warn_once(<<~MSG) + datagrid_column_classes is deprecated. Assign necessary classes manually. + Correspond to default datagrid/rows partial for example.) + MSG + column = grid.column_by_name(column) order_class = if grid.ordered_by?(column) - grid.descending ? "datagrid-order-active-desc" : "datagrid-order-active-asc" + ["ordered", grid.descending ? "desc" : "asc"] end - [order_class, column.html_class].compact.join(" ") + [column.name, order_class, column.options[:class]].compact.join(" ") end end end diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 566b7b6..8313432 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -726,4 +726,22 @@ def param_name HTML end end + + describe ".datagrid_column_classes" do + it "is deprecated" do + grid = test_report(order: :name, descending: true) do + scope { Entry } + column(:name) + column(:group_id, class: 'short-column') + end + silence_warnings do + expect(subject.send(:datagrid_column_classes, grid, :name)).to eq( + "name ordered desc" + ) + expect(subject.send(:datagrid_column_classes, grid, :group_id)).to eq( + "group_id short-column" + ) + end + end + end end diff --git a/spec/support/test_partials/client/datagrid/_head.html.erb b/spec/support/test_partials/client/datagrid/_head.html.erb index eba7f60..e22a008 100644 --- a/spec/support/test_partials/client/datagrid/_head.html.erb +++ b/spec/support/test_partials/client/datagrid/_head.html.erb @@ -1,9 +1,9 @@ <tr> <p>Namespaced head partial.</p> <% grid.html_columns(*options[:columns]).each do |column| %> - <th class="<%= datagrid_column_classes(grid, column) %>"> + <th> <%= column.header %> - <%= datagrid_order_for(grid, column, options) if column.order && options[:order]%> + <%= datagrid_order_for(grid, column, **options) if column.order && options[:order]%> </th> <% end %> </tr> diff --git a/spec/support/test_partials/client/datagrid/_row.html.erb b/spec/support/test_partials/client/datagrid/_row.html.erb index b35da9b..3ec8df3 100644 --- a/spec/support/test_partials/client/datagrid/_row.html.erb +++ b/spec/support/test_partials/client/datagrid/_row.html.erb @@ -1,6 +1,6 @@ <tr> <p>Namespaced row partial.</p> <% grid.html_columns(*options[:columns]).each do |column| %> - <td class="<%= datagrid_column_classes(grid, column) %>"><%= datagrid_value(grid, column, asset) %></td> + <td><%= datagrid_value(grid, column, asset) %></td> <% end %> </tr> From c2a8e83983e04e738366605024133e29161a0bf0 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 10 Nov 2024 11:58:46 +0100 Subject: [PATCH 074/157] Deprecate datagrid_order_for and related partial --- app/views/datagrid/_head.html.erb | 19 +++++++++++++++++-- app/views/datagrid/_order_for.html.erb | 10 +++++----- lib/datagrid/helper.rb | 6 +++++- lib/tasks/datagrid_tasks.rake | 2 ++ spec/datagrid/helper_spec.rb | 13 +++++++------ .../client/datagrid/_head.html.erb | 1 - version-2/Readme.markdown | 7 +++++++ 7 files changed, 43 insertions(+), 15 deletions(-) diff --git a/app/views/datagrid/_head.html.erb b/app/views/datagrid/_head.html.erb index a1bbd51..b355528 100644 --- a/app/views/datagrid/_head.html.erb +++ b/app/views/datagrid/_head.html.erb @@ -2,7 +2,6 @@ <% grid.html_columns(*options[:columns]).each do |column| %> <%= content_tag( :th, - safe_join([column.header, datagrid_order_for(grid, column, **options)]), class: { # Adding html clases based on condition # Consider maintaining consistency with datagrid/rows partial @@ -11,6 +10,22 @@ column.html_class => column.html_class.present?, }, "data-column": column.name - ) %> + ) do %> + <%= column.header %> + <% if column.supports_order? && options[:order] -%> + <div class="datagrid-order"> + <%= link_to( + I18n.t("datagrid.table.order.asc"), + datagrid_order_path(grid, column, false), + class: "datagrid-order-control-asc" + ) %> + <%= link_to( + I18n.t("datagrid.table.order.desc"), + datagrid_order_path(grid, column, true), + class: "datagrid-order-control-desc" + ) %> + </div> + <% end -%> + <% end -%> <% end %> </tr> diff --git a/app/views/datagrid/_order_for.html.erb b/app/views/datagrid/_order_for.html.erb index 1c33c37..1545a8e 100644 --- a/app/views/datagrid/_order_for.html.erb +++ b/app/views/datagrid/_order_for.html.erb @@ -1,10 +1,10 @@ -<div class="datagrid-order"> +<div class="order"> <%= link_to( - I18n.t("datagrid.table.order.asc"), + I18n.t("datagrid.table.order.asc").html_safe, datagrid_order_path(grid, column, false), - class: "datagrid-order-control-asc") %> + class: "asc") %> <%= link_to( - I18n.t("datagrid.table.order.desc"), + I18n.t("datagrid.table.order.desc").html_safe, datagrid_order_path(grid, column, true), - class: "datagrid-order-control-desc") %> + class: "desc") %> </div> diff --git a/lib/datagrid/helper.rb b/lib/datagrid/helper.rb index d55b8e6..be58a10 100644 --- a/lib/datagrid/helper.rb +++ b/lib/datagrid/helper.rb @@ -94,7 +94,11 @@ def datagrid_rows(grid, assets = grid.assets, **options, &block) # * <tt>:partials</tt> - Path for partials lookup. # Default: 'datagrid'. def datagrid_order_for(grid, column, order: true, **options) - return "" unless column.supports_order? && order + Datagrid::Utils.warn_once(<<~MSG) + datagrid_order_for is deprecated. + Put necessary code inline inside datagrid/head partial. + See built-in partial for example. + MSG datagrid_renderer.order_for(grid, column, **options) end diff --git a/lib/tasks/datagrid_tasks.rake b/lib/tasks/datagrid_tasks.rake index e1ca194..5c468ef 100644 --- a/lib/tasks/datagrid_tasks.rake +++ b/lib/tasks/datagrid_tasks.rake @@ -8,6 +8,8 @@ namespace :datagrid do destination_dir = (Rails.root + views_path).to_s pattern = "#{File.expand_path(File.dirname(__FILE__) + "/../../#{views_path}")}/*" Dir[pattern].each do |template| + # Deprecated partial + next if template.include?("/_order_for.") puts "* copy #{template} => #{destination_dir}" FileUtils.mkdir_p destination_dir FileUtils.cp template, destination_dir diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 8313432..f5d6bfb 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -144,7 +144,6 @@ expect(rendered_partial).to include "Namespaced table partial." expect(rendered_partial).to include "Namespaced row partial." expect(rendered_partial).to include "Namespaced head partial." - expect(rendered_partial).to include "Namespaced order_for partial." end end @@ -427,12 +426,14 @@ class OrderedGrid < Datagrid::Base column(:category) end object = OrderedGrid.new(descending: true, order: :category) - expect(subject.datagrid_order_for(object, object.column_by_name(:category))).to equal_to_dom(<<~HTML) - <div class="datagrid-order"> - <a class="datagrid-order-control-asc" href="/location?ordered_grid%5Bdescending%5D=false&ordered_grid%5Border%5D=category">↑</a> - <a class="datagrid-order-control-desc" href="/location?ordered_grid%5Bdescending%5D=true&ordered_grid%5Border%5D=category">↓</a> + silence_warnings do + expect(subject.datagrid_order_for(object, object.column_by_name(:category))).to equal_to_dom(<<~HTML) + <div class="order"> + <a class="asc" href="/location?ordered_grid%5Bdescending%5D=false&ordered_grid%5Border%5D=category">↑</a> + <a class="desc" href="/location?ordered_grid%5Bdescending%5D=true&ordered_grid%5Border%5D=category">↓</a> </div> - HTML + HTML + end end end diff --git a/spec/support/test_partials/client/datagrid/_head.html.erb b/spec/support/test_partials/client/datagrid/_head.html.erb index e22a008..1e25878 100644 --- a/spec/support/test_partials/client/datagrid/_head.html.erb +++ b/spec/support/test_partials/client/datagrid/_head.html.erb @@ -3,7 +3,6 @@ <% grid.html_columns(*options[:columns]).each do |column| %> <th> <%= column.header %> - <%= datagrid_order_for(grid, column, **options) if column.order && options[:order]%> </th> <% end %> </tr> diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index 7bdc956..cbb3bad 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -10,6 +10,7 @@ Version 2 addresses all that evolution. List of things introduces: 1. Use `form_with` instead of `form_for`. +1. Deprecated `datagrid_order_for` 1. Ruby infinite ranges for range filters. 1. Modern modular CSS classes. 1. HTML5 input types: number, date, datetime-local. @@ -37,6 +38,12 @@ datagrid_form_for(@users_grid, url: users_path) datagrid_form_with(model: @users_grid, url: users_path) ``` +## Deprecated datagrid\_order\_for + +`datagrid_order_for` helper serves no purpose and should not be used directly. +The recommended way is to include your ordering code directly into `datagrid/head` partial. +See default [head partial](../app/views/datagrid/_head.html.erb) for example. + ## Infinite Ranges for range filters Ruby supports infinite ranges now, From 1195f033db19d4cf657dedc1e4faf2c54539f083 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 10 Nov 2024 12:03:07 +0100 Subject: [PATCH 075/157] Update views diff --- version-2/views.diff | 74 +++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 28 deletions(-) diff --git a/version-2/views.diff b/version-2/views.diff index e0a83c4..f971d0e 100644 --- a/version-2/views.diff +++ b/version-2/views.diff @@ -39,37 +39,44 @@ index 7e175c1..fc4f4ae 100644 </div> <% end -%> diff --git a/app/views/datagrid/_head.html.erb b/app/views/datagrid/_head.html.erb -index e939128..c3264bb 100644 +index e939128..b355528 100644 --- a/app/views/datagrid/_head.html.erb +++ b/app/views/datagrid/_head.html.erb -@@ -1,6 +1,6 @@ +@@ -1,8 +1,31 @@ <tr> <% grid.html_columns(*options[:columns]).each do |column| %> - <th class="<%= datagrid_column_classes(grid, column) %>"> -+ <th class="<%= datagrid_column_classes(grid, column) %>" data-column="<%= column.name %>"> ++ <%= content_tag( ++ :th, ++ class: { ++ # Adding html clases based on condition ++ # Consider maintaining consistency with datagrid/rows partial ++ "datagrid-order-active-asc": grid.ordered_by?(column, false), ++ "datagrid-order-active-desc": grid.ordered_by?(column ,true), ++ column.html_class => column.html_class.present?, ++ }, ++ "data-column": column.name ++ ) do %> <%= column.header %> - <%= datagrid_order_for(grid, column, options) if column.supports_order? && options[:order]%> - </th> -diff --git a/app/views/datagrid/_order_for.html.erb b/app/views/datagrid/_order_for.html.erb -index 1545a8e..1c33c37 100644 ---- a/app/views/datagrid/_order_for.html.erb -+++ b/app/views/datagrid/_order_for.html.erb -@@ -1,10 +1,10 @@ --<div class="order"> -+<div class="datagrid-order"> - <%= link_to( -- I18n.t("datagrid.table.order.asc").html_safe, -+ I18n.t("datagrid.table.order.asc"), - datagrid_order_path(grid, column, false), -- class: "asc") %> -+ class: "datagrid-order-control-asc") %> - <%= link_to( -- I18n.t("datagrid.table.order.desc").html_safe, -+ I18n.t("datagrid.table.order.desc"), - datagrid_order_path(grid, column, true), -- class: "desc") %> -+ class: "datagrid-order-control-desc") %> - </div> +- <%= datagrid_order_for(grid, column, options) if column.supports_order? && options[:order]%> +- </th> ++ <% if column.supports_order? && options[:order] -%> ++ <div class="datagrid-order"> ++ <%= link_to( ++ I18n.t("datagrid.table.order.asc"), ++ datagrid_order_path(grid, column, false), ++ class: "datagrid-order-control-asc" ++ ) %> ++ <%= link_to( ++ I18n.t("datagrid.table.order.desc"), ++ datagrid_order_path(grid, column, true), ++ class: "datagrid-order-control-desc" ++ ) %> ++ </div> ++ <% end -%> ++ <% end -%> + <% end %> + </tr> diff --git a/app/views/datagrid/_range_filter.html.erb b/app/views/datagrid/_range_filter.html.erb index 7a8a123..3b8ca85 100644 --- a/app/views/datagrid/_range_filter.html.erb @@ -82,14 +89,25 @@ index 7a8a123..3b8ca85 100644 +<span class="datagrid-range-separator"><%= I18n.t('datagrid.filters.range.separator') %></span> +<%= form.datagrid_filter_input(filter, class: 'datagrid-range-to', **to_options) %> diff --git a/app/views/datagrid/_row.html.erb b/app/views/datagrid/_row.html.erb -index f54d21c..20f3ffb 100644 +index f54d21c..340aea6 100644 --- a/app/views/datagrid/_row.html.erb +++ b/app/views/datagrid/_row.html.erb -@@ -1,5 +1,5 @@ +@@ -1,5 +1,16 @@ <tr> <% grid.html_columns(*options[:columns]).each do |column| %> - <td class="<%= datagrid_column_classes(grid, column) %>"><%= datagrid_value(grid, column, asset) %></td> -+ <td class="<%= datagrid_column_classes(grid, column) %>" data-column="<%= column.name %>"><%= datagrid_value(grid, column, asset) %></td> ++ <%= content_tag( ++ :td, ++ datagrid_value(grid, column, asset), ++ class: { ++ # Adding html clases based on condition ++ # Consider maintaining consistency with datagrid/head partial ++ "datagrid-order-active-asc": grid.ordered_by?(column, false), ++ "datagrid-order-active-desc": grid.ordered_by?(column ,true), ++ column.html_class => column.html_class.present?, ++ }, ++ "data-column": column.name ++ ) %> <% end %> </tr> diff --git a/app/views/datagrid/_table.html.erb b/app/views/datagrid/_table.html.erb From 6ac1194c5dadca0fb81b03f643797a54bf15774c Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 10 Nov 2024 12:17:15 +0100 Subject: [PATCH 076/157] Update v2 guide --- version-2/Readme.markdown | 44 +++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index cbb3bad..96f343e 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -11,7 +11,7 @@ List of things introduces: 1. Use `form_with` instead of `form_for`. 1. Deprecated `datagrid_order_for` -1. Ruby infinite ranges for range filters. +1. Ruby endless ranges for range filters. 1. Modern modular CSS classes. 1. HTML5 input types: number, date, datetime-local. 1. Use Hash instead of Array for multiparameter attirubtes. @@ -44,17 +44,17 @@ datagrid_form_with(model: @users_grid, url: users_path) The recommended way is to include your ordering code directly into `datagrid/head` partial. See default [head partial](../app/views/datagrid/_head.html.erb) for example. -## Infinite Ranges for range filters +## Endless ranges for range filters -Ruby supports infinite ranges now, -so there is no need to present infinite ranges as Hash or Array. +Ruby supports endless ranges now, +so there is no need to present endless ranges as Hash or Array. But it introduces a breaking changes to range filters in Datagrid: ``` ruby class UsersGrid < Datagrid::Base filter(:id, :integer, range: true) do |value, scope| - # V1 value: [1, nil] - # V2 value: 1..nil + # V1 value is [1, nil] + # V2 value is 1..nil scope.where(id: value) end end @@ -103,8 +103,8 @@ and avoid collisions with other libraries: | noresults | datagrid-no-results | | datagrid | datagrid-table | | order | datagrid-order | -| a.asc | datagrid-order-control-asc | -| a.desc | datagrid-order-control-desc | +| asc | datagrid-order-control-asc | +| desc | datagrid-order-control-desc | | ordered.asc | datagrid-order-active-asc | | ordered.desc | datagrid-order-active-desc | | field | datagrid-dynamic-field | @@ -113,6 +113,9 @@ and avoid collisions with other libraries: | separator | datagrid-range-separator | | checkboxes | datagrid-enum-checkboxes | +Diff for [built-in partials between V1 and V2](./views.diff) +See [a new built-in CSS file](../app/assets/datagrid.css). + ### Example The difference in layout generation from v1 to v2. @@ -180,7 +183,7 @@ The default behavior can be changed back by using `input_options`: ``` ruby filter(:created_at, :date, range: true, input_options: {type: 'text'}) -filter(:salary, :integer, range: true, input_options: {type: 'text'}) +filter(:salary, :integer, range: true, input_options: {type: 'text', step: nil}) ``` Additionally, textarea inputs are now supported this way: @@ -190,10 +193,9 @@ Additionally, textarea inputs are now supported this way: filter(:text, :string, input_options: {type: 'textarea'}) ``` -## Names collision restriction +## Prefer Hash instead of Array for multiparameter filter types -HTML5 prohibits multiple inputs to have the same name. -This is contradicts to Rails parameters convention that serializes multiple inputs with same name into array: +Rails multiple input had been a problem [#325](https://github.com/bogdan/datagrid/issues/325). ``` html Date From: @@ -250,6 +252,8 @@ instead of classes for meta information from backend. Therefor built-in partials now generate data attributes by default instead of classes for column names: +Diff for [built-in partials between V1 and V2](./views.diff) + ### Filters ``` html @@ -263,10 +267,7 @@ instead of classes for column names: Version 2: ``` html -<div class="datagrid-filter" - data-filter="category" - data-type="string" -> +<div class="datagrid-filter" data-filter="category" data-type="string"> <label for="form_for_grid_category">Category</label> <input type="text" name="form_for_grid[category]" id="form_for_grid_category" /> @@ -338,7 +339,7 @@ end ## ApplicationGrid base class Previously recommended base class `BaseGrid` is incosistent -with Rails naming conventionsa. +with Rails naming conventions. It was renamed to `ApplicationGrid` instead: ``` ruby @@ -361,16 +362,9 @@ class UsersGrid < ApplicationGrid end ``` -## All changes in built-in partials - -Version 2 built-in partials are trying to expose -as much UI as possible for user modification. - -Here is a complete [diff for built-in partials between V1 and V2](./views.diff) - ## Remove SASS dependency SASS is no longer a default choice when starting a rails project. Version 2 makes it more flexible by avoiding the dependency on any particular CSS framework. -Inspect [a new built-in CSS file](../app/assets/datagrid.css). +See [a new built-in CSS file](../app/assets/datagrid.css). From 74aa904ca3bc3a1718228fa87fa395d9d1d61b10 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 10 Nov 2024 12:44:33 +0100 Subject: [PATCH 077/157] Generate local form when using datagrid_form_for --- lib/datagrid/renderer.rb | 13 ++++++++++--- spec/datagrid/helper_spec.rb | 2 +- version-2/Readme.markdown | 4 +++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/datagrid/renderer.rb b/lib/datagrid/renderer.rb index be9ca2e..8423cec 100644 --- a/lib/datagrid/renderer.rb +++ b/lib/datagrid/renderer.rb @@ -20,9 +20,16 @@ def format_value(grid, column, asset) end def form_for(grid, options = {}) - options[:method] ||= :get - options[:as] ||= grid.param_name - _render_partial("form", options[:partials], { grid: grid, options: options }) + _render_partial( + "form", options[:partials], + grid: grid, + options: { + method: :get, + as: grid.param_name, + local: true, + **options + }, + ) end def form_with(**options) diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index f5d6bfb..76c16fe 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -458,7 +458,7 @@ class FormForGrid < Datagrid::Base end object = FormForGrid.new(category: "hello") expect(subject.datagrid_form_for(object, url: "/grid")).to equal_to_dom(<<~HTML) - <form class="datagrid-form" action="/grid" accept-charset="UTF-8" data-remote="true" method="get"> + <form class="datagrid-form" action="/grid" accept-charset="UTF-8" method="get"> <input name="utf8" type="hidden" value="✓" autocomplete="off" /> <div class="datagrid-filter" data-filter="category" data-type="string"> <label for="form_for_grid_category">Category</label> diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index 96f343e..3e057ba 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -1,6 +1,6 @@ # Datagrid Version 2 -Datagrid v1 was released Sep 19 2013 - more than 10 years ago. +Datagrid v1 was released on Sep 19 2013 - more than 10 years ago. A lot of changes in best practices and available technology had happened during this period. It caused the library to be designed without support of those technologies @@ -38,6 +38,8 @@ datagrid_form_for(@users_grid, url: users_path) datagrid_form_with(model: @users_grid, url: users_path) ``` +Built-in partial uses `form_with` no matter + ## Deprecated datagrid\_order\_for `datagrid_order_for` helper serves no purpose and should not be used directly. From ace61b34e6a9ab4ae732b67dbd58fec78444491f Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 10 Nov 2024 21:11:20 +0100 Subject: [PATCH 078/157] Rollback changes in datagrid_order_for --- lib/datagrid/helper.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/datagrid/helper.rb b/lib/datagrid/helper.rb index be58a10..dc5e157 100644 --- a/lib/datagrid/helper.rb +++ b/lib/datagrid/helper.rb @@ -93,13 +93,13 @@ def datagrid_rows(grid, assets = grid.assets, **options, &block) # # * <tt>:partials</tt> - Path for partials lookup. # Default: 'datagrid'. - def datagrid_order_for(grid, column, order: true, **options) + def datagrid_order_for(grid, column, options = {}) Datagrid::Utils.warn_once(<<~MSG) datagrid_order_for is deprecated. Put necessary code inline inside datagrid/head partial. See built-in partial for example. MSG - datagrid_renderer.order_for(grid, column, **options) + datagrid_renderer.order_for(grid, column, options) end # Renders HTML for grid with all filters inputs and labels defined in it From 5ead01260ac529454769f559727e5b59f113247c Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 10 Nov 2024 21:18:12 +0100 Subject: [PATCH 079/157] Update migration guide --- version-2/Readme.markdown | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index 3e057ba..f8e958b 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -115,6 +115,10 @@ and avoid collisions with other libraries: | separator | datagrid-range-separator | | checkboxes | datagrid-enum-checkboxes | +All classes are now explicitly assinged inside datagrid partials. +[Modify built-in partials](https://github.com/bogdan/datagrid/wiki/Frontend#modifying-built-in-partials) +if you want to change them. + Diff for [built-in partials between V1 and V2](./views.diff) See [a new built-in CSS file](../app/assets/datagrid.css). @@ -254,10 +258,11 @@ instead of classes for meta information from backend. Therefor built-in partials now generate data attributes by default instead of classes for column names: -Diff for [built-in partials between V1 and V2](./views.diff) ### Filters +Version 1: + ``` html <div class="datagrid-filter filter"> <label for="form_for_grid_category">Category</label> @@ -276,6 +281,8 @@ Version 2: </div> ``` +Diff for [built-in partials between V1 and V2](./views.diff) + ### Columns Version 1: @@ -318,14 +325,16 @@ If you still want to have an HTML class attached to a column use `class` column column(:name, class: 'short-column') ``` +Renders: + ``` html <th class="short-column" data-column="name">Name</th> ... <td class="short-column" data-column="name">John</td> ``` -If you want to change this behavior completely, -modify [built-in partials](https://github.com/bogdan/datagrid/wiki/Frontend#modifying-built-in-partials) +[Modify built-in partials](https://github.com/bogdan/datagrid/wiki/Frontend#modifying-built-in-partials) +if you want to change this behavior completely. ## Inherit Datagrid::Base From a0c451d930212a463e63511dc0512d2d06fe4335 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 10 Nov 2024 21:57:21 +0100 Subject: [PATCH 080/157] Update doc --- Readme.markdown | 10 ++++++---- lib/datagrid/form_builder.rb | 5 +---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Readme.markdown b/Readme.markdown index 98a9f80..924fa4c 100644 --- a/Readme.markdown +++ b/Readme.markdown @@ -1,11 +1,13 @@ # Datagrid -[](https://github.com/bogdan/datagrid/actions) +Datagrid Version 2.0.0 is here. + +[Migration Guide](./version-2). -[](https://app.fossa.io/projects/git%2Bgithub.com%2Fbogdan%2Fdatagrid?ref=badge_shield) +[](https://github.com/bogdan/datagrid/actions) A really mighty and flexible ruby library that generates reports -including admin panels, analytics and data representation: +including admin panels, analytics and data browsers: * Filtering * Columns @@ -31,7 +33,7 @@ including admin panels, analytics and data representation: ## Documentation -* [Readme](/Readme.markdown) - this read-me for basic information. +* Readme - this read-me for basic information. * [Wiki](https://github.com/bogdan/datagrid/wiki) - general reference on how to use the gem. * [Rdoc](https://rubydoc.info/gems/datagrid) - API reference. diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index a53b79a..aec1cc0 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -6,10 +6,7 @@ module Datagrid module FormBuilder # @param filter_or_attribute [Datagrid::Filters::BaseFilter, String, Symbol] filter object or filter name # @param options [Hash] options of rails form input helper - # @return [String] a form input html for the corresponding filter name - # * <tt>select</tt> for enum, xboolean filter types - # * <tt>check_box</tt> for boolean filter type - # * <tt>text_field</tt> for other filter types + # @return [String] a form input html for the corresponding filter def datagrid_filter(filter_or_attribute, **options, &block) filter = datagrid_get_filter(filter_or_attribute) send(filter.form_builder_helper_name, filter, **options, &block) From fb96d98520a76dd1f341edb461a0c3d6fe7d7784 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 11 Nov 2024 10:34:56 +0100 Subject: [PATCH 081/157] v2.0.0 --- lib/datagrid/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/datagrid/version.rb b/lib/datagrid/version.rb index 12d0cd3..9b62e71 100644 --- a/lib/datagrid/version.rb +++ b/lib/datagrid/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Datagrid - VERSION = "1.8.4" + VERSION = "2.0.0" end From 80d56f58d2a4805fa2904190acc69347aa899654 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 11 Nov 2024 10:50:31 +0100 Subject: [PATCH 082/157] BaseFilter#default_scope? method --- lib/datagrid/filters/base_filter.rb | 23 +++++++++++------------ spec/datagrid/filters/base_filter_spec.rb | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/lib/datagrid/filters/base_filter.rb b/lib/datagrid/filters/base_filter.rb index 262aed5..f7f3074 100644 --- a/lib/datagrid/filters/base_filter.rb +++ b/lib/datagrid/filters/base_filter.rb @@ -17,7 +17,7 @@ def initialize(grid_class, name, options = {}, &block) self.grid_class = grid_class self.name = name.to_sym self.options = options - self.block = block || default_filter_block + self.block = block end def parse(value) @@ -39,7 +39,7 @@ def apply(grid_object, scope, value) return scope unless result - result = default_filter(value, scope, grid_object) if result == Datagrid::Filters::DEFAULT_FILTER_BLOCK + result = default_filter(value, scope) if result == Datagrid::Filters::DEFAULT_FILTER_BLOCK unless grid_object.driver.match?(result) raise( Datagrid::FilteringError, @@ -116,13 +116,6 @@ def self.form_builder_helper_name :"datagrid_#{to_s.demodulize.underscore}" end - def default_filter_block - filter = self - lambda do |value, scope, grid| - filter.default_filter(value, scope, grid) - end - end - def supports_range? self.class.ancestors.include?(::Datagrid::Filters::RangedFilter) end @@ -150,6 +143,10 @@ def enum_checkboxes? false end + def default_scope? + !block + end + protected def default_filter_where(scope, value) @@ -157,10 +154,12 @@ def default_filter_where(scope, value) end def execute(value, scope, grid_object) - if block.arity == 1 + if block&.arity == 1 scope.instance_exec(value, &block) - else + elsif block Datagrid::Utils.apply_args(value, scope, grid_object, &block) + else + default_filter(value, scope) end end @@ -185,7 +184,7 @@ def driver grid_class.driver end - def default_filter(value, scope, _grid) + def default_filter(value, scope) return nil if dummy? if !driver.scope_has_column?(scope, name) && scope.respond_to?(name, true) diff --git a/spec/datagrid/filters/base_filter_spec.rb b/spec/datagrid/filters/base_filter_spec.rb index fc60ca1..9a6340f 100644 --- a/spec/datagrid/filters/base_filter_spec.rb +++ b/spec/datagrid/filters/base_filter_spec.rb @@ -15,4 +15,20 @@ def name_default expect(report.assets).not_to include(Entry.create!(name: "world")) expect(report.assets).not_to include(Entry.create!(name: "")) end + + describe "#default_scope?" do + + it "identifies filters without custom block" do + grid = test_report do + scope { Entry } + filter(:id, :integer) + filter(:group_id, :integer) do |value, scope| + scope("group_id >= ?", value) + end + end + + expect(grid.filter_by_name(:id)).to be_default_scope + expect(grid.filter_by_name(:group_id)).to_not be_default_scope + end + end end From cb8d752889a0cae0fdc15219b1aefd351b2829f9 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 11 Nov 2024 10:50:40 +0100 Subject: [PATCH 083/157] Finding deprecation scripts --- version-2/Readme.markdown | 32 +++++++++++++++++--------- version-2/deprecations.sh | 16 +++++++++++++ version-2/find_broken_range_filters.rb | 15 ++++++++++++ 3 files changed, 52 insertions(+), 11 deletions(-) create mode 100644 version-2/deprecations.sh create mode 100644 version-2/find_broken_range_filters.rb diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index f8e958b..236ffdf 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -40,11 +40,27 @@ datagrid_form_with(model: @users_grid, url: users_path) Built-in partial uses `form_with` no matter +[Grep all deprecations](./deprecations.sh). + ## Deprecated datagrid\_order\_for `datagrid_order_for` helper serves no purpose and should not be used directly. The recommended way is to include your ordering code directly into `datagrid/head` partial. See default [head partial](../app/views/datagrid/_head.html.erb) for example. +[Grep all deprecations](./deprecations.sh). + +## Inherit Datagrid::Base + +`include Datagrid` causes method name space to be clamsy. +Version 2 introduces a difference between the class +that needs to be inherited and high level namespace (just like most gems do): + +``` ruby +class ApplicationGrid < Datagrid::Base +end +``` + +[Grep all deprecations](./deprecations.sh). ## Endless ranges for range filters @@ -92,6 +108,11 @@ grid = UsersGrid.new(ActiveSupport::JSON.load(grid.attributes.to_json)) grid.id # => 3..7 ``` +This very likely breaks all `range: true` filters with custom block passed. +All such filters can be seen with this script (works only for V2): + +[Search all broken range filters](./find_broken_range_filters.rb) + ## Modern CSS classes naming conventions Built-in generated CSS classes renamed to match modern CSS naming conventions @@ -336,17 +357,6 @@ Renders: [Modify built-in partials](https://github.com/bogdan/datagrid/wiki/Frontend#modifying-built-in-partials) if you want to change this behavior completely. -## Inherit Datagrid::Base - -`include Datagrid` causes method name space to be clamsy. -Version 2 introduces a difference between the class -that needs to be inherited and high level namespace (just like most gems do): - -``` ruby -class ApplicationGrid < Datagrid::Base -end -``` - ## ApplicationGrid base class Previously recommended base class `BaseGrid` is incosistent diff --git a/version-2/deprecations.sh b/version-2/deprecations.sh new file mode 100644 index 0000000..9671188 --- /dev/null +++ b/version-2/deprecations.sh @@ -0,0 +1,16 @@ +# Use datagrid_form_with +git grep 'datagrid_form_for' + +# Inline content of datagrid/order_for partial +git grep 'datagrid_order_for' + +# Put necessary classes manually +git grep 'datagrid_column_classes' + +# Inherit Datagrid::Base +git grep 'include Datagrid' + +# Rename to ApplicationGrid (optional) +git grep 'BaseDatagrid' +git grep 'BaseGrid' + diff --git a/version-2/find_broken_range_filters.rb b/version-2/find_broken_range_filters.rb new file mode 100644 index 0000000..b8a988f --- /dev/null +++ b/version-2/find_broken_range_filters.rb @@ -0,0 +1,15 @@ +# Important in development to have all classes in memory +Rails.application.eager_load! + +raise "Use version 2" if Datagrid::VERSION < "2.0.0" + +included_classes = ObjectSpace.each_object(Class).select do |klass| + klass.included_modules.include?(Datagrid) +end +classes = [*included_classes, *Datagrid::Base.subclasses].uniq + +classes.flat_map(&:filters).select do |f| + f.respond_to?(:range?) && f.range? && f.block +end.map do |f| + [f.grid_class, f.name].join("#") +end From dbe6600190682518eb506136111b4e86c424cef6 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 11 Nov 2024 10:57:05 +0100 Subject: [PATCH 084/157] Fix script bug --- version-2/find_broken_range_filters.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/version-2/find_broken_range_filters.rb b/version-2/find_broken_range_filters.rb index b8a988f..989643d 100644 --- a/version-2/find_broken_range_filters.rb +++ b/version-2/find_broken_range_filters.rb @@ -6,7 +6,11 @@ included_classes = ObjectSpace.each_object(Class).select do |klass| klass.included_modules.include?(Datagrid) end -classes = [*included_classes, *Datagrid::Base.subclasses].uniq + +base_subclasses = ObjectSpace.each_object(Class).select do |klass| + klass < Datagrid::Base +end +classes = [*included_classes, *base_subclasses].uniq classes.flat_map(&:filters).select do |f| f.respond_to?(:range?) && f.range? && f.block From 3059c07e9607abab7ff03a120b26664a7c8e36f7 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 11 Nov 2024 11:18:46 +0100 Subject: [PATCH 085/157] Replace rake datagrid:copy_partials with rails g datagrid::views --- Readme.markdown | 6 +++--- lib/datagrid.rb | 3 ++- lib/datagrid/{ => generators}/scaffold.rb | 3 +++ lib/datagrid/generators/views.rb | 18 ++++++++++++++++++ lib/tasks/datagrid_tasks.rake | 18 ------------------ .../datagrid/{ => generators}/scaffold_spec.rb | 4 ++-- version-2/Readme.markdown | 1 + version-2/deprecations.sh | 3 +++ 8 files changed, 32 insertions(+), 24 deletions(-) rename lib/datagrid/{ => generators}/scaffold.rb (98%) create mode 100644 lib/datagrid/generators/views.rb delete mode 100644 lib/tasks/datagrid_tasks.rake rename spec/datagrid/{ => generators}/scaffold_spec.rb (90%) diff --git a/Readme.markdown b/Readme.markdown index 924fa4c..c5a0729 100644 --- a/Readme.markdown +++ b/Readme.markdown @@ -183,12 +183,12 @@ route resources :skills insert app/assets/stylesheet/application.css ``` -#### Customize Built-in partials +#### Customize Built-in views -In order to get a control on datagrid built-in partials run: +In order to get a control on datagrid built-in views run: ``` sh -rake datagrid:copy_partials +rails g datagrid::views ``` #### Advanced frontend diff --git a/lib/datagrid.rb b/lib/datagrid.rb index a63a21b..74e19c9 100644 --- a/lib/datagrid.rb +++ b/lib/datagrid.rb @@ -25,5 +25,6 @@ class ColumnUnavailableError < StandardError; end end require "datagrid/base" -require "datagrid/scaffold" +require "datagrid/generators/scaffold" +require "datagrid/generators/views" I18n.load_path << File.expand_path("datagrid/locale/en.yml", __dir__) diff --git a/lib/datagrid/scaffold.rb b/lib/datagrid/generators/scaffold.rb similarity index 98% rename from lib/datagrid/scaffold.rb rename to lib/datagrid/generators/scaffold.rb index 6f8a310..0956e46 100644 --- a/lib/datagrid/scaffold.rb +++ b/lib/datagrid/generators/scaffold.rb @@ -4,6 +4,8 @@ # @!visibility private module Datagrid + # @!visibility private + module Generators # @!visibility private class Scaffold < Rails::Generators::NamedBase include Rails::Generators::ResourceHelpers @@ -167,4 +169,5 @@ def file_exists?(name) File.exist?(name) end end + end end diff --git a/lib/datagrid/generators/views.rb b/lib/datagrid/generators/views.rb new file mode 100644 index 0000000..0a85252 --- /dev/null +++ b/lib/datagrid/generators/views.rb @@ -0,0 +1,18 @@ +module Datagrid + module Generators + class Views < Rails::Generators::Base + source_root File.expand_path("../../../app/views/datagrid", __dir__) + + desc "Copies Datagrid partials to your application." + def copy_views + Dir.glob(File.join(self.class.source_root, "**", "*")).each do |file_path| + relative_path = file_path.sub(self.class.source_root + "/", "") + + next if relative_path == "_order_for.html.erb" + + copy_file(relative_path, File.join("app/views/datagrid", relative_path)) + end + end + end + end +end diff --git a/lib/tasks/datagrid_tasks.rake b/lib/tasks/datagrid_tasks.rake deleted file mode 100644 index 5c468ef..0000000 --- a/lib/tasks/datagrid_tasks.rake +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: true - -namespace :datagrid do - desc "Copy table partials into rails application" - task :copy_partials do - require "fileutils" - views_path = "app/views/datagrid" - destination_dir = (Rails.root + views_path).to_s - pattern = "#{File.expand_path(File.dirname(__FILE__) + "/../../#{views_path}")}/*" - Dir[pattern].each do |template| - # Deprecated partial - next if template.include?("/_order_for.") - puts "* copy #{template} => #{destination_dir}" - FileUtils.mkdir_p destination_dir - FileUtils.cp template, destination_dir - end - end -end diff --git a/spec/datagrid/scaffold_spec.rb b/spec/datagrid/generators/scaffold_spec.rb similarity index 90% rename from spec/datagrid/scaffold_spec.rb rename to spec/datagrid/generators/scaffold_spec.rb index 0fcf45e..d83f88d 100644 --- a/spec/datagrid/scaffold_spec.rb +++ b/spec/datagrid/generators/scaffold_spec.rb @@ -2,8 +2,8 @@ require "spec_helper" -describe Datagrid::Scaffold do - subject { Datagrid::Scaffold.new(["user"]) } +describe Datagrid::Generators::Scaffold do + subject { Datagrid::Generators::Scaffold.new(["user"]) } describe ".pagination_helper_code" do it "uses kaminari by default" do diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index 236ffdf..235d46d 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -21,6 +21,7 @@ List of things introduces: 1. Inherit `Datagrid::Base` instead of `include Datagrid` 1. `ApplicationGrid` is recommended base class instead of `BaseGrid` 1. Remove SASS dependency +1. Replace `rake datagrid:copy_partials` with `rails g datagrid:views` ## Use form\_with diff --git a/version-2/deprecations.sh b/version-2/deprecations.sh index 9671188..01a4341 100644 --- a/version-2/deprecations.sh +++ b/version-2/deprecations.sh @@ -10,6 +10,9 @@ git grep 'datagrid_column_classes' # Inherit Datagrid::Base git grep 'include Datagrid' +# Use rails g datagrid:views +git grep 'datagrid:copy_partials' + # Rename to ApplicationGrid (optional) git grep 'BaseDatagrid' git grep 'BaseGrid' From 6020fd66759010f135e17d4920d3ddad2ee291e4 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 11 Nov 2024 11:46:43 +0100 Subject: [PATCH 086/157] Set new rails default ActionView::Helpers::FormTagHelper.default_enforce_utf8 = false --- spec/datagrid/helper_spec.rb | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 76c16fe..47f70dc 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -20,8 +20,10 @@ allow(subject).to receive(:url_for) do |options| options.is_a?(String) ? options : ["/location", options.to_param.presence].compact.join("?") end - # Rails default since 5.x + + # Rails defaults since 6.x ActionView::Helpers::FormHelper.form_with_generates_ids = true + ActionView::Helpers::FormTagHelper.default_enforce_utf8 = false end let(:group) { Group.create!(name: "Pop") } @@ -459,11 +461,10 @@ class FormForGrid < Datagrid::Base object = FormForGrid.new(category: "hello") expect(subject.datagrid_form_for(object, url: "/grid")).to equal_to_dom(<<~HTML) <form class="datagrid-form" action="/grid" accept-charset="UTF-8" method="get"> - <input name="utf8" type="hidden" value="✓" autocomplete="off" /> - <div class="datagrid-filter" data-filter="category" data-type="string"> - <label for="form_for_grid_category">Category</label> - <input value="hello" type="text" name="form_for_grid[category]" id="form_for_grid_category" /> - </div> + <div class="datagrid-filter" data-filter="category" data-type="string"> + <label for="form_for_grid_category">Category</label> + <input value="hello" type="text" name="form_for_grid[category]" id="form_for_grid_category" /> + </div> <div class="datagrid-actions"> <input type="submit" name="commit" value="Search" class="datagrid-submit" data-disable-with="Search" /> <a class="datagrid-reset" href="/location">Reset</a> @@ -533,11 +534,10 @@ class FormWithGrid < Datagrid::Base object = FormWithGrid.new(category: "hello") expect(subject.datagrid_form_with(model: object, url: "/grid")).to equal_to_dom(<<~HTML) <form class="datagrid-form" action="/grid" accept-charset="UTF-8" data-remote="true" method="get"> - <input name="utf8" type="hidden" value="✓" autocomplete="off" /> - <div class="datagrid-filter" data-filter="category" data-type="string"> - <label for="form_with_grid_category">Category</label> - <input value="hello" type="text" name="form_with_grid[category]" id="form_with_grid_category" /> - </div> + <div class="datagrid-filter" data-filter="category" data-type="string"> + <label for="form_with_grid_category">Category</label> + <input value="hello" type="text" name="form_with_grid[category]" id="form_with_grid_category" /> + </div> <div class="datagrid-actions"> <input type="submit" name="commit" value="Search" class="datagrid-submit" data-disable-with="Search" /> <a class="datagrid-reset" href="/location">Reset</a> From 18b97b3f854dfd978e8af8f4796e7ed1bcf3dc3f Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 11 Nov 2024 11:51:12 +0100 Subject: [PATCH 087/157] Set form_with_generates_remote_forms to false as it is default value --- spec/datagrid/helper_spec.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 47f70dc..a5c40b3 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -21,8 +21,9 @@ options.is_a?(String) ? options : ["/location", options.to_param.presence].compact.join("?") end - # Rails defaults since 6.x + # Rails defaults since 6.1 ActionView::Helpers::FormHelper.form_with_generates_ids = true + ActionView::Helpers::FormHelper.form_with_generates_remote_forms = false ActionView::Helpers::FormTagHelper.default_enforce_utf8 = false end @@ -533,7 +534,7 @@ class FormWithGrid < Datagrid::Base end object = FormWithGrid.new(category: "hello") expect(subject.datagrid_form_with(model: object, url: "/grid")).to equal_to_dom(<<~HTML) - <form class="datagrid-form" action="/grid" accept-charset="UTF-8" data-remote="true" method="get"> + <form class="datagrid-form" action="/grid" accept-charset="UTF-8" method="get"> <div class="datagrid-filter" data-filter="category" data-type="string"> <label for="form_with_grid_category">Category</label> <input value="hello" type="text" name="form_with_grid[category]" id="form_with_grid_category" /> From 5fa36cb251dd588a2fcd090eec1b42e9330473a6 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 11 Nov 2024 11:57:38 +0100 Subject: [PATCH 088/157] Update form-v2.html --- version-2/form-v2.html | 2 -- 1 file changed, 2 deletions(-) diff --git a/version-2/form-v2.html b/version-2/form-v2.html index 03a40a3..a67fd98 100644 --- a/version-2/form-v2.html +++ b/version-2/form-v2.html @@ -1,6 +1,4 @@ <form class="datagrid-form" id="new_g" action="/users" accept-charset="UTF-8" method="get"> - <input name="utf8" type="hidden" value="✓" autocomplete="off" /> - <div class="datagrid-filter" data-filter="id" data-type="integer"> <label for="g_id">Id</label> <input step="1" class="datagrid-range-from" name="g[id][from]" type="number" /> From 5315eee5056eabb76e87c6467a24f4c020d23fa2 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 11 Nov 2024 11:57:54 +0100 Subject: [PATCH 089/157] Update form-v1.html --- version-2/form-v1.html | 2 -- 1 file changed, 2 deletions(-) diff --git a/version-2/form-v1.html b/version-2/form-v1.html index 5e8241a..2df12dc 100644 --- a/version-2/form-v1.html +++ b/version-2/form-v1.html @@ -1,6 +1,4 @@ <form class="datagrid-form partial_default_grid" id="new_g" action="/users" accept-charset="UTF-8" method="get"> - <input name="utf8" type="hidden" value="✓" autocomplete="off" /> - <div class="datagrid-filter filter"> <label for="g_id">Id</label> <input class="id integer_filter from" multiple type="text" name="g[id][]" /> From 0f9b3653654c6a9b9426055a2c40096efcc51ef0 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 11 Nov 2024 19:30:27 +0100 Subject: [PATCH 090/157] Additional doc --- lib/datagrid/core.rb | 14 +++++++++++++- version-2/Readme.markdown | 18 ++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/lib/datagrid/core.rb b/lib/datagrid/core.rb index 1a167c9..e11830a 100644 --- a/lib/datagrid/core.rb +++ b/lib/datagrid/core.rb @@ -137,6 +137,15 @@ def initialize(attributes = nil, &block) end # @return [{Symbol => Object}] grid attributes including filter values and ordering values + # @example + # class UsersGrid < ApplicationGrid + # scope { User } + # filter(:first_name, :string) + # filter(:last_name, :string) + # end + # + # grid = UsersGrid.new(first_name: 'John', last_name: 'Smith') + # grid.attributes # => {first_name: 'John', last_name: 'Smith', order: nil, descending: nil} def attributes result = {} datagrid_attributes.each do |name| @@ -148,10 +157,13 @@ def attributes # Updates datagrid attributes with a passed hash argument # @param attributes [{Symbol => Object}] # @example - # grid = MyGrid.new + # grid = UsersGrid.new # grid.attributes = {first_name: 'John', last_name: 'Smith'} # grid.first_name # => 'John' # grid.last_name # => 'Smith' + def attributes=(value) + super + end # @return [Object] Any datagrid attribute value def [](attribute) diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index 235d46d..1ab4c4c 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -193,7 +193,7 @@ TODO ## HTML5 input types -Version 1 generated `<input type="text"/>` for every filter type. +Version 1 generated `<input type="text"/>` for most filter types. Version 2 uses the appropriate input type for each filter type: | Type | HTML Input Element | @@ -214,6 +214,20 @@ filter(:created_at, :date, range: true, input_options: {type: 'text'}) filter(:salary, :integer, range: true, input_options: {type: 'text', step: nil}) ``` +You can disable HTML5 inputs with: + +``` ruby +class ApplicationGrid < Datagrid::Base + def self.filter(name, type = :default, input_options: {}, **options) + if [:date, :datetime, :float, :integer].include?(type) + input_options[:type] ||= 'text' + end + + super(name, type, input_options:, **options) + end +end +``` + Additionally, textarea inputs are now supported this way: ``` ruby @@ -389,4 +403,4 @@ end SASS is no longer a default choice when starting a rails project. Version 2 makes it more flexible by avoiding the dependency on any particular CSS framework. -See [a new built-in CSS file](../app/assets/datagrid.css). +See [a new built-in CSS file](../app/assets/stylesheets/datagrid.css). From d6ce92cbdba578c35b3ad436abbd4587320b88ab Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Tue, 12 Nov 2024 16:23:13 +0100 Subject: [PATCH 091/157] Update datagrid_spec.rb Co-authored-by: Bohdan Zhuravel <bohdan@zhuravel.bz> --- spec/datagrid_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/datagrid_spec.rb b/spec/datagrid_spec.rb index 881cb57..154623d 100644 --- a/spec/datagrid_spec.rb +++ b/spec/datagrid_spec.rb @@ -91,7 +91,7 @@ end end - it "deprecates inclucsion of Datagrid module" do + it "deprecates inclusion of Datagrid module" do silence_warnings do class DeprecatedInclusion include Datagrid From 0cd654383d58910befb78f582dde6682d6112eee Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Tue, 12 Nov 2024 16:23:22 +0100 Subject: [PATCH 092/157] Update Readme.markdown Co-authored-by: Bohdan Zhuravel <bohdan@zhuravel.bz> --- version-2/Readme.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index 1ab4c4c..ce1973a 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -27,7 +27,7 @@ List of things introduces: Rails [deprecates form\_for in favor of form\_with](https://guides.rubyonrails.org/form_helpers.html#using-form-tag-and-form-for). -`datagrid_form_for` is now depreacted if favor of `datagrid_form_with`. +`datagrid_form_for` is now deprecated if favor of `datagrid_form_with`. However, `datagrid_form_for` would also use Rails `form_with` because they share the same view partial. TODO: update the wiki From a26b59f9dfd6d3e33e1a789d029e6c6eb5e55424 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Tue, 12 Nov 2024 16:23:38 +0100 Subject: [PATCH 093/157] Update Readme.markdown Co-authored-by: Bohdan Zhuravel <bohdan@zhuravel.bz> --- version-2/Readme.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index ce1973a..d4d5d13 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -400,7 +400,7 @@ end ## Remove SASS dependency -SASS is no longer a default choice when starting a rails project. +SASS is no longer a default choice when starting a Ruby on Rails project. Version 2 makes it more flexible by avoiding the dependency on any particular CSS framework. See [a new built-in CSS file](../app/assets/stylesheets/datagrid.css). From 5ae09eecd050728ca7bf89ae8f0d90955e4b1b0a Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Tue, 12 Nov 2024 20:26:35 +0100 Subject: [PATCH 094/157] Use Rails.deprecator --- CHANGELOG.md | 4 ++++ lib/datagrid/utils.rb | 8 +++++++- spec/datagrid/helper_spec.rb | 6 +++--- spec/datagrid/utils_spec.rb | 4 ++-- spec/datagrid_spec.rb | 2 +- spec/spec_helper.rb | 4 ++++ 6 files changed, 21 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b928556..75abc2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 2.0.0 + +[Changes and migration guide](./version-2) + ## 1.8.3 * Fix rails hooking for version 7.1. [#327](https://github.com/bogdan/datagrid/issues/327) diff --git a/lib/datagrid/utils.rb b/lib/datagrid/utils.rb index 56a85a7..6ff31f4 100644 --- a/lib/datagrid/utils.rb +++ b/lib/datagrid/utils.rb @@ -23,12 +23,18 @@ def translate_from_namespace(namespace, grid_class, key) I18n.t(lookups.shift, default: lookups).presence end + def deprecator + defined?(Rails) && Rails.version >= "7.1.0" ? + Rails.deprecator : ActiveSupport::Deprecator + end + def warn_once(message, delay = 5) + @warnings ||= {} timestamp = @warnings[message] return false if timestamp && timestamp >= Time.now - delay - warn message + deprecator.warn(message) @warnings[message] = Time.now true end diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index a5c40b3..4a8ec28 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -429,7 +429,7 @@ class OrderedGrid < Datagrid::Base column(:category) end object = OrderedGrid.new(descending: true, order: :category) - silence_warnings do + silence_deprecator do expect(subject.datagrid_order_for(object, object.column_by_name(:category))).to equal_to_dom(<<~HTML) <div class="order"> <a class="asc" href="/location?ordered_grid%5Bdescending%5D=false&ordered_grid%5Border%5D=category">↑</a> @@ -442,7 +442,7 @@ class OrderedGrid < Datagrid::Base describe ".datagrid_form_for" do around(:each) do |e| - silence_warnings do + silence_deprecator do e.run end end @@ -736,7 +736,7 @@ def param_name column(:name) column(:group_id, class: 'short-column') end - silence_warnings do + silence_deprecator do expect(subject.send(:datagrid_column_classes, grid, :name)).to eq( "name ordered desc" ) diff --git a/spec/datagrid/utils_spec.rb b/spec/datagrid/utils_spec.rb index 1128edb..e3ef21a 100644 --- a/spec/datagrid/utils_spec.rb +++ b/spec/datagrid/utils_spec.rb @@ -5,13 +5,13 @@ describe Datagrid::Utils do describe ".warn_once" do it "should work" do - silence_warnings do + silence_deprecator do expect(Datagrid::Utils.warn_once("hello", 0.2)).to eq(true) end sleep(0.1) expect(Datagrid::Utils.warn_once("hello", 0.2)).to eq(false) sleep(0.2) - silence_warnings do + silence_deprecator do expect(Datagrid::Utils.warn_once("hello", 0.2)).to eq(true) end end diff --git a/spec/datagrid_spec.rb b/spec/datagrid_spec.rb index 881cb57..db0b6bc 100644 --- a/spec/datagrid_spec.rb +++ b/spec/datagrid_spec.rb @@ -92,7 +92,7 @@ end it "deprecates inclucsion of Datagrid module" do - silence_warnings do + silence_deprecator do class DeprecatedInclusion include Datagrid scope { Entry } diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 617d4ab..4735698 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -102,6 +102,10 @@ def action_view_template template end +def silence_deprecator(&block) + Datagrid::Utils.deprecator.silence(&block) +end + # Requires supporting files with custom matchers and macros, etc, # in ./support/ and its subdirectories. Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].sort.each { |f| require f } From 26dabcb51cb05c3d829e74acd9f79c43b8e43af5 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Tue, 12 Nov 2024 20:29:40 +0100 Subject: [PATCH 095/157] Fix rails 7.0 build --- lib/datagrid/utils.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/datagrid/utils.rb b/lib/datagrid/utils.rb index 6ff31f4..fea258f 100644 --- a/lib/datagrid/utils.rb +++ b/lib/datagrid/utils.rb @@ -25,7 +25,7 @@ def translate_from_namespace(namespace, grid_class, key) def deprecator defined?(Rails) && Rails.version >= "7.1.0" ? - Rails.deprecator : ActiveSupport::Deprecator + Rails.deprecator : ActiveSupport::Deprecation end def warn_once(message, delay = 5) From ff5193fd60bc120c13233699e5c738a35cb2eeba Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Tue, 12 Nov 2024 20:38:58 +0100 Subject: [PATCH 096/157] Cleanup old monkey patch --- lib/datagrid/drivers/abstract_driver.rb | 7 ------- lib/datagrid/drivers/active_record.rb | 8 -------- lib/datagrid/utils.rb | 6 +++--- spec/datagrid/drivers/active_record_spec.rb | 4 ++-- 4 files changed, 5 insertions(+), 20 deletions(-) diff --git a/lib/datagrid/drivers/abstract_driver.rb b/lib/datagrid/drivers/abstract_driver.rb index 6125e53..b663558 100644 --- a/lib/datagrid/drivers/abstract_driver.rb +++ b/lib/datagrid/drivers/abstract_driver.rb @@ -93,13 +93,6 @@ def default_cache_key(asset) raise NotImplementedError end - def where_by_timestamp_gotcha(scope, name, value) - value = Datagrid::Utils.format_date_as_timestamp(value) - scope = greater_equal(scope, name, value.first) if value.first - scope = less_equal(scope, name, value.last) if value.last - scope - end - def default_preload(scope, value) raise NotImplementedError end diff --git a/lib/datagrid/drivers/active_record.rb b/lib/datagrid/drivers/active_record.rb index 282dccd..bf10cac 100644 --- a/lib/datagrid/drivers/active_record.rb +++ b/lib/datagrid/drivers/active_record.rb @@ -142,11 +142,3 @@ def contains_predicate end end end - -if defined?(ActiveRecord::Base) - ActiveRecord::Base.class_eval do - def self.datagrid_where_by_timestamp(column, value) - Datagrid::Drivers::ActiveRecord.new.where_by_timestamp_gotcha(self, column, value) - end - end -end diff --git a/lib/datagrid/utils.rb b/lib/datagrid/utils.rb index fea258f..3d24995 100644 --- a/lib/datagrid/utils.rb +++ b/lib/datagrid/utils.rb @@ -120,10 +120,10 @@ def parse_datetime(value) def format_date_as_timestamp(value) if !value value - elsif value.is_a?(Array) - [value.first&.beginning_of_day, value.last&.end_of_day] + # elsif value.is_a?(Array) + # value.first&.beginning_of_day..value.last&.end_of_day elsif value.is_a?(Range) - (value.begin&.beginning_of_day..value.end&.end_of_day) + value.begin&.beginning_of_day..value.end&.end_of_day else value.beginning_of_day..value.end_of_day end diff --git a/spec/datagrid/drivers/active_record_spec.rb b/spec/datagrid/drivers/active_record_spec.rb index 1dd671a..d99b77a 100644 --- a/spec/datagrid/drivers/active_record_spec.rb +++ b/spec/datagrid/drivers/active_record_spec.rb @@ -37,13 +37,13 @@ end end - describe "gotcha #datagrid_where_by_timestamp" do + describe "where by timestamp" do subject do test_report(created_at: 10.days.ago..5.days.ago) do scope { Entry } filter(:created_at, :date, range: true) do |value, scope, _grid| - scope.joins(:group).datagrid_where_by_timestamp("groups.created_at", value) + scope.joins(:group).where(groups: {created_at: value}) end end.assets end From 3ab520c1c7bf10d3c0645fef87aa5841001dd4e5 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Tue, 12 Nov 2024 21:04:03 +0100 Subject: [PATCH 097/157] Forbid Range argument for non-range filter --- lib/datagrid/filters/base_filter.rb | 10 ++++-- lib/datagrid/filters/integer_filter.rb | 4 +++ spec/datagrid/filters/date_filter_spec.rb | 24 ++++++++++--- spec/datagrid/filters/integer_filter_spec.rb | 36 +++++++++++++++++++- 4 files changed, 66 insertions(+), 8 deletions(-) diff --git a/lib/datagrid/filters/base_filter.rb b/lib/datagrid/filters/base_filter.rb index f7f3074..0080d5a 100644 --- a/lib/datagrid/filters/base_filter.rb +++ b/lib/datagrid/filters/base_filter.rb @@ -54,12 +54,18 @@ def parse_values(value) if multiple? return nil if value.nil? - normalize_multiple_value(value).map do |v| + return normalize_multiple_value(value).map do |v| parse(v) end - elsif value.is_a?(Array) + end + + case value + when Array raise Datagrid::ArgumentError, "#{grid_class}##{name} filter can not accept Array argument. Use :multiple option." + when Range + raise Datagrid::ArgumentError, + "#{grid_class}##{name} filter can not accept Range argument. Use :range option." else parse(value) end diff --git a/lib/datagrid/filters/integer_filter.rb b/lib/datagrid/filters/integer_filter.rb index 79ff5f8..4ebde9b 100644 --- a/lib/datagrid/filters/integer_filter.rb +++ b/lib/datagrid/filters/integer_filter.rb @@ -19,6 +19,10 @@ def parse(value) end return value if value.is_a?(Range) + if value.to_i == 0 && value.is_a?(String) && value !~ %r{\A\s*-?0} + return nil + end + value.to_i end end diff --git a/spec/datagrid/filters/date_filter_spec.rb b/spec/datagrid/filters/date_filter_spec.rb index 72fa450..fa26d34 100644 --- a/spec/datagrid/filters/date_filter_spec.rb +++ b/spec/datagrid/filters/date_filter_spec.rb @@ -7,14 +7,28 @@ it "supports date range argument" do e1 = Entry.create!(created_at: 7.days.ago) e2 = Entry.create!(created_at: 4.days.ago) - e3 = Entry.create!(created_at: 1.day.ago) + e3 = Entry.create!(created_at: 3.days.ago) + e4 = Entry.create!(created_at: 1.day.ago) + report = test_report(created_at: 5.day.ago..3.days.ago) do scope { Entry } - filter(:created_at, :date) + filter(:created_at, :date, range: true) end + + expect(report.created_at).to eq(5.days.ago.to_date..3.days.ago.to_date) expect(report.assets).not_to include(e1) expect(report.assets).to include(e2) - expect(report.assets).not_to include(e3) + expect(report.assets).to include(e3) + expect(report.assets).not_to include(e4) + end + + it "raises when range assigned to non-range filter" do + expect { + test_report(created_at: 5.day.ago..3.days.ago) do + scope { Entry } + filter(:created_at, :date) + end + }.to raise_error(ArgumentError) end it "endless date range argument" do @@ -22,7 +36,7 @@ e2 = Entry.create!(created_at: 4.days.ago) report = test_report(created_at: 5.days.ago..) do scope { Entry } - filter(:created_at, :date) + filter(:created_at, :date, range: true) end expect(report.assets).not_to include(e1) expect(report.assets).to include(e2) @@ -31,7 +45,7 @@ expect(report.assets).not_to include(e2) end - it "supports hash argument" do + it "supports hash argument for range filter" do report = test_report do scope { Entry } filter(:created_at, :date, range: true) diff --git a/spec/datagrid/filters/integer_filter_spec.rb b/spec/datagrid/filters/integer_filter_spec.rb index 913249d..776d58f 100644 --- a/spec/datagrid/filters/integer_filter_spec.rb +++ b/spec/datagrid/filters/integer_filter_spec.rb @@ -13,7 +13,7 @@ it "should support integer range argument" do report = test_report(group_id: 3..5) do scope { Entry } - filter(:group_id, :integer) + filter(:group_id, :integer, range: true) end expect(report.assets).not_to include(entry1) expect(report.assets).to include(entry4) @@ -170,4 +170,38 @@ report.group_id = (nil...nil).as_json expect(report.group_id).to eq(nil) end + + it "type casts value" do + report = test_report do + scope { Entry } + filter(:group_id, :integer) + end + + report.group_id = "1" + expect(report.group_id).to eq(1) + + report.group_id = " 1 " + expect(report.group_id).to eq(1) + + report.group_id = 1.1 + expect(report.group_id).to eq(1) + + report.group_id = "1.1" + expect(report.group_id).to eq(1) + + report.group_id = "-1" + expect(report.group_id).to eq(-1) + + report.group_id = "-1.1" + expect(report.group_id).to eq(-1) + + report.group_id = "1a" + expect(report.group_id).to eq(1) + + report.group_id = "aa" + expect(report.group_id).to eq(nil) + + report.group_id = "a1" + expect(report.group_id).to eq(nil) + end end From 7aa28321257ee2f656fadb1446d125e83ae3ac78 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Tue, 12 Nov 2024 21:28:19 +0100 Subject: [PATCH 098/157] Add date range deserialization test --- lib/datagrid/filters/date_filter.rb | 8 ++++++-- spec/datagrid/filters/date_filter_spec.rb | 11 +++++++++++ spec/datagrid/filters/integer_filter_spec.rb | 2 +- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/datagrid/filters/date_filter.rb b/lib/datagrid/filters/date_filter.rb index 9793698..f3eccd8 100644 --- a/lib/datagrid/filters/date_filter.rb +++ b/lib/datagrid/filters/date_filter.rb @@ -12,7 +12,9 @@ def default_input_options end def apply(grid_object, scope, value) - value = value.begin&.beginning_of_day..value.end&.end_of_day if value.is_a?(Range) + if value.is_a?(Range) + value = value.begin&.beginning_of_day..value.end&.end_of_day + end super end @@ -29,7 +31,9 @@ def format(value) end def default_filter_where(scope, value) - value = Datagrid::Utils.format_date_as_timestamp(value) if driver.is_timestamp?(scope, name) + if driver.is_timestamp?(scope, name) + value = Datagrid::Utils.format_date_as_timestamp(value) + end super end diff --git a/spec/datagrid/filters/date_filter_spec.rb b/spec/datagrid/filters/date_filter_spec.rb index fa26d34..288b1cd 100644 --- a/spec/datagrid/filters/date_filter_spec.rb +++ b/spec/datagrid/filters/date_filter_spec.rb @@ -239,4 +239,15 @@ def entry_dated(date) expect(report.filter_value_as_string(:created_at)).to eq("01/02/2012") end end + + it "deserializes range" do + report = test_report do + scope { Entry } + filter(:created_at, :date, range: true) + end + + value = Date.new(2012, 1, 1)..Date.new(2012, 1, 2) + report.created_at = value.as_json + expect(report.created_at).to eq(value) + end end diff --git a/spec/datagrid/filters/integer_filter_spec.rb b/spec/datagrid/filters/integer_filter_spec.rb index 776d58f..19ed985 100644 --- a/spec/datagrid/filters/integer_filter_spec.rb +++ b/spec/datagrid/filters/integer_filter_spec.rb @@ -53,7 +53,7 @@ end it "should find something in one integer interval" do - report = test_report(group_id: (4..4)) do + report = test_report(group_id: 4) do scope { Entry } filter(:group_id, :integer, range: true) end From 12de0d4bbf1f68992fb2ada961843f8ec3a2d53f Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Wed, 13 Nov 2024 11:12:25 +0100 Subject: [PATCH 099/157] Fix regression for boolean filter default value --- lib/datagrid/filters.rb | 7 +++---- lib/datagrid/filters/base_filter.rb | 2 +- lib/datagrid/filters/boolean_filter.rb | 7 +++++++ lib/datagrid/filters/dynamic_filter.rb | 8 +++----- lib/datagrid/filters/enum_filter.rb | 7 ++++--- lib/datagrid/filters/extended_boolean_filter.rb | 2 +- 6 files changed, 19 insertions(+), 14 deletions(-) diff --git a/lib/datagrid/filters.rb b/lib/datagrid/filters.rb index c5fee88..7ec0ae4 100644 --- a/lib/datagrid/filters.rb +++ b/lib/datagrid/filters.rb @@ -100,7 +100,7 @@ def filter(name, type = :default, **options, &block) raise ConfigurationError, "filter class #{type.inspect} not found" unless klass position = Datagrid::Utils.extract_position_from_options(filters_array, options) - filter = klass.new(self, name, options, &block) + filter = klass.new(self, name, **options, &block) filters_array.insert(position, filter) datagrid_attribute(name) do |value| @@ -144,9 +144,8 @@ def filters_inspection def initialize(...) self.filters_array = self.class.filters_array.clone filters_array.each do |filter| - if (value = filter.default(self)) - self[filter.name] = value - end + value = filter.default(self) + self[filter.name] = value unless value.nil? end super end diff --git a/lib/datagrid/filters/base_filter.rb b/lib/datagrid/filters/base_filter.rb index 0080d5a..cb2ec9a 100644 --- a/lib/datagrid/filters/base_filter.rb +++ b/lib/datagrid/filters/base_filter.rb @@ -13,7 +13,7 @@ module Filters class BaseFilter attr_accessor :grid_class, :options, :block, :name - def initialize(grid_class, name, options = {}, &block) + def initialize(grid_class, name, **options, &block) self.grid_class = grid_class self.name = name.to_sym self.options = options diff --git a/lib/datagrid/filters/boolean_filter.rb b/lib/datagrid/filters/boolean_filter.rb index 6c16209..f6ff874 100644 --- a/lib/datagrid/filters/boolean_filter.rb +++ b/lib/datagrid/filters/boolean_filter.rb @@ -5,6 +5,13 @@ module Datagrid module Filters class BooleanFilter < Datagrid::Filters::BaseFilter + + # @!visibility private + def initialize(grid, name, **opts) + super(grid, name, **opts) + options[:default] ||= false + end + def default_input_options { **super, type: "checkbox" } end diff --git a/lib/datagrid/filters/dynamic_filter.rb b/lib/datagrid/filters/dynamic_filter.rb index 8ac9d2e..b05721a 100644 --- a/lib/datagrid/filters/dynamic_filter.rb +++ b/lib/datagrid/filters/dynamic_filter.rb @@ -19,13 +19,11 @@ class DynamicFilter < Datagrid::Filters::BaseFilter ].freeze AVAILABLE_OPERATIONS = %w[= =~ >= <=].freeze - def initialize(*) - super + def initialize(grid, name, **options, &block) options[:select] ||= default_select options[:operations] ||= DEFAULT_OPERATIONS - return if options.key?(:include_blank) - - options[:include_blank] = false + options[:include_blank] = false unless options.key?(:include_blank) + super(grid, name, **options, &block) end def default_input_options diff --git a/lib/datagrid/filters/enum_filter.rb b/lib/datagrid/filters/enum_filter.rb index 0c9e15e..ac21aac 100644 --- a/lib/datagrid/filters/enum_filter.rb +++ b/lib/datagrid/filters/enum_filter.rb @@ -7,9 +7,10 @@ module Filters class EnumFilter < Datagrid::Filters::BaseFilter include Datagrid::Filters::SelectOptions - def initialize(*args) - super - options[:multiple] = true if enum_checkboxes? + # @!visibility private + def initialize(grid, name, **options, &block) + options[:multiple] = true if options[:checkboxes] + super(grid, name, **options, &block) raise Datagrid::ConfigurationError, ":select option not specified" unless options[:select] end diff --git a/lib/datagrid/filters/extended_boolean_filter.rb b/lib/datagrid/filters/extended_boolean_filter.rb index ad8efa8..c771fd9 100644 --- a/lib/datagrid/filters/extended_boolean_filter.rb +++ b/lib/datagrid/filters/extended_boolean_filter.rb @@ -9,7 +9,7 @@ class ExtendedBooleanFilter < Datagrid::Filters::EnumFilter TRUTH_VALUES = [true, "true", "y", "yes"].freeze FALSE_VALUES = [false, "false", "n", "no"].freeze - def initialize(report, attribute, options = {}, &block) + def initialize(*args, **options) options[:select] = -> { boolean_select } super end From 5bf9208d184c8acc8f18b27033790cb954f8e2b1 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Wed, 13 Nov 2024 11:20:28 +0100 Subject: [PATCH 100/157] Add separator localization to upgrade guide --- version-2/Readme.markdown | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index d4d5d13..2538e17 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -20,6 +20,7 @@ List of things introduces: 1. HTML5 data attributes 1. Inherit `Datagrid::Base` instead of `include Datagrid` 1. `ApplicationGrid` is recommended base class instead of `BaseGrid` +1. Introduced `datagrid.filters.range.separator` localization 1. Remove SASS dependency 1. Replace `rake datagrid:copy_partials` with `rails g datagrid:views` @@ -398,6 +399,14 @@ class UsersGrid < ApplicationGrid end ``` +## Introduced range filter separator localization + +A separator symbol between range filter inputs is now a part of localizations to avoid hardcore. +Add `datagrid.filters.range.separator` to your localization file. + +[See commit for details](https://github.com/bogdan/datagrid/commit/2bd914a39a5f8367758ad697d7ccf8d98379fff7#diff-0e78e11f3e693a6523052bc71095ec539fa390cf04b50d74c35c9af5260f50f3L2) + + ## Remove SASS dependency SASS is no longer a default choice when starting a Ruby on Rails project. From ee983ffb49cb30000c7c5c95b58af805f8810d43 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Wed, 13 Nov 2024 11:35:36 +0100 Subject: [PATCH 101/157] linting --- Gemfile | 3 +- lib/datagrid/core.rb | 3 - lib/datagrid/filters/boolean_filter.rb | 3 +- lib/datagrid/filters/date_filter.rb | 8 +- lib/datagrid/filters/dynamic_filter.rb | 6 +- lib/datagrid/filters/enum_filter.rb | 2 +- lib/datagrid/filters/integer_filter.rb | 4 +- lib/datagrid/filters/ranged_filter.rb | 2 +- lib/datagrid/form_builder.rb | 8 +- lib/datagrid/generators/scaffold.rb | 260 +++++++++---------- lib/datagrid/generators/views.rb | 4 +- lib/datagrid/helper.rb | 13 +- lib/datagrid/renderer.rb | 7 +- lib/datagrid/utils.rb | 14 +- spec/datagrid/drivers/active_record_spec.rb | 2 +- spec/datagrid/filters/base_filter_spec.rb | 3 +- spec/datagrid/filters/boolean_filter_spec.rb | 4 +- spec/datagrid/filters/date_filter_spec.rb | 4 +- spec/datagrid/form_builder_spec.rb | 4 +- spec/datagrid/helper_spec.rb | 56 ++-- spec/spec_helper.rb | 2 +- version-2/find_broken_range_filters.rb | 2 + 22 files changed, 201 insertions(+), 213 deletions(-) diff --git a/Gemfile b/Gemfile index 55d01f1..cf4744e 100644 --- a/Gemfile +++ b/Gemfile @@ -14,13 +14,12 @@ group :development do gem "pry-byebug" gem "rails-dom-testing", "~> 2.2" gem "rspec" + gem "rubocop", "~> 1.68" gem "sequel" gem "sqlite3", "~> 1.7.0" - gem "rubocop", "~> 1.68" group :mongo do gem "bson" gem "mongoid", "~> 9.0" end end - diff --git a/lib/datagrid/core.rb b/lib/datagrid/core.rb index e11830a..8bc04d8 100644 --- a/lib/datagrid/core.rb +++ b/lib/datagrid/core.rb @@ -161,9 +161,6 @@ def attributes # grid.attributes = {first_name: 'John', last_name: 'Smith'} # grid.first_name # => 'John' # grid.last_name # => 'Smith' - def attributes=(value) - super - end # @return [Object] Any datagrid attribute value def [](attribute) diff --git a/lib/datagrid/filters/boolean_filter.rb b/lib/datagrid/filters/boolean_filter.rb index f6ff874..753f3da 100644 --- a/lib/datagrid/filters/boolean_filter.rb +++ b/lib/datagrid/filters/boolean_filter.rb @@ -5,10 +5,9 @@ module Datagrid module Filters class BooleanFilter < Datagrid::Filters::BaseFilter - # @!visibility private def initialize(grid, name, **opts) - super(grid, name, **opts) + super options[:default] ||= false end diff --git a/lib/datagrid/filters/date_filter.rb b/lib/datagrid/filters/date_filter.rb index f3eccd8..9793698 100644 --- a/lib/datagrid/filters/date_filter.rb +++ b/lib/datagrid/filters/date_filter.rb @@ -12,9 +12,7 @@ def default_input_options end def apply(grid_object, scope, value) - if value.is_a?(Range) - value = value.begin&.beginning_of_day..value.end&.end_of_day - end + value = value.begin&.beginning_of_day..value.end&.end_of_day if value.is_a?(Range) super end @@ -31,9 +29,7 @@ def format(value) end def default_filter_where(scope, value) - if driver.is_timestamp?(scope, name) - value = Datagrid::Utils.format_date_as_timestamp(value) - end + value = Datagrid::Utils.format_date_as_timestamp(value) if driver.is_timestamp?(scope, name) super end diff --git a/lib/datagrid/filters/dynamic_filter.rb b/lib/datagrid/filters/dynamic_filter.rb index b05721a..9926ff0 100644 --- a/lib/datagrid/filters/dynamic_filter.rb +++ b/lib/datagrid/filters/dynamic_filter.rb @@ -22,12 +22,12 @@ class DynamicFilter < Datagrid::Filters::BaseFilter def initialize(grid, name, **options, &block) options[:select] ||= default_select options[:operations] ||= DEFAULT_OPERATIONS - options[:include_blank] = false unless options.key?(:include_blank) - super(grid, name, **options, &block) + options[:include_blank] = false unless options.key?(:include_blank) + super end def default_input_options - {**super, type: nil} + { **super, type: nil } end def parse_values(filter) diff --git a/lib/datagrid/filters/enum_filter.rb b/lib/datagrid/filters/enum_filter.rb index ac21aac..ec154a8 100644 --- a/lib/datagrid/filters/enum_filter.rb +++ b/lib/datagrid/filters/enum_filter.rb @@ -10,7 +10,7 @@ class EnumFilter < Datagrid::Filters::BaseFilter # @!visibility private def initialize(grid, name, **options, &block) options[:multiple] = true if options[:checkboxes] - super(grid, name, **options, &block) + super raise Datagrid::ConfigurationError, ":select option not specified" unless options[:select] end diff --git a/lib/datagrid/filters/integer_filter.rb b/lib/datagrid/filters/integer_filter.rb index 4ebde9b..26146ff 100644 --- a/lib/datagrid/filters/integer_filter.rb +++ b/lib/datagrid/filters/integer_filter.rb @@ -19,9 +19,7 @@ def parse(value) end return value if value.is_a?(Range) - if value.to_i == 0 && value.is_a?(String) && value !~ %r{\A\s*-?0} - return nil - end + return nil if value.to_i.zero? && value.is_a?(String) && value !~ %r{\A\s*-?0} value.to_i end diff --git a/lib/datagrid/filters/ranged_filter.rb b/lib/datagrid/filters/ranged_filter.rb index a18cb18..421a13a 100644 --- a/lib/datagrid/filters/ranged_filter.rb +++ b/lib/datagrid/filters/ranged_filter.rb @@ -3,7 +3,7 @@ module Datagrid module Filters module RangedFilter - SERIALIZED_RANGE = %r{\A(.*)\.{2,3}(.*)\z}.freeze + SERIALIZED_RANGE = %r{\A(.*)\.{2,3}(.*)\z} def parse_values(value) return super unless range? diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index aec1cc0..b901822 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -7,9 +7,9 @@ module FormBuilder # @param filter_or_attribute [Datagrid::Filters::BaseFilter, String, Symbol] filter object or filter name # @param options [Hash] options of rails form input helper # @return [String] a form input html for the corresponding filter - def datagrid_filter(filter_or_attribute, **options, &block) + def datagrid_filter(filter_or_attribute, ...) filter = datagrid_get_filter(filter_or_attribute) - send(filter.form_builder_helper_name, filter, **options, &block) + send(filter.form_builder_helper_name, filter, ...) end # @param filter_or_attribute [Datagrid::Filters::BaseFilter, String, Symbol] filter object or filter name @@ -44,9 +44,7 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) text_area filter.name, value: object.filter_value_as_string(filter), **options, &block when :checkbox value = options.fetch(:value, 1).to_s - if filter.enum_checkboxes? && enum_checkbox_checked?(filter, value) - options = {checked: true, **options} - end + options = { checked: true, **options } if filter.enum_checkboxes? && enum_checkbox_checked?(filter, value) check_box filter.name, options, value when :hidden hidden_field filter.name, **options diff --git a/lib/datagrid/generators/scaffold.rb b/lib/datagrid/generators/scaffold.rb index 0956e46..172c8b5 100644 --- a/lib/datagrid/generators/scaffold.rb +++ b/lib/datagrid/generators/scaffold.rb @@ -6,168 +6,168 @@ module Datagrid # @!visibility private module Generators - # @!visibility private - class Scaffold < Rails::Generators::NamedBase - include Rails::Generators::ResourceHelpers - - check_class_collision suffix: "Grid" - source_root File.expand_path("#{__FILE__}/../../../templates") - - def create_scaffold - template "base.rb.erb", base_grid_file unless file_exists?(base_grid_file) - template "grid.rb.erb", "app/grids/#{grid_class_name.underscore}.rb" - if file_exists?(grid_controller_file) - inject_into_file grid_controller_file, index_action, after: %r{class .*#{grid_controller_class_name}.*\n} - else - create_file grid_controller_file, controller_code - end - create_file view_file, view_code - route(generate_routing_namespace("resources :#{grid_controller_short_name}")) - gem "kaminari" unless defined?(::Kaminari) || defined?(::WillPaginate) || defined?(::Pagy) - in_root do - { - "css" => " *= require datagrid", - "css.sass" => " *= require datagrid", - "css.scss" => " *= require datagrid", - }.each do |extension, string| - file = "app/assets/stylesheets/application.#{extension}" - if file_exists?(file) - inject_into_file file, "#{string}\n", { before: %r{.*require_self} } # before all + # @!visibility private + class Scaffold < Rails::Generators::NamedBase + include Rails::Generators::ResourceHelpers + + check_class_collision suffix: "Grid" + source_root File.expand_path("#{__FILE__}/../../../templates") + + def create_scaffold + template "base.rb.erb", base_grid_file unless file_exists?(base_grid_file) + template "grid.rb.erb", "app/grids/#{grid_class_name.underscore}.rb" + if file_exists?(grid_controller_file) + inject_into_file grid_controller_file, index_action, after: %r{class .*#{grid_controller_class_name}.*\n} + else + create_file grid_controller_file, controller_code + end + create_file view_file, view_code + route(generate_routing_namespace("resources :#{grid_controller_short_name}")) + gem "kaminari" unless defined?(::Kaminari) || defined?(::WillPaginate) || defined?(::Pagy) + in_root do + { + "css" => " *= require datagrid", + "css.sass" => " *= require datagrid", + "css.scss" => " *= require datagrid", + }.each do |extension, string| + file = "app/assets/stylesheets/application.#{extension}" + if file_exists?(file) + inject_into_file file, "#{string}\n", { before: %r{.*require_self} } # before all + end end end end - end - def view_file - Rails.root.join("app/views").join(controller_file_path).join("index.html.erb") - end + def view_file + Rails.root.join("app/views").join(controller_file_path).join("index.html.erb") + end - def grid_class_name - "#{file_name.camelize.pluralize}Grid" - end + def grid_class_name + "#{file_name.camelize.pluralize}Grid" + end - def grid_base_class - file_exists?("app/grids/base_grid.rb") ? "BaseGrid" : "ApplicationGrid" - end + def grid_base_class + file_exists?("app/grids/base_grid.rb") ? "BaseGrid" : "ApplicationGrid" + end - def grid_controller_class_name - "#{controller_class_name.camelize}Controller" - end + def grid_controller_class_name + "#{controller_class_name.camelize}Controller" + end - def grid_controller_file - Rails.root.join("app/controllers").join("#{grid_controller_class_name.underscore}.rb") - end + def grid_controller_file + Rails.root.join("app/controllers").join("#{grid_controller_class_name.underscore}.rb") + end - def grid_controller_short_name - controller_file_name - end + def grid_controller_short_name + controller_file_name + end - def grid_model_name - file_name.camelize.singularize - end + def grid_model_name + file_name.camelize.singularize + end - def grid_param_name - grid_class_name.underscore - end + def grid_param_name + grid_class_name.underscore + end - def pagination_helper_code - if defined?(::WillPaginate) - "will_paginate(@grid.assets)" - elsif defined?(::Pagy) - "pagy_nav(@pagy)" - else - # Kaminari is default - "paginate(@grid.assets)" + def pagination_helper_code + if defined?(::WillPaginate) + "will_paginate(@grid.assets)" + elsif defined?(::Pagy) + "pagy_nav(@pagy)" + else + # Kaminari is default + "paginate(@grid.assets)" + end end - end - def table_helper_code - if defined?(::Pagy) - "datagrid_table @grid, @records" - else - "datagrid_table @grid" + def table_helper_code + if defined?(::Pagy) + "datagrid_table @grid, @records" + else + "datagrid_table @grid" + end end - end - def base_grid_file - "app/grids/application_grid.rb" - end + def base_grid_file + "app/grids/application_grid.rb" + end - def grid_route_name - "#{controller_class_name.underscore.gsub('/', '_')}_path" - end + def grid_route_name + "#{controller_class_name.underscore.gsub('/', '_')}_path" + end - def index_code - if defined?(::Pagy) - <<-RUBY + def index_code + if defined?(::Pagy) + <<-RUBY @grid = #{grid_class_name}.new(grid_params) @pagy, @assets = pagy(@grid.assets) - RUBY - else - <<-RUBY + RUBY + else + <<-RUBY @grid = #{grid_class_name}.new(grid_params) do |scope| scope.page(params[:page]) end - RUBY + RUBY + end end - end - def controller_code - <<~RUBY - class #{grid_controller_class_name} < ApplicationController - def index - #{index_code.rstrip} - end + def controller_code + <<~RUBY + class #{grid_controller_class_name} < ApplicationController + def index + #{index_code.rstrip} + end - protected + protected - def grid_params - params.fetch(:#{grid_param_name}, {}).permit! + def grid_params + params.fetch(:#{grid_param_name}, {}).permit! + end end - end - RUBY - end + RUBY + end - def view_code - indent(<<~ERB) - <%= datagrid_form_with model: @grid, url: #{grid_route_name} %> + def view_code + indent(<<~ERB) + <%= datagrid_form_with model: @grid, url: #{grid_route_name} %> - <%= #{pagination_helper_code} %> - <%= #{table_helper_code} %> - <%= #{pagination_helper_code} %> - ERB - end + <%= #{pagination_helper_code} %> + <%= #{table_helper_code} %> + <%= #{pagination_helper_code} %> + ERB + end - protected - - def generate_routing_namespace(code) - depth = regular_class_path.length - # Create 'namespace' ladder - # namespace :foo do - # namespace :bar do - namespace_ladder = regular_class_path.each_with_index.map do |ns, i| - indent("namespace :#{ns} do\n", i * 2) - end.join - - # Create route - # get 'baz/index' - route = indent(code, depth * 2) - - # Create `end` ladder - # end - # end - end_ladder = (1..depth).reverse_each.map do |i| - indent("end\n", i * 2) - end.join - - # Combine the 3 parts to generate complete route entry - "#{namespace_ladder}#{route}\n#{end_ladder}" - end + protected + + def generate_routing_namespace(code) + depth = regular_class_path.length + # Create 'namespace' ladder + # namespace :foo do + # namespace :bar do + namespace_ladder = regular_class_path.each_with_index.map do |ns, i| + indent("namespace :#{ns} do\n", i * 2) + end.join + + # Create route + # get 'baz/index' + route = indent(code, depth * 2) + + # Create `end` ladder + # end + # end + end_ladder = (1..depth).reverse_each.map do |i| + indent("end\n", i * 2) + end.join + + # Combine the 3 parts to generate complete route entry + "#{namespace_ladder}#{route}\n#{end_ladder}" + end - def file_exists?(name) - name = Rails.root.join(name) unless name.to_s.first == "/" - File.exist?(name) + def file_exists?(name) + name = Rails.root.join(name) unless name.to_s.first == "/" + File.exist?(name) + end end end - end end diff --git a/lib/datagrid/generators/views.rb b/lib/datagrid/generators/views.rb index 0a85252..3f00a35 100644 --- a/lib/datagrid/generators/views.rb +++ b/lib/datagrid/generators/views.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Datagrid module Generators class Views < Rails::Generators::Base @@ -6,7 +8,7 @@ class Views < Rails::Generators::Base desc "Copies Datagrid partials to your application." def copy_views Dir.glob(File.join(self.class.source_root, "**", "*")).each do |file_path| - relative_path = file_path.sub(self.class.source_root + "/", "") + relative_path = file_path.sub("#{self.class.source_root}/", "") next if relative_path == "_order_for.html.erb" diff --git a/lib/datagrid/helper.rb b/lib/datagrid/helper.rb index dc5e157..f18b124 100644 --- a/lib/datagrid/helper.rb +++ b/lib/datagrid/helper.rb @@ -114,9 +114,8 @@ def datagrid_order_for(grid, column, options = {}) # @param grid [Datagrid] grid object # @return [String] form HTML tag markup def datagrid_form_with(**options) - if block_given? - raise ArgumentError, 'datagrid_form_with block argument is invalid. Use form_with instead.' - end + raise ArgumentError, "datagrid_form_with block argument is invalid. Use form_with instead." if block_given? + datagrid_renderer.form_with(**options) end @@ -155,8 +154,8 @@ def datagrid_form_for(grid, options = {}) # Last Name: <%= row.last_name %> # @example # <%= datagrid_row(grid, user, columns: [:first_name, :last_name, :actions]) %> - def datagrid_row(grid, asset, **options, &block) - datagrid_renderer.row(grid, asset, **options, &block) + def datagrid_row(grid, asset, ...) + datagrid_renderer.row(grid, asset, ...) end # Generates an ascending or descending order url for the given column @@ -176,8 +175,8 @@ def datagrid_renderer def datagrid_column_classes(grid, column) Datagrid::Utils.warn_once(<<~MSG) - datagrid_column_classes is deprecated. Assign necessary classes manually. - Correspond to default datagrid/rows partial for example.) + datagrid_column_classes is deprecated. Assign necessary classes manually. + Correspond to default datagrid/rows partial for example.) MSG column = grid.column_by_name(column) order_class = if grid.ordered_by?(column) diff --git a/lib/datagrid/renderer.rb b/lib/datagrid/renderer.rb index 8423cec..e2fbbc6 100644 --- a/lib/datagrid/renderer.rb +++ b/lib/datagrid/renderer.rb @@ -27,16 +27,15 @@ def form_for(grid, options = {}) method: :get, as: grid.param_name, local: true, - **options + **options, }, ) end def form_with(**options) grid = options[:model] - if grid&.filters&.empty? - raise ArgumentError, "Grid has no available filters" - end + raise ArgumentError, "Grid has no available filters" if grid&.filters&.empty? + _render_partial("form", options[:partials], { grid: options[:model], options: options }) end diff --git a/lib/datagrid/utils.rb b/lib/datagrid/utils.rb index 3d24995..f97707d 100644 --- a/lib/datagrid/utils.rb +++ b/lib/datagrid/utils.rb @@ -24,12 +24,14 @@ def translate_from_namespace(namespace, grid_class, key) end def deprecator - defined?(Rails) && Rails.version >= "7.1.0" ? - Rails.deprecator : ActiveSupport::Deprecation + if defined?(Rails) && Rails.version >= "7.1.0" + Rails.deprecator + else + ActiveSupport::Deprecation + end end def warn_once(message, delay = 5) - @warnings ||= {} timestamp = @warnings[message] return false if timestamp && timestamp >= Time.now - delay @@ -99,9 +101,7 @@ def parse_date(value) def parse_datetime(value) return nil if value.blank? return value if value.is_a?(Range) - if defined?(ActiveSupport::TimeWithZone) && value.is_a?(ActiveSupport::TimeWithZone) - return value - end + return value if defined?(ActiveSupport::TimeWithZone) && value.is_a?(ActiveSupport::TimeWithZone) if value.is_a?(String) Array(Datagrid.configuration.datetime_formats).each do |format| @@ -120,7 +120,7 @@ def parse_datetime(value) def format_date_as_timestamp(value) if !value value - # elsif value.is_a?(Array) + # elsif value.is_a?(Array) # value.first&.beginning_of_day..value.last&.end_of_day elsif value.is_a?(Range) value.begin&.beginning_of_day..value.end&.end_of_day diff --git a/spec/datagrid/drivers/active_record_spec.rb b/spec/datagrid/drivers/active_record_spec.rb index d99b77a..872cb49 100644 --- a/spec/datagrid/drivers/active_record_spec.rb +++ b/spec/datagrid/drivers/active_record_spec.rb @@ -43,7 +43,7 @@ scope { Entry } filter(:created_at, :date, range: true) do |value, scope, _grid| - scope.joins(:group).where(groups: {created_at: value}) + scope.joins(:group).where(groups: { created_at: value }) end end.assets end diff --git a/spec/datagrid/filters/base_filter_spec.rb b/spec/datagrid/filters/base_filter_spec.rb index 9a6340f..9f86ec2 100644 --- a/spec/datagrid/filters/base_filter_spec.rb +++ b/spec/datagrid/filters/base_filter_spec.rb @@ -17,12 +17,11 @@ def name_default end describe "#default_scope?" do - it "identifies filters without custom block" do grid = test_report do scope { Entry } filter(:id, :integer) - filter(:group_id, :integer) do |value, scope| + filter(:group_id, :integer) do |value, _scope| scope("group_id >= ?", value) end end diff --git a/spec/datagrid/filters/boolean_filter_spec.rb b/spec/datagrid/filters/boolean_filter_spec.rb index 96ed6cd..4b10491 100644 --- a/spec/datagrid/filters/boolean_filter_spec.rb +++ b/spec/datagrid/filters/boolean_filter_spec.rb @@ -1,4 +1,6 @@ -require 'spec_helper' +# frozen_string_literal: true + +require "spec_helper" describe Datagrid::Filters::BooleanFilter do it "applies default filtering" do diff --git a/spec/datagrid/filters/date_filter_spec.rb b/spec/datagrid/filters/date_filter_spec.rb index 288b1cd..d42646b 100644 --- a/spec/datagrid/filters/date_filter_spec.rb +++ b/spec/datagrid/filters/date_filter_spec.rb @@ -23,12 +23,12 @@ end it "raises when range assigned to non-range filter" do - expect { + expect do test_report(created_at: 5.day.ago..3.days.ago) do scope { Entry } filter(:created_at, :date) end - }.to raise_error(ArgumentError) + end.to raise_error(ArgumentError) end it "endless date range argument" do diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 6279457..98f16fa 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -132,8 +132,8 @@ class MyTemplate context "datetime filter type is text" do let(:_filter) { :created_at } let(:_grid) do - created_at = ActiveSupport::TimeZone['UTC'].local( - 2024, 1, 1, 9, 25, 15 + created_at = ActiveSupport::TimeZone["UTC"].local( + 2024, 1, 1, 9, 25, 15, ) test_report(created_at: created_at) do scope { Entry } diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 4a8ec28..822c60e 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -431,10 +431,10 @@ class OrderedGrid < Datagrid::Base object = OrderedGrid.new(descending: true, order: :category) silence_deprecator do expect(subject.datagrid_order_for(object, object.column_by_name(:category))).to equal_to_dom(<<~HTML) - <div class="order"> - <a class="asc" href="/location?ordered_grid%5Bdescending%5D=false&ordered_grid%5Border%5D=category">↑</a> - <a class="desc" href="/location?ordered_grid%5Bdescending%5D=true&ordered_grid%5Border%5D=category">↓</a> - </div> + <div class="order"> + <a class="asc" href="/location?ordered_grid%5Bdescending%5D=false&ordered_grid%5Border%5D=category">↑</a> + <a class="desc" href="/location?ordered_grid%5Bdescending%5D=true&ordered_grid%5Border%5D=category">↓</a> + </div> HTML end end @@ -461,16 +461,16 @@ class FormForGrid < Datagrid::Base end object = FormForGrid.new(category: "hello") expect(subject.datagrid_form_for(object, url: "/grid")).to equal_to_dom(<<~HTML) - <form class="datagrid-form" action="/grid" accept-charset="UTF-8" method="get"> - <div class="datagrid-filter" data-filter="category" data-type="string"> - <label for="form_for_grid_category">Category</label> - <input value="hello" type="text" name="form_for_grid[category]" id="form_for_grid_category" /> - </div> - <div class="datagrid-actions"> - <input type="submit" name="commit" value="Search" class="datagrid-submit" data-disable-with="Search" /> - <a class="datagrid-reset" href="/location">Reset</a> - </div> -</form> + <form class="datagrid-form" action="/grid" accept-charset="UTF-8" method="get"> + <div class="datagrid-filter" data-filter="category" data-type="string"> + <label for="form_for_grid_category">Category</label> + <input value="hello" type="text" name="form_for_grid[category]" id="form_for_grid_category" /> + </div> + <div class="datagrid-actions"> + <input type="submit" name="commit" value="Search" class="datagrid-submit" data-disable-with="Search" /> + <a class="datagrid-reset" href="/location">Reset</a> + </div> + </form> HTML end it "should support html classes for grid class with namespace" do @@ -517,7 +517,6 @@ def param_name end end - describe ".datagrid_form_with" do it "returns namespaced partial if partials options is passed" do rendered_form = subject.datagrid_form_with( @@ -534,16 +533,16 @@ class FormWithGrid < Datagrid::Base end object = FormWithGrid.new(category: "hello") expect(subject.datagrid_form_with(model: object, url: "/grid")).to equal_to_dom(<<~HTML) - <form class="datagrid-form" action="/grid" accept-charset="UTF-8" method="get"> - <div class="datagrid-filter" data-filter="category" data-type="string"> - <label for="form_with_grid_category">Category</label> - <input value="hello" type="text" name="form_with_grid[category]" id="form_with_grid_category" /> - </div> - <div class="datagrid-actions"> - <input type="submit" name="commit" value="Search" class="datagrid-submit" data-disable-with="Search" /> - <a class="datagrid-reset" href="/location">Reset</a> - </div> -</form> + <form class="datagrid-form" action="/grid" accept-charset="UTF-8" method="get"> + <div class="datagrid-filter" data-filter="category" data-type="string"> + <label for="form_with_grid_category">Category</label> + <input value="hello" type="text" name="form_with_grid[category]" id="form_with_grid_category" /> + </div> + <div class="datagrid-actions"> + <input type="submit" name="commit" value="Search" class="datagrid-submit" data-disable-with="Search" /> + <a class="datagrid-reset" href="/location">Reset</a> + </div> + </form> HTML end it "should support html classes for grid class with namespace" do @@ -591,7 +590,6 @@ def param_name end end - describe ".datagrid_row" do let(:grid) do test_report do @@ -734,14 +732,14 @@ def param_name grid = test_report(order: :name, descending: true) do scope { Entry } column(:name) - column(:group_id, class: 'short-column') + column(:group_id, class: "short-column") end silence_deprecator do expect(subject.send(:datagrid_column_classes, grid, :name)).to eq( - "name ordered desc" + "name ordered desc", ) expect(subject.send(:datagrid_column_classes, grid, :group_id)).to eq( - "group_id short-column" + "group_id short-column", ) end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 4735698..2322b78 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -108,4 +108,4 @@ def silence_deprecator(&block) # Requires supporting files with custom matchers and macros, etc, # in ./support/ and its subdirectories. -Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].sort.each { |f| require f } +Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } diff --git a/version-2/find_broken_range_filters.rb b/version-2/find_broken_range_filters.rb index 989643d..c53fff6 100644 --- a/version-2/find_broken_range_filters.rb +++ b/version-2/find_broken_range_filters.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Important in development to have all classes in memory Rails.application.eager_load! From 61b0b5082f5f82967558d56962ef99984a494ffb Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Wed, 13 Nov 2024 21:09:49 +0100 Subject: [PATCH 102/157] Fix w3 validator warning for label[for] not corresponding to any input[id] --- app/views/datagrid/_range_filter.html.erb | 4 +++- lib/datagrid/form_builder.rb | 11 --------- spec/datagrid/form_builder_spec.rb | 26 ++++++++++----------- version-2/Readme.markdown | 28 ++++++++++++++++++++++- 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/app/views/datagrid/_range_filter.html.erb b/app/views/datagrid/_range_filter.html.erb index 3b8ca85..b308d43 100644 --- a/app/views/datagrid/_range_filter.html.erb +++ b/app/views/datagrid/_range_filter.html.erb @@ -1,3 +1,5 @@ <%= form.datagrid_filter_input(filter, class: 'datagrid-range-from', **from_options) %> <span class="datagrid-range-separator"><%= I18n.t('datagrid.filters.range.separator') %></span> -<%= form.datagrid_filter_input(filter, class: 'datagrid-range-to', **to_options) %> +<%# Generating id only for "from" input to make sure + # there is no duplicate id in DOM and click on label focuses the first input -%> +<%= form.datagrid_filter_input(filter, class: 'datagrid-range-to', **to_options, id: nil) %> diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index b901822..49e1d90 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -190,17 +190,6 @@ def datagrid_range_filter_options(object, filter, type, **options) type_method_map = { from: :begin, to: :end } options[:value] = object[filter.name]&.public_send(type_method_map[type]) options[:name] = @template.field_name(object_name, filter.name, type) - # In case of datagrid ranged filter - # from and to input will have same id - if !options.key?(:id) - # Rails provides it's own default id for all inputs - # In order to prevent that we assign no id by default - options[:id] = nil - elsif options[:id].present? - # If the id was given we prefix it - # with from_ and to_ accordingly - options[:id] = [type, options[:id]].join("_") - end options end diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 98f16fa..89960be 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -189,10 +189,10 @@ class MyTemplate let(:_range) { [1, 2] } it { should equal_to_dom( - '<input value="1" id="from_hello" class="datagrid-range-from" + '<input value="1" id="hello" class="datagrid-range-from" type="number" step="1" name="report[group_id][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ - '<input value="2" id="to_hello" class="datagrid-range-to" + '<input value="2" class="datagrid-range-to" type="number" step="1" name="report[group_id][to]"/>', ) } @@ -201,7 +201,7 @@ class MyTemplate let(:_range) { [10, nil] } it { should equal_to_dom( - '<input value="10" class="datagrid-range-from" + '<input value="10" class="datagrid-range-from" id="report_group_id" type="number" step="1" name="report[group_id][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input class="datagrid-range-to" @@ -214,7 +214,7 @@ class MyTemplate let(:_range) { [nil, 10] } it { should equal_to_dom( - '<input class="datagrid-range-from" type="number" step="1" name="report[group_id][from]"/>' \ + '<input class="datagrid-range-from" type="number" step="1" name="report[group_id][from]" id="report_group_id"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="10" class="datagrid-range-to" type="number" step="1" name="report[group_id][to]"/>', ) @@ -226,7 +226,7 @@ class MyTemplate let(:_range) { 2..1 } it { should equal_to_dom( - '<input value="1" class="datagrid-range-from" type="number" step="1" name="report[group_id][from]"/>' \ + '<input value="1" class="datagrid-range-from" type="number" step="1" name="report[group_id][from]" id="report_group_id"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2" class="datagrid-range-to" type="number" step="1" name="report[group_id][to]"/>', ) @@ -248,7 +248,7 @@ class MyTemplate let(:_range) { nil } it { should equal_to_dom( - '<input class="datagrid-range-from" type="number" step="1" name="report[group_id][from]"> + '<input class="datagrid-range-from" type="number" step="1" name="report[group_id][from]" id="report_group_id"> <span class="datagrid-range-separator"> - </span> <input class="datagrid-range-to" type="number" step="1" name="report[group_id][to]">', ) @@ -267,7 +267,7 @@ class MyTemplate let(:_range) { [1.5, 2.5] } it { should equal_to_dom( - '<input value="1.5" class="datagrid-range-from" + '<input value="1.5" class="datagrid-range-from" id="report_rating" type="number" step="any" name="report[rating][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2.5" class="datagrid-range-to" @@ -288,7 +288,7 @@ class MyTemplate let(:_range) { ["2012-01-03", nil] } it { should equal_to_dom( - '<input value="2012-01-03" class="datagrid-range-from" type="date" name="report[created_at][from]"/>' \ + '<input value="2012-01-03" class="datagrid-range-from" type="date" name="report[created_at][from]" id="report_created_at"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input class="datagrid-range-to" type="date" name="report[created_at][to]" value=""/>', ) @@ -304,7 +304,7 @@ class MyTemplate let(:_range) { ["2013/01/01", "2013/02/02"] } it { should equal_to_dom( - '<input value="2013-01-01" class="datagrid-range-from" + '<input value="2013-01-01" class="datagrid-range-from" id="report_created_at" type="date" name="report[created_at][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2013-02-02" class="datagrid-range-to" @@ -316,11 +316,11 @@ class MyTemplate let(:_range) { [nil, "2012-01-03"] } it { should equal_to_dom( - '<input class="datagrid-range-from" + '<input class="datagrid-range-from" id="report_created_at" type="date" value="" name="report[created_at][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2012-01-03" class="datagrid-range-to" - type="date" name="report[created_at][to]"/>', + type="date" name="report[created_at][to]"/>', ) } it { should be_html_safe } @@ -330,7 +330,7 @@ class MyTemplate let(:_range) { Date.parse("2012-01-02")..Date.parse("2012-01-01") } it { should equal_to_dom( - '<input value="2012-01-01" class="datagrid-range-from" + '<input value="2012-01-01" class="datagrid-range-from" id="report_created_at" type="date" name="report[created_at][from]"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input value="2012-01-02" class="datagrid-range-to" @@ -347,7 +347,7 @@ class MyTemplate let(:_range) { [nil, nil] } it { should equal_to_dom( - '<input class="datagrid-range-from" type="date" value="" name="report[created_at][from]"/>' \ + '<input class="datagrid-range-from" type="date" value="" name="report[created_at][from]" id="report_created_at"/>' \ '<span class="datagrid-range-separator"> - </span>' \ '<input class="datagrid-range-to" type="date" value="" name="report[created_at][to]"/>', ) diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index 2538e17..68772e1 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -18,6 +18,7 @@ List of things introduces: 1. Native Rails Engines. * while supported, the library was not initially designed for it. 1. HTML5 data attributes +1. Consistent id attribute for range filter inputs 1. Inherit `Datagrid::Base` instead of `include Datagrid` 1. `ApplicationGrid` is recommended base class instead of `BaseGrid` 1. Introduced `datagrid.filters.range.separator` localization @@ -373,6 +374,31 @@ Renders: [Modify built-in partials](https://github.com/bogdan/datagrid/wiki/Frontend#modifying-built-in-partials) if you want to change this behavior completely. +## id attribute for range filter inputs + +[W3 validator](https://validator.w3.org/) complains when +a `label[for]` attribute doesn't correspond to any `input[id]` in the same form. +Version 1 generated no id attribute for range filter inputs by default which resulted in a warning: + +``` html +<label for="musics_grid_year">Year</label> +<input class="year integer_fiilter from" multiple name="musics_grid[year][]" type="text"> +<span class="separator integer"> - </span> +<input class="year integer_filter to" multiple name="musics_grid[year][]" type="text"> +``` + +Version 2 generates id attribute only for the first input, so that a click on label focuses the first input: + +``` html +<label for="musics_grid_year">Year</label> +<input id="musics_grid_year" step="1" class="datagrid-range-from" name="musics_grid[year][from]" type="number"> +<span class="datagrid-range-separator"> - </span> +<input step="1" class="datagrid-range-to" name="musics_grid[year][to]" type="number"> +``` + +The behavior can be changed by modifying +[built-in view](https://github.com/bogdan/datagrid/blob/version-2/app/views/datagrid/_range_filter.html.erb#L3). + ## ApplicationGrid base class Previously recommended base class `BaseGrid` is incosistent @@ -404,7 +430,7 @@ end A separator symbol between range filter inputs is now a part of localizations to avoid hardcore. Add `datagrid.filters.range.separator` to your localization file. -[See commit for details](https://github.com/bogdan/datagrid/commit/2bd914a39a5f8367758ad697d7ccf8d98379fff7#diff-0e78e11f3e693a6523052bc71095ec539fa390cf04b50d74c35c9af5260f50f3L2) +[See related view](https://github.com/bogdan/datagrid/blob/version-2/app/views/datagrid/_range_filter.html.erb#L2) ## Remove SASS dependency From 05cf3dec447ab23de1228ca8a9ab4a8a55573334 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Wed, 13 Nov 2024 21:27:27 +0100 Subject: [PATCH 103/157] Change error type --- lib/datagrid/form_builder.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 49e1d90..09c8b6a 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -205,7 +205,7 @@ def datagrid_get_filter(attribute_or_filter) return attribute_or_filter unless Utils.string_like?(attribute_or_filter) object.class.filter_by_name(attribute_or_filter) || - raise(Error, "Datagrid filter #{attribute_or_filter} not found") + raise(ArgumentError, "Datagrid filter #{attribute_or_filter} not found") end def add_html_classes(options, *classes) @@ -228,8 +228,5 @@ def render_partial(name, locals) def add_filter_options(filter, **options) { **filter.default_input_options, **filter.input_options, **options } end - - class Error < StandardError - end end end From ff1924df9efc532a2311d3c3e3f469b37363c80b Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Wed, 13 Nov 2024 21:28:05 +0100 Subject: [PATCH 104/157] cleanup --- lib/datagrid/form_builder.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 09c8b6a..f603023 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -28,9 +28,9 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) options = add_filter_options(filter, **options) type = options.delete(:type)&.to_sym if %i[datetime-local date].include?(type) - if options.key?(:value) && options[:value].nil? && + if options.key?(:value) && options[:value].nil? # https://github.com/rails/rails/pull/53387 - (options[:value] = "") + options[:value] = "" end elsif options[:value] options[:value] = filter.format(options[:value]) From b4878f17c1c34edf4f9fcefaad818921ae46730b Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Thu, 14 Nov 2024 09:57:36 +0100 Subject: [PATCH 105/157] Cleanup --- lib/datagrid/form_builder.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 12be3fa..5788744 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -75,11 +75,11 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) protected def datagrid_extended_boolean_filter(filter, options = {}, &block) - datagrid_filter_input(filter, **options, type: :select, &block) + datagrid_filter_input(filter, **options, &block) end def datagrid_boolean_filter(filter, options = {}) - datagrid_filter_input(filter.name, **options, type: :checkbox) + datagrid_filter_input(filter.name, **options) end def datagrid_date_filter(filter, options = {}) @@ -111,7 +111,7 @@ def datagrid_enum_filter(filter, options = {}, &block) }, ) else - datagrid_filter_input(filter, **options, type: :select, &block) + datagrid_filter_input(filter, **options, &block) end end @@ -190,10 +190,10 @@ def datagrid_range_filter(_type, filter, options = {}) end end - def datagrid_range_filter_options(object, filter, type, **options) + def datagrid_range_filter_options(object, filter, section, **options) type_method_map = { from: :begin, to: :end } - options[:value] = object[filter.name]&.public_send(type_method_map[type]) - options[:name] = @template.field_name(object_name, filter.name, type) + options[:value] = object[filter.name]&.public_send(type_method_map[section]) + options[:name] = @template.field_name(object_name, filter.name, section) options end From c133d7e83ad3ae842eaf504ce4f9782a9a6bd024 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Thu, 14 Nov 2024 10:05:49 +0100 Subject: [PATCH 106/157] Cleanup --- lib/datagrid/filters/base_filter.rb | 4 ++ lib/datagrid/form_builder.rb | 93 ++++++++++------------------- 2 files changed, 34 insertions(+), 63 deletions(-) diff --git a/lib/datagrid/filters/base_filter.rb b/lib/datagrid/filters/base_filter.rb index cb2ec9a..01c7663 100644 --- a/lib/datagrid/filters/base_filter.rb +++ b/lib/datagrid/filters/base_filter.rb @@ -98,6 +98,10 @@ def multiple? options[:multiple] end + def range? + false + end + def allow_nil? options.key?(:allow_nil) ? options[:allow_nil] : options[:allow_blank] end diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 5788744..9ab6279 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -7,9 +7,17 @@ module FormBuilder # @param filter_or_attribute [Datagrid::Filters::BaseFilter, String, Symbol] filter object or filter name # @param options [Hash] options of rails form input helper # @return [String] a form input html for the corresponding filter - def datagrid_filter(filter_or_attribute, ...) + def datagrid_filter(filter_or_attribute, **options, &block) filter = datagrid_get_filter(filter_or_attribute) - send(filter.form_builder_helper_name, filter, ...) + if filter.range? + datagrid_range_filter(filter, options, &block) + elsif filter.enum_checkboxes? + datagrid_enum_checkboxes_filter(filter, options, &block) + elsif filter.type == :dynamic + datagrid_dynamic_filter(filter, options, &block) + else + datagrid_filter_input(filter, **options, &block) + end end # @param filter_or_attribute [Datagrid::Filters::BaseFilter, String, Symbol] filter object or filter name @@ -74,45 +82,21 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) protected - def datagrid_extended_boolean_filter(filter, options = {}, &block) - datagrid_filter_input(filter, **options, &block) - end - - def datagrid_boolean_filter(filter, options = {}) - datagrid_filter_input(filter.name, **options) - end - - def datagrid_date_filter(filter, options = {}) - datagrid_range_filter(:date, filter, options) - end - - def datagrid_date_time_filter(filter, options = {}) - datagrid_range_filter(:datetime, filter, options) - end - - def datagrid_default_filter(filter, options = {}) - datagrid_filter_input(filter, **options) - end - - def datagrid_enum_filter(filter, options = {}, &block) - if filter.enum_checkboxes? - elements = object.select_options(filter).map do |element| - text, value = @template.send(:option_text_and_value, element) - checked = enum_checkbox_checked?(filter, value) - [value, text, checked] - end - render_partial( - "enum_checkboxes", - { - elements: elements, - form: self, - filter: filter, - options: options, - }, - ) - else - datagrid_filter_input(filter, **options, &block) + def datagrid_enum_checkboxes_filter(filter, options = {}, &block) + elements = object.select_options(filter).map do |element| + text, value = @template.send(:option_text_and_value, element) + checked = enum_checkbox_checked?(filter, value) + [value, text, checked] end + render_partial( + "enum_checkboxes", + { + elements: elements, + form: self, + filter: filter, + options: options, + }, + ) end def enum_checkbox_checked?(filter, option_value) @@ -126,11 +110,6 @@ def enum_checkbox_checked?(filter, option_value) end end - def datagrid_integer_filter(filter, options = {}) - options[:value] = "" if filter.multiple? && object[filter.name].blank? - datagrid_range_filter(:integer, filter, options) - end - def datagrid_dynamic_filter(filter, options = {}) field, operation, value = object.filter_value(filter) options = add_filter_options(filter, **options) @@ -178,16 +157,12 @@ def dynamic_filter_select(name, variants, select_options, html_options) end end - def datagrid_range_filter(_type, filter, options = {}) - if filter.range? - from_options = datagrid_range_filter_options(object, filter, :from, **options) - to_options = datagrid_range_filter_options(object, filter, :to, **options) - render_partial "range_filter", { - from_options: from_options, to_options: to_options, filter: filter, form: self, - } - else - datagrid_filter_input(filter, **options) - end + def datagrid_range_filter(filter, options = {}) + from_options = datagrid_range_filter_options(object, filter, :from, **options) + to_options = datagrid_range_filter_options(object, filter, :to, **options) + render_partial "range_filter", { + from_options: from_options, to_options: to_options, filter: filter, form: self, + } end def datagrid_range_filter_options(object, filter, section, **options) @@ -197,14 +172,6 @@ def datagrid_range_filter_options(object, filter, section, **options) options end - def datagrid_string_filter(filter, options = {}) - datagrid_range_filter(:string, filter, options) - end - - def datagrid_float_filter(filter, options = {}) - datagrid_range_filter(:float, filter, options) - end - def datagrid_get_filter(attribute_or_filter) return attribute_or_filter unless Utils.string_like?(attribute_or_filter) From f5e082ab75a10ef69b0db44b09c04dadd3b2655b Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Thu, 14 Nov 2024 10:11:41 +0100 Subject: [PATCH 107/157] Linting --- lib/datagrid/drivers/array.rb | 2 +- lib/datagrid/form_builder.rb | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/datagrid/drivers/array.rb b/lib/datagrid/drivers/array.rb index 32007cd..5a47d8c 100644 --- a/lib/datagrid/drivers/array.rb +++ b/lib/datagrid/drivers/array.rb @@ -58,7 +58,7 @@ def scope_has_column?(scope, column_name) scope.any? && scope.first.respond_to?(column_name) end - def is_timestamp?(scope, column_name) + def timestamp_column?(scope, column_name) scope_has_column?(scope, column_name) && timestamp_class?(get(scope.first, column_name).class) end diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 9ab6279..6f497b5 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -41,8 +41,8 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) type = options.delete(:type)&.to_sym if %i[datetime-local date].include?(type) if options.key?(:value) && options[:value].nil? - # https://github.com/rails/rails/pull/53387 - options[:value] = "" + # https://github.com/rails/rails/pull/53387 + options[:value] = "" end elsif options[:value] options[:value] = filter.format(options[:value]) @@ -82,7 +82,7 @@ def datagrid_filter_input(attribute_or_filter, **options, &block) protected - def datagrid_enum_checkboxes_filter(filter, options = {}, &block) + def datagrid_enum_checkboxes_filter(filter, options = {}) elements = object.select_options(filter).map do |element| text, value = @template.send(:option_text_and_value, element) checked = enum_checkbox_checked?(filter, value) From e12826bb59e5fa388adc370d6a0c96f5437e02de Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Thu, 14 Nov 2024 10:26:28 +0100 Subject: [PATCH 108/157] Mention the removal of grid class from table[class] --- version-2/Readme.markdown | 68 +++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index 68772e1..506dd92 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -294,8 +294,18 @@ will always generate from/to inputs instead: It is more semantic and collision proof to use `data-*` attributes instead of classes for meta information from backend. Therefor built-in partials now generate data attributes by default -instead of classes for column names: +instead of classes for column names. +* Filter name `input[class]` implemented as `.datagrid-filter[data-filter]`. +* Filter type `input[class]` implemented as `.datagrid-filter[data-type]`. +* Grid class `table[class]` removed due to: + * security concerns from some users + * breaking CSS classes naming convention +* Column name `th[class], td[class]` implemented as `td[data-column], th[data-column]`. + +Note that the behavior change can be reverted by +[updating built-in partials](https://github.com/bogdan/datagrid/wiki/Frontend#modifying-built-in-partials). +Version 2 makes it as easy as possible to override the defaults of the UI. ### Filters @@ -319,42 +329,46 @@ Version 2: </div> ``` -Diff for [built-in partials between V1 and V2](./views.diff) +Diff for [built-in views between V1 and V2](./views.diff) ### Columns Version 1: ``` html -<tr> - <th class="name">Name</th> - <th class="category">Category</th> -</tr> -<tr> - <td class="name">John</th> - <td class="category">Worker</th> -</tr> -<tr> - <td class="name">Mike</th> - <td class="category">Manager</th> -</tr> +<table class="datagrid users_grid"> + <tr> + <th class="name">Name</th> + <th class="category">Category</th> + </tr> + <tr> + <td class="name">John</th> + <td class="category">Worker</th> + </tr> + <tr> + <td class="name">Mike</th> + <td class="category">Manager</th> + </tr> +</table> ``` Version 2: ``` html -<tr> - <th data-column="name">Name</th> - <th data-column="category">Category</th> -</tr> -<tr> - <td data-column="name">John</th> - <td data-column="category">Worker</th> -</tr> -<tr> - <td data-column="name">Mike</th> - <td data-column="category">Manager</th> -</tr> +<table class="datagrid-table"> + <tr> + <th data-column="name">Name</th> + <th data-column="category">Category</th> + </tr> + <tr> + <td data-column="name">John</th> + <td data-column="category">Worker</th> + </tr> + <tr> + <td data-column="name">Mike</th> + <td data-column="category">Manager</th> + </tr> +</table> ``` If you still want to have an HTML class attached to a column use `class` column option: @@ -371,7 +385,7 @@ Renders: <td class="short-column" data-column="name">John</td> ``` -[Modify built-in partials](https://github.com/bogdan/datagrid/wiki/Frontend#modifying-built-in-partials) +[Modify built-in views](https://github.com/bogdan/datagrid/wiki/Frontend#modifying-built-in-partials) if you want to change this behavior completely. ## id attribute for range filter inputs From b7756755ed0d1eb8f96cfbe99aa18a5955424258 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Thu, 14 Nov 2024 11:05:01 +0100 Subject: [PATCH 109/157] column[url] option removal guide --- version-2/Readme.markdown | 42 +++++++++++++++++++++---- version-2/find_deprecated_url_option.rb | 19 +++++++++++ 2 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 version-2/find_deprecated_url_option.rb diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index 506dd92..6f22c0e 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -9,22 +9,52 @@ Version 2 addresses all that evolution. List of things introduces: +## API changes + +1. Ruby endless ranges for range filters. +1. Use Hash instead of Array for multiparameter attributes. +1. Remove `column[url]` option. +1. Inherit `Datagrid::Base` instead of `include Datagrid`. +1. `ApplicationGrid` is recommended base class instead of `BaseGrid`. + +## Frontend Changes + 1. Use `form_with` instead of `form_for`. 1. Deprecated `datagrid_order_for` -1. Ruby endless ranges for range filters. 1. Modern modular CSS classes. 1. HTML5 input types: number, date, datetime-local. -1. Use Hash instead of Array for multiparameter attirubtes. -1. Native Rails Engines. +1. Native Rails Engines: * while supported, the library was not initially designed for it. 1. HTML5 data attributes -1. Consistent id attribute for range filter inputs -1. Inherit `Datagrid::Base` instead of `include Datagrid` -1. `ApplicationGrid` is recommended base class instead of `BaseGrid` +1. Consistent `label[for]` and `input[id]` for range filters. 1. Introduced `datagrid.filters.range.separator` localization 1. Remove SASS dependency 1. Replace `rake datagrid:copy_partials` with `rails g datagrid:views` +## Remove column[url] option + +`column[url]` option was introduced before flexible data/html output layer for columns was established. Here is how the deprecated option can be migrated to modern setup: + +Version 1: + +``` ruby +column(:user, url: -> (user) => { user_profile_path(user) }) do + user.name +end +``` + +Version 2: + +``` ruby +column(:user) do |user| + format(user.name) do |value| + link_to value, user_profile_path(user) + end +end +``` + +All deprecated columns can be found [with a script](./find_deprecated_url_option.rb) + ## Use form\_with Rails [deprecates form\_for in favor of form\_with](https://guides.rubyonrails.org/form_helpers.html#using-form-tag-and-form-for). diff --git a/version-2/find_deprecated_url_option.rb b/version-2/find_deprecated_url_option.rb new file mode 100644 index 0000000..fbb5f19 --- /dev/null +++ b/version-2/find_deprecated_url_option.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +# Important in development to have all classes in memory +Rails.application.eager_load! + +included_classes = ObjectSpace.each_object(Class).select do |klass| + klass.included_modules.include?(Datagrid) +end + +base_subclasses = ObjectSpace.each_object(Class).select do |klass| + klass < Datagrid::Base +end +classes = [*included_classes, *base_subclasses].uniq + +classes.flat_map(&:columns).select do |f| + f.options[:url] +end.map do |f| + [f.grid_class, f.name].join("#") +end From c153d67b41fbf0f4a38b54360f9f493c0a55a92e Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Thu, 14 Nov 2024 11:14:40 +0100 Subject: [PATCH 110/157] column[url] removal guide --- version-2/Readme.markdown | 16 ++++++++++++++-- version-2/deprecations.sh | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index 6f22c0e..5154ba4 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -60,7 +60,6 @@ All deprecated columns can be found [with a script](./find_deprecated_url_option Rails [deprecates form\_for in favor of form\_with](https://guides.rubyonrails.org/form_helpers.html#using-form-tag-and-form-for). `datagrid_form_for` is now deprecated if favor of `datagrid_form_with`. -However, `datagrid_form_for` would also use Rails `form_with` because they share the same view partial. TODO: update the wiki @@ -71,7 +70,8 @@ datagrid_form_for(@users_grid, url: users_path) datagrid_form_with(model: @users_grid, url: users_path) ``` -Built-in partial uses `form_with` no matter +Version 2 built-in view `datagrid/form` uses `form_with` no matter of the with helper is used. +Beware of that. [Grep all deprecations](./deprecations.sh). @@ -79,6 +79,18 @@ Built-in partial uses `form_with` no matter `datagrid_order_for` helper serves no purpose and should not be used directly. The recommended way is to include your ordering code directly into `datagrid/head` partial. +You implement `datagrid_order_for` in `ApplicationHelper` +and copy [datagrid/order\_for](../app/views/datagrid/_order_for.html.erb) into your project +if you consider it useful: + +``` ruby +module ApplicationHelper + def datagrid_order_for(grid, column) + render(partial: "datagrid/order_for", locals: { grid: grid, column: column }) + end +end +``` + See default [head partial](../app/views/datagrid/_head.html.erb) for example. [Grep all deprecations](./deprecations.sh). diff --git a/version-2/deprecations.sh b/version-2/deprecations.sh index 01a4341..3460343 100644 --- a/version-2/deprecations.sh +++ b/version-2/deprecations.sh @@ -5,6 +5,7 @@ git grep 'datagrid_form_for' git grep 'datagrid_order_for' # Put necessary classes manually +# or copy the helper from datagrid source code to ApplicationHelper git grep 'datagrid_column_classes' # Inherit Datagrid::Base From 5a0d9665bbf7bf7b810cc691ee9146c3982744b2 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Thu, 14 Nov 2024 11:15:29 +0100 Subject: [PATCH 111/157] Cleanup --- app/views/datagrid/_range_filter.html.erb | 5 ++--- lib/datagrid/filters/date_filter.rb | 9 +++------ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/app/views/datagrid/_range_filter.html.erb b/app/views/datagrid/_range_filter.html.erb index b308d43..ffbb0f8 100644 --- a/app/views/datagrid/_range_filter.html.erb +++ b/app/views/datagrid/_range_filter.html.erb @@ -1,5 +1,4 @@ <%= form.datagrid_filter_input(filter, class: 'datagrid-range-from', **from_options) %> <span class="datagrid-range-separator"><%= I18n.t('datagrid.filters.range.separator') %></span> -<%# Generating id only for "from" input to make sure - # there is no duplicate id in DOM and click on label focuses the first input -%> -<%= form.datagrid_filter_input(filter, class: 'datagrid-range-to', **to_options, id: nil) %> +<%# Generating id only for "from" input to make sure -%> +<%# there is no duplicate id in DOM and click on label focuses the first input -%> <%= form.datagrid_filter_input(filter, class: 'datagrid-range-to', **to_options, id: nil) %> diff --git a/lib/datagrid/filters/date_filter.rb b/lib/datagrid/filters/date_filter.rb index c219276..e8398f4 100644 --- a/lib/datagrid/filters/date_filter.rb +++ b/lib/datagrid/filters/date_filter.rb @@ -12,7 +12,9 @@ def default_input_options end def apply(grid_object, scope, value) - value = value.begin&.beginning_of_day..value.end&.end_of_day if value.is_a?(Range) + if value.is_a?(Range) && driver.timestamp_column?(scope, name) + value = value.begin&.beginning_of_day..value.end&.end_of_day + end super end @@ -28,11 +30,6 @@ def format(value) end end - def default_filter_where(scope, value) - value = Datagrid::Utils.format_date_as_timestamp(value) if driver.timestamp_column?(scope, name) - super - end - protected def formats From d7f75ba40db3034bf16736fab8dc40a0638bab9b Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Thu, 14 Nov 2024 11:19:44 +0100 Subject: [PATCH 112/157] Cleanup --- app/views/datagrid/_range_filter.html.erb | 3 ++- lib/datagrid/utils.rb | 2 -- version-2/views.diff | 7 ++++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/views/datagrid/_range_filter.html.erb b/app/views/datagrid/_range_filter.html.erb index ffbb0f8..21d1f0e 100644 --- a/app/views/datagrid/_range_filter.html.erb +++ b/app/views/datagrid/_range_filter.html.erb @@ -1,4 +1,5 @@ <%= form.datagrid_filter_input(filter, class: 'datagrid-range-from', **from_options) %> <span class="datagrid-range-separator"><%= I18n.t('datagrid.filters.range.separator') %></span> <%# Generating id only for "from" input to make sure -%> -<%# there is no duplicate id in DOM and click on label focuses the first input -%> <%= form.datagrid_filter_input(filter, class: 'datagrid-range-to', **to_options, id: nil) %> +<%# there is no duplicate id in DOM and click on label focuses the first input -%> +<%= form.datagrid_filter_input(filter, class: 'datagrid-range-to', **to_options, id: nil) %> diff --git a/lib/datagrid/utils.rb b/lib/datagrid/utils.rb index f0c5d26..c7ea68d 100644 --- a/lib/datagrid/utils.rb +++ b/lib/datagrid/utils.rb @@ -121,8 +121,6 @@ def parse_datetime(value) def format_date_as_timestamp(value) if !value value - # elsif value.is_a?(Array) - # value.first&.beginning_of_day..value.last&.end_of_day elsif value.is_a?(Range) value.begin&.beginning_of_day..value.end&.end_of_day else diff --git a/version-2/views.diff b/version-2/views.diff index f971d0e..61c42fa 100644 --- a/version-2/views.diff +++ b/version-2/views.diff @@ -78,16 +78,17 @@ index e939128..b355528 100644 <% end %> </tr> diff --git a/app/views/datagrid/_range_filter.html.erb b/app/views/datagrid/_range_filter.html.erb -index 7a8a123..3b8ca85 100644 +index 7a8a123..ffbb0f8 100644 --- a/app/views/datagrid/_range_filter.html.erb +++ b/app/views/datagrid/_range_filter.html.erb -@@ -1,3 +1,3 @@ +@@ -1,3 +1,4 @@ -<%= form.datagrid_filter_input(filter, **from_options) %> -<span class="separator <%= filter.type %>"><%= I18n.t('datagrid.filters.range.separator') %></span> -<%= form.datagrid_filter_input(filter, **to_options) %> +<%= form.datagrid_filter_input(filter, class: 'datagrid-range-from', **from_options) %> +<span class="datagrid-range-separator"><%= I18n.t('datagrid.filters.range.separator') %></span> -+<%= form.datagrid_filter_input(filter, class: 'datagrid-range-to', **to_options) %> ++<%# Generating id only for "from" input to make sure -%> ++<%# there is no duplicate id in DOM and click on label focuses the first input -%> <%= form.datagrid_filter_input(filter, class: 'datagrid-range-to', **to_options, id: nil) %> diff --git a/app/views/datagrid/_row.html.erb b/app/views/datagrid/_row.html.erb index f54d21c..340aea6 100644 --- a/app/views/datagrid/_row.html.erb From a80b0bcd463224d54d52a46970698226951e5762 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Thu, 14 Nov 2024 17:23:02 +0100 Subject: [PATCH 113/157] Fix regression bug --- lib/datagrid/filters/date_filter.rb | 2 +- spec/datagrid/filters/date_filter_spec.rb | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/datagrid/filters/date_filter.rb b/lib/datagrid/filters/date_filter.rb index 3557214..cf3b7a5 100644 --- a/lib/datagrid/filters/date_filter.rb +++ b/lib/datagrid/filters/date_filter.rb @@ -12,7 +12,7 @@ def default_input_options end def apply(grid_object, scope, value) - if driver.timestamp_column?(scope, name) + if grid_object.driver.timestamp_column?(scope, name) value = Datagrid::Utils.format_date_as_timestamp(value) end super diff --git a/spec/datagrid/filters/date_filter_spec.rb b/spec/datagrid/filters/date_filter_spec.rb index 9941b5f..01f8cdf 100644 --- a/spec/datagrid/filters/date_filter_spec.rb +++ b/spec/datagrid/filters/date_filter_spec.rb @@ -267,4 +267,19 @@ def entry_dated(date) expect(report.assets).to include(e4) expect(report.assets).to_not include(e5) end + + + it "allows filter to be defined before scope" do + class ParentGrid < Datagrid::Base + filter(:created_at, :date, range: true) + end + + class ChildGrid < ParentGrid + scope do + Entry + end + end + + expect(ChildGrid.new.assets).to eq([]) + end end From 481e3f566d364a433676f528b24bc0020a554435 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Thu, 14 Nov 2024 21:44:26 +0100 Subject: [PATCH 114/157] Disable default label[for] for enum checkboxes --- lib/datagrid/filters/enum_filter.rb | 11 +++++++++++ spec/datagrid/form_builder_spec.rb | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/lib/datagrid/filters/enum_filter.rb b/lib/datagrid/filters/enum_filter.rb index ec154a8..75ea00a 100644 --- a/lib/datagrid/filters/enum_filter.rb +++ b/lib/datagrid/filters/enum_filter.rb @@ -29,6 +29,17 @@ def default_input_options } end + def label_options + if enum_checkboxes? + # Each checkbox has its own label + # The main label has no specific input to focus + # See app/views/datagrid/_enum_checkboxes.html.erb + {for: nil, **super} + else + super + end + end + def strict options[:strict] end diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 89960be..04bbe6b 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -466,6 +466,10 @@ class MyTemplate ) } + it "disables label[for] attribute" do + expect(view.datagrid_label(_filter)).to eq("<label>Category</label>") + end + context "when partials option passed and partial exists" do let(:view_options) { { partials: "custom_checkboxes" } } it { should equal_to_dom("custom_enum_checkboxes") } From bad591423268a0fcb0f7416dd5cec18cfa4eaa42 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 15 Nov 2024 09:49:41 +0100 Subject: [PATCH 115/157] Fix assignment hash value with string keys to range filter --- lib/datagrid/filters/ranged_filter.rb | 2 +- spec/datagrid/filters/date_filter_spec.rb | 8 ++++++++ version-2/Readme.markdown | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/datagrid/filters/ranged_filter.rb b/lib/datagrid/filters/ranged_filter.rb index 421a13a..5b3fac0 100644 --- a/lib/datagrid/filters/ranged_filter.rb +++ b/lib/datagrid/filters/ranged_filter.rb @@ -46,7 +46,7 @@ def default_filter_where(scope, value) protected def parse_hash(result) - to_range(result[:from], result[:to]) + to_range(result[:from] || result["from"], result[:to] || result["to"]) end def to_range(from, to, exclusive = false) diff --git a/spec/datagrid/filters/date_filter_spec.rb b/spec/datagrid/filters/date_filter_spec.rb index 01f8cdf..60f2d9c 100644 --- a/spec/datagrid/filters/date_filter_spec.rb +++ b/spec/datagrid/filters/date_filter_spec.rb @@ -54,14 +54,22 @@ to = 3.days.ago report.created_at = { from: from, to: to } expect(report.created_at).to eq(from.to_date..to.to_date) + + report.created_at = { "from" => from, "to" => to } + expect(report.created_at).to eq(from.to_date..to.to_date) + report.created_at = {} expect(report.created_at).to eq(nil) + report.created_at = { from: nil, to: nil } expect(report.created_at).to eq(nil) + report.created_at = { from: Date.today, to: nil } expect(report.created_at).to eq(Date.today..nil) + report.created_at = { from: nil, to: Date.today } expect(report.created_at).to eq(nil..Date.today) + report.created_at = { from: Time.now, to: Time.now } expect(report.created_at).to eq(Date.today..Date.today) end diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index 5154ba4..dbca39f 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -483,7 +483,7 @@ end ## Introduced range filter separator localization -A separator symbol between range filter inputs is now a part of localizations to avoid hardcore. +A separator symbol between range filter inputs is now a part of localizations to avoid hard coding. Add `datagrid.filters.range.separator` to your localization file. [See related view](https://github.com/bogdan/datagrid/blob/version-2/app/views/datagrid/_range_filter.html.erb#L2) From e872fec6abc63daea887c9184c9315422e6ba315 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 15 Nov 2024 11:31:52 +0100 Subject: [PATCH 116/157] Update upgrade guide --- version-2/Readme.markdown | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index dbca39f..35397d0 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -79,9 +79,10 @@ Beware of that. `datagrid_order_for` helper serves no purpose and should not be used directly. The recommended way is to include your ordering code directly into `datagrid/head` partial. -You implement `datagrid_order_for` in `ApplicationHelper` -and copy [datagrid/order\_for](../app/views/datagrid/_order_for.html.erb) into your project -if you consider it useful: +See default [head partial](../app/views/datagrid/_head.html.erb) for example. + +You can implement `datagrid_order_for` in `ApplicationHelper` +and copy [datagrid/order\_for](../app/views/datagrid/_order_for.html.erb) into your project if you consider it useful: ``` ruby module ApplicationHelper @@ -91,7 +92,6 @@ module ApplicationHelper end ``` -See default [head partial](../app/views/datagrid/_head.html.erb) for example. [Grep all deprecations](./deprecations.sh). ## Inherit Datagrid::Base @@ -188,7 +188,7 @@ if you want to change them. Diff for [built-in partials between V1 and V2](./views.diff) See [a new built-in CSS file](../app/assets/datagrid.css). -### Example +### Form layout difference The difference in layout generation from v1 to v2. @@ -230,9 +230,32 @@ Version 1 layout: Version 2 layout: -TODO - ``` html +<form class="datagrid-form" action="/users" accept-charset="UTF-8" method="get"> + <div class="datagrid-filter" data-filter="id" data-type="integer"> + <label for="g_id">Id</label> + <input step="1" class="datagrid-range-from" name="g[id][from]" type="number" id="g_id" /> + <span class="datagrid-range-separator"> - </span> + <input step="1" class="datagrid-range-to" name="g[id][to]" type="number" /> + </div> + + <div class="datagrid-filter" data-filter="group_id" data-type="enum"> + <label>Group</label> + <div class="datagrid-enum-checkboxes"> + <label for="g_group_id_1" class="datagrid-enum-checkbox-label"> + <input id="g_group_id_1" value="1" type="checkbox" name="g[group_id][]" />1 + </label> + <label for="g_group_id_2" class="datagrid-enum-checkbox-label"> + <input id="g_group_id_2" value="2" type="checkbox" name="g[group_id][]" />2 + </label> + </div> + </div> + + <div class="datagrid-actions"> + <input type="submit" name="commit" value="Search" class="datagrid-submit" data-disable-with="Search" /> + <a class="datagrid-reset" href="/location">Reset</a> + </div> +</form> ``` ## HTML5 input types From 95c289a973e9d2040c967b55c290219c5bbd8ec4 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 15 Nov 2024 13:49:41 +0100 Subject: [PATCH 117/157] Cleanup --- version-2/Readme.markdown | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index 35397d0..fbae3f6 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -201,8 +201,6 @@ Version 1 layout: ``` html <form class="datagrid-form partial_default_grid" id="new_g" action="/users" accept-charset="UTF-8" method="get"> - <input name="utf8" type="hidden" value="✓" autocomplete="off" /> - <div class="datagrid-filter filter"> <label for="g_id">Id</label> <input class="id integer_filter from" multiple type="text" name="g[id][]" /> @@ -252,7 +250,8 @@ Version 2 layout: </div> <div class="datagrid-actions"> - <input type="submit" name="commit" value="Search" class="datagrid-submit" data-disable-with="Search" /> + <input type="submit" name="commit" value="Search" + class="datagrid-submit" data-disable-with="Search" /> <a class="datagrid-reset" href="/location">Reset</a> </div> </form> From 5ee5555aee5e245df720ba8cf9edcbb51d7d18ee Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 15 Nov 2024 19:12:11 +0100 Subject: [PATCH 118/157] Update version-2/views.diff Co-authored-by: Bohdan Zhuravel <bohdan@zhuravel.bz> --- version-2/views.diff | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version-2/views.diff b/version-2/views.diff index 61c42fa..d31ca27 100644 --- a/version-2/views.diff +++ b/version-2/views.diff @@ -49,7 +49,7 @@ index e939128..b355528 100644 + <%= content_tag( + :th, + class: { -+ # Adding html clases based on condition ++ # Adding HTML classes based on condition + # Consider maintaining consistency with datagrid/rows partial + "datagrid-order-active-asc": grid.ordered_by?(column, false), + "datagrid-order-active-desc": grid.ordered_by?(column ,true), From 41832ef5c5e686de668e3f1ee792a9dd0e457643 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 15 Nov 2024 19:12:17 +0100 Subject: [PATCH 119/157] Update version-2/views.diff Co-authored-by: Bohdan Zhuravel <bohdan@zhuravel.bz> --- version-2/views.diff | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version-2/views.diff b/version-2/views.diff index d31ca27..d4ffe8f 100644 --- a/version-2/views.diff +++ b/version-2/views.diff @@ -52,7 +52,7 @@ index e939128..b355528 100644 + # Adding HTML classes based on condition + # Consider maintaining consistency with datagrid/rows partial + "datagrid-order-active-asc": grid.ordered_by?(column, false), -+ "datagrid-order-active-desc": grid.ordered_by?(column ,true), ++ "datagrid-order-active-desc": grid.ordered_by?(column, true), + column.html_class => column.html_class.present?, + }, + "data-column": column.name From a9190adf418a6e278126f3412612e5e2993ce222 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 15 Nov 2024 19:12:23 +0100 Subject: [PATCH 120/157] Update version-2/views.diff Co-authored-by: Bohdan Zhuravel <bohdan@zhuravel.bz> --- version-2/views.diff | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version-2/views.diff b/version-2/views.diff index d4ffe8f..e157c6b 100644 --- a/version-2/views.diff +++ b/version-2/views.diff @@ -101,7 +101,7 @@ index f54d21c..340aea6 100644 + :td, + datagrid_value(grid, column, asset), + class: { -+ # Adding html clases based on condition ++ # Adding HTML classes based on condition + # Consider maintaining consistency with datagrid/head partial + "datagrid-order-active-asc": grid.ordered_by?(column, false), + "datagrid-order-active-desc": grid.ordered_by?(column ,true), From 6981dc51084d8adb827ce798ddd66936f83b2b77 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 15 Nov 2024 19:12:32 +0100 Subject: [PATCH 121/157] Update version-2/views.diff Co-authored-by: Bohdan Zhuravel <bohdan@zhuravel.bz> --- version-2/views.diff | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version-2/views.diff b/version-2/views.diff index e157c6b..93f3047 100644 --- a/version-2/views.diff +++ b/version-2/views.diff @@ -104,7 +104,7 @@ index f54d21c..340aea6 100644 + # Adding HTML classes based on condition + # Consider maintaining consistency with datagrid/head partial + "datagrid-order-active-asc": grid.ordered_by?(column, false), -+ "datagrid-order-active-desc": grid.ordered_by?(column ,true), ++ "datagrid-order-active-desc": grid.ordered_by?(column, true), + column.html_class => column.html_class.present?, + }, + "data-column": column.name From c2b5543d8367ac4cec61c0e57d45a48a99af412e Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 15 Nov 2024 19:12:38 +0100 Subject: [PATCH 122/157] Update app/views/datagrid/_head.html.erb Co-authored-by: Bohdan Zhuravel <bohdan@zhuravel.bz> --- app/views/datagrid/_head.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/datagrid/_head.html.erb b/app/views/datagrid/_head.html.erb index b355528..248bc0c 100644 --- a/app/views/datagrid/_head.html.erb +++ b/app/views/datagrid/_head.html.erb @@ -3,7 +3,7 @@ <%= content_tag( :th, class: { - # Adding html clases based on condition + # Adding HTML classes based on condition # Consider maintaining consistency with datagrid/rows partial "datagrid-order-active-asc": grid.ordered_by?(column, false), "datagrid-order-active-desc": grid.ordered_by?(column ,true), From 47a2d09bfba23763e3a0f23d4b388e7bcaf3d2b6 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 15 Nov 2024 19:23:01 +0100 Subject: [PATCH 123/157] Update app/views/datagrid/_head.html.erb Co-authored-by: Bohdan Zhuravel <bohdan@zhuravel.bz> --- app/views/datagrid/_head.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/datagrid/_head.html.erb b/app/views/datagrid/_head.html.erb index 248bc0c..2aa1779 100644 --- a/app/views/datagrid/_head.html.erb +++ b/app/views/datagrid/_head.html.erb @@ -6,7 +6,7 @@ # Adding HTML classes based on condition # Consider maintaining consistency with datagrid/rows partial "datagrid-order-active-asc": grid.ordered_by?(column, false), - "datagrid-order-active-desc": grid.ordered_by?(column ,true), + "datagrid-order-active-desc": grid.ordered_by?(column, true), column.html_class => column.html_class.present?, }, "data-column": column.name From cbece13e4af2a8007b0efe5d1c23e533ad8e7992 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 15 Nov 2024 19:23:43 +0100 Subject: [PATCH 124/157] Update app/views/datagrid/_table.html.erb Co-authored-by: Bohdan Zhuravel <bohdan@zhuravel.bz> --- app/views/datagrid/_table.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/datagrid/_table.html.erb b/app/views/datagrid/_table.html.erb index 0b5ff24..afcb9ab 100644 --- a/app/views/datagrid/_table.html.erb +++ b/app/views/datagrid/_table.html.erb @@ -5,7 +5,7 @@ Local variables: * options - passed options Hash %> <% if grid.html_columns(*options[:columns]).any? %> - <%= content_tag :table, class: 'datagrid-table', **options.fetch(:html, {}) do %> + <%= tag.table, class: 'datagrid-table', **options.fetch(:html, {}) do %> <thead> <%= datagrid_header(grid, options) %> </thead> From dbd3d4624eaa5b2233b005c75143f930a94908c2 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 15 Nov 2024 19:28:18 +0100 Subject: [PATCH 125/157] Migrate from content_tag to tag --- app/views/datagrid/_head.html.erb | 3 +-- app/views/datagrid/_range_filter.html.erb | 2 +- app/views/datagrid/_row.html.erb | 3 +-- app/views/datagrid/_table.html.erb | 2 +- lib/datagrid/columns.rb | 4 ++-- spec/datagrid/columns_spec.rb | 2 +- spec/datagrid/form_builder_spec.rb | 2 +- spec/datagrid/helper_spec.rb | 12 ++++++------ 8 files changed, 14 insertions(+), 16 deletions(-) diff --git a/app/views/datagrid/_head.html.erb b/app/views/datagrid/_head.html.erb index 2aa1779..71e6b03 100644 --- a/app/views/datagrid/_head.html.erb +++ b/app/views/datagrid/_head.html.erb @@ -1,7 +1,6 @@ <tr> <% grid.html_columns(*options[:columns]).each do |column| %> - <%= content_tag( - :th, + <%= tag.th( class: { # Adding HTML classes based on condition # Consider maintaining consistency with datagrid/rows partial diff --git a/app/views/datagrid/_range_filter.html.erb b/app/views/datagrid/_range_filter.html.erb index 21d1f0e..faa2575 100644 --- a/app/views/datagrid/_range_filter.html.erb +++ b/app/views/datagrid/_range_filter.html.erb @@ -1,5 +1,5 @@ <%= form.datagrid_filter_input(filter, class: 'datagrid-range-from', **from_options) %> <span class="datagrid-range-separator"><%= I18n.t('datagrid.filters.range.separator') %></span> <%# Generating id only for "from" input to make sure -%> -<%# there is no duplicate id in DOM and click on label focuses the first input -%> +<%# there is no duplicate id in DOM and click on label focuses the first input -%> <%= form.datagrid_filter_input(filter, class: 'datagrid-range-to', **to_options, id: nil) %> diff --git a/app/views/datagrid/_row.html.erb b/app/views/datagrid/_row.html.erb index 340aea6..f57c729 100644 --- a/app/views/datagrid/_row.html.erb +++ b/app/views/datagrid/_row.html.erb @@ -1,7 +1,6 @@ <tr> <% grid.html_columns(*options[:columns]).each do |column| %> - <%= content_tag( - :td, + <%= tag.td( datagrid_value(grid, column, asset), class: { # Adding html clases based on condition diff --git a/app/views/datagrid/_table.html.erb b/app/views/datagrid/_table.html.erb index afcb9ab..2e9273e 100644 --- a/app/views/datagrid/_table.html.erb +++ b/app/views/datagrid/_table.html.erb @@ -5,7 +5,7 @@ Local variables: * options - passed options Hash %> <% if grid.html_columns(*options[:columns]).any? %> - <%= tag.table, class: 'datagrid-table', **options.fetch(:html, {}) do %> + <%= tag.table class: 'datagrid-table', **options.fetch(:html, {}) do %> <thead> <%= datagrid_header(grid, options) %> </thead> diff --git a/lib/datagrid/columns.rb b/lib/datagrid/columns.rb index dca4638..5b495ac 100644 --- a/lib/datagrid/columns.rb +++ b/lib/datagrid/columns.rb @@ -115,7 +115,7 @@ def respond_to(&block) # @example # column(:name) do |model| # format(model.name) do |value| - # content_tag(:strong, value) + # tag.strong(value) # end # end def format(value, &block) @@ -325,7 +325,7 @@ def column_by_name(name) # @example # column(:name) do |model| # format(model.name) do |value| - # content_tag(:strong, value) + # tag.strong(value) # end # end # diff --git a/spec/datagrid/columns_spec.rb b/spec/datagrid/columns_spec.rb index 3e313f0..dbd47b3 100644 --- a/spec/datagrid/columns_spec.rb +++ b/spec/datagrid/columns_spec.rb @@ -215,7 +215,7 @@ class Report27 < Datagrid::Base filter(:name) column(:entries_count, "count(entries.id)") do |model| format("(#{model.entries_count})") do |value| - content_tag(:span, value) + tag.span(value) end end end diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 04bbe6b..a1a42d4 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -376,7 +376,7 @@ class MyTemplate context "when block is given" do let(:_filter_block) do proc do - template.content_tag(:option, "block option", value: "block_value") + template.tag.option("block option", value: "block_value") end end it { diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 822c60e..b5fcdd7 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -201,7 +201,7 @@ end expect( subject.datagrid_rows(rp) do |row| - subject.content_tag(:strong, row.name) + subject.tag.strong(row.name) end, ).to match_css_pattern( "strong" => "Star", @@ -233,7 +233,7 @@ rp = test_report do scope { Entry } column(:name, html: true) do |model| - content_tag(:span, model.name) + tag.span(model.name) end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( @@ -279,7 +279,7 @@ it "should render argument-based html columns" do rp = test_report do scope { Entry } - column(:name, html: ->(data) { content_tag :h1, data }) + column(:name, html: ->(data) { tag.h1 data }) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( "tr td[data-column=name] h1" => "Star", @@ -289,7 +289,7 @@ it "should render argument-based html columns with custom data" do rp = test_report do scope { Entry } - column(:name, html: ->(data) { content_tag :em, data }) do + column(:name, html: ->(data) { tag.em data }) do name.upcase end end @@ -302,7 +302,7 @@ rp = test_report do scope { Entry } column(:name, html: true) do |model, grid| - content_tag(:span, "#{model.name}-#{grid.assets.klass}") + tag.span("#{model.name}-#{grid.assets.klass}") end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( @@ -314,7 +314,7 @@ rp = test_report do scope { Entry } column(:name, html: lambda { |data, model| - content_tag :h1, "#{data}-#{model.name.downcase}" + tag.h1 "#{data}-#{model.name.downcase}" },) end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( From 0f761ca6fbde0b15abb5119520d98e81f92b9625 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 15 Nov 2024 19:28:47 +0100 Subject: [PATCH 126/157] Update view diff --- version-2/views.diff | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/version-2/views.diff b/version-2/views.diff index 93f3047..97aeb0e 100644 --- a/version-2/views.diff +++ b/version-2/views.diff @@ -39,15 +39,14 @@ index 7e175c1..fc4f4ae 100644 </div> <% end -%> diff --git a/app/views/datagrid/_head.html.erb b/app/views/datagrid/_head.html.erb -index e939128..b355528 100644 +index e939128..71e6b03 100644 --- a/app/views/datagrid/_head.html.erb +++ b/app/views/datagrid/_head.html.erb -@@ -1,8 +1,31 @@ +@@ -1,8 +1,30 @@ <tr> <% grid.html_columns(*options[:columns]).each do |column| %> - <th class="<%= datagrid_column_classes(grid, column) %>"> -+ <%= content_tag( -+ :th, ++ <%= tag.th( + class: { + # Adding HTML classes based on condition + # Consider maintaining consistency with datagrid/rows partial @@ -78,33 +77,33 @@ index e939128..b355528 100644 <% end %> </tr> diff --git a/app/views/datagrid/_range_filter.html.erb b/app/views/datagrid/_range_filter.html.erb -index 7a8a123..ffbb0f8 100644 +index 7a8a123..faa2575 100644 --- a/app/views/datagrid/_range_filter.html.erb +++ b/app/views/datagrid/_range_filter.html.erb -@@ -1,3 +1,4 @@ +@@ -1,3 +1,5 @@ -<%= form.datagrid_filter_input(filter, **from_options) %> -<span class="separator <%= filter.type %>"><%= I18n.t('datagrid.filters.range.separator') %></span> -<%= form.datagrid_filter_input(filter, **to_options) %> +<%= form.datagrid_filter_input(filter, class: 'datagrid-range-from', **from_options) %> +<span class="datagrid-range-separator"><%= I18n.t('datagrid.filters.range.separator') %></span> +<%# Generating id only for "from" input to make sure -%> -+<%# there is no duplicate id in DOM and click on label focuses the first input -%> <%= form.datagrid_filter_input(filter, class: 'datagrid-range-to', **to_options, id: nil) %> ++<%# there is no duplicate id in DOM and click on label focuses the first input -%> ++<%= form.datagrid_filter_input(filter, class: 'datagrid-range-to', **to_options, id: nil) %> diff --git a/app/views/datagrid/_row.html.erb b/app/views/datagrid/_row.html.erb -index f54d21c..340aea6 100644 +index f54d21c..f57c729 100644 --- a/app/views/datagrid/_row.html.erb +++ b/app/views/datagrid/_row.html.erb -@@ -1,5 +1,16 @@ +@@ -1,5 +1,15 @@ <tr> <% grid.html_columns(*options[:columns]).each do |column| %> - <td class="<%= datagrid_column_classes(grid, column) %>"><%= datagrid_value(grid, column, asset) %></td> -+ <%= content_tag( -+ :td, ++ <%= tag.td( + datagrid_value(grid, column, asset), + class: { -+ # Adding HTML classes based on condition ++ # Adding html clases based on condition + # Consider maintaining consistency with datagrid/head partial + "datagrid-order-active-asc": grid.ordered_by?(column, false), -+ "datagrid-order-active-desc": grid.ordered_by?(column, true), ++ "datagrid-order-active-desc": grid.ordered_by?(column ,true), + column.html_class => column.html_class.present?, + }, + "data-column": column.name @@ -112,7 +111,7 @@ index f54d21c..340aea6 100644 <% end %> </tr> diff --git a/app/views/datagrid/_table.html.erb b/app/views/datagrid/_table.html.erb -index 8708c05..0b5ff24 100644 +index 8708c05..2e9273e 100644 --- a/app/views/datagrid/_table.html.erb +++ b/app/views/datagrid/_table.html.erb @@ -5,7 +5,7 @@ Local variables: @@ -120,7 +119,7 @@ index 8708c05..0b5ff24 100644 %> <% if grid.html_columns(*options[:columns]).any? %> - <%= content_tag :table, options[:html] do %> -+ <%= content_tag :table, class: 'datagrid-table', **options.fetch(:html, {}) do %> ++ <%= tag.table class: 'datagrid-table', **options.fetch(:html, {}) do %> <thead> <%= datagrid_header(grid, options) %> </thead> From ad56fe61af11e2716ce440e5344368a4620b4228 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 15 Nov 2024 20:46:15 +0100 Subject: [PATCH 127/157] Update lib/datagrid/core.rb Co-authored-by: Bohdan Zhuravel <bohdan@zhuravel.bz> --- lib/datagrid/core.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/datagrid/core.rb b/lib/datagrid/core.rb index 8bc04d8..ddc450c 100644 --- a/lib/datagrid/core.rb +++ b/lib/datagrid/core.rb @@ -273,7 +273,7 @@ def sanitize_for_mass_assignment(attributes) if forbidden_attributes_protection super elsif defined?(ActionController::Parameters) && attributes.is_a?(ActionController::Parameters) - attributes.permit!.to_h + attributes.to_unsafe_h else attributes end From 6fab0e8c07705c1a694aad3ebc9aa3e528b20ecf Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 15 Nov 2024 20:46:33 +0100 Subject: [PATCH 128/157] Update app/views/datagrid/_row.html.erb Co-authored-by: Bohdan Zhuravel <bohdan@zhuravel.bz> --- app/views/datagrid/_row.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/datagrid/_row.html.erb b/app/views/datagrid/_row.html.erb index f57c729..c64b0bf 100644 --- a/app/views/datagrid/_row.html.erb +++ b/app/views/datagrid/_row.html.erb @@ -6,7 +6,7 @@ # Adding html clases based on condition # Consider maintaining consistency with datagrid/head partial "datagrid-order-active-asc": grid.ordered_by?(column, false), - "datagrid-order-active-desc": grid.ordered_by?(column ,true), + "datagrid-order-active-desc": grid.ordered_by?(column, true), column.html_class => column.html_class.present?, }, "data-column": column.name From f30a9bba953a9cb24314bf3a5b6811e32016834f Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Fri, 15 Nov 2024 20:46:39 +0100 Subject: [PATCH 129/157] Update version-2/views.diff Co-authored-by: Bohdan Zhuravel <bohdan@zhuravel.bz> --- version-2/views.diff | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version-2/views.diff b/version-2/views.diff index 97aeb0e..69d50c6 100644 --- a/version-2/views.diff +++ b/version-2/views.diff @@ -103,7 +103,7 @@ index f54d21c..f57c729 100644 + # Adding html clases based on condition + # Consider maintaining consistency with datagrid/head partial + "datagrid-order-active-asc": grid.ordered_by?(column, false), -+ "datagrid-order-active-desc": grid.ordered_by?(column ,true), ++ "datagrid-order-active-desc": grid.ordered_by?(column, true), + column.html_class => column.html_class.present?, + }, + "data-column": column.name From 14452df3865e9e1e8162f9dda10e2fd247c32e0e Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sat, 16 Nov 2024 11:03:17 +0100 Subject: [PATCH 130/157] Fix specifying inline class in #datagrid_filter for enum checkboxes --- app/views/datagrid/_enum_checkboxes.html.erb | 2 +- spec/datagrid/form_builder_spec.rb | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/app/views/datagrid/_enum_checkboxes.html.erb b/app/views/datagrid/_enum_checkboxes.html.erb index f225cc6..a5d4dcb 100644 --- a/app/views/datagrid/_enum_checkboxes.html.erb +++ b/app/views/datagrid/_enum_checkboxes.html.erb @@ -5,7 +5,7 @@ You can add indent if whitespace doesn't matter for you <div class="datagrid-enum-checkboxes"> <%- elements.each do |value, text, checked| -%> <%- id = [form.object_name, filter.name, value].join('_').underscore -%> -<%= form.datagrid_label(filter.name, **options, for: id, class: 'datagrid-enum-checkbox-label') do -%> +<%= form.datagrid_label(filter.name, for: id, class: 'datagrid-enum-checkbox-label', **options) do -%> <%= form.datagrid_filter_input(filter.name, id: id, value: value) -%> <%= text -%> <%- end -%> diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index a1a42d4..947749c 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -474,6 +474,21 @@ class MyTemplate let(:view_options) { { partials: "custom_checkboxes" } } it { should equal_to_dom("custom_enum_checkboxes") } end + + context "when inline class attribute specified" do + let(:_filter_options) { {for: nil, class: 'custom-class'} } + + it { should equal_to_dom(<<~HTML) } + <div class="datagrid-enum-checkboxes"> + <label class="custom-class"> + <input id="report_category_first" value="first" type="checkbox" name="report[category][]">first + </label> + <label class="custom-class"> + <input id="report_category_second" value="second" type="checkbox" name="report[category][]">second + </label> + </div> + HTML + end end end From 757fd562e6faeae1123e6504d9854dc3344df7d6 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sat, 16 Nov 2024 11:06:40 +0100 Subject: [PATCH 131/157] Remove datagrid-enum-checkbox-label css class as styling by tag name is good enough --- app/views/datagrid/_enum_checkboxes.html.erb | 2 +- spec/datagrid/form_builder_spec.rb | 10 +++++----- version-2/Readme.markdown | 4 ++-- version-2/form-v2.html | 4 ++-- version-2/views.diff | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/views/datagrid/_enum_checkboxes.html.erb b/app/views/datagrid/_enum_checkboxes.html.erb index a5d4dcb..5668c49 100644 --- a/app/views/datagrid/_enum_checkboxes.html.erb +++ b/app/views/datagrid/_enum_checkboxes.html.erb @@ -5,7 +5,7 @@ You can add indent if whitespace doesn't matter for you <div class="datagrid-enum-checkboxes"> <%- elements.each do |value, text, checked| -%> <%- id = [form.object_name, filter.name, value].join('_').underscore -%> -<%= form.datagrid_label(filter.name, for: id, class: 'datagrid-enum-checkbox-label', **options) do -%> +<%= form.datagrid_label(filter.name, for: id, **options) do -%> <%= form.datagrid_filter_input(filter.name, id: id, value: value) -%> <%= text -%> <%- end -%> diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 947749c..59434c0 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -451,12 +451,12 @@ class MyTemplate should equal_to_dom( <<~HTML, <div class="datagrid-enum-checkboxes"> - <label for="report_category_first" class="datagrid-enum-checkbox-label"> + <label for="report_category_first"> <input type="checkbox" id="report_category_first" value="first" name="report[category][]" /> first </label> - <label for="report_category_second" class="datagrid-enum-checkbox-label"> + <label for="report_category_second"> <input type="checkbox" id="report_category_second" value="second" name="report[category][]" /> second @@ -643,15 +643,15 @@ class MyTemplate let(:expected_html) do <<~DOM <div class="datagrid-enum-checkboxes"> - <label for="report_column_names_id" class="datagrid-enum-checkbox-label"> + <label for="report_column_names_id"> <input id="report_column_names_id" type="checkbox" value="id" checked name="report[column_names][]"> Id </label> - <label for="report_column_names_name" class="datagrid-enum-checkbox-label"> + <label for="report_column_names_name"> <input id="report_column_names_name" type="checkbox" value="name" checked name="report[column_names][]"/> Name </label> - <label for="report_column_names_category" class="datagrid-enum-checkbox-label"> + <label for="report_column_names_category"> <input id="report_column_names_category" type="checkbox" value="category" name="report[column_names][]"> Category </label> diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index fbae3f6..116fcc8 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -240,10 +240,10 @@ Version 2 layout: <div class="datagrid-filter" data-filter="group_id" data-type="enum"> <label>Group</label> <div class="datagrid-enum-checkboxes"> - <label for="g_group_id_1" class="datagrid-enum-checkbox-label"> + <label for="g_group_id_1"> <input id="g_group_id_1" value="1" type="checkbox" name="g[group_id][]" />1 </label> - <label for="g_group_id_2" class="datagrid-enum-checkbox-label"> + <label for="g_group_id_2"> <input id="g_group_id_2" value="2" type="checkbox" name="g[group_id][]" />2 </label> </div> diff --git a/version-2/form-v2.html b/version-2/form-v2.html index a67fd98..49d696b 100644 --- a/version-2/form-v2.html +++ b/version-2/form-v2.html @@ -9,10 +9,10 @@ <div class="datagrid-filter" data-filter="group_id" data-type="enum"> <label for="g_group_id">Group</label> <div class="datagrid-enum-checkboxes"> - <label class="datagrid-enum-checkbox-label" for="g_group_id_1"> + <label for="g_group_id_1"> <input id="g_group_id_1" value="1" type="checkbox" name="g[group_id][]" />1 </label> - <label class="datagrid-enum-checkbox-label" for="g_group_id_2"> + <label for="g_group_id_2"> <input id="g_group_id_2" type="checkbox" value="2" name="g[group_id][]" />2 </label> </div> diff --git a/version-2/views.diff b/version-2/views.diff index 97aeb0e..54e411f 100644 --- a/version-2/views.diff +++ b/version-2/views.diff @@ -11,7 +11,7 @@ index 9f48319..f225cc6 100644 <%- id = [form.object_name, filter.name, value].join('_').underscore -%> -<%= form.label filter.name, options.merge(for: id) do -%> -<%= form.check_box(filter.name, {multiple: true, id: id, checked: checked, include_hidden: false}, value.to_s, nil) -%> -+<%= form.datagrid_label(filter.name, **options, for: id, class: 'datagrid-enum-checkbox-label') do -%> ++<%= form.datagrid_label(filter.name, **options, for: id) do -%> +<%= form.datagrid_filter_input(filter.name, id: id, value: value) -%> <%= text -%> <%- end -%> From c7b66ce07cf0a1b5d75b773123781095a95d1509 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sat, 16 Nov 2024 11:08:07 +0100 Subject: [PATCH 132/157] Update view diff --- version-2/views.diff | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/version-2/views.diff b/version-2/views.diff index 977385c..e49aaa8 100644 --- a/version-2/views.diff +++ b/version-2/views.diff @@ -1,5 +1,5 @@ diff --git a/app/views/datagrid/_enum_checkboxes.html.erb b/app/views/datagrid/_enum_checkboxes.html.erb -index 9f48319..f225cc6 100644 +index 9f48319..5668c49 100644 --- a/app/views/datagrid/_enum_checkboxes.html.erb +++ b/app/views/datagrid/_enum_checkboxes.html.erb @@ -2,10 +2,12 @@ @@ -11,7 +11,7 @@ index 9f48319..f225cc6 100644 <%- id = [form.object_name, filter.name, value].join('_').underscore -%> -<%= form.label filter.name, options.merge(for: id) do -%> -<%= form.check_box(filter.name, {multiple: true, id: id, checked: checked, include_hidden: false}, value.to_s, nil) -%> -+<%= form.datagrid_label(filter.name, **options, for: id) do -%> ++<%= form.datagrid_label(filter.name, for: id, **options) do -%> +<%= form.datagrid_filter_input(filter.name, id: id, value: value) -%> <%= text -%> <%- end -%> @@ -90,7 +90,7 @@ index 7a8a123..faa2575 100644 +<%# there is no duplicate id in DOM and click on label focuses the first input -%> +<%= form.datagrid_filter_input(filter, class: 'datagrid-range-to', **to_options, id: nil) %> diff --git a/app/views/datagrid/_row.html.erb b/app/views/datagrid/_row.html.erb -index f54d21c..f57c729 100644 +index f54d21c..c64b0bf 100644 --- a/app/views/datagrid/_row.html.erb +++ b/app/views/datagrid/_row.html.erb @@ -1,5 +1,15 @@ From 2a3fb80c37deb62ae17026062415db65b7b7216b Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sat, 16 Nov 2024 13:23:17 +0100 Subject: [PATCH 133/157] Improve stylesheet to support enum filter --- app/assets/stylesheets/datagrid.css | 33 +++++++---------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/app/assets/stylesheets/datagrid.css b/app/assets/stylesheets/datagrid.css index 7083c37..1d13d62 100644 --- a/app/assets/stylesheets/datagrid.css +++ b/app/assets/stylesheets/datagrid.css @@ -51,36 +51,21 @@ table.datagrid-table th { margin: 10px; } -.datagrid-filter::before, -.datagrid-filter::after { - content: ''; - display: table; -} - -.datagrid-filter::after { - clear: both; -} - .datagrid-filter label { width: 150px; - float: left; + display: inline-block; } -.datagrid-filter input { +.datagrid-filter input, .datagrid-filter select { border: 2px solid #ccc; border-radius: 4px; - float: left; + display: inline-block; padding: 5px 12px; width: 300px; } input.datagrid-range-from, input.datagrid-range-to { - width: 144px; -} - -.datagrid-filter select { - float: left; - width: 300px + width: 138px; } .datagrid-filter select[multiple] { @@ -95,32 +80,30 @@ select.datagrid-dynamic-operation { } .datagrid-dynamic-value { - margin: 10px 0 0 150px; + margin: 10px 0 0 154px; clear: both; } .datagrid-range-separator { - float: left; + display: inline-block; margin: 6px 4px 0; } .datagrid-enum-checkboxes { - float: left; + display: inline-block; } select.datagrid-dynamic-field { - width: 242px + width: 238px } .datagrid-enum-checkboxes input { margin: 7px; - float: none; width: auto; } .datagrid-enum-checkboxes label { display: block; - float: none; width: 100%; } From f072cde083d8e959fd4c3e0420595b27d7806551 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sat, 16 Nov 2024 13:25:05 +0100 Subject: [PATCH 134/157] Fix dynamic filter layout --- app/assets/stylesheets/datagrid.css | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/assets/stylesheets/datagrid.css b/app/assets/stylesheets/datagrid.css index 1d13d62..89d42a9 100644 --- a/app/assets/stylesheets/datagrid.css +++ b/app/assets/stylesheets/datagrid.css @@ -74,9 +74,13 @@ input.datagrid-range-from, input.datagrid-range-to { height: 100px; } +select.datagrid-dynamic-field { + width: 228px +} + select.datagrid-dynamic-operation { margin-left: 7px; - width: 50px; + width: 60px; } .datagrid-dynamic-value { @@ -93,10 +97,6 @@ select.datagrid-dynamic-operation { display: inline-block; } -select.datagrid-dynamic-field { - width: 238px -} - .datagrid-enum-checkboxes input { margin: 7px; width: auto; From a33986c864939783ad8602b61ca2a55be34fb292 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sat, 16 Nov 2024 13:31:21 +0100 Subject: [PATCH 135/157] Cleanup stylesheet --- app/assets/stylesheets/datagrid.css | 1 - 1 file changed, 1 deletion(-) diff --git a/app/assets/stylesheets/datagrid.css b/app/assets/stylesheets/datagrid.css index 89d42a9..d06f1a4 100644 --- a/app/assets/stylesheets/datagrid.css +++ b/app/assets/stylesheets/datagrid.css @@ -85,7 +85,6 @@ select.datagrid-dynamic-operation { .datagrid-dynamic-value { margin: 10px 0 0 154px; - clear: both; } .datagrid-range-separator { From 5b6cd380ca7bb0896372e038dcdada10b0dffb12 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 17 Nov 2024 11:23:14 +0100 Subject: [PATCH 136/157] Improve Scaffold.view_code --- lib/datagrid/generators/scaffold.rb | 24 +++++++++++++++++------ spec/datagrid/generators/scaffold_spec.rb | 14 ++++++++++++- templates/controller.rb.erb | 6 ------ templates/index.html.erb | 5 ----- 4 files changed, 31 insertions(+), 18 deletions(-) delete mode 100644 templates/controller.rb.erb delete mode 100644 templates/index.html.erb diff --git a/lib/datagrid/generators/scaffold.rb b/lib/datagrid/generators/scaffold.rb index 172c8b5..d361bc1 100644 --- a/lib/datagrid/generators/scaffold.rb +++ b/lib/datagrid/generators/scaffold.rb @@ -23,7 +23,7 @@ def create_scaffold end create_file view_file, view_code route(generate_routing_namespace("resources :#{grid_controller_short_name}")) - gem "kaminari" unless defined?(::Kaminari) || defined?(::WillPaginate) || defined?(::Pagy) + gem "kaminari" unless kaminari? || will_paginate? || pagy? in_root do { "css" => " *= require datagrid", @@ -71,9 +71,9 @@ def grid_param_name end def pagination_helper_code - if defined?(::WillPaginate) + if will_paginate? "will_paginate(@grid.assets)" - elsif defined?(::Pagy) + elsif pagy? "pagy_nav(@pagy)" else # Kaminari is default @@ -82,7 +82,7 @@ def pagination_helper_code end def table_helper_code - if defined?(::Pagy) + if pagy? "datagrid_table @grid, @records" else "datagrid_table @grid" @@ -98,7 +98,7 @@ def grid_route_name end def index_code - if defined?(::Pagy) + if pagy? <<-RUBY @grid = #{grid_class_name}.new(grid_params) @pagy, @assets = pagy(@grid.assets) @@ -129,7 +129,7 @@ def grid_params end def view_code - indent(<<~ERB) + <<~ERB <%= datagrid_form_with model: @grid, url: #{grid_route_name} %> <%= #{pagination_helper_code} %> @@ -168,6 +168,18 @@ def file_exists?(name) name = Rails.root.join(name) unless name.to_s.first == "/" File.exist?(name) end + + def pagy? + defined?(::Pagy) + end + + def will_paginate? + defined?(::WillPaginate) + end + + def kaminari? + defined?(::Kaminari) + end end end end diff --git a/spec/datagrid/generators/scaffold_spec.rb b/spec/datagrid/generators/scaffold_spec.rb index d83f88d..0282055 100644 --- a/spec/datagrid/generators/scaffold_spec.rb +++ b/spec/datagrid/generators/scaffold_spec.rb @@ -24,7 +24,7 @@ end end - describe ".controller_code" do + describe "#controller_code" do it "works" do expect(subject.controller_code).to eq(<<~RUBY) class UsersController < ApplicationController @@ -43,4 +43,16 @@ def grid_params RUBY end end + + describe "#view_code" do + it "works" do + expect(subject.view_code).to eq(<<~ERB) + <%= datagrid_form_with model: @grid, url: users_path %> + + <%= paginate(@grid.assets) %> + <%= datagrid_table @grid %> + <%= paginate(@grid.assets) %> + ERB + end + end end diff --git a/templates/controller.rb.erb b/templates/controller.rb.erb deleted file mode 100644 index 71a6253..0000000 --- a/templates/controller.rb.erb +++ /dev/null @@ -1,6 +0,0 @@ -class <%= grid_controller_class_name %> < ApplicationController - -<%= index_action -%> - -end - diff --git a/templates/index.html.erb b/templates/index.html.erb deleted file mode 100644 index 133754b..0000000 --- a/templates/index.html.erb +++ /dev/null @@ -1,5 +0,0 @@ -<%%= datagrid_form_with model: @grid, url: <%= grid_route_name %> %> - -<%%= <%=pagination_helper_code%> %> -<%%= <%=table_helper_code%> %> -<%%= <%=pagination_helper_code%> %> From 0769160987913320c6c5c7c122cdbf958aeb0033 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 17 Nov 2024 11:31:16 +0100 Subject: [PATCH 137/157] Pagy tests for scaffold --- spec/datagrid/generators/scaffold_spec.rb | 39 +++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/spec/datagrid/generators/scaffold_spec.rb b/spec/datagrid/generators/scaffold_spec.rb index 0282055..19a00df 100644 --- a/spec/datagrid/generators/scaffold_spec.rb +++ b/spec/datagrid/generators/scaffold_spec.rb @@ -42,6 +42,29 @@ def grid_params end RUBY end + + context "with pagy" do + before do + allow(subject).to receive(:pagy?).and_return(true) + end + + it "works" do + expect(subject.controller_code).to eq(<<~RUBY) + class UsersController < ApplicationController + def index + @grid = UsersGrid.new(grid_params) + @pagy, @assets = pagy(@grid.assets) + end + + protected + + def grid_params + params.fetch(:users_grid, {}).permit! + end + end + RUBY + end + end end describe "#view_code" do @@ -54,5 +77,21 @@ def grid_params <%= paginate(@grid.assets) %> ERB end + + context "with pagy" do + before do + allow(subject).to receive(:pagy?).and_return(true) + end + + it "works" do + expect(subject.view_code).to eq(<<~ERB) + <%= datagrid_form_with model: @grid, url: users_path %> + + <%= pagy_nav(@pagy) %> + <%= datagrid_table @grid, @records %> + <%= pagy_nav(@pagy) %> + ERB + end + end end end From 76b9792d75eef6a179c2decbe32334b2d6acf6d4 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 17 Nov 2024 11:40:47 +0100 Subject: [PATCH 138/157] Reprecate elements in favor of choices inside enum_checkboxes --- app/views/datagrid/_enum_checkboxes.html.erb | 2 +- lib/datagrid/deprecated_object.rb | 18 ++++++++++++++++++ lib/datagrid/form_builder.rb | 14 +++++++++++++- spec/datagrid/form_builder_spec.rb | 12 ++++++++++++ .../_enum_checkboxes.html.erb | 1 + version-2/Readme.markdown | 12 ++++++++++++ version-2/deprecations.sh | 5 +++++ 7 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 lib/datagrid/deprecated_object.rb create mode 100644 spec/support/test_partials/deprecated_enum_checkboxes/_enum_checkboxes.html.erb diff --git a/app/views/datagrid/_enum_checkboxes.html.erb b/app/views/datagrid/_enum_checkboxes.html.erb index 5668c49..281bb6f 100644 --- a/app/views/datagrid/_enum_checkboxes.html.erb +++ b/app/views/datagrid/_enum_checkboxes.html.erb @@ -3,7 +3,7 @@ Indent in this file may cause extra space to appear. You can add indent if whitespace doesn't matter for you %> <div class="datagrid-enum-checkboxes"> -<%- elements.each do |value, text, checked| -%> +<%- choices.each do |value, text| -%> <%- id = [form.object_name, filter.name, value].join('_').underscore -%> <%= form.datagrid_label(filter.name, for: id, **options) do -%> <%= form.datagrid_filter_input(filter.name, id: id, value: value) -%> diff --git a/lib/datagrid/deprecated_object.rb b/lib/datagrid/deprecated_object.rb new file mode 100644 index 0000000..6d964eb --- /dev/null +++ b/lib/datagrid/deprecated_object.rb @@ -0,0 +1,18 @@ +module Datagrid + # @!visibility private + class DeprecatedObject < BasicObject + def initialize(real_object, &block) + @real_object = real_object + @block = block + end + + def method_missing(method_name, *args, &block) + @block.call + @real_object.public_send(method_name, *args, &block) + end + + def respond_to_missing?(method_name, include_private = false) + @real_object.respond_to?(method_name, include_private) + end + end +end diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 6f497b5..378cf75 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require "action_view" +require 'datagrid/deprecated_object' module Datagrid module FormBuilder @@ -88,11 +89,22 @@ def datagrid_enum_checkboxes_filter(filter, options = {}) checked = enum_checkbox_checked?(filter, value) [value, text, checked] end + choices = elements.map do |value, text, *_| + [value, text] + end render_partial( "enum_checkboxes", { - elements: elements, form: self, + elements: Datagrid::DeprecatedObject.new( + elements, + + ) do + Datagrid::Utils.warn_once( + "Using `elements` variable in app/views/datagrid/enum_checkboxes is deprecated, use `choices` instead." + ) + end, + choices: choices, filter: filter, options: options, }, diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 59434c0..4ac369a 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -475,6 +475,18 @@ class MyTemplate it { should equal_to_dom("custom_enum_checkboxes") } end + context "when using deprecated elements variable in partial" do + around do |ex| + Datagrid::Utils.deprecator.silence do + ex.run + end + end + let(:view_options) { { partials: "deprecated_enum_checkboxes" } } + it { should equal_to_dom( + [["first", "first",false],["second","second",false]].to_json + ) } + end + context "when inline class attribute specified" do let(:_filter_options) { {for: nil, class: 'custom-class'} } diff --git a/spec/support/test_partials/deprecated_enum_checkboxes/_enum_checkboxes.html.erb b/spec/support/test_partials/deprecated_enum_checkboxes/_enum_checkboxes.html.erb new file mode 100644 index 0000000..cae2685 --- /dev/null +++ b/spec/support/test_partials/deprecated_enum_checkboxes/_enum_checkboxes.html.erb @@ -0,0 +1 @@ +<%= elements.to_json %> diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index 116fcc8..147d87f 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -27,6 +27,7 @@ List of things introduces: * while supported, the library was not initially designed for it. 1. HTML5 data attributes 1. Consistent `label[for]` and `input[id]` for range filters. +1. Updated app/views/datagrid/enum\_checkboxes 1. Introduced `datagrid.filters.range.separator` localization 1. Remove SASS dependency 1. Replace `rake datagrid:copy_partials` with `rails g datagrid:views` @@ -477,6 +478,17 @@ Version 2 generates id attribute only for the first input, so that a click on la The behavior can be changed by modifying [built-in view](https://github.com/bogdan/datagrid/blob/version-2/app/views/datagrid/_range_filter.html.erb#L3). +## Updated enum\_checkboxes view + +`app/views/datagrid/enum_checkboxes` is now configured differently: + +1. Use `datagrid_filter_input` instead of `check_box` to ensure `filter` options behave consistently. +2. Use `choices` local variable instead of `elements` + * `elements` variables contains values: `value`, `text` and `checked`. + * `choices` has only first two values to ensure `checked` is determined automatically and consistently. + +Diff for [built-in partials between V1 and V2](./views.diff) + ## ApplicationGrid base class Previously recommended base class `BaseGrid` is incosistent diff --git a/version-2/deprecations.sh b/version-2/deprecations.sh index 3460343..46340f5 100644 --- a/version-2/deprecations.sh +++ b/version-2/deprecations.sh @@ -18,3 +18,8 @@ git grep 'datagrid:copy_partials' git grep 'BaseDatagrid' git grep 'BaseGrid' +# Use choices instead +git grep 'elements' app/views/datagrid/_enum_checkboxes.* + +# Use datagrid_filter_input instead +git grep 'check_box' app/views/datagrid/_enum_checkboxes.* From e82f48bc4f2c6b8672d4c9f8affa7e05bdeb41f2 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 17 Nov 2024 11:51:01 +0100 Subject: [PATCH 139/157] Linting --- .rubocop.yml | 4 ++ lib/datagrid/deprecated_object.rb | 6 +- lib/datagrid/filters/date_filter.rb | 4 +- lib/datagrid/filters/enum_filter.rb | 2 +- lib/datagrid/form_builder.rb | 7 ++- spec/datagrid/filters/date_filter_spec.rb | 3 +- spec/datagrid/form_builder_spec.rb | 74 ++++++++++++----------- spec/datagrid/generators/scaffold_spec.rb | 34 +++++------ 8 files changed, 70 insertions(+), 64 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 8ff7392..0c4cec2 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -35,3 +35,7 @@ Metrics/ModuleLength: Enabled: false Style/Documentation: Enabled: false +Style/OptionalBooleanParameter: + Enabled: false +Style/MultilineBlockChain: + Enabled: false diff --git a/lib/datagrid/deprecated_object.rb b/lib/datagrid/deprecated_object.rb index 6d964eb..aa31646 100644 --- a/lib/datagrid/deprecated_object.rb +++ b/lib/datagrid/deprecated_object.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Datagrid # @!visibility private class DeprecatedObject < BasicObject @@ -6,9 +8,9 @@ def initialize(real_object, &block) @block = block end - def method_missing(method_name, *args, &block) + def method_missing(method_name, ...) @block.call - @real_object.public_send(method_name, *args, &block) + @real_object.public_send(method_name, ...) end def respond_to_missing?(method_name, include_private = false) diff --git a/lib/datagrid/filters/date_filter.rb b/lib/datagrid/filters/date_filter.rb index cf3b7a5..e846226 100644 --- a/lib/datagrid/filters/date_filter.rb +++ b/lib/datagrid/filters/date_filter.rb @@ -12,9 +12,7 @@ def default_input_options end def apply(grid_object, scope, value) - if grid_object.driver.timestamp_column?(scope, name) - value = Datagrid::Utils.format_date_as_timestamp(value) - end + value = Datagrid::Utils.format_date_as_timestamp(value) if grid_object.driver.timestamp_column?(scope, name) super end diff --git a/lib/datagrid/filters/enum_filter.rb b/lib/datagrid/filters/enum_filter.rb index 75ea00a..d21d6f4 100644 --- a/lib/datagrid/filters/enum_filter.rb +++ b/lib/datagrid/filters/enum_filter.rb @@ -34,7 +34,7 @@ def label_options # Each checkbox has its own label # The main label has no specific input to focus # See app/views/datagrid/_enum_checkboxes.html.erb - {for: nil, **super} + { for: nil, **super } else super end diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 378cf75..e6fe3bd 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require "action_view" -require 'datagrid/deprecated_object' +require "datagrid/deprecated_object" module Datagrid module FormBuilder @@ -98,10 +98,11 @@ def datagrid_enum_checkboxes_filter(filter, options = {}) form: self, elements: Datagrid::DeprecatedObject.new( elements, - ) do Datagrid::Utils.warn_once( - "Using `elements` variable in app/views/datagrid/enum_checkboxes is deprecated, use `choices` instead." + <<~MSG, + Using `elements` variable in enum_checkboxes view is deprecated, use `choices` instead. + MSG ) end, choices: choices, diff --git a/spec/datagrid/filters/date_filter_spec.rb b/spec/datagrid/filters/date_filter_spec.rb index 60f2d9c..15e3fb3 100644 --- a/spec/datagrid/filters/date_filter_spec.rb +++ b/spec/datagrid/filters/date_filter_spec.rb @@ -261,7 +261,7 @@ def entry_dated(date) it "supports search by timestamp column" do report = test_report(created_at: Date.today) do - scope {Entry} + scope { Entry } filter(:created_at, :date) end e1 = Entry.create!(created_at: Date.yesterday + 23.hours) @@ -276,7 +276,6 @@ def entry_dated(date) expect(report.assets).to_not include(e5) end - it "allows filter to be defined before scope" do class ParentGrid < Datagrid::Base filter(:created_at, :date, range: true) diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 4ac369a..2519c3b 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -213,11 +213,11 @@ class MyTemplate context "with only right bound" do let(:_range) { [nil, 10] } it { - should equal_to_dom( - '<input class="datagrid-range-from" type="number" step="1" name="report[group_id][from]" id="report_group_id"/>' \ - '<span class="datagrid-range-separator"> - </span>' \ - '<input value="10" class="datagrid-range-to" type="number" step="1" name="report[group_id][to]"/>', - ) + should equal_to_dom(<<~HTML) + <input class="datagrid-range-from" type="number" step="1" name="report[group_id][from]" id="report_group_id"/> + <span class="datagrid-range-separator"> - </span> + <input value="10" class="datagrid-range-to" type="number" step="1" name="report[group_id][to]"/> + HTML } it { should be_html_safe } end @@ -225,11 +225,11 @@ class MyTemplate context "with invalid range value" do let(:_range) { 2..1 } it { - should equal_to_dom( - '<input value="1" class="datagrid-range-from" type="number" step="1" name="report[group_id][from]" id="report_group_id"/>' \ - '<span class="datagrid-range-separator"> - </span>' \ - '<input value="2" class="datagrid-range-to" type="number" step="1" name="report[group_id][to]"/>', - ) + should equal_to_dom(<<~HTML) + <input value="1" class="datagrid-range-from" type="number" step="1" name="report[group_id][from]" id="report_group_id"/> + <span class="datagrid-range-separator"> - </span> + <input value="2" class="datagrid-range-to" type="number" step="1" name="report[group_id][to]"/> + HTML } end @@ -247,11 +247,11 @@ class MyTemplate let(:view_options) { { partials: "not_existed" } } let(:_range) { nil } it { - should equal_to_dom( - '<input class="datagrid-range-from" type="number" step="1" name="report[group_id][from]" id="report_group_id"> + should equal_to_dom(<<~HTML) + <input class="datagrid-range-from" type="number" step="1" name="report[group_id][from]" id="report_group_id"> <span class="datagrid-range-separator"> - </span> - <input class="datagrid-range-to" type="number" step="1" name="report[group_id][to]">', - ) + <input class="datagrid-range-to" type="number" step="1" name="report[group_id][to]"> + HTML } end end @@ -287,11 +287,11 @@ class MyTemplate context "with only left bound" do let(:_range) { ["2012-01-03", nil] } it { - should equal_to_dom( - '<input value="2012-01-03" class="datagrid-range-from" type="date" name="report[created_at][from]" id="report_created_at"/>' \ - '<span class="datagrid-range-separator"> - </span>' \ - '<input class="datagrid-range-to" type="date" name="report[created_at][to]" value=""/>', - ) + should equal_to_dom(<<~HTML) + <input value="2012-01-03" class="datagrid-range-from" type="date" name="report[created_at][from]" id="report_created_at"/> + <span class="datagrid-range-separator"> - </span> + <input class="datagrid-range-to" type="date" name="report[created_at][to]" value=""/> + HTML } it { should be_html_safe } end @@ -346,11 +346,11 @@ class MyTemplate end let(:_range) { [nil, nil] } it { - should equal_to_dom( - '<input class="datagrid-range-from" type="date" value="" name="report[created_at][from]" id="report_created_at"/>' \ - '<span class="datagrid-range-separator"> - </span>' \ - '<input class="datagrid-range-to" type="date" value="" name="report[created_at][to]"/>', - ) + should equal_to_dom(<<~HTML) + <input class="datagrid-range-from" type="date" value="" name="report[created_at][from]" id="report_created_at"/> + <span class="datagrid-range-separator"> - </span> + <input class="datagrid-range-to" type="date" value="" name="report[created_at][to]"/> + HTML } end end @@ -482,23 +482,25 @@ class MyTemplate end end let(:view_options) { { partials: "deprecated_enum_checkboxes" } } - it { should equal_to_dom( - [["first", "first",false],["second","second",false]].to_json - ) } + it { + should equal_to_dom( + [["first", "first", false], ["second", "second", false]].to_json, + ) + } end context "when inline class attribute specified" do - let(:_filter_options) { {for: nil, class: 'custom-class'} } + let(:_filter_options) { { for: nil, class: "custom-class" } } it { should equal_to_dom(<<~HTML) } - <div class="datagrid-enum-checkboxes"> - <label class="custom-class"> - <input id="report_category_first" value="first" type="checkbox" name="report[category][]">first - </label> - <label class="custom-class"> - <input id="report_category_second" value="second" type="checkbox" name="report[category][]">second - </label> - </div> + <div class="datagrid-enum-checkboxes"> + <label class="custom-class"> + <input id="report_category_first" value="first" type="checkbox" name="report[category][]">first + </label> + <label class="custom-class"> + <input id="report_category_second" value="second" type="checkbox" name="report[category][]">second + </label> + </div> HTML end end diff --git a/spec/datagrid/generators/scaffold_spec.rb b/spec/datagrid/generators/scaffold_spec.rb index 19a00df..843b187 100644 --- a/spec/datagrid/generators/scaffold_spec.rb +++ b/spec/datagrid/generators/scaffold_spec.rb @@ -50,18 +50,18 @@ def grid_params it "works" do expect(subject.controller_code).to eq(<<~RUBY) - class UsersController < ApplicationController - def index - @grid = UsersGrid.new(grid_params) - @pagy, @assets = pagy(@grid.assets) - end + class UsersController < ApplicationController + def index + @grid = UsersGrid.new(grid_params) + @pagy, @assets = pagy(@grid.assets) + end - protected + protected - def grid_params - params.fetch(:users_grid, {}).permit! + def grid_params + params.fetch(:users_grid, {}).permit! + end end - end RUBY end end @@ -70,11 +70,11 @@ def grid_params describe "#view_code" do it "works" do expect(subject.view_code).to eq(<<~ERB) - <%= datagrid_form_with model: @grid, url: users_path %> + <%= datagrid_form_with model: @grid, url: users_path %> - <%= paginate(@grid.assets) %> - <%= datagrid_table @grid %> - <%= paginate(@grid.assets) %> + <%= paginate(@grid.assets) %> + <%= datagrid_table @grid %> + <%= paginate(@grid.assets) %> ERB end @@ -85,11 +85,11 @@ def grid_params it "works" do expect(subject.view_code).to eq(<<~ERB) - <%= datagrid_form_with model: @grid, url: users_path %> + <%= datagrid_form_with model: @grid, url: users_path %> - <%= pagy_nav(@pagy) %> - <%= datagrid_table @grid, @records %> - <%= pagy_nav(@pagy) %> + <%= pagy_nav(@pagy) %> + <%= datagrid_table @grid, @records %> + <%= pagy_nav(@pagy) %> ERB end end From 7d6eca1b58f06225c22f3bb29da17bd1570bd1a8 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 17 Nov 2024 11:58:37 +0100 Subject: [PATCH 140/157] Update diff --- version-2/views.diff | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/version-2/views.diff b/version-2/views.diff index e49aaa8..da806d5 100644 --- a/version-2/views.diff +++ b/version-2/views.diff @@ -1,13 +1,14 @@ diff --git a/app/views/datagrid/_enum_checkboxes.html.erb b/app/views/datagrid/_enum_checkboxes.html.erb -index 9f48319..5668c49 100644 +index 9f48319..281bb6f 100644 --- a/app/views/datagrid/_enum_checkboxes.html.erb +++ b/app/views/datagrid/_enum_checkboxes.html.erb @@ -2,10 +2,12 @@ Indent in this file may cause extra space to appear. You can add indent if whitespace doesn't matter for you %> +-<%- elements.each do |value, text, checked| -%> +<div class="datagrid-enum-checkboxes"> - <%- elements.each do |value, text, checked| -%> ++<%- choices.each do |value, text| -%> <%- id = [form.object_name, filter.name, value].join('_').underscore -%> -<%= form.label filter.name, options.merge(for: id) do -%> -<%= form.check_box(filter.name, {multiple: true, id: id, checked: checked, include_hidden: false}, value.to_s, nil) -%> From 036575035ba28d1e7e41b8b856bacdae56bc418a Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 17 Nov 2024 15:08:54 +0100 Subject: [PATCH 141/157] Add column[tag_options] option instead of column[class] --- CHANGELOG.md | 3 +++ app/views/datagrid/_head.html.erb | 4 ++-- app/views/datagrid/_row.html.erb | 4 ++-- lib/datagrid/columns.rb | 4 +++- lib/datagrid/columns/column.rb | 16 ++++++++++++++++ spec/datagrid/helper_spec.rb | 26 ++++++++++++++++++++++---- spec/spec_helper.rb | 5 +++++ version-2/Readme.markdown | 15 +++++++++++++++ 8 files changed, 68 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75abc2c..d9e0c68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## 2.0.0 +Version 2 is a major update implementing a lot of major improvements +at the cost of backward compatibility. + [Changes and migration guide](./version-2) ## 1.8.3 diff --git a/app/views/datagrid/_head.html.erb b/app/views/datagrid/_head.html.erb index 71e6b03..a7880e4 100644 --- a/app/views/datagrid/_head.html.erb +++ b/app/views/datagrid/_head.html.erb @@ -6,9 +6,9 @@ # Consider maintaining consistency with datagrid/rows partial "datagrid-order-active-asc": grid.ordered_by?(column, false), "datagrid-order-active-desc": grid.ordered_by?(column, true), - column.html_class => column.html_class.present?, }, - "data-column": column.name + "data-column": column.name, + **column.tag_options, ) do %> <%= column.header %> <% if column.supports_order? && options[:order] -%> diff --git a/app/views/datagrid/_row.html.erb b/app/views/datagrid/_row.html.erb index c64b0bf..6d293cf 100644 --- a/app/views/datagrid/_row.html.erb +++ b/app/views/datagrid/_row.html.erb @@ -7,9 +7,9 @@ # Consider maintaining consistency with datagrid/head partial "datagrid-order-active-asc": grid.ordered_by?(column, false), "datagrid-order-active-desc": grid.ordered_by?(column, true), - column.html_class => column.html_class.present?, }, - "data-column": column.name + "data-column": column.name, + **column.tag_options, ) %> <% end %> </tr> diff --git a/lib/datagrid/columns.rb b/lib/datagrid/columns.rb index 5b495ac..9f146f6 100644 --- a/lib/datagrid/columns.rb +++ b/lib/datagrid/columns.rb @@ -71,7 +71,7 @@ def columns(*column_names, data: false, html: false) # * <tt>html</tt> - determines if current column should be present in html table and how is it formatted # * <tt>order</tt> - determines if this column could be sortable and how. # The value of order is explicitly passed to ORM ordering method. - # Ex: <tt>"created_at, id"</tt> for ActiveRecord, <tt>[:created_at, :id]</tt> for Mongoid + # Example: <tt>"created_at, id"</tt> for ActiveRecord, <tt>[:created_at, :id]</tt> for Mongoid # * <tt>order_desc</tt> - determines a descending order for given column # (only in case when <tt>:order</tt> can not be easily reversed by ORM) # * <tt>order_by_value</tt> - used in case it is easier to perform ordering at ruby level not on database level. @@ -85,6 +85,8 @@ def columns(*column_names, data: false, html: false) # * <tt>if</tt> - the column is shown if the reult of calling this argument is true # * <tt>unless</tt> - the column is shown unless the reult of calling this argument is true # * <tt>preload</tt> - spefies which associations of the scope should be preloaded for this column + # * `tag_options` - specify HTML attributes to be set for `<td>` or `<th>` of a column + # Example: `{ class: "content-align-right", "data-group": "statistics" }` # # @see https://github.com/bogdan/datagrid/wiki/Columns def column(name, query = nil, **options, &block) diff --git a/lib/datagrid/columns/column.rb b/lib/datagrid/columns/column.rb index 502295d..65f4aad 100644 --- a/lib/datagrid/columns/column.rb +++ b/lib/datagrid/columns/column.rb @@ -39,6 +39,15 @@ def initialize(grid_class, name, query, options = {}, &block) self.grid_class = grid_class self.name = name.to_sym self.options = options + if options[:class] + Datagrid::Utils.warn_once( + "column[class] option is deprecated. Use {tag_options: {class: ...}} instead." + ) + self.options[:tag_options] = { + **self.options.fetch(:tag_options, {}), + class: options[:class], + } + end if options[:html] == true self.html_block = block else @@ -108,7 +117,14 @@ def mandatory? !!options[:mandatory] end + def tag_options + options[:tag_options] || {} + end + def html_class + Datagrid::Utils.warn_once( + "Column#html_class is deprecated. Use Column#tag_options instead." + ) options[:class] end diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index b5fcdd7..45bd6ef 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -377,16 +377,34 @@ end it "should allow CSS classes to be specified for a column" do - rp = test_report do - scope { Entry } - column(:name, class: "my_class") + rp = expect_deprecated do + test_report do + scope { Entry } + column(:name, class: "my-class") + end end expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( - "tr td[data-column=name].my_class" => "Star", + "tr td[data-column=name].my-class" => "Star", ) end + it "supports tag_options option" do + report = test_report do + scope { Entry } + column(:name, tag_options: { + class: 'my-class', + "data-sort-method": "qsort" + }) + end + + expect(subject.datagrid_rows(report, [entry])).to equal_to_dom(<<~HTML) + <tr> + <td class="my-class" data-column="name" data-sort-method="qsort">Star</td> + </tr> + HTML + end + context "when grid has complicated columns" do let(:grid) do test_report(name: "Hello") do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 2322b78..cbcefb8 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -106,6 +106,11 @@ def silence_deprecator(&block) Datagrid::Utils.deprecator.silence(&block) end +def expect_deprecated(message = /deprecated/, &block) + expect(Datagrid::Utils.deprecator).to receive(:warn).with(message) + block.call +end + # Requires supporting files with custom matchers and macros, etc, # in ./support/ and its subdirectories. Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index 147d87f..3d8c9e5 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -26,6 +26,7 @@ List of things introduces: 1. Native Rails Engines: * while supported, the library was not initially designed for it. 1. HTML5 data attributes +1. Use `column[tag_options]` option instead of `column[class]`. 1. Consistent `label[for]` and `input[id]` for range filters. 1. Updated app/views/datagrid/enum\_checkboxes 1. Introduced `datagrid.filters.range.separator` localization @@ -453,6 +454,20 @@ Renders: [Modify built-in views](https://github.com/bogdan/datagrid/wiki/Frontend#modifying-built-in-partials) if you want to change this behavior completely. +## Use column[tag\_options] + +`column[class]` option is deprecated in favor of more flexible `column[tag_options]` +that allows to specify any `td/td` html attribute. + +Example migration: + +``` ruby +# V1 +column(:status, class: 'issue-status') +# V2 +column(:status, tag_options: {class: 'issue-status'}) +``` + ## id attribute for range filter inputs [W3 validator](https://validator.w3.org/) complains when From 5acee620b38dcd2fd568a1e13c2837436adeb94e Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Sun, 17 Nov 2024 19:14:14 +0100 Subject: [PATCH 142/157] Improve tag_options: merge custom class with order classes --- app/views/datagrid/_head.html.erb | 11 +++++---- app/views/datagrid/_row.html.erb | 13 +++++----- spec/datagrid/helper_spec.rb | 24 ++++++++++++++++--- version-2/Readme.markdown | 4 +++- ...n.rb => find_deprecated_column_options.rb} | 2 +- 5 files changed, 38 insertions(+), 16 deletions(-) rename version-2/{find_deprecated_url_option.rb => find_deprecated_column_options.rb} (92%) diff --git a/app/views/datagrid/_head.html.erb b/app/views/datagrid/_head.html.erb index a7880e4..ee5d89e 100644 --- a/app/views/datagrid/_head.html.erb +++ b/app/views/datagrid/_head.html.erb @@ -1,14 +1,15 @@ <tr> <% grid.html_columns(*options[:columns]).each do |column| %> <%= tag.th( - class: { + # Consider maintaining consistency with datagrid/rows partial + "data-column": column.name, + **column.tag_options, + class: class_names( + column.tag_options[:class], # Adding HTML classes based on condition - # Consider maintaining consistency with datagrid/rows partial "datagrid-order-active-asc": grid.ordered_by?(column, false), "datagrid-order-active-desc": grid.ordered_by?(column, true), - }, - "data-column": column.name, - **column.tag_options, + ) ) do %> <%= column.header %> <% if column.supports_order? && options[:order] -%> diff --git a/app/views/datagrid/_row.html.erb b/app/views/datagrid/_row.html.erb index 6d293cf..b493cfe 100644 --- a/app/views/datagrid/_row.html.erb +++ b/app/views/datagrid/_row.html.erb @@ -2,14 +2,15 @@ <% grid.html_columns(*options[:columns]).each do |column| %> <%= tag.td( datagrid_value(grid, column, asset), - class: { - # Adding html clases based on condition - # Consider maintaining consistency with datagrid/head partial - "datagrid-order-active-asc": grid.ordered_by?(column, false), - "datagrid-order-active-desc": grid.ordered_by?(column, true), - }, + # Consider maintaining consistency with datagrid/rows partial "data-column": column.name, **column.tag_options, + class: class_names( + column.tag_options[:class], + # Adding HTML classes based on condition + "datagrid-order-active-asc": grid.ordered_by?(column, false), + "datagrid-order-active-desc": grid.ordered_by?(column, true), + ) ) %> <% end %> </tr> diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 45bd6ef..ce89042 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -390,17 +390,18 @@ end it "supports tag_options option" do - report = test_report do + report = test_report(order: :name, descending: true) do scope { Entry } column(:name, tag_options: { class: 'my-class', - "data-sort-method": "qsort" + "data-column-group": "core", + "data-column": nil, }) end expect(subject.datagrid_rows(report, [entry])).to equal_to_dom(<<~HTML) <tr> - <td class="my-class" data-column="name" data-sort-method="qsort">Star</td> + <td class="my-class datagrid-order-active-desc" data-column-group="core">Star</td> </tr> HTML end @@ -743,6 +744,23 @@ def param_name </th></tr> HTML end + + it "supports tag_options option" do + grid = test_report(order: :name, descending: true) do + scope { Entry } + column(:name, order: false, tag_options: { + class: 'my-class', + "data-column-group": "core", + "data-column": nil, + }) + end + + expect(subject.datagrid_header(grid)).to equal_to_dom(<<~HTML) + <tr> + <th class="my-class datagrid-order-active-desc" data-column-group="core">Name</th> + </tr> + HTML + end end describe ".datagrid_column_classes" do diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index 3d8c9e5..b9f0b12 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -55,7 +55,7 @@ column(:user) do |user| end ``` -All deprecated columns can be found [with a script](./find_deprecated_url_option.rb) +All deprecated columns can be found [with a script](./find_deprecated_column_options.rb). ## Use form\_with @@ -468,6 +468,8 @@ column(:status, class: 'issue-status') column(:status, tag_options: {class: 'issue-status'}) ``` +All deprecated columns can be found [with a script](./find_deprecated_column_options.rb). + ## id attribute for range filter inputs [W3 validator](https://validator.w3.org/) complains when diff --git a/version-2/find_deprecated_url_option.rb b/version-2/find_deprecated_column_options.rb similarity index 92% rename from version-2/find_deprecated_url_option.rb rename to version-2/find_deprecated_column_options.rb index fbb5f19..1b03e50 100644 --- a/version-2/find_deprecated_url_option.rb +++ b/version-2/find_deprecated_column_options.rb @@ -13,7 +13,7 @@ classes = [*included_classes, *base_subclasses].uniq classes.flat_map(&:columns).select do |f| - f.options[:url] + f.options[:url] || f.options[:class] end.map do |f| [f.grid_class, f.name].join("#") end From af0985f6e7c67ccbd4c6819d43fd58eb0f2f5128 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 18 Nov 2024 11:30:18 +0100 Subject: [PATCH 143/157] Cleanup --- spec/datagrid/core_spec.rb | 9 ++---- spec/datagrid/filters/integer_filter_spec.rb | 7 ++--- version-2/Readme.markdown | 6 ++-- version-2/views.diff | 32 +++++++++++--------- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/spec/datagrid/core_spec.rb b/spec/datagrid/core_spec.rb index 35a03a4..58cae7e 100644 --- a/spec/datagrid/core_spec.rb +++ b/spec/datagrid/core_spec.rb @@ -231,12 +231,9 @@ class EqualTest < Datagrid::Base end it "supports hash attribute assignment" do - grid = test_grid( - ActionController::Parameters.new(group_id: { from: 1, to: 2 }), - ) do - scope { Entry } - filter(:group_id, :integer, range: true) - end + grid = test_grid_filter(:group_id, :integer, range: true) + grid.attributes = ActionController::Parameters.new(group_id: { from: 1, to: 2 }) + expect(grid.group_id).to eq(1..2) end end diff --git a/spec/datagrid/filters/integer_filter_spec.rb b/spec/datagrid/filters/integer_filter_spec.rb index 0ffd5d9..4c310bb 100644 --- a/spec/datagrid/filters/integer_filter_spec.rb +++ b/spec/datagrid/filters/integer_filter_spec.rb @@ -64,10 +64,9 @@ end it "converts infinite range to nil" do - report = test_grid(group_id: (nil..nil)) do - scope { Entry } - filter(:group_id, :integer, range: true) - end + report = test_grid_filter(:group_id, :integer, range: true) + report.group_id = nil..nil + expect(report.group_id).to eq(nil) end diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index b9f0b12..50487b3 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -72,7 +72,7 @@ datagrid_form_for(@users_grid, url: users_path) datagrid_form_with(model: @users_grid, url: users_path) ``` -Version 2 built-in view `datagrid/form` uses `form_with` no matter of the with helper is used. +Version 2 built-in view `datagrid/form` uses `form_with` no matter of the which helper is used. Beware of that. [Grep all deprecations](./deprecations.sh). @@ -133,7 +133,7 @@ grid.id # V1: [1, nil] Version 2 makes an effort to make the transition as smooth as possible to you: * Old Array format will be converted to new Range format -* Serialization/Deserialization of Range is help correctly +* Serialization/Deserialization of Range is held correctly ``` ruby grid.id = 1..5 @@ -457,7 +457,7 @@ if you want to change this behavior completely. ## Use column[tag\_options] `column[class]` option is deprecated in favor of more flexible `column[tag_options]` -that allows to specify any `td/td` html attribute. +that allows to specify any `th/td` html attribute. Example migration: diff --git a/version-2/views.diff b/version-2/views.diff index da806d5..5d13642 100644 --- a/version-2/views.diff +++ b/version-2/views.diff @@ -40,22 +40,23 @@ index 7e175c1..fc4f4ae 100644 </div> <% end -%> diff --git a/app/views/datagrid/_head.html.erb b/app/views/datagrid/_head.html.erb -index e939128..71e6b03 100644 +index e939128..ee5d89e 100644 --- a/app/views/datagrid/_head.html.erb +++ b/app/views/datagrid/_head.html.erb -@@ -1,8 +1,30 @@ +@@ -1,8 +1,31 @@ <tr> <% grid.html_columns(*options[:columns]).each do |column| %> - <th class="<%= datagrid_column_classes(grid, column) %>"> + <%= tag.th( -+ class: { ++ # Consider maintaining consistency with datagrid/rows partial ++ "data-column": column.name, ++ **column.tag_options, ++ class: class_names( ++ column.tag_options[:class], + # Adding HTML classes based on condition -+ # Consider maintaining consistency with datagrid/rows partial + "datagrid-order-active-asc": grid.ordered_by?(column, false), + "datagrid-order-active-desc": grid.ordered_by?(column, true), -+ column.html_class => column.html_class.present?, -+ }, -+ "data-column": column.name ++ ) + ) do %> <%= column.header %> - <%= datagrid_order_for(grid, column, options) if column.supports_order? && options[:order]%> @@ -91,23 +92,24 @@ index 7a8a123..faa2575 100644 +<%# there is no duplicate id in DOM and click on label focuses the first input -%> +<%= form.datagrid_filter_input(filter, class: 'datagrid-range-to', **to_options, id: nil) %> diff --git a/app/views/datagrid/_row.html.erb b/app/views/datagrid/_row.html.erb -index f54d21c..c64b0bf 100644 +index f54d21c..b493cfe 100644 --- a/app/views/datagrid/_row.html.erb +++ b/app/views/datagrid/_row.html.erb -@@ -1,5 +1,15 @@ +@@ -1,5 +1,16 @@ <tr> <% grid.html_columns(*options[:columns]).each do |column| %> - <td class="<%= datagrid_column_classes(grid, column) %>"><%= datagrid_value(grid, column, asset) %></td> + <%= tag.td( + datagrid_value(grid, column, asset), -+ class: { -+ # Adding html clases based on condition -+ # Consider maintaining consistency with datagrid/head partial ++ # Consider maintaining consistency with datagrid/rows partial ++ "data-column": column.name, ++ **column.tag_options, ++ class: class_names( ++ column.tag_options[:class], ++ # Adding HTML classes based on condition + "datagrid-order-active-asc": grid.ordered_by?(column, false), + "datagrid-order-active-desc": grid.ordered_by?(column, true), -+ column.html_class => column.html_class.present?, -+ }, -+ "data-column": column.name ++ ) + ) %> <% end %> </tr> From f5fb22d628f342003eb3714c5722ec69644cddb4 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 18 Nov 2024 11:41:01 +0100 Subject: [PATCH 144/157] Support tag_options in deprecated datagrid_column_classes --- lib/datagrid/helper.rb | 15 ++++++++------- spec/datagrid/helper_spec.rb | 8 ++++++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/lib/datagrid/helper.rb b/lib/datagrid/helper.rb index f18b124..bc42a56 100644 --- a/lib/datagrid/helper.rb +++ b/lib/datagrid/helper.rb @@ -167,12 +167,7 @@ def datagrid_order_path(grid, column, descending) datagrid_renderer.order_path(grid, column, descending, request) end - protected - - def datagrid_renderer - Renderer.for(self) - end - + # @!visibility private def datagrid_column_classes(grid, column) Datagrid::Utils.warn_once(<<~MSG) datagrid_column_classes is deprecated. Assign necessary classes manually. @@ -182,7 +177,13 @@ def datagrid_column_classes(grid, column) order_class = if grid.ordered_by?(column) ["ordered", grid.descending ? "desc" : "asc"] end - [column.name, order_class, column.options[:class]].compact.join(" ") + class_names(column.name, order_class, column.options[:class], column.tag_options[:class]) + end + + protected + + def datagrid_renderer + Renderer.for(self) end end end diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 0c7bce9..37aaa34 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -731,13 +731,17 @@ def param_name grid = test_grid(order: :name, descending: true) do scope { Entry } column(:name) + column(:category, tag_options: { class: "long-column" }) column(:group_id, class: "short-column") end silence_deprecator do - expect(subject.send(:datagrid_column_classes, grid, :name)).to eq( + expect(subject.datagrid_column_classes(grid, :name)).to eq( "name ordered desc", ) - expect(subject.send(:datagrid_column_classes, grid, :group_id)).to eq( + expect(subject.datagrid_column_classes(grid, :category)).to eq( + "category long-column", + ) + expect(subject.datagrid_column_classes(grid, :group_id)).to eq( "group_id short-column", ) end From fd2af34ff12d1bad78b2aa4dd243d1666d693ced Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 18 Nov 2024 12:25:32 +0100 Subject: [PATCH 145/157] Merge Renderer into Helper --- app/views/datagrid/_head.html.erb | 2 +- app/views/datagrid/_table.html.erb | 2 +- lib/datagrid/base.rb | 2 - lib/datagrid/helper.rb | 129 ++++++++++++-- lib/datagrid/renderer.rb | 158 ------------------ spec/datagrid/helper_spec.rb | 15 ++ .../client/datagrid/_table.html.erb | 2 +- 7 files changed, 134 insertions(+), 176 deletions(-) delete mode 100644 lib/datagrid/renderer.rb diff --git a/app/views/datagrid/_head.html.erb b/app/views/datagrid/_head.html.erb index ee5d89e..de2f969 100644 --- a/app/views/datagrid/_head.html.erb +++ b/app/views/datagrid/_head.html.erb @@ -9,7 +9,7 @@ # Adding HTML classes based on condition "datagrid-order-active-asc": grid.ordered_by?(column, false), "datagrid-order-active-desc": grid.ordered_by?(column, true), - ) + ).presence ) do %> <%= column.header %> <% if column.supports_order? && options[:order] -%> diff --git a/app/views/datagrid/_table.html.erb b/app/views/datagrid/_table.html.erb index 2e9273e..88eeafb 100644 --- a/app/views/datagrid/_table.html.erb +++ b/app/views/datagrid/_table.html.erb @@ -7,7 +7,7 @@ Local variables: <% if grid.html_columns(*options[:columns]).any? %> <%= tag.table class: 'datagrid-table', **options.fetch(:html, {}) do %> <thead> - <%= datagrid_header(grid, options) %> + <%= datagrid_header(grid, **options) %> </thead> <tbody> <% if assets.any? %> diff --git a/lib/datagrid/base.rb b/lib/datagrid/base.rb index f904d16..f941241 100644 --- a/lib/datagrid/base.rb +++ b/lib/datagrid/base.rb @@ -14,8 +14,6 @@ module Datagrid autoload :Helper autoload :FormBuilder - autoload :Renderer - autoload :Engine # Main datagrid class allowing to define columns and filters on your objects diff --git a/lib/datagrid/helper.rb b/lib/datagrid/helper.rb index bc42a56..74ca557 100644 --- a/lib/datagrid/helper.rb +++ b/lib/datagrid/helper.rb @@ -16,7 +16,9 @@ module Helper # <% end %> # </ul> def datagrid_value(grid, column, model) - datagrid_renderer.format_value(grid, column, model) + column = grid.column_by_name(column) if column.is_a?(String) || column.is_a?(Symbol) + + grid.html_value(column, self, model) end # @!visibility private @@ -44,7 +46,14 @@ def datagrid_format_value(grid, column, model) # assets = grid.assets.page(params[:page]) # datagrid_table(grid, assets, options) def datagrid_table(grid, assets = grid.assets, **options) - datagrid_renderer.table(grid, assets, **options) + _render_partial( + "table", options[:partials], + { + grid: grid, + options: options, + assets: assets, + }, + ) end # Renders HTML table header for given grid instance using columns defined in it @@ -60,8 +69,15 @@ def datagrid_table(grid, assets = grid.assets, **options) # Default: 'datagrid'. # @param grid [Datagrid] grid object # @return [String] HTML table header tag markup - def datagrid_header(grid, options = {}) - datagrid_renderer.header(grid, options) + def datagrid_header(grid, opts = :__unspecified__, **options) + unless opts == :__unspecified__ + Datagrid::Utils.warn_once("datagrid_header now requires ** operator when passing options.") + options.reverse_merge!(opts) + end + options[:order] = true unless options.key?(:order) + + _render_partial("head", options[:partials], + { grid: grid, options: options },) end # Renders HTML table rows using given grid definition using columns defined in it. @@ -84,7 +100,11 @@ def datagrid_header(grid, options = {}) # %td= row.project_name # %td.project-status{class: row.status}= row.status def datagrid_rows(grid, assets = grid.assets, **options, &block) - datagrid_renderer.rows(grid, assets, **options, &block) + safe_join( + assets.map do |asset| + datagrid_row(grid, asset, **options, &block) + end.to_a, + ) end # @return [String] renders ordering controls for the given column name @@ -99,7 +119,8 @@ def datagrid_order_for(grid, column, options = {}) Put necessary code inline inside datagrid/head partial. See built-in partial for example. MSG - datagrid_renderer.order_for(grid, column, options) + _render_partial("order_for", options[:partials], + { grid: grid, column: column },) end # Renders HTML for grid with all filters inputs and labels defined in it @@ -116,7 +137,10 @@ def datagrid_order_for(grid, column, options = {}) def datagrid_form_with(**options) raise ArgumentError, "datagrid_form_with block argument is invalid. Use form_with instead." if block_given? - datagrid_renderer.form_with(**options) + grid = options[:model] + raise ArgumentError, "Grid has no available filters" if grid&.filters&.empty? + + _render_partial("form", options[:partials], { grid: options[:model], options: options }) end # Renders HTML for grid with all filters inputs and labels defined in it @@ -131,7 +155,16 @@ def datagrid_form_with(**options) # @return [String] form HTML tag markup def datagrid_form_for(grid, options = {}) Datagrid::Utils.warn_once("datagrid_form_for is deprecated if favor of datagrid_form_with.") - datagrid_renderer.form_for(grid, options) + _render_partial( + "form", options[:partials], + grid: grid, + options: { + method: :get, + as: grid.param_name, + local: true, + **options, + }, + ) end # Provides access to datagrid columns data. @@ -154,8 +187,10 @@ def datagrid_form_for(grid, options = {}) # Last Name: <%= row.last_name %> # @example # <%= datagrid_row(grid, user, columns: [:first_name, :last_name, :actions]) %> - def datagrid_row(grid, asset, ...) - datagrid_renderer.row(grid, asset, ...) + def datagrid_row(grid, asset, **options, &block) + Datagrid::Helper::HtmlRow.new(self, grid, asset, options).tap do |row| + return capture(row, &block) if block_given? + end end # Generates an ascending or descending order url for the given column @@ -164,7 +199,12 @@ def datagrid_row(grid, asset, ...) # @param descending [Boolean] specifies order direction. Ascending if false, otherwise descending. # @return [String] order layout HTML markup def datagrid_order_path(grid, column, descending) - datagrid_renderer.order_path(grid, column, descending, request) + column = grid.column_by_name(column) + query = request&.query_parameters || {} + ActionDispatch::Http::URL.path_for( + path: request&.path || "/", + params: query.merge(grid.query_params(order: column.name, descending: descending)), + ) end # @!visibility private @@ -182,8 +222,71 @@ def datagrid_column_classes(grid, column) protected - def datagrid_renderer - Renderer.for(self) + def _render_partial(partial_name, partials_path, locals = {}) + render({ + partial: File.join(partials_path || "datagrid", partial_name), + locals: locals, + }) + end + + # Represents a datagrid row that provides access to column values for the given asset + # @example + # row = datagrid_row(grid, user) + # row.class # => Datagrid::Helper::HtmlRow + # row.first_name # => "<strong>Bogdan</strong>" + # row.grid # => Grid object + # row.asset # => User object + # row.each do |value| + # puts value + # end + class HtmlRow + include Enumerable + + attr_reader :grid, :asset, :options + + # @!visibility private + def initialize(renderer, grid, asset, options) + @renderer = renderer + @grid = grid + @asset = asset + @options = options + end + + # @return [Object] a column value for given column name + def get(column) + @renderer.datagrid_value(@grid, column, @asset) + end + + # Iterates over all column values that are available in the row + # param block [Proc] column value iterator + def each(&block) + (@options[:columns] || @grid.html_columns).each do |column| + block.call(get(column)) + end + end + + # @return [String] HTML row format + def to_s + @renderer.send(:_render_partial, "row", options[:partials], { + grid: grid, + options: options, + asset: asset, + },) + end + + protected + + def method_missing(method, *args, &blk) + if (column = @grid.column_by_name(method)) + get(column) + else + super + end + end + + def respond_to_missing?(method, include_private = false) + !!@grid.column_by_name(method) || super + end end end end diff --git a/lib/datagrid/renderer.rb b/lib/datagrid/renderer.rb deleted file mode 100644 index e2fbbc6..0000000 --- a/lib/datagrid/renderer.rb +++ /dev/null @@ -1,158 +0,0 @@ -# frozen_string_literal: true - -require "action_view" - -module Datagrid - # @!visibility private - class Renderer - def self.for(template) - new(template) - end - - def initialize(template) - @template = template - end - - def format_value(grid, column, asset) - column = grid.column_by_name(column) if column.is_a?(String) || column.is_a?(Symbol) - - grid.html_value(column, @template, asset) - end - - def form_for(grid, options = {}) - _render_partial( - "form", options[:partials], - grid: grid, - options: { - method: :get, - as: grid.param_name, - local: true, - **options, - }, - ) - end - - def form_with(**options) - grid = options[:model] - raise ArgumentError, "Grid has no available filters" if grid&.filters&.empty? - - _render_partial("form", options[:partials], { grid: options[:model], options: options }) - end - - def table(grid, assets, **options) - _render_partial( - "table", options[:partials], - { - grid: grid, - options: options, - assets: assets, - }, - ) - end - - def header(grid, options = {}) - options[:order] = true unless options.key?(:order) - - _render_partial("head", options[:partials], - { grid: grid, options: options },) - end - - def rows(grid, assets = grid.assets, **options, &block) - @template.safe_join( - assets.map do |asset| - row(grid, asset, **options, &block) - end.to_a, - ) - end - - def row(grid, asset, **options, &block) - Datagrid::Helper::HtmlRow.new(self, grid, asset, options).tap do |row| - return @template.capture(row, &block) if block_given? - end - end - - def order_for(grid, column, options = {}) - _render_partial("order_for", options[:partials], - { grid: grid, column: column },) - end - - def order_path(grid, column, descending, request) - column = grid.column_by_name(column) - query = request&.query_parameters || {} - ActionDispatch::Http::URL.path_for( - path: request&.path || "/", - params: query.merge(grid.query_params(order: column.name, descending: descending)), - ) - end - - private - - def _render_partial(partial_name, partials_path, locals = {}) - @template.render({ - partial: File.join(partials_path || "datagrid", partial_name), - locals: locals, - }) - end - end - - module Helper - # Represents a datagrid row that provides access to column values for the given asset - # @example - # row = datagrid_row(grid, user) - # row.class # => Datagrid::Helper::HtmlRow - # row.first_name # => "<strong>Bogdan</strong>" - # row.grid # => Grid object - # row.asset # => User object - # row.each do |value| - # puts value - # end - class HtmlRow - include Enumerable - - attr_reader :grid, :asset, :options - - # @!visibility private - def initialize(renderer, grid, asset, options) - @renderer = renderer - @grid = grid - @asset = asset - @options = options - end - - # @return [Object] a column value for given column name - def get(column) - @renderer.format_value(@grid, column, @asset) - end - - # Iterates over all column values that are available in the row - # param block [Proc] column value iterator - def each(&block) - (@options[:columns] || @grid.html_columns).each do |column| - block.call(get(column)) - end - end - - def to_s - @renderer.send(:_render_partial, "row", options[:partials], { - grid: grid, - options: options, - asset: asset, - },) - end - - protected - - def method_missing(method, *args, &blk) - if (column = @grid.column_by_name(method)) - get(column) - else - super - end - end - - def respond_to_missing?(method, include_private = false) - !!@grid.column_by_name(method) || super - end - end - end -end diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 37aaa34..6f88613 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -724,6 +724,21 @@ def param_name </tr> HTML end + + it "supports deprecated options passing" do + grid = test_grid_column(:name) + silence_deprecator do + expect( + subject.datagrid_header(grid, {order: false}) + ).to equal_to_dom(<<~HTML) + <tr> + <th data-column="name"> + Name + </th> + </tr> + HTML + end + end end describe ".datagrid_column_classes" do diff --git a/spec/support/test_partials/client/datagrid/_table.html.erb b/spec/support/test_partials/client/datagrid/_table.html.erb index 84ff466..336ce88 100644 --- a/spec/support/test_partials/client/datagrid/_table.html.erb +++ b/spec/support/test_partials/client/datagrid/_table.html.erb @@ -7,7 +7,7 @@ Local variables: <p>Namespaced table partial.</p> <%= content_tag :table, options[:html] do %> <thead> - <%= datagrid_header(grid, options) %> + <%= datagrid_header(grid, **options) %> </thead> <tbody> <% if assets.empty? %> From 6702193dad7d3e7b92c84c886efcfac2a23027c9 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 18 Nov 2024 12:30:33 +0100 Subject: [PATCH 146/157] Cleanup --- app/views/datagrid/_head.html.erb | 4 ++-- app/views/datagrid/_row.html.erb | 4 ++-- spec/datagrid/helper_spec.rb | 4 +--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/app/views/datagrid/_head.html.erb b/app/views/datagrid/_head.html.erb index de2f969..2c59aa7 100644 --- a/app/views/datagrid/_head.html.erb +++ b/app/views/datagrid/_head.html.erb @@ -4,12 +4,12 @@ # Consider maintaining consistency with datagrid/rows partial "data-column": column.name, **column.tag_options, - class: class_names( + class: [ column.tag_options[:class], # Adding HTML classes based on condition "datagrid-order-active-asc": grid.ordered_by?(column, false), "datagrid-order-active-desc": grid.ordered_by?(column, true), - ).presence + ] ) do %> <%= column.header %> <% if column.supports_order? && options[:order] -%> diff --git a/app/views/datagrid/_row.html.erb b/app/views/datagrid/_row.html.erb index b493cfe..a2254b0 100644 --- a/app/views/datagrid/_row.html.erb +++ b/app/views/datagrid/_row.html.erb @@ -5,12 +5,12 @@ # Consider maintaining consistency with datagrid/rows partial "data-column": column.name, **column.tag_options, - class: class_names( + class: [ column.tag_options[:class], # Adding HTML classes based on condition "datagrid-order-active-asc": grid.ordered_by?(column, false), "datagrid-order-active-desc": grid.ordered_by?(column, true), - ) + ] ) %> <% end %> </tr> diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 6f88613..429d56a 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -5,8 +5,6 @@ require "active_support/core_ext/object" require "action_controller" -require "datagrid/renderer" - describe Datagrid::Helper do subject do action_view_template @@ -732,7 +730,7 @@ def param_name subject.datagrid_header(grid, {order: false}) ).to equal_to_dom(<<~HTML) <tr> - <th data-column="name"> + <th data-column="name" class=""> Name </th> </tr> From b208fd78f657a76d75682688c698f213584497eb Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 18 Nov 2024 13:05:15 +0100 Subject: [PATCH 147/157] Update views diff --- version-2/views.diff | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/version-2/views.diff b/version-2/views.diff index 5d13642..b43cb66 100644 --- a/version-2/views.diff +++ b/version-2/views.diff @@ -40,7 +40,7 @@ index 7e175c1..fc4f4ae 100644 </div> <% end -%> diff --git a/app/views/datagrid/_head.html.erb b/app/views/datagrid/_head.html.erb -index e939128..ee5d89e 100644 +index e939128..2c59aa7 100644 --- a/app/views/datagrid/_head.html.erb +++ b/app/views/datagrid/_head.html.erb @@ -1,8 +1,31 @@ @@ -51,12 +51,12 @@ index e939128..ee5d89e 100644 + # Consider maintaining consistency with datagrid/rows partial + "data-column": column.name, + **column.tag_options, -+ class: class_names( ++ class: [ + column.tag_options[:class], + # Adding HTML classes based on condition + "datagrid-order-active-asc": grid.ordered_by?(column, false), + "datagrid-order-active-desc": grid.ordered_by?(column, true), -+ ) ++ ] + ) do %> <%= column.header %> - <%= datagrid_order_for(grid, column, options) if column.supports_order? && options[:order]%> @@ -92,7 +92,7 @@ index 7a8a123..faa2575 100644 +<%# there is no duplicate id in DOM and click on label focuses the first input -%> +<%= form.datagrid_filter_input(filter, class: 'datagrid-range-to', **to_options, id: nil) %> diff --git a/app/views/datagrid/_row.html.erb b/app/views/datagrid/_row.html.erb -index f54d21c..b493cfe 100644 +index f54d21c..a2254b0 100644 --- a/app/views/datagrid/_row.html.erb +++ b/app/views/datagrid/_row.html.erb @@ -1,5 +1,16 @@ @@ -104,29 +104,30 @@ index f54d21c..b493cfe 100644 + # Consider maintaining consistency with datagrid/rows partial + "data-column": column.name, + **column.tag_options, -+ class: class_names( ++ class: [ + column.tag_options[:class], + # Adding HTML classes based on condition + "datagrid-order-active-asc": grid.ordered_by?(column, false), + "datagrid-order-active-desc": grid.ordered_by?(column, true), -+ ) ++ ] + ) %> <% end %> </tr> diff --git a/app/views/datagrid/_table.html.erb b/app/views/datagrid/_table.html.erb -index 8708c05..2e9273e 100644 +index 8708c05..88eeafb 100644 --- a/app/views/datagrid/_table.html.erb +++ b/app/views/datagrid/_table.html.erb -@@ -5,7 +5,7 @@ Local variables: +@@ -5,18 +5,18 @@ Local variables: * options - passed options Hash %> <% if grid.html_columns(*options[:columns]).any? %> - <%= content_tag :table, options[:html] do %> + <%= tag.table class: 'datagrid-table', **options.fetch(:html, {}) do %> <thead> - <%= datagrid_header(grid, options) %> +- <%= datagrid_header(grid, options) %> ++ <%= datagrid_header(grid, **options) %> </thead> -@@ -13,10 +13,10 @@ Local variables: + <tbody> <% if assets.any? %> <%= datagrid_rows(grid, assets, **options) %> <% else %> From f110fd0ecd9dd0bf99768d434a181b8fe605bf11 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 18 Nov 2024 14:02:58 +0100 Subject: [PATCH 148/157] Fix ci status icon --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c5a0729..78e2b03 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Datagrid Version 2.0.0 is here. [Migration Guide](./version-2). -[](https://github.com/bogdan/datagrid/actions) +[](https://github.com/bogdan/datagrid/actions/workflows/ci.yml) A really mighty and flexible ruby library that generates reports including admin panels, analytics and data browsers: From e9b1ba54e6032c32961d898cecc708a1484ae68e Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 18 Nov 2024 14:03:22 +0100 Subject: [PATCH 149/157] Fix changelog url --- datagrid.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datagrid.gemspec b/datagrid.gemspec index e6904a7..f583ca4 100644 --- a/datagrid.gemspec +++ b/datagrid.gemspec @@ -28,7 +28,7 @@ Gem::Specification.new do |s| "homepage_uri" => s.homepage, "bug_tracker_uri" => "#{s.homepage}/issues", "documentation_uri" => "#{s.homepage}/wiki", - "changelog_uri" => "#{s.homepage}/blob/master/CHANGELOG.md", + "changelog_uri" => "#{s.homepage}/blob/main/CHANGELOG.md", "source_code_uri" => s.homepage, "rubygems_mfa_required" => "true", } From 4ddd8585d6042d7c8d417fa481696afd96464d3b Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 18 Nov 2024 18:30:53 +0100 Subject: [PATCH 150/157] Rubocop --- lib/datagrid/columns/column.rb | 4 +-- lib/datagrid/form_builder.rb | 1 + lib/datagrid/helper.rb | 2 ++ .../datagrid/filters/date_time_filter_spec.rb | 2 +- spec/datagrid/filters/integer_filter_spec.rb | 2 +- spec/datagrid/form_builder_spec.rb | 2 +- spec/datagrid/helper_spec.rb | 26 +++++++++---------- spec/spec_helper.rb | 2 +- 8 files changed, 22 insertions(+), 19 deletions(-) diff --git a/lib/datagrid/columns/column.rb b/lib/datagrid/columns/column.rb index 65f4aad..f41d410 100644 --- a/lib/datagrid/columns/column.rb +++ b/lib/datagrid/columns/column.rb @@ -41,7 +41,7 @@ def initialize(grid_class, name, query, options = {}, &block) self.options = options if options[:class] Datagrid::Utils.warn_once( - "column[class] option is deprecated. Use {tag_options: {class: ...}} instead." + "column[class] option is deprecated. Use {tag_options: {class: ...}} instead.", ) self.options[:tag_options] = { **self.options.fetch(:tag_options, {}), @@ -123,7 +123,7 @@ def tag_options def html_class Datagrid::Utils.warn_once( - "Column#html_class is deprecated. Use Column#tag_options instead." + "Column#html_class is deprecated. Use Column#tag_options instead.", ) options[:class] end diff --git a/lib/datagrid/form_builder.rb b/lib/datagrid/form_builder.rb index 1562298..078d739 100644 --- a/lib/datagrid/form_builder.rb +++ b/lib/datagrid/form_builder.rb @@ -39,6 +39,7 @@ def datagrid_label(filter_or_attribute, text = nil, **options, &block) # * `type` - special attribute the determines an input tag to be made. # Examples: `text`, `select`, `textarea`, `number`, `date` etc. # @return [String] an input tag for the corresponding filter name + # @param [Object] attribute_or_filter def datagrid_filter_input(attribute_or_filter, **options, &block) filter = datagrid_get_filter(attribute_or_filter) options = add_filter_options(filter, **options) diff --git a/lib/datagrid/helper.rb b/lib/datagrid/helper.rb index 7a8af0e..9cdb5f4 100644 --- a/lib/datagrid/helper.rb +++ b/lib/datagrid/helper.rb @@ -69,6 +69,7 @@ def datagrid_table(grid, assets = grid.assets, **options) # * <tt>:partials</tt> - Path for partials lookup. # Default: 'datagrid'. # @param grid [Datagrid] grid object + # @param [Object] opts (deprecated) pass keyword arguments instead # @param [Hash] options # @return [String] HTML table header tag markup def datagrid_header(grid, opts = :__unspecified__, **options) @@ -135,6 +136,7 @@ def datagrid_order_for(grid, column, options = {}) # * <tt>:model</tt> - Datagrid object to be rendedred. # * All options supported by Rails <tt>form_with</tt> helper # @param grid [Datagrid] grid object + # @param [Hash{Symbol => Object}] options # @return [String] form HTML tag markup def datagrid_form_with(**options) raise ArgumentError, "datagrid_form_with block argument is invalid. Use form_with instead." if block_given? diff --git a/spec/datagrid/filters/date_time_filter_spec.rb b/spec/datagrid/filters/date_time_filter_spec.rb index 9b6f807..990c1be 100644 --- a/spec/datagrid/filters/date_time_filter_spec.rb +++ b/spec/datagrid/filters/date_time_filter_spec.rb @@ -168,7 +168,7 @@ def entry_dated(date) it "supports serialized range value" do from = Time.parse("2013-01-01 01:00") to = Time.parse("2013-01-02 02:00") - report = test_grid_filter(:created_at, :datetime, range: true) + report = test_grid_filter(:created_at, :datetime, range: true) report.created_at = (from..to).as_json expect(report.created_at).to eq(from..to) diff --git a/spec/datagrid/filters/integer_filter_spec.rb b/spec/datagrid/filters/integer_filter_spec.rb index 4c310bb..c5b76fb 100644 --- a/spec/datagrid/filters/integer_filter_spec.rb +++ b/spec/datagrid/filters/integer_filter_spec.rb @@ -132,7 +132,7 @@ end it "supports serialized range value" do - report = test_grid_filter(:group_id, :integer, range: true) + report = test_grid_filter(:group_id, :integer, range: true) report.group_id = (1..5).as_json expect(report.group_id).to eq(1..5) diff --git a/spec/datagrid/form_builder_spec.rb b/spec/datagrid/form_builder_spec.rb index 4fbf5b5..cdccec7 100644 --- a/spec/datagrid/form_builder_spec.rb +++ b/spec/datagrid/form_builder_spec.rb @@ -102,7 +102,7 @@ class MyTemplate context "date filter type is text" do let(:_filter) { :created_at } let(:_grid) do - test_grid_filter(:created_at, :date, input_options: { type: 'text' }) + test_grid_filter(:created_at, :date, input_options: { type: "text" }) end it { diff --git a/spec/datagrid/helper_spec.rb b/spec/datagrid/helper_spec.rb index 8d0c4d5..d99a9e6 100644 --- a/spec/datagrid/helper_spec.rb +++ b/spec/datagrid/helper_spec.rb @@ -286,7 +286,7 @@ it "should render argument-based html blocks with double arguments" do rp = test_grid_column(:name, html: lambda { |data, model| tag.h1 "#{data}-#{model.name.downcase}" - }) + },) expect(subject.datagrid_rows(rp, [entry])).to match_css_pattern( "tr td[data-column=name] h1" => "Star-star", ) @@ -354,17 +354,17 @@ report = test_grid(order: :name, descending: true) do scope { Entry } column(:name, tag_options: { - class: 'my-class', + class: "my-class", "data-column-group": "core", "data-column": nil, - }) + },) end expect(subject.datagrid_rows(report, [entry])).to equal_to_dom(<<~HTML) <tr> <td class="my-class datagrid-order-active-desc" data-column-group="core">Star</td> </tr> - HTML + HTML end context "when grid has complicated columns" do @@ -710,30 +710,30 @@ def param_name grid = test_grid(order: :name, descending: true) do scope { Entry } column(:name, order: false, tag_options: { - class: 'my-class', + class: "my-class", "data-column-group": "core", "data-column": nil, - }) + },) end expect(subject.datagrid_header(grid)).to equal_to_dom(<<~HTML) <tr> <th class="my-class datagrid-order-active-desc" data-column-group="core">Name</th> </tr> - HTML + HTML end it "supports deprecated options passing" do grid = test_grid_column(:name) silence_deprecator do expect( - subject.datagrid_header(grid, {order: false}) + subject.datagrid_header(grid, { order: false }), ).to equal_to_dom(<<~HTML) - <tr> - <th data-column="name" class=""> - Name - </th> - </tr> + <tr> + <th data-column="name" class=""> + Name + </th> + </tr> HTML end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index cbcefb8..345c7c7 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -106,7 +106,7 @@ def silence_deprecator(&block) Datagrid::Utils.deprecator.silence(&block) end -def expect_deprecated(message = /deprecated/, &block) +def expect_deprecated(message = %r{deprecated}, &block) expect(Datagrid::Utils.deprecator).to receive(:warn).with(message) block.call end From 1b1fc9c518bd246979d60f6c2d5bcfb1903e8ba9 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 18 Nov 2024 20:38:40 +0100 Subject: [PATCH 151/157] Readme links to rdoc --- README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 47a620b..8f5b067 100644 --- a/README.md +++ b/README.md @@ -33,9 +33,12 @@ including admin panels, analytics and data browsers: ## Documentation -* Readme - this read-me for basic information. -* [Wiki](https://github.com/bogdan/datagrid/wiki) - general reference on how to use the gem. -* [Rdoc](https://rubydoc.info/gems/datagrid) - API reference. +* [Rdoc](https://rubydoc.info/gems/datagrid) - full API reference +* [Scope](https://rubydoc.info/gems/datagrid/Datagrid/Core) - working with datagrid scope +* [Columns](https://rubydoc.info/gems/datagrid/Datagrid/Columns) - definging datagrid columns +* [Filters](https://rubydoc.info/gems/datagrid/Datagrid/Filters) - defining datagrid filters +* [Frontend](https://rubydoc.info/gems/datagrid/Datagrid/Helper) - building a frontend +* [Configuration](https://rubydoc.info/gems/datagrid/Datagrid/Configuration) - configuring the gem ### Live Demo @@ -122,7 +125,7 @@ scope do end ``` -[More about scope](https://github.com/bogdan/datagrid/wiki/Scope) +[More about scope](https://rubydoc.info/gems/datagrid/Datagrid/Core) ### Filters @@ -146,7 +149,7 @@ Datagrid supports different type of filters including: * string * dynamic - build dynamic SQL condition -[More about filters](https://github.com/bogdan/datagrid/wiki/Filters) +[More about filters](https://rubydoc.info/gems/datagrid/Datagrid/Filters) ### Columns @@ -195,7 +198,7 @@ rails g datagrid::views All advanced frontend things are described in: -[Frontend section on wiki](https://github.com/bogdan/datagrid/wiki/Frontend) +[Frontend section on wiki](https://rubydoc.info/gems/datagrid/Datagrid/Helper) ## Questions & Issues From a26aa1a31060002864fe440672b1da9b31575c8a Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Mon, 18 Nov 2024 20:53:02 +0100 Subject: [PATCH 152/157] Update doc according to v2 --- lib/datagrid/columns.rb | 4 +--- lib/datagrid/filters.rb | 12 +++++------- lib/datagrid/helper.rb | 36 +++++++++++++++--------------------- 3 files changed, 21 insertions(+), 31 deletions(-) diff --git a/lib/datagrid/columns.rb b/lib/datagrid/columns.rb index bf3c4c8..87a3599 100644 --- a/lib/datagrid/columns.rb +++ b/lib/datagrid/columns.rb @@ -6,9 +6,7 @@ module Datagrid # Defines a column to be used for displaying data in a Datagrid. # - # class UserGrid - # include Datagrid - # + # class UserGrid < ApplicationGrid # scope do # User.order("users.created_at desc").joins(:group) # end diff --git a/lib/datagrid/filters.rb b/lib/datagrid/filters.rb index 67cdec6..f13540f 100644 --- a/lib/datagrid/filters.rb +++ b/lib/datagrid/filters.rb @@ -6,9 +6,7 @@ module Datagrid # Defines the accessible attribute that is used to filter # the scope by the specified value with specified code. # - # class UserGrid - # include Datagrid - # + # class UserGrid < ApplicationGrid # scope do # User # end @@ -64,13 +62,13 @@ module Datagrid # # `:date` - Converts value to a date. Supports the `:range` option to accept date ranges. # - # filter(:created_at, :date, range: true, default: proc { [1.month.ago.to_date, Date.today] }) + # filter(:created_at, :date, range: true, default: proc { 1.month.ago.to_date..Date.today }) # # == Datetime # # `:datetime` - Converts value to a timestamp. Supports the `:range` option to accept time ranges. # - # filter(:created_at, :datetime, range: true, default: proc { [1.hour.ago, Time.now] }) + # filter(:created_at, :datetime, range: true, default: proc { 1.hour.ago..Time.now }) # # == Enum # @@ -93,7 +91,7 @@ module Datagrid # # `:integer` - Converts value to an integer. Supports the `:range` option. # - # filter(:posts_count, :integer, range: true, default: [1, nil]) + # filter(:posts_count, :integer, range: true, default: (1..nil)) # # == String # @@ -123,7 +121,7 @@ module Datagrid # Example: # # filter(:id, :integer, header: "Identifier") - # filter(:created_at, :date, range: true, default: proc { [1.month.ago.to_date, Date.today] }) + # filter(:created_at, :date, range: true, default: proc { 1.month.ago.to_date..Date.today }) # # = Localization # diff --git a/lib/datagrid/helper.rb b/lib/datagrid/helper.rb index e5cd312..a298b0f 100644 --- a/lib/datagrid/helper.rb +++ b/lib/datagrid/helper.rb @@ -55,15 +55,15 @@ module Datagrid # # Use the built-in partial: # - # = datagrid_form_for @grid, url: report_path, other_form_for_option: value + # = datagrid_form_with model: @grid, url: report_path, other_form_for_option: value # - # {#datagrid_form_for} supports the same options as Rails `form_for`. + # {#datagrid_form_with} supports the same options as Rails `form_with`. # # === Advanced Method # # You can use Rails built-in tools to create a form. Additionally, Datagrid provides helpers to generate input/select elements for filters: # - # - form_for UserGrid.new, method: :get, url: users_path do |f| + # - form_with model: UserGrid.new, method: :get, url: users_path do |f| # %div # = f.datagrid_label :name # = f.datagrid_filter :name # => <input name="grid[name]" type="text"/> @@ -73,7 +73,7 @@ module Datagrid # # To create a report form: # - # - form_for @report, method: :get, url: users_path do |f| + # - form_with model: @report, method: :get, url: users_path do |f| # - @report.filters.each do |filter| # %div # = f.datagrid_label filter @@ -156,7 +156,7 @@ module Datagrid # # Modify the form for AJAX: # - # = datagrid_form_for @grid, html: {class: 'js-datagrid-form'} + # = datagrid_form_with model: @grid, html: {class: 'js-datagrid-form'} # .js-datagrid-table # = datagrid_table @grid # .js-pagination @@ -179,9 +179,8 @@ module Datagrid # # app/views/datagrid/ # ├── _enum_checkboxes.html.erb # datagrid_filter for filter(name, :enum, checkboxes: true) - # ├── _form.html.erb # datagrid_form_for + # ├── _form.html.erb # datagrid_form_with # ├── _head.html.erb # datagrid_header - # ├── _order_for.html.erb # datagrid_order_for # ├── _range_filter.html.erb # datagrid_filter for filter(name, type, range: true) # ├── _row.html.erb # datagrid_rows/datagrid_rows # └── _table.html.erb # datagrid_table @@ -198,18 +197,14 @@ module Datagrid # category.orders.sum(:subtotal) / category.orders.count # end # - # The `:description` option is not built into Datagrid, but you can implement it by modifying the column header - # partial `app/views/datagrid/_header.html.erb` like this: + # The `:description` option is not built into Datagrid, but you can implement it + # by adding the following to partial `app/views/datagrid/_header.html.erb`: # - # %tr - # - grid.html_columns(*options[:columns]).each do |column| - # %th{class: datagrid_column_classes(grid, column)} - # = column.header - # - if column.options[:description] - # %a{data: {toggle: 'tooltip', title: column.options[:description]}} - # %i.icon-question-sign - # - if column.order && options[:order] - # = datagrid_order_for(grid, column, options) + # <% if column.options[:description] %> + # <a data-toggle="tooltip" title="<%= column.options[:description] %>"> + # <i class="icon-question-sign"></i> + # </a> + # <% end %> # # This modification allows the `:description` tooltip to work with your chosen UI and JavaScript library. # The same technique can be applied to filters by calling `filter.options` in corresponding partials. @@ -228,8 +223,7 @@ module Datagrid # # This allows you to define a custom `row_class` method in your grid class, like this: # - # class IssuesGrid - # include Datagrid + # class IssuesGrid < ApplicationGrid # scope { Issue } # # def row_class(issue) @@ -396,7 +390,7 @@ def datagrid_form_with(**options) # # * <tt>:partials</tt> - Path for form partial lookup. # Default: 'datagrid'. - # * All options supported by Rails <tt>form_for</tt> helper + # * All options supported by Rails <tt>form_with</tt> helper # @deprecated Use {#datagrid_form_with} instead. # @param grid [Datagrid] grid object # @param [Hash] options From 08e236955f0ae6b024b1e811072d279f163f381e Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Tue, 19 Nov 2024 10:33:22 +0100 Subject: [PATCH 153/157] v2.0.0-alpha --- lib/datagrid/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/datagrid/version.rb b/lib/datagrid/version.rb index 9b62e71..403ac57 100644 --- a/lib/datagrid/version.rb +++ b/lib/datagrid/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Datagrid - VERSION = "2.0.0" + VERSION = "2.0.0-alpha" end From 42aabb1e79fa21c3fb73e4367c1caef7276dfefe Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Tue, 19 Nov 2024 10:38:41 +0100 Subject: [PATCH 154/157] Add yardopts to gemspec --- datagrid.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/datagrid.gemspec b/datagrid.gemspec index f1aac51..be63ba3 100644 --- a/datagrid.gemspec +++ b/datagrid.gemspec @@ -19,6 +19,7 @@ Gem::Specification.new do |s| "CHANGELOG.md", "README.md", "datagrid.gemspec", + ".yardopts", ] s.files += `git ls-files | grep -E '^(app|lib|templates)'`.split("\n") s.homepage = "https://github.com/bogdan/datagrid" From dff4a5f9273f8aa84209b84a13fddf82cc142658 Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Tue, 19 Nov 2024 19:29:17 +0100 Subject: [PATCH 155/157] Improve doc --- README.md | 2 -- lib/datagrid/columns.rb | 21 +++++++++++------- lib/datagrid/filters.rb | 1 - lib/datagrid/filters/float_filter.rb | 1 - lib/datagrid/helper.rb | 33 +++++++++++++++------------- 5 files changed, 31 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 8f5b067..24fa669 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,6 @@ including admin panels, analytics and data browsers: * Sequel * Array (in-memory data of smaller scale) -[Create an issue](https://github.com/bogdan/datagrid/issues/new) if you want more. - ## Datagrid Philosophy 1. Expressive DSL complements OOD instead of replacing it. diff --git a/lib/datagrid/columns.rb b/lib/datagrid/columns.rb index f18d55d..8570396 100644 --- a/lib/datagrid/columns.rb +++ b/lib/datagrid/columns.rb @@ -403,14 +403,14 @@ def assets ) end - # @param column_names [Array<String>] list of column names if you want to limit data only to specified columns + # @param column_names [Array<String, Symbol>] list of column names if you want to limit data only to specified columns # @return [Array<String>] human readable column names. See also "Localization" section def header(*column_names) data_columns(*column_names).map(&:header) end # @param asset [Object] asset from datagrid scope - # @param column_names [Array<String>] list of column names if you want to limit data only to specified columns + # @param column_names [Array<String, Symbol>] list of column names if you want to limit data only to specified columns # @return [Array<Object>] column values for given asset def row_for(asset, *column_names) data_columns(*column_names).map do |column| @@ -428,7 +428,7 @@ def hash_for(asset) result end - # @param column_names [Array<String>] list of column names if you want to limit data only to specified columns + # @param column_names [Array<String,Symbol>] list of column names if you want to limit data only to specified columns # @return [Array<Array<Object>>] with data for each row in datagrid assets without header def rows(*column_names) map_with_batches do |asset| @@ -436,7 +436,7 @@ def rows(*column_names) end end - # @param column_names [Array<String>] list of column names if you want to limit data only to specified columns + # @param column_names [Array<String, Symbol>] list of column names if you want to limit data only to specified columns # @return [Array<Array<Object>>] data for each row in datagrid assets with header. def data(*column_names) rows(*column_names).unshift(header(*column_names)) @@ -461,7 +461,7 @@ def data_hash end end - # @param column_names [Array<String>] + # @param column_names [Array<String,Symbol>] # @param options [Hash] CSV generation options # @return [String] a CSV representation of the data in the grid # @@ -537,7 +537,7 @@ def column_by_name(name) # end # @return [Datagrid::Columns::Column::ResponseFormat] Format object def format(value, &block) - if block_given? + if block self.class.format(value, &block) else # don't override Object#format method @@ -545,6 +545,7 @@ def format(value, &block) end end + # @param [Object] asset one of the assets from grid scope # @return [Datagrid::Columns::DataRow] an object representing a grid row. # @example # class MyGrid @@ -564,7 +565,6 @@ def data_row(asset) end # Defines a column at instance level - # # @see Datagrid::Columns::ClassMethods#column def column(name, query = nil, **options, &block) self.class.define_column(columns_array, name, query, **options, &block) @@ -578,7 +578,6 @@ def initialize(*) # @return [Array<Datagrid::Columns::Column>] all columns # that are possible to be displayed for the current grid object - # # @example # class MyGrid # filter(:search) {|scope, value| scope.full_text_search(value)} @@ -600,6 +599,8 @@ def available_columns end end + # @param [String,Symbol] column_name column name + # @param [Object] asset one of the assets from grid scope # @return [Object] a cell data value for given column name and asset def data_value(column_name, asset) column = column_by_name(column_name) @@ -611,6 +612,9 @@ def data_value(column_name, asset) end end + # @param [String,Symbol] column_name column name + # @param [Object] asset one of the assets from grid scope + # @param [ActionView::Base] context view context object # @return [Object] a cell HTML value for given column name and asset and view context def html_value(column_name, context, asset) column = column_by_name(column_name) @@ -624,6 +628,7 @@ def html_value(column_name, context, asset) end end + # @param [Object] model one of the assets from grid scope # @return [Object] a decorated version of given model if decorator is specified or the model otherwise. def decorate(model) self.class.decorate(model) diff --git a/lib/datagrid/filters.rb b/lib/datagrid/filters.rb index 8e5a2cb..6856b77 100644 --- a/lib/datagrid/filters.rb +++ b/lib/datagrid/filters.rb @@ -161,7 +161,6 @@ module Filters extend ActiveSupport::Concern - # @!visibility private included do include Datagrid::Core class_attribute :filters_array, default: [] diff --git a/lib/datagrid/filters/float_filter.rb b/lib/datagrid/filters/float_filter.rb index 2c9b164..d6b586c 100644 --- a/lib/datagrid/filters/float_filter.rb +++ b/lib/datagrid/filters/float_filter.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -# @!visibility private module Datagrid module Filters class FloatFilter < Datagrid::Filters::BaseFilter diff --git a/lib/datagrid/helper.rb b/lib/datagrid/helper.rb index 3bf4e75..dca8579 100644 --- a/lib/datagrid/helper.rb +++ b/lib/datagrid/helper.rb @@ -240,7 +240,7 @@ module Datagrid # # https://github.com/bogdan/datagrid/blob/master/lib/datagrid/locale/en.yml module Helper - # @param grid [Datagrid] grid object + # @param grid [Datagrid::Base] grid object # @param column [Datagrid::Columns::Column, String, Symbol] column name # @param model [Object] an object from grid scope # @return [Object] individual cell value from the given grid, column name and model @@ -264,7 +264,7 @@ def datagrid_format_value(grid, column, model) # Renders html table with columns defined in grid class. # In the most common used you need to pass paginated collection # to datagrid table because datagrid do not have pagination compatibilities: - # @param grid [Datagrid] grid object + # @param grid [Datagrid::Base] grid object # @param assets [Array] objects from grid scope # @param [Hash{Symbol => Object}] options HTML attributes to be passed to `<table>` tag # @option options [Hash] html A hash of attributes for the `<table>` tag. @@ -298,7 +298,7 @@ def datagrid_table(grid, assets = grid.assets, **options) # Default: all defined columns. # @option options [String] partials The path for partials lookup. # Default: `'datagrid'`. - # @param grid [Datagrid] grid object + # @param grid [Datagrid::Base] grid object # @param [Object] opts (deprecated) pass keyword arguments instead # @param [Hash] options # @return [String] HTML table header tag markup @@ -329,6 +329,8 @@ def datagrid_header(grid, opts = :__unspecified__, **options) # %tr # %td= row.project_name # %td.project-status{class: row.status}= row.status + # @param [Datagrid::Base] grid datagrid object + # @param [Array<Object>] assets assets as per defined in grid scope def datagrid_rows(grid, assets = grid.assets, **options, &block) safe_join( assets.map do |asset| @@ -340,6 +342,10 @@ def datagrid_rows(grid, assets = grid.assets, **options, &block) # @return [String] renders ordering controls for the given column name # @option options [String] partials The path for partials lookup. # Default: `'datagrid'`. + # @param [Datagrid::Base] grid datagrid object + # @param [Datagrid::Columns::Column] column + # @deprecated Put necessary code inline inside datagrid/head partial. + # See built-in partial for example. def datagrid_order_for(grid, column, options = {}) Datagrid::Utils.warn_once(<<~MSG) datagrid_order_for is deprecated. @@ -351,15 +357,12 @@ def datagrid_order_for(grid, column, options = {}) end # Renders HTML for grid with all filters inputs and labels defined in it - # - # Supported options: - # - # * <tt>:partials</tt> - Path for form partial lookup. - # Default: 'datagrid' results in using `app/views/datagrid/` partials. - # Example: 'datagrid_admin' results in using `app/views/datagrid_admin` partials. - # * <tt>:model</tt> - Datagrid object to be rendedred. - # * All options supported by Rails <tt>form_with</tt> helper - # @param grid [Datagrid] grid object + # @option options [String] partials Path for form partial lookup. + # Default: `'datagrid'`, which uses `app/views/datagrid/` partials. + # Example: `'datagrid_admin'` uses `app/views/datagrid_admin` partials. + # @option options [Object] model The Datagrid object to be rendered. + # @option options [Hash] All options supported by Rails `form_with` helper. + # @param grid [Datagrid::Base] grid object # @param [Hash{Symbol => Object}] options # @return [String] form HTML tag markup def datagrid_form_with(**options) @@ -379,7 +382,7 @@ def datagrid_form_with(**options) # Default: 'datagrid'. # * All options supported by Rails <tt>form_with</tt> helper # @deprecated Use {#datagrid_form_with} instead. - # @param grid [Datagrid] grid object + # @param grid [Datagrid::Base] grid object # @param [Hash] options # @return [String] form HTML tag markup def datagrid_form_for(grid, options = {}) @@ -398,7 +401,7 @@ def datagrid_form_for(grid, options = {}) # Provides access to datagrid columns data. # Used in case you want to build html table completelly manually - # @param grid [Datagrid] grid object + # @param grid [Datagrid::Base] grid object # @param asset [Object] object from grid scope # @param block [Proc] block with Datagrid::Helper::HtmlRow as an argument returning a HTML markup as a String # @param [Hash{Symbol => Object}] options @@ -423,7 +426,7 @@ def datagrid_row(grid, asset, **options, &block) end # Generates an ascending or descending order url for the given column - # @param grid [Datagrid] grid object + # @param grid [Datagrid::Base] grid object # @param column [Datagrid::Columns::Column, String, Symbol] column name # @param descending [Boolean] order direction, descending if true, otherwise ascending. # @return [String] order layout HTML markup From 3558341687f4648f866cab87c8a931130e78dc7d Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Tue, 19 Nov 2024 20:11:04 +0100 Subject: [PATCH 156/157] Improve docs --- README.md | 2 +- datagrid.gemspec | 2 +- lib/datagrid/columns.rb | 128 ++++++++++++++++------------------ lib/datagrid/configuration.rb | 6 +- lib/datagrid/filters.rb | 4 +- lib/datagrid/helper.rb | 11 +-- version-2/Readme.markdown | 8 +-- 7 files changed, 79 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index 24fa669..19d8fd2 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,7 @@ end Some formatting options are also available. Each column is sortable. -[More about columns](https://github.com/bogdan/datagrid/wiki/Columns) +[More about columns](https://rubydoc.info/gems/datagrid/Datagrid/Columns) ### Front end diff --git a/datagrid.gemspec b/datagrid.gemspec index be63ba3..419c4d1 100644 --- a/datagrid.gemspec +++ b/datagrid.gemspec @@ -28,7 +28,7 @@ Gem::Specification.new do |s| s.metadata = { "homepage_uri" => s.homepage, "bug_tracker_uri" => "#{s.homepage}/issues", - "documentation_uri" => "#{s.homepage}/wiki", + "documentation_uri" => "https://rubydoc.info/gems/datagrid", "changelog_uri" => "#{s.homepage}/blob/main/CHANGELOG.md", "source_code_uri" => s.homepage, "rubygems_mfa_required" => "true", diff --git a/lib/datagrid/columns.rb b/lib/datagrid/columns.rb index 8570396..795f1e7 100644 --- a/lib/datagrid/columns.rb +++ b/lib/datagrid/columns.rb @@ -2,6 +2,7 @@ require "datagrid/utils" require "active_support/core_ext/class/attribute" +require "datagrid/columns/column" module Datagrid # Defines a column to be used for displaying data in a Datagrid. @@ -199,29 +200,26 @@ module Datagrid # presenter.user.created_at # end module Columns - require "datagrid/columns/column" - - # @!method default_column_options=(value) - # @param [Hash] value default options passed to #column method call - # @return [Hash] default options passed to #column method call - # @example - # # Disable default order + # @param [Hash] value default options passed to {#column} method call + # @return [Hash] default options passed to {#column} method call + # @example Disable default order # self.default_column_options = { order: false } - # # Makes entire report HTML + # @example Makes entire report HTML # self.default_column_options = { html: true } + # @!method default_column_options=(value) - # @!method default_column_options - # @return [Hash] + # @return [Hash] default options passed to {#column} method call # @see #default_column_options= + # @!method default_column_options # @!method batch_size=(value) - # @param [Integer] value Specify a default batch size when generating CSV or just data. Default: 1000 - # @return [Integer] Specify a default batch size when generating CSV or just data. - # @example + # Specify a default batch size when generating CSV or just data. + # @param [Integer] value a batch size when generating CSV or just data. Default: 1000 + # @return [void] + # @example Set batch size to 500 # self.batch_size = 500 - # # Disable batches + # @example Disable batches # self.batch_size = nil - # # @!method batch_size # @return [Integer] @@ -253,37 +251,31 @@ def columns(*column_names, data: false, html: false) filter_columns(columns_array, *column_names, data: data, html: html) end - # Defines new datagrid column - # + # Defines a new datagrid column # @param name [Symbol] column name # @param query [String, nil] a string representing the query to select this column (supports only ActiveRecord) - # @param options [Hash{Symbol => Object}] hash of options # @param block [Block] proc to calculate a column value + # @option options [Boolean, String] html Determines if the column should be present + # in the HTML table and how it is formatted. + # @option options [String, Array<Symbol>] order Determines if the column can be sortable and + # specifies the ORM ordering method. + # Example: `"created_at, id"` for ActiveRecord, `[:created_at, :id]` for Mongoid. + # @option options [String] order_desc Specifies a descending order for the column + # (used when `:order` cannot be easily reversed by the ORM). + # @option options [Boolean, Proc] order_by_value Enables Ruby-level ordering for the column. + # Warning: Sorting large datasets in Ruby is not recommended. + # If `true`, Datagrid orders by the column value. + # If a block is provided, Datagrid orders by the block's return value. + # @option options [Boolean] mandatory If `true`, the column will never be hidden by the `#column_names` selection. + # @option options [Symbol] before Places the column before the specified column when determining order. + # @option options [Symbol] after Places the column after the specified column when determining order. + # @option options [Boolean, Proc] if conditions when a column is available. + # @option options [Boolean, Proc] unless conditions when a column is not available. + # @option options [Symbol, Array<Symbol>] preload Specifies associations + # to preload for the column within the scope. + # @option options [Hash] tag_options Specifies HTML attributes for the `<td>` or `<th>` of the column. + # Example: `{ class: "content-align-right", "data-group": "statistics" }`. # @return [Datagrid::Columns::Column] - # - # Available options: - # - # * <tt>html</tt> - determines if current column should be present in html table and how is it formatted - # * <tt>order</tt> - determines if this column could be sortable and how. - # The value of order is explicitly passed to ORM ordering method. - # Example: <tt>"created_at, id"</tt> for ActiveRecord, <tt>[:created_at, :id]</tt> for Mongoid - # * <tt>order_desc</tt> - determines a descending order for given column - # (only in case when <tt>:order</tt> can not be easily reversed by ORM) - # * <tt>order_by_value</tt> - used in case it is easier to perform ordering at ruby level not on database level. - # Warning: using ruby to order large datasets is very unrecommended. - # If set to true - datagrid will use column value to order by this column - # If block is given - datagrid will use value returned from block - # * <tt>mandatory</tt> - if true, column will never be hidden with #column_names selection - # * <tt>url</tt> - a proc with one argument, pass this option to easily convert the value into an URL - # * <tt>before</tt> - determines the position of this column, by adding it before the column passed here - # * <tt>after</tt> - determines the position of this column, by adding it after the column passed here - # * <tt>if</tt> - the column is shown if the reult of calling this argument is true - # * <tt>unless</tt> - the column is shown unless the reult of calling this argument is true - # * <tt>preload</tt> - spefies which associations of the scope should be preloaded for this column - # * `tag_options` - specify HTML attributes to be set for `<td>` or `<th>` of a column - # Example: `{ class: "content-align-right", "data-group": "statistics" }` - # - # @see https://github.com/bogdan/datagrid/wiki/Columns def column(name, query = nil, **options, &block) define_column(columns_array, name, query, **options, &block) end @@ -333,10 +325,10 @@ def format(value, &block) # Defines a model decorator that will be used to define a column value. # All column blocks will be given a decorated version of the model. # @return [void] - # @example + # @example Wrapping a model with presenter # decorate { |user| UserPresenter.new(user) } - # - # decorate { UserPresenter } # a shortcut + # @example A shortcut for doing the same + # decorate { UserPresenter } def decorate(model = nil, &block) if !model && !block raise ArgumentError, "decorate needs either a block to define decoration or a model to decorate" @@ -403,14 +395,16 @@ def assets ) end - # @param column_names [Array<String, Symbol>] list of column names if you want to limit data only to specified columns + # @param column_names [Array<String, Symbol>] list of column names + # if you want to limit data only to specified columns # @return [Array<String>] human readable column names. See also "Localization" section def header(*column_names) data_columns(*column_names).map(&:header) end # @param asset [Object] asset from datagrid scope - # @param column_names [Array<String, Symbol>] list of column names if you want to limit data only to specified columns + # @param column_names [Array<String, Symbol>] list of column names + # if you want to limit data only to specified columns # @return [Array<Object>] column values for given asset def row_for(asset, *column_names) data_columns(*column_names).map do |column| @@ -419,7 +413,8 @@ def row_for(asset, *column_names) end # @param asset [Object] asset from datagrid scope - # @return [Hash] A mapping where keys are column names and values are column values for the given asset + # @return [Hash] A mapping where keys are column names and + # values are column values for the given asset def hash_for(asset) result = {} data_columns.each do |column| @@ -428,7 +423,8 @@ def hash_for(asset) result end - # @param column_names [Array<String,Symbol>] list of column names if you want to limit data only to specified columns + # @param column_names [Array<String,Symbol>] list of column names + # if you want to limit data only to specified columns # @return [Array<Array<Object>>] with data for each row in datagrid assets without header def rows(*column_names) map_with_batches do |asset| @@ -436,7 +432,8 @@ def rows(*column_names) end end - # @param column_names [Array<String, Symbol>] list of column names if you want to limit data only to specified columns + # @param column_names [Array<String, Symbol>] list of column names + # if you want to limit data only to specified columns. # @return [Array<Array<Object>>] data for each row in datagrid assets with header. def data(*column_names) rows(*column_names).unshift(header(*column_names)) @@ -514,7 +511,7 @@ def html_columns(*column_names, data: false) columns(*column_names, data: data, html: true) end - # Finds a column definition by name + # Finds a column by name # @param name [String, Symbol] column name to be found # @return [Datagrid::Columns::Column, nil] def column_by_name(name) @@ -522,17 +519,16 @@ def column_by_name(name) end # Gives ability to have a different formatting for CSV and HTML column value. - # - # @example + # @example Formating using Rails view helpers # column(:name) do |model| # format(model.name) do |value| # tag.strong(value) # end # end - # + # @example Formatting using a separated view template # column(:company) do |model| # format(model.company.name) do - # render partial: "company_with_logo", locals: {company: model.company } + # render partial: "companies/company_with_logo", locals: {company: model.company } # end # end # @return [Datagrid::Columns::Column::ResponseFormat] Format object @@ -548,18 +544,18 @@ def format(value, &block) # @param [Object] asset one of the assets from grid scope # @return [Datagrid::Columns::DataRow] an object representing a grid row. # @example - # class MyGrid - # scope { User } - # column(:id) - # column(:name) - # column(:number_of_purchases) do |user| - # user.purchases.count - # end - # end + # class MyGrid + # scope { User } + # column(:id) + # column(:name) + # column(:number_of_purchases) do |user| + # user.purchases.count + # end + # end # - # row = MyGrid.new.data_row(User.last) - # row.id # => user.id - # row.number_of_purchases # => user.purchases.count + # row = MyGrid.new.data_row(User.last) + # row.id # => user.id + # row.number_of_purchases # => user.purchases.count def data_row(asset) ::Datagrid::Columns::DataRow.new(self, asset) end diff --git a/lib/datagrid/configuration.rb b/lib/datagrid/configuration.rb index 5c64e3e..a80e8b2 100644 --- a/lib/datagrid/configuration.rb +++ b/lib/datagrid/configuration.rb @@ -25,12 +25,14 @@ def self.configure(&block) # Datagrid.configure do |config| # # Defines date formats that can be used to parse dates. # # Note: Multiple formats can be specified. The first format is used to format dates as strings, - # # while other formats are used only for parsing dates from strings (e.g., if your app supports multiple formats). + # # while other formats are used only for parsing dates + # # from strings (e.g., if your app supports multiple formats). # config.date_formats = "%m/%d/%Y", "%Y-%m-%d" # # # Defines timestamp formats that can be used to parse timestamps. # # Note: Multiple formats can be specified. The first format is used to format timestamps as strings, - # # while other formats are used only for parsing timestamps from strings (e.g., if your app supports multiple formats). + # # while other formats are used only for parsing timestamps + # # from strings (e.g., if your app supports multiple formats). # config.datetime_formats = ["%m/%d/%Y %h:%M", "%Y-%m-%d %h:%M:%s"] # end # ``` diff --git a/lib/datagrid/filters.rb b/lib/datagrid/filters.rb index 6856b77..19637c8 100644 --- a/lib/datagrid/filters.rb +++ b/lib/datagrid/filters.rb @@ -204,8 +204,8 @@ def filter_by_name(attribute) # Used with the `datagrid_form_for` helper. # @option options [Symbol] after Specifies the position of this filter by placing it after another filter. # Used with the `datagrid_form_for` helper. - # @option options [Boolean] dummy If true, the filter is not applied automatically and is only displayed in the form. - # Useful for manual application. + # @option options [Boolean] dummy If true, the filter is not applied automatically and + # is only displayed in the form. Useful for manual application. # @option options [Proc, Symbol] if Specifies a condition under which the filter is displayed and used. # Accepts a block or the name of an instance method. # @option options [Proc, Symbol] unless Specifies a condition under which the filter is NOT displayed or used. diff --git a/lib/datagrid/helper.rb b/lib/datagrid/helper.rb index dca8579..5a1bc37 100644 --- a/lib/datagrid/helper.rb +++ b/lib/datagrid/helper.rb @@ -17,7 +17,8 @@ module Datagrid # [built-in CSS](https://github.com/bogdan/datagrid/blob/master/app/assets/stylesheets/datagrid.sass). # # Datagrid includes helpers and a form builder for easy frontend generation. - # If you need a fully-featured custom GUI, create your templates manually with the help of the {Datagrid::Columns} API. + # If you need a fully-featured custom GUI, create your templates manually + # with the help of the {Datagrid::Columns} API. # # ## Controller and Routing # @@ -63,7 +64,8 @@ module Datagrid # # ### Advanced Method # - # You can use Rails built-in tools to create a form. Additionally, Datagrid provides helpers to generate input/select elements for filters: + # You can use Rails built-in tools to create a form. + # Additionally, Datagrid provides helpers to generate input/select elements for filters: # # ``` haml # - form_with model: UserGrid.new, method: :get, url: users_path do |f| @@ -360,9 +362,8 @@ def datagrid_order_for(grid, column, options = {}) # @option options [String] partials Path for form partial lookup. # Default: `'datagrid'`, which uses `app/views/datagrid/` partials. # Example: `'datagrid_admin'` uses `app/views/datagrid_admin` partials. - # @option options [Object] model The Datagrid object to be rendered. + # @option options [Datagrid::Base] model a Datagrid object to be rendered. # @option options [Hash] All options supported by Rails `form_with` helper. - # @param grid [Datagrid::Base] grid object # @param [Hash{Symbol => Object}] options # @return [String] form HTML tag markup def datagrid_form_with(**options) @@ -466,7 +467,7 @@ def _render_partial(partial_name, partials_path, locals = {}) # row = datagrid_row(grid, user) # row.class # => Datagrid::Helper::HtmlRow # row.first_name # => "<strong>Bogdan</strong>" - # row.grid # => Grid object + # row.grid # => Datagrid::Base object # row.asset # => User object # row.each do |value| # puts value diff --git a/version-2/Readme.markdown b/version-2/Readme.markdown index 50487b3..50a8e12 100644 --- a/version-2/Readme.markdown +++ b/version-2/Readme.markdown @@ -63,8 +63,6 @@ Rails [deprecates form\_for in favor of form\_with](https://guides.rubyonrails.o `datagrid_form_for` is now deprecated if favor of `datagrid_form_with`. -TODO: update the wiki - ``` ruby # V1 datagrid_form_for(@users_grid, url: users_path) @@ -184,7 +182,7 @@ and avoid collisions with other libraries: | checkboxes | datagrid-enum-checkboxes | All classes are now explicitly assinged inside datagrid partials. -[Modify built-in partials](https://github.com/bogdan/datagrid/wiki/Frontend#modifying-built-in-partials) +[Modify built-in partials](https://rubydoc.info/gems/datagrid/Datagrid/Helper#modifying-built-in-partials) if you want to change them. Diff for [built-in partials between V1 and V2](./views.diff) @@ -370,7 +368,7 @@ instead of classes for column names. * Column name `th[class], td[class]` implemented as `td[data-column], th[data-column]`. Note that the behavior change can be reverted by -[updating built-in partials](https://github.com/bogdan/datagrid/wiki/Frontend#modifying-built-in-partials). +[Modify built-in partials](https://rubydoc.info/gems/datagrid/Datagrid/Helper#modifying-built-in-partials) Version 2 makes it as easy as possible to override the defaults of the UI. ### Filters @@ -451,7 +449,7 @@ Renders: <td class="short-column" data-column="name">John</td> ``` -[Modify built-in views](https://github.com/bogdan/datagrid/wiki/Frontend#modifying-built-in-partials) +[Modify built-in partials](https://rubydoc.info/gems/datagrid/Datagrid/Helper#modifying-built-in-partials) if you want to change this behavior completely. ## Use column[tag\_options] From cca04d990c7997005fbbb1db9c428d870ee59c3f Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev <agresso@gmail.com> Date: Tue, 19 Nov 2024 20:31:38 +0100 Subject: [PATCH 157/157] Fix meta methods doc --- lib/datagrid/columns.rb | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/datagrid/columns.rb b/lib/datagrid/columns.rb index 795f1e7..fdd23e9 100644 --- a/lib/datagrid/columns.rb +++ b/lib/datagrid/columns.rb @@ -200,30 +200,30 @@ module Datagrid # presenter.user.created_at # end module Columns - # @param [Hash] value default options passed to {#column} method call - # @return [Hash] default options passed to {#column} method call - # @example Disable default order - # self.default_column_options = { order: false } - # @example Makes entire report HTML - # self.default_column_options = { html: true } # @!method default_column_options=(value) + # @param [Hash] value default options passed to {#column} method call + # @return [Hash] default options passed to {#column} method call + # @example Disable default order + # self.default_column_options = { order: false } + # @example Makes entire report HTML + # self.default_column_options = { html: true } - # @return [Hash] default options passed to {#column} method call - # @see #default_column_options= # @!method default_column_options + # @return [Hash] default options passed to {#column} method call + # @see #default_column_options= # @!method batch_size=(value) - # Specify a default batch size when generating CSV or just data. - # @param [Integer] value a batch size when generating CSV or just data. Default: 1000 - # @return [void] - # @example Set batch size to 500 - # self.batch_size = 500 - # @example Disable batches - # self.batch_size = nil + # Specify a default batch size when generating CSV or just data. + # @param [Integer] value a batch size when generating CSV or just data. Default: 1000 + # @return [void] + # @example Set batch size to 500 + # self.batch_size = 500 + # @example Disable batches + # self.batch_size = nil # @!method batch_size - # @return [Integer] - # @see #batch_size= + # @return [Integer] + # @see #batch_size= # @visibility private # @param [Object] base