diff --git a/.rubocop.yml b/.rubocop.yml index 0c50cff35..65eae4945 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -219,7 +219,7 @@ Performance/CollectionLiteralInLoop: Exclude: - 'packages/forest_admin_agent/lib/forest_admin_agent/utils/condition_tree_parser.rb' -Naming/PredicateName: +Naming/PredicatePrefix: Exclude: - 'packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/collection.rb' @@ -312,6 +312,7 @@ Metrics/ClassLength: - 'packages/forest_admin_datasource_active_record/lib/forest_admin_datasource_active_record/utils/query.rb' - 'packages/forest_admin_datasource_active_record/lib/forest_admin_datasource_active_record/collection.rb' - 'packages/forest_admin_datasource_active_record/lib/forest_admin_datasource_active_record/datasource.rb' + - 'packages/forest_admin_datasource_active_record/lib/forest_admin_datasource_active_record/utils/query_aggregate.rb' - 'packages/forest_admin_datasource_customizer/lib/forest_admin_datasource_customizer/collection_customizer.rb' - 'packages/forest_admin_datasource_customizer/lib/forest_admin_datasource_customizer/decorators/binary/binary_collection_decorator.rb' - 'packages/forest_admin_datasource_customizer/lib/forest_admin_datasource_customizer/decorators/search/search_collection_decorator.rb' @@ -401,3 +402,10 @@ Style/RedundantParentheses: Style/ClassVars: Enabled: - 'packages/forest_admin_rpc_agent/lib/forest_admin_rpc_agent/middleware/authentication.rb' + +Naming/PredicateMethod: + Exclude: + - 'packages/forest_admin_agent/lib/forest_admin_agent/utils/query_string_parser.rb' + - 'packages/forest_admin_datasource_customizer/lib/forest_admin_datasource_customizer/decorators/empty/empty_collection_decorator.rb' + - 'packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/query/condition_tree/nodes/condition_tree_leaf.rb' + - 'packages/forest_admin_datasource_mongoid/lib/forest_admin_datasource_mongoid/options_parser.rb' diff --git a/Gemfile b/Gemfile index 4404d8130..9b00e1964 100644 --- a/Gemfile +++ b/Gemfile @@ -5,8 +5,8 @@ gemspec group :development, :tests do gem "overcommit", "~> 0.60" gem "rspec", "~> 3.0" - gem "rubocop", "1.72.2" - gem "rubocop-performance", "1.24.0" + gem "rubocop", "1.77" + gem "rubocop-performance", "1.25.0" gem "rubocop-rspec", "3.5.0" gem 'simplecov', "~> 0.22", require: false gem 'simplecov_json_formatter', "~> 0.1.4" diff --git a/packages/forest_admin_agent/lib/forest_admin_agent/routes/charts/charts.rb b/packages/forest_admin_agent/lib/forest_admin_agent/routes/charts/charts.rb index 7e8a52610..2bb67988a 100644 --- a/packages/forest_admin_agent/lib/forest_admin_agent/routes/charts/charts.rb +++ b/packages/forest_admin_agent/lib/forest_admin_agent/routes/charts/charts.rb @@ -118,7 +118,7 @@ def make_line filter_only_with_values, Aggregation.new( operation: @args[:params][:aggregator], - field: @args[:params][:aggregateField], + field: @args[:params][:aggregateFieldName], groups: [{ field: group_by_field_name, operation: time_range }] ) ) diff --git a/packages/forest_admin_agent/lib/forest_admin_agent/routes/resources/native_query.rb b/packages/forest_admin_agent/lib/forest_admin_agent/routes/resources/native_query.rb index 4b365595e..6534adf5e 100644 --- a/packages/forest_admin_agent/lib/forest_admin_agent/routes/resources/native_query.rb +++ b/packages/forest_admin_agent/lib/forest_admin_agent/routes/resources/native_query.rb @@ -103,7 +103,7 @@ def make_leaderboard(result) def make_line(result) return unless result.count - result = result.map! do |result_line| + result.map! do |result_line| raise_error(result_line, "'key', 'value'") if !result_line.key?(:value) || !result_line.key?(:key) { label: result_line[:key], values: { value: result_line[:value] } } diff --git a/packages/forest_admin_agent/lib/forest_admin_agent/services/ip_whitelist.rb b/packages/forest_admin_agent/lib/forest_admin_agent/services/ip_whitelist.rb index f2441440c..cc3e74d5f 100644 --- a/packages/forest_admin_agent/lib/forest_admin_agent/services/ip_whitelist.rb +++ b/packages/forest_admin_agent/lib/forest_admin_agent/services/ip_whitelist.rb @@ -73,7 +73,7 @@ def ip_match_range?(ip, min, max) ip_range_maximum = (IPAddress max) ip_value = (IPAddress ip) - ip_value >= ip_range_minimum && ip_value <= ip_range_maximum + ip_value.between?(ip_range_minimum, ip_range_maximum) end def ip_match_subnet?(ip, subnet) diff --git a/packages/forest_admin_agent/lib/forest_admin_agent/services/permissions.rb b/packages/forest_admin_agent/lib/forest_admin_agent/services/permissions.rb index 4c9902337..f102f9b57 100644 --- a/packages/forest_admin_agent/lib/forest_admin_agent/services/permissions.rb +++ b/packages/forest_admin_agent/lib/forest_admin_agent/services/permissions.rb @@ -123,7 +123,7 @@ def can_smart_action?(request, collection, filter, allow_fetch: true) is_allowed = smart_action_approval.can_execute? ForestAdminAgent::Facades::Container.logger.log( 'Debug', - "User #{user_data[:roleId]} is #{is_allowed ? "" : "not"} allowed to perform #{action["name"]}" + "User #{user_data[:roleId]} is #{"not" unless is_allowed} allowed to perform #{action["name"]}" ) end diff --git a/packages/forest_admin_agent/lib/forest_admin_agent/utils/schema/generator_action_field_widget.rb b/packages/forest_admin_agent/lib/forest_admin_agent/utils/schema/generator_action_field_widget.rb index 75a27d599..a54904558 100644 --- a/packages/forest_admin_agent/lib/forest_admin_agent/utils/schema/generator_action_field_widget.rb +++ b/packages/forest_admin_agent/lib/forest_admin_agent/utils/schema/generator_action_field_widget.rb @@ -171,7 +171,7 @@ def build_number_input_list_widget_edit(field) parameters: { placeholder: field.placeholder, allowDuplicate: field.allow_duplicates.nil? ? false : field.allow_duplicates, - enableReorder: field.enable_reorder.nil? ? true : field.enable_reorder, + enableReorder: field.enable_reorder.nil? || field.enable_reorder, min: valid_number?(field.min) ? field.min : nil, max: valid_number?(field.max) ? field.max : nil, step: valid_number?(field.step) ? field.step : nil diff --git a/packages/forest_admin_datasource_active_record/lib/forest_admin_datasource_active_record/parser/relation.rb b/packages/forest_admin_datasource_active_record/lib/forest_admin_datasource_active_record/parser/relation.rb index 2ea039669..1d5318b0a 100644 --- a/packages/forest_admin_datasource_active_record/lib/forest_admin_datasource_active_record/parser/relation.rb +++ b/packages/forest_admin_datasource_active_record/lib/forest_admin_datasource_active_record/parser/relation.rb @@ -5,7 +5,7 @@ def associations(model, support_polymorphic_relations: false) model.reflect_on_all_associations.select do |association| is_valid_association = !get_class(association).nil? && !active_type?(get_class(association)) if support_polymorphic_relations - polymorphic?(association) ? true : is_valid_association + polymorphic?(association) || is_valid_association else !polymorphic?(association) && is_valid_association end diff --git a/packages/forest_admin_datasource_active_record/lib/forest_admin_datasource_active_record/utils/query_aggregate.rb b/packages/forest_admin_datasource_active_record/lib/forest_admin_datasource_active_record/utils/query_aggregate.rb index ff5e1001b..c37d86a93 100644 --- a/packages/forest_admin_datasource_active_record/lib/forest_admin_datasource_active_record/utils/query_aggregate.rb +++ b/packages/forest_admin_datasource_active_record/lib/forest_admin_datasource_active_record/utils/query_aggregate.rb @@ -5,6 +5,7 @@ class QueryAggregate < Query include ForestAdminDatasourceToolkit::Components::Query def initialize(collection, aggregation, filter = nil, limit = nil) + filter ||= Filter.new super(collection, ForestAdminDatasourceToolkit::Components::Query::Projection.new, filter) @aggregation = aggregation @limit = limit @@ -13,12 +14,16 @@ def initialize(collection, aggregation, filter = nil, limit = nil) end def get + build_select(@collection, @projection) + apply_filter + group_fields = [] @aggregation.groups.each do |group| field = format_field(group[:field]) if group[:operation] - @select << "DATE_TRUNC('#{group[:operation].downcase}', #{field}) AS \"#{group[:field]}\"" - group_fields << "DATE_TRUNC('#{group[:operation].downcase}', #{field})" + date_trunc_expression = date_trunc_sql(group[:operation], field) + @select << "#{date_trunc_expression} AS \"#{group[:field]}\"" + group_fields << date_trunc_expression else @select << "#{field} AS \"#{group[:field]}\"" group_fields << field @@ -29,7 +34,7 @@ def get @query = @query.order("#{@operation} DESC") @query = @query.limit(@limit) if @limit @query = @query.group(group_fields.join(',')) - build + apply_select compute_result_aggregate(@query) end @@ -50,6 +55,74 @@ def add_join_relation(relation_name) @query end + + private + + def date_trunc_sql(operation, field) + adapter_name = @collection.model.connection.adapter_name.downcase + operation = operation.downcase + + case adapter_name + when 'postgresql' + "DATE_TRUNC('#{operation}', #{field})" + when 'mysql2', 'mysql' + mysql_date_trunc(operation, field) + when 'sqlite3', 'sqlite' + sqlite_date_trunc(operation, field) + else + raise ArgumentError, "Unsupported database adapter '#{adapter_name}' for date truncation" + end + end + + # rubocop:disable Layout/LineLength + def mysql_date_trunc(operation, field) + case operation + when 'year' + "DATE_FORMAT(#{field}, '%Y-01-01 00:00:00')" + when 'quarter' + "DATE_FORMAT(#{field}, CONCAT(YEAR(#{field}), '-', LPAD((QUARTER(#{field}) - 1) * 3 + 1, 2, '0'), '-01 00:00:00'))" + when 'month' + "DATE_FORMAT(#{field}, '%Y-%m-01 00:00:00')" + when 'week' + "DATE_SUB(#{field}, INTERVAL WEEKDAY(#{field}) DAY)" + when 'day' + "DATE(#{field})" + when 'hour' + "DATE_FORMAT(#{field}, '%Y-%m-%d %H:00:00')" + when 'minute' + "DATE_FORMAT(#{field}, '%Y-%m-%d %H:%i:00')" + when 'second' + "DATE_FORMAT(#{field}, '%Y-%m-%d %H:%i:%s')" + else + raise ArgumentError, "Unsupported date truncation operation '#{operation}' for MySQL" + end + end + # rubocop:enable Layout/LineLength + + # rubocop:disable Layout/LineLength + def sqlite_date_trunc(operation, field) + case operation + when 'year' + "strftime('%Y-01-01 00:00:00', #{field}, 'localtime')" + when 'quarter' + "strftime('%Y-', #{field}, 'localtime') || printf('%02d', ((CAST(strftime('%m', #{field}, 'localtime') AS INTEGER) - 1) / 3) * 3 + 1) || '-01 00:00:00'" + when 'month' + "strftime('%Y-%m-01 00:00:00', #{field}, 'localtime')" + when 'week' + "datetime(#{field}, 'localtime', 'weekday 0', '-6 days')" + when 'day' + "strftime('%Y-%m-%d 00:00:00', #{field}, 'localtime')" + when 'hour' + "strftime('%Y-%m-%d %H:00:00', #{field}, 'localtime')" + when 'minute' + "strftime('%Y-%m-%d %H:%M:00', #{field}, 'localtime')" + when 'second' + "strftime('%Y-%m-%d %H:%M:%S', #{field}, 'localtime')" + else + raise ArgumentError, "Unsupported date truncation operation '#{operation}' for SQLite" + end + end + # rubocop:enable Layout/LineLength end end end diff --git a/packages/forest_admin_datasource_active_record/spec/lib/forest_admin_datasource_active_record/utils/query_aggregate_spec.rb b/packages/forest_admin_datasource_active_record/spec/lib/forest_admin_datasource_active_record/utils/query_aggregate_spec.rb new file mode 100644 index 000000000..7c5ba5545 --- /dev/null +++ b/packages/forest_admin_datasource_active_record/spec/lib/forest_admin_datasource_active_record/utils/query_aggregate_spec.rb @@ -0,0 +1,109 @@ +require 'spec_helper' + +module ForestAdminDatasourceActiveRecord + module Utils + include ForestAdminDatasourceToolkit::Components::Query + + describe QueryAggregate do + let(:datasource) { Datasource.new({ adapter: 'sqlite3', database: 'db/database.db' }) } + let(:collection) { Collection.new(datasource, Car) } + + describe 'initialize' do + it 'initializes with correct attributes' do + aggregation = Aggregation.new(operation: 'Count', field: nil, groups: []) + query_aggregate = described_class.new(collection, aggregation) + + expect(query_aggregate.instance_variable_get(:@aggregation)).to eq(aggregation) + expect(query_aggregate.instance_variable_get(:@operation)).to eq('count') + expect(query_aggregate.instance_variable_get(:@field)).to eq('*') + end + + it 'formats field when provided' do + aggregation = Aggregation.new(operation: 'Count', field: 'price', groups: []) + + query_aggregate = described_class.new(collection, aggregation) + + expect(query_aggregate.instance_variable_get(:@field)).to eq('price') + end + end + + it 'sets the limit when provided' do + aggregation = Aggregation.new(operation: 'Sum', field: 'price', groups: []) + query_aggregate = described_class.new(collection, aggregation, nil, 10) + + expect(query_aggregate.instance_variable_get(:@limit)).to eq(10) + end + + describe '#get', :db_truncation do + before do + Car.delete_all + Category.delete_all + + category = Category.create!(label: 'SUV') + Car.create!(category: category, brand: 'Toyota', nb_seats: 4, created_at: Time.parse('2024-01-01 UTC')) + Car.create!(category: category, brand: 'Toyota', nb_seats: 5, created_at: Time.parse('2024-01-01 UTC')) + Car.create!(category: category, brand: 'Ford', nb_seats: 5, created_at: Time.parse('2024-02-01 UTC')) + end + + it 'returns aggregated data grouped by a field' do + aggregation = Aggregation.new( + operation: 'Sum', + field: 'nb_seats', + groups: [{ field: 'brand' }] + ) + + query_aggregate = described_class.new(collection, aggregation) + result = query_aggregate.get + + expect(result).to contain_exactly( + { 'value' => 5, 'group' => { 'brand' => 'Ford' } }, + { 'value' => 9, 'group' => { 'brand' => 'Toyota' } } + ) + end + + it 'returns aggregated data grouped by truncated date' do + aggregation = Aggregation.new( + operation: 'Sum', + field: 'nb_seats', + groups: [{ field: 'created_at', operation: 'month' }] + ) + + query_aggregate = described_class.new(collection, aggregation) + result = query_aggregate.get + + expect(result).to contain_exactly( + { 'value' => 9, 'group' => { 'created_at' => Time.parse('2024-01-01 00:00:00 UTC') } }, + { 'value' => 5, 'group' => { 'created_at' => Time.parse('2024-02-01 00:00:00 UTC') } } + ) + end + + it 'respects the limit when provided' do + aggregation = Aggregation.new( + operation: 'Sum', + field: 'nb_seats', + groups: [{ field: 'brand' }] + ) + + query_aggregate = described_class.new(collection, aggregation, nil, 1) + result = query_aggregate.get + + expect(result.size).to eq(1) + end + + it 'raises an error when given an unsupported date truncation operation' do + aggregation = Aggregation.new( + operation: 'Sum', + field: 'nb_seats', + groups: [{ field: 'created_at', operation: 'not_a_real_unit' }] + ) + + query_aggregate = described_class.new(collection, aggregation) + + expect do + query_aggregate.get + end.to raise_error(ArgumentError, /Unsupported date truncation operation 'not_a_real_unit'/) + end + end + end + end +end diff --git a/packages/forest_admin_datasource_active_record/spec/spec_helper.rb b/packages/forest_admin_datasource_active_record/spec/spec_helper.rb index 640a44ac2..60174ff93 100644 --- a/packages/forest_admin_datasource_active_record/spec/spec_helper.rb +++ b/packages/forest_admin_datasource_active_record/spec/spec_helper.rb @@ -33,18 +33,15 @@ # database_cleaner config config.before(:suite) do - DatabaseCleaner.clean_with :truncation, except: %w[ar_internal_metadata] - end - - config.before do DatabaseCleaner.strategy = :transaction + DatabaseCleaner.clean_with :truncation end - config.before do - DatabaseCleaner.start - end - - config.after do - DatabaseCleaner.clean + config.around(:each, :db_truncation) do |example| + DatabaseCleaner.strategy = :truncation + DatabaseCleaner.cleaning do + example.run + end + DatabaseCleaner.strategy = :transaction end end diff --git a/packages/forest_admin_datasource_customizer/lib/forest_admin_datasource_customizer/decorators/relation/relation_collection_decorator.rb b/packages/forest_admin_datasource_customizer/lib/forest_admin_datasource_customizer/decorators/relation/relation_collection_decorator.rb index 2d9f022cb..b993920ba 100644 --- a/packages/forest_admin_datasource_customizer/lib/forest_admin_datasource_customizer/decorators/relation/relation_collection_decorator.rb +++ b/packages/forest_admin_datasource_customizer/lib/forest_admin_datasource_customizer/decorators/relation/relation_collection_decorator.rb @@ -183,7 +183,7 @@ def rewrite_field(field) result = [] if !@relations.key?(prefix) - result = relation.rewrite_field(field[prefix.length + 1..]).map { |sub_field| "#{prefix}:#{sub_field}" } + result = relation.rewrite_field(field[(prefix.length + 1)..]).map { |sub_field| "#{prefix}:#{sub_field}" } elsif field_schema.is_a? Relations::ManyToOneSchema result = [field_schema.foreign_key] elsif field_schema.is_a?(Relations::OneToOneSchema) || diff --git a/packages/forest_admin_datasource_customizer/lib/forest_admin_datasource_customizer/decorators/rename_field/rename_field_collection_decorator.rb b/packages/forest_admin_datasource_customizer/lib/forest_admin_datasource_customizer/decorators/rename_field/rename_field_collection_decorator.rb index 022632fda..60dfdb5e4 100644 --- a/packages/forest_admin_datasource_customizer/lib/forest_admin_datasource_customizer/decorators/rename_field/rename_field_collection_decorator.rb +++ b/packages/forest_admin_datasource_customizer/lib/forest_admin_datasource_customizer/decorators/rename_field/rename_field_collection_decorator.rb @@ -152,13 +152,13 @@ def mark_all_schema_as_dirty # Convert field path from child collection to this collection def path_from_child_collection(path) if path.include?(':') - child_field = path[0..path.index(':') - 1] + child_field = path[0..(path.index(':') - 1)] relation_name = from_child_collection[child_field] || child_field relation_schema = schema[:fields][relation_name] if relation_schema.type != 'PolymorphicManyToOne' relation = datasource.get_collection(relation_schema.foreign_collection) - return "#{relation_name}:#{relation.path_from_child_collection(path[path.index(":") + 1..])}" + return "#{relation_name}:#{relation.path_from_child_collection(path[(path.index(":") + 1)..])}" end end @@ -168,17 +168,17 @@ def path_from_child_collection(path) # Convert field path from this collection to child collection def path_to_child_collection(path) if path.include?(':') - relation_name = path[0..path.index(':') - 1] + relation_name = path[0..(path.index(':') - 1)] relation_schema = schema[:fields][relation_name] if relation_schema.type == 'PolymorphicManyToOne' relation_name = to_child_collection[relation_name] || relation_name - return "#{relation_name}:#{path[path.index(":") + 1..]}" + return "#{relation_name}:#{path[(path.index(":") + 1)..]}" else relation = datasource.get_collection(relation_schema.foreign_collection) child_field = to_child_collection[relation_name] || relation_name - return "#{child_field}:#{relation.path_to_child_collection(path[path.index(":") + 1..])}" + return "#{child_field}:#{relation.path_to_child_collection(path[(path.index(":") + 1)..])}" end end diff --git a/packages/forest_admin_datasource_mongoid/lib/forest_admin_datasource_mongoid/utils/add_null_values.rb b/packages/forest_admin_datasource_mongoid/lib/forest_admin_datasource_mongoid/utils/add_null_values.rb index b404e0eb3..878e0dade 100644 --- a/packages/forest_admin_datasource_mongoid/lib/forest_admin_datasource_mongoid/utils/add_null_values.rb +++ b/packages/forest_admin_datasource_mongoid/lib/forest_admin_datasource_mongoid/utils/add_null_values.rb @@ -32,7 +32,7 @@ def add_null_values_on_record(record, projection) nested_prefixes.each do |nested_prefix| child_paths = projection.filter { |field| field.start_with?("#{nested_prefix}:") } - .map { |field| field[nested_prefix.size + 1..] } + .map { |field| field[(nested_prefix.size + 1)..] } next unless result[nested_prefix] && !result[nested_prefix].nil? diff --git a/packages/forest_admin_datasource_mongoid/lib/forest_admin_datasource_mongoid/utils/helpers.rb b/packages/forest_admin_datasource_mongoid/lib/forest_admin_datasource_mongoid/utils/helpers.rb index 5e0d403fe..2b9043049 100644 --- a/packages/forest_admin_datasource_mongoid/lib/forest_admin_datasource_mongoid/utils/helpers.rb +++ b/packages/forest_admin_datasource_mongoid/lib/forest_admin_datasource_mongoid/utils/helpers.rb @@ -5,7 +5,7 @@ module Helpers # @example # unnest(['firstname', 'book.title', 'book.author'], 'book') == ['title', 'author'] def unnest(strings, prefix) - strings.select { |field| field.start_with?("#{prefix}.") }.map { |field| field[prefix.size + 1..] } + strings.select { |field| field.start_with?("#{prefix}.") }.map { |field| field[(prefix.size + 1)..] } end def escape(str) @@ -30,8 +30,8 @@ def recursive_delete(target, path) if index.nil? target.delete(path) else - prefix = path[0..index - 1] - suffix = path[index + 1..] + prefix = path[0..(index - 1)] + suffix = path[(index + 1)..] if target.is_a?(Hash) && target.key?(prefix) recursive_delete(target[prefix], suffix) diff --git a/packages/forest_admin_datasource_mongoid/lib/forest_admin_datasource_mongoid/utils/pipeline/lookup_generator.rb b/packages/forest_admin_datasource_mongoid/lib/forest_admin_datasource_mongoid/utils/pipeline/lookup_generator.rb index 47b6108b9..be9620643 100644 --- a/packages/forest_admin_datasource_mongoid/lib/forest_admin_datasource_mongoid/utils/pipeline/lookup_generator.rb +++ b/packages/forest_admin_datasource_mongoid/lib/forest_admin_datasource_mongoid/utils/pipeline/lookup_generator.rb @@ -10,7 +10,7 @@ def self.lookup(model, stack, projection, options) schema_stack = stack.each_with_index.reduce([MongoidSchema.from_model(model)]) do |acc, (_, index)| [ *acc, - MongoidSchema.from_model(model).apply_stack(stack.slice(0..index + 1), skip_as_models: true) + MongoidSchema.from_model(model).apply_stack(stack.slice(0..(index + 1)), skip_as_models: true) ] end @@ -51,7 +51,7 @@ def self.lookup_relation(current_path, schema_stack, name, projection, options) as = current_path ? "#{current_path}.#{name}" : name last_schema = schema_stack[schema_stack.length - 1] - previous_schema = schema_stack.slice(0..schema_stack.length - 1) + previous_schema = schema_stack.slice(0..(schema_stack.length - 1)) return {} if options[:include] && !options[:include].include?(as) return {} if options[:exclude]&.include?(as) diff --git a/packages/forest_admin_datasource_mongoid/lib/forest_admin_datasource_mongoid/utils/pipeline/reparent_generator.rb b/packages/forest_admin_datasource_mongoid/lib/forest_admin_datasource_mongoid/utils/pipeline/reparent_generator.rb index c1dfeec58..4985ac7a5 100644 --- a/packages/forest_admin_datasource_mongoid/lib/forest_admin_datasource_mongoid/utils/pipeline/reparent_generator.rb +++ b/packages/forest_admin_datasource_mongoid/lib/forest_admin_datasource_mongoid/utils/pipeline/reparent_generator.rb @@ -20,7 +20,7 @@ def self.reparent(model, stack) relative_prefix = if stack[index - 1][:prefix].nil? step[:prefix] else - step[:prefix][stack[index - 1][:prefix].length + 1..] + step[:prefix][(stack[index - 1][:prefix].length + 1)..] end result = if local_schema.is_array diff --git a/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/query/aggregation.rb b/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/query/aggregation.rb index 331d3b075..b84bcdf0f 100644 --- a/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/query/aggregation.rb +++ b/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/query/aggregation.rb @@ -64,7 +64,7 @@ def apply(records, timezone, limit = nil) end end - rows = rows[0..limit - 1] if limit && rows.size > limit + rows = rows[0..(limit - 1)] if limit && rows.size > limit rows end diff --git a/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/query/condition_tree/nodes/condition_tree.rb b/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/query/condition_tree/nodes/condition_tree.rb index 3bd473920..9c1920d3f 100644 --- a/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/query/condition_tree/nodes/condition_tree.rb +++ b/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/query/condition_tree/nodes/condition_tree.rb @@ -56,7 +56,7 @@ def unnest raise ForestException, 'Cannot unnest condition tree.' end - replace_leafs { |leaf| leaf.override(field: leaf.field[prefix.length + 1..]) } + replace_leafs { |leaf| leaf.override(field: leaf.field[(prefix.length + 1)..]) } end def replace_fields diff --git a/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/query/sort.rb b/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/query/sort.rb index c33e6186c..ea52396fc 100644 --- a/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/query/sort.rb +++ b/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/query/sort.rb @@ -46,7 +46,7 @@ def unnest def apply(records) records.sort do |a, b| comparison = 0 - (0..length - 1).each do |i| + (0..(length - 1)).each do |i| field = self[i][:field] ascending = self[i][:ascending] break unless comparison.zero?