From 7530c4705d28c1b7101a6f2f53719ae9d9c8df4c Mon Sep 17 00:00:00 2001 From: Geremia Taglialatela Date: Sat, 9 Sep 2023 17:21:18 +0200 Subject: [PATCH 1/6] Initial config --- .gitattributes | 1 + .rubocop.yml | 19 +- .rubocop_todo.yml | 605 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 621 insertions(+), 4 deletions(-) create mode 100644 .gitattributes create mode 100644 .rubocop_todo.yml diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..6fd60616 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +.rubocop_todo.yml linguist-generated diff --git a/.rubocop.yml b/.rubocop.yml index 743e656d..f7a59c27 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,3 +1,5 @@ +inherit_from: .rubocop_todo.yml + require: - rubocop-packaging - rubocop-performance @@ -11,7 +13,6 @@ AllCops: TargetRubyVersion: 2.2 Exclude: - 'gemfiles/**/*' - - 'lib/**/*' - 'vendor/bundle/**/*' - 'tmp/**/*' @@ -19,9 +20,7 @@ Gemspec/DevelopmentDependencies: Enabled: false Layout/LineLength: - Max: 140 - Exclude: - - 'spec/**/*' + Enabled: false Lint/MissingSuper: Exclude: @@ -40,6 +39,15 @@ Metrics/MethodLength: Exclude: - 'spec/**/*' +Naming/MethodName: + AllowedPatterns: + - '_INSERT_' + - '_UPDATE_' + - '_DELETE_' + +Naming/PredicateName: + Enabled: false + Rails/ApplicationRecord: Enabled: false @@ -75,6 +83,9 @@ Style/GlobalVars: Exclude: - 'spec/**/*' +Style/IfUnlessModifier: + Enabled: false + # NOTE: This cop is enabled by RuboCop Rails, because active support adds this # method to hash, but `except` is not available in specs Style/HashExcept: diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 00000000..b9749e98 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,605 @@ +# This configuration was generated by +# `rubocop --auto-gen-config --no-offense-counts --no-auto-gen-timestamp` +# using RuboCop version 1.56.2. +# 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. + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: with_first_argument, with_fixed_indentation +Layout/ArgumentAlignment: + Exclude: + - 'lib/chrono_model/time_machine/timeline.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: leading, trailing +Layout/DotPosition: + Exclude: + - 'lib/chrono_model/patches/join_node.rb' + - 'lib/chrono_model/time_machine/timeline.rb' + +# This cop supports safe autocorrection (--autocorrect). +Layout/ElseAlignment: + Exclude: + - 'lib/chrono_model/adapter/ddl.rb' + - 'lib/chrono_model/time_machine/time_query.rb' + +# This cop supports safe autocorrection (--autocorrect). +Layout/EmptyLineAfterGuardClause: + Exclude: + - 'lib/chrono_model.rb' + - 'lib/chrono_model/adapter.rb' + - 'lib/chrono_model/adapter/migrations.rb' + - 'lib/chrono_model/adapter/upgrade.rb' + - 'lib/chrono_model/time_machine.rb' + +# This cop supports safe autocorrection (--autocorrect). +Layout/EmptyLines: + Exclude: + - 'lib/chrono_model/adapter/indexes.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: around, only_before +Layout/EmptyLinesAroundAccessModifier: + Exclude: + - 'lib/chrono_model/adapter.rb' + - 'lib/chrono_model/adapter/ddl.rb' + - 'lib/chrono_model/adapter/indexes.rb' + - 'lib/chrono_model/adapter/migrations.rb' + - 'lib/chrono_model/adapter/upgrade.rb' + - 'lib/chrono_model/json.rb' + - 'lib/chrono_model/patches/association.rb' + - 'lib/chrono_model/time_machine/history_model.rb' + - 'lib/chrono_model/time_machine/time_query.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: empty_lines, no_empty_lines +Layout/EmptyLinesAroundBlockBody: + Exclude: + - 'lib/chrono_model/adapter/migrations.rb' + - 'lib/chrono_model/adapter/upgrade.rb' + - 'lib/chrono_model/patches/relation.rb' + +# 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: + Exclude: + - 'lib/chrono_model/adapter/ddl.rb' + - 'lib/chrono_model/adapter/indexes.rb' + - 'lib/chrono_model/adapter/migrations.rb' + - 'lib/chrono_model/adapter/tsrange.rb' + - 'lib/chrono_model/adapter/upgrade.rb' + +# This cop supports safe autocorrection (--autocorrect). +Layout/EmptyLinesAroundExceptionHandlingKeywords: + Exclude: + - 'lib/active_record/connection_adapters/chronomodel_adapter.rb' + - 'lib/chrono_model/adapter.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines +Layout/EmptyLinesAroundModuleBody: + Enabled: false + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyleAlignWith, Severity. +# SupportedStylesAlignWith: keyword, variable, start_of_line +Layout/EndAlignment: + Exclude: + - 'lib/chrono_model/adapter/ddl.rb' + - 'lib/chrono_model/time_machine/time_query.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment. +Layout/ExtraSpacing: + Exclude: + - 'lib/chrono_model/adapter/indexes.rb' + - 'lib/chrono_model/adapter/tsrange.rb' + +# 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: + - 'lib/chrono_model/adapter/tsrange.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: normal, indented_internal_methods +Layout/IndentationConsistency: + Exclude: + - 'lib/chrono_model/adapter.rb' + - 'lib/chrono_model/adapter/ddl.rb' + - 'lib/chrono_model/adapter/indexes.rb' + - 'lib/chrono_model/adapter/migrations.rb' + - 'lib/chrono_model/adapter/upgrade.rb' + - 'lib/chrono_model/patches/association.rb' + - 'lib/chrono_model/patches/relation.rb' + - 'lib/chrono_model/time_machine/history_model.rb' + - 'lib/chrono_model/time_machine/time_query.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: Width, AllowedPatterns. +Layout/IndentationWidth: + Exclude: + - 'lib/chrono_model/adapter.rb' + - 'lib/chrono_model/adapter/ddl.rb' + - 'lib/chrono_model/adapter/indexes.rb' + - 'lib/chrono_model/adapter/migrations.rb' + - 'lib/chrono_model/adapter/upgrade.rb' + - 'lib/chrono_model/patches/association.rb' + - 'lib/chrono_model/patches/relation.rb' + - 'lib/chrono_model/time_machine/history_model.rb' + - 'lib/chrono_model/time_machine/time_query.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowDoxygenCommentStyle, AllowGemfileRubyComment. +Layout/LeadingCommentSpace: + Exclude: + - 'lib/chrono_model.rb' + - 'lib/chrono_model/time_machine/history_model.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: space, no_space +Layout/LineContinuationSpacing: + Exclude: + - 'lib/active_record/connection_adapters/chronomodel_adapter.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: aligned, indented +Layout/LineEndStringConcatenationIndentation: + Exclude: + - 'lib/active_record/connection_adapters/chronomodel_adapter.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns. +# URISchemes: http, https +Layout/LineLength: + Max: 197 + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: symmetrical, new_line, same_line +Layout/MultilineArrayBraceLayout: + Exclude: + - 'lib/chrono_model/adapter/indexes.rb' + - 'lib/chrono_model/time_machine/timeline.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: symmetrical, new_line, same_line +Layout/MultilineMethodCallBraceLayout: + Exclude: + - 'lib/chrono_model/adapter.rb' + - 'lib/chrono_model/patches/relation.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: aligned, indented, indented_relative_to_receiver +Layout/MultilineMethodCallIndentation: + Exclude: + - 'lib/chrono_model/patches/join_node.rb' + - 'lib/chrono_model/time_machine/timeline.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: aligned, indented +Layout/MultilineOperationIndentation: + Exclude: + - 'lib/chrono_model/adapter/indexes.rb' + - 'lib/chrono_model/time_machine.rb' + +# This cop supports safe autocorrection (--autocorrect). +Layout/SpaceAfterComma: + Exclude: + - 'lib/chrono_model/time_machine/timeline.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowForAlignment, EnforcedStyleForExponentOperator. +# SupportedStylesForExponentOperator: space, no_space +Layout/SpaceAroundOperators: + Exclude: + - 'lib/chrono_model.rb' + - 'lib/chrono_model/adapter/indexes.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBrackets. +# SupportedStyles: space, no_space, compact +# SupportedStylesForEmptyBrackets: space, no_space +Layout/SpaceInsideArrayLiteralBrackets: + Exclude: + - 'lib/chrono_model/adapter/ddl.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters. +# SupportedStyles: space, no_space +# SupportedStylesForEmptyBraces: space, no_space +Layout/SpaceInsideBlockBraces: + Exclude: + - 'lib/chrono_model/adapter/ddl.rb' + - 'lib/chrono_model/adapter/indexes.rb' + - 'lib/chrono_model/adapter/migrations.rb' + - 'lib/chrono_model/patches/relation.rb' + - 'lib/chrono_model/time_machine/time_query.rb' + - 'lib/chrono_model/time_machine/timeline.rb' + - 'lib/chrono_model/utilities.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. +# SupportedStyles: space, no_space, compact +# SupportedStylesForEmptyBraces: space, no_space +Layout/SpaceInsideHashLiteralBraces: + Exclude: + - 'lib/chrono_model/adapter/upgrade.rb' + +# This cop supports safe autocorrection (--autocorrect). +Layout/SpaceInsidePercentLiteralDelimiters: + Exclude: + - 'lib/chrono_model/adapter/ddl.rb' + - 'lib/chrono_model/time_machine.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBrackets. +# SupportedStyles: space, no_space +# SupportedStylesForEmptyBrackets: space, no_space +Layout/SpaceInsideReferenceBrackets: + Exclude: + - 'lib/chrono_model/adapter/tsrange.rb' + - 'lib/chrono_model/time_machine/timeline.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: final_newline, final_blank_line +Layout/TrailingEmptyLines: + Exclude: + - 'lib/active_record/connection_adapters/chronomodel_adapter.rb' + +# This cop supports safe autocorrection (--autocorrect). +Lint/AmbiguousOperator: + Exclude: + - 'lib/chrono_model/patches/preloader.rb' + +# This cop supports safe autocorrection (--autocorrect). +Lint/TripleQuotes: + Exclude: + - 'lib/chrono_model/adapter/upgrade.rb' + +# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. +Metrics/AbcSize: + Max: 72 + +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode. +# AllowedMethods: refine +Metrics/BlockLength: + Max: 44 + +# Configuration parameters: AllowedMethods, AllowedPatterns. +Metrics/CyclomaticComplexity: + Max: 21 + +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. +Metrics/MethodLength: + Max: 44 + +# Configuration parameters: CountComments, CountAsOne. +Metrics/ModuleLength: + Max: 140 + +# Configuration parameters: CountKeywordArgs, MaxOptionalParameters. +Metrics/ParameterLists: + Max: 8 + +# Configuration parameters: AllowedMethods, AllowedPatterns. +Metrics/PerceivedComplexity: + Max: 22 + +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyleForLeadingUnderscores. +# SupportedStylesForLeadingUnderscores: disallowed, required, optional +Naming/MemoizedInstanceVariableName: + Exclude: + - 'lib/chrono_model.rb' + +# Configuration parameters: AllowedPatterns. +# SupportedStyles: snake_case, camelCase +Naming/MethodName: + EnforcedStyle: snake_case + +# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. +# AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to +Naming/MethodParameterName: + Exclude: + - 'lib/chrono_model/adapter/ddl.rb' + - 'lib/chrono_model/adapter/tsrange.rb' + - 'lib/chrono_model/time_machine/time_query.rb' + +# 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: + - 'lib/chrono_model/adapter.rb' + - 'lib/chrono_model/time_machine.rb' + - 'lib/chrono_model/time_machine/timeline.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: PreferredName. +Naming/RescuedExceptionsVariableName: + Exclude: + - 'lib/active_record/connection_adapters/chronomodel_adapter.rb' + +# Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns. +# SupportedStyles: snake_case, normalcase, non_integer +# AllowedIdentifiers: capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64 +Naming/VariableNumber: + Exclude: + - 'lib/chrono_model/adapter/upgrade.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforceForPrefixed. +Rails/Delegate: + Exclude: + - 'lib/chrono_model/time_machine.rb' + - 'lib/chrono_model/time_machine/history_model.rb' + +# This cop supports unsafe autocorrection (--autocorrect-all). +Rails/SquishedSQLHeredocs: + Exclude: + - 'lib/chrono_model/adapter/ddl.rb' + - 'lib/chrono_model/adapter/indexes.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: prefer_alias, prefer_alias_method +Style/Alias: + Exclude: + - 'lib/chrono_model/time_machine/history_model.rb' + +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: always, conditionals +Style/AndOr: + Exclude: + - 'lib/chrono_model/adapter.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: is_a?, kind_of? +Style/ClassCheck: + Exclude: + - 'lib/chrono_model/time_machine/time_query.rb' + +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/CommentedKeyword: + Exclude: + - 'lib/chrono_model/adapter.rb' + +# Configuration parameters: AllowedConstants. +Style/Documentation: + Enabled: false + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: compact, expanded +Style/EmptyMethod: + Exclude: + - 'lib/chrono_model/adapter.rb' + +# This cop supports safe autocorrection (--autocorrect). +Style/ExplicitBlockArgument: + Exclude: + - 'lib/chrono_model/adapter/indexes.rb' + - 'lib/chrono_model/adapter/migrations.rb' + - 'lib/chrono_model/time_machine/history_model.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: format, sprintf, percent +Style/FormatString: + Exclude: + - 'lib/chrono_model/conversions.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: MinBodyLength, AllowConsecutiveConditionals. +Style/GuardClause: + Exclude: + - 'lib/active_record/connection_adapters/chronomodel_adapter.rb' + - 'lib/chrono_model/adapter/migrations.rb' + - 'lib/chrono_model/conversions.rb' + - 'lib/chrono_model/time_machine.rb' + +# This cop supports safe autocorrection (--autocorrect). +Style/IfUnlessModifier: + Exclude: + - 'lib/active_record/tasks/chronomodel_database_tasks.rb' + - 'lib/chrono_model.rb' + - 'lib/chrono_model/adapter.rb' + - 'lib/chrono_model/adapter/ddl.rb' + - 'lib/chrono_model/adapter/migrations.rb' + - 'lib/chrono_model/patches/preloader.rb' + - 'lib/chrono_model/time_machine.rb' + - 'lib/chrono_model/time_machine/timeline.rb' + - 'lib/chrono_model/utilities.rb' + +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle, Autocorrect. +# SupportedStyles: module_function, extend_self, forbidden +Style/ModuleFunction: + Exclude: + - 'lib/chrono_model/conversions.rb' + +# This cop supports safe autocorrection (--autocorrect). +Style/MultilineIfModifier: + Exclude: + - 'lib/chrono_model/adapter.rb' + +# This cop supports safe autocorrection (--autocorrect). +Style/MultilineTernaryOperator: + Exclude: + - 'lib/chrono_model/patches/association.rb' + - 'lib/chrono_model/time_machine.rb' + - 'lib/chrono_model/time_machine/history_model.rb' + - 'lib/chrono_model/time_machine/timeline.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowMethodComparison, ComparisonsThreshold. +Style/MultipleComparison: + Exclude: + - 'lib/chrono_model/time_machine/time_query.rb' + +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: literals, strict +Style/MutableConstant: + Exclude: + - 'lib/chrono_model/adapter.rb' + - 'lib/chrono_model/conversions.rb' + - 'lib/chrono_model/version.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: both, prefix, postfix +Style/NegatedIf: + Exclude: + - 'lib/chrono_model/adapter/migrations.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowedMethods. +# AllowedMethods: be, be_a, be_an, be_between, be_falsey, be_kind_of, be_instance_of, be_truthy, be_within, eq, eql, end_with, include, match, raise_error, respond_to, start_with +Style/NestedParenthesizedCalls: + Exclude: + - 'lib/chrono_model/json.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: Strict, AllowedNumbers, AllowedPatterns. +Style/NumericLiterals: + MinDigits: 6 + +# This cop supports safe autocorrection (--autocorrect). +Style/ParallelAssignment: + Exclude: + - 'lib/chrono_model/adapter/ddl.rb' + - 'lib/chrono_model/time_machine.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowSafeAssignment, AllowInMultilineConditions. +Style/ParenthesesAroundCondition: + Exclude: + - 'lib/chrono_model/patches/relation.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: PreferredDelimiters. +Style/PercentLiteralDelimiters: + Exclude: + - 'lib/chrono_model/adapter.rb' + - 'lib/chrono_model/adapter/ddl.rb' + - 'lib/chrono_model/adapter/indexes.rb' + - 'lib/chrono_model/time_machine.rb' + - 'lib/chrono_model/time_machine/history_model.rb' + - 'lib/chrono_model/time_machine/time_query.rb' + - 'lib/chrono_model/time_machine/timeline.rb' + +# This cop supports safe autocorrection (--autocorrect). +Style/PerlBackrefs: + Exclude: + - 'lib/chrono_model/conversions.rb' + +# This cop supports safe autocorrection (--autocorrect). +Style/RedundantParentheses: + Exclude: + - 'lib/chrono_model/patches/relation.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowMultipleReturnValues. +Style/RedundantReturn: + Exclude: + - 'lib/active_record/connection_adapters/chronomodel_adapter.rb' + - 'lib/chrono_model/adapter/upgrade.rb' + - 'lib/chrono_model/patches/association.rb' + - 'lib/chrono_model/patches/preloader.rb' + +# This cop supports safe autocorrection (--autocorrect). +Style/RedundantSelf: + Exclude: + - 'lib/chrono_model/adapter.rb' + - 'lib/chrono_model/patches/relation.rb' + - 'lib/chrono_model/time_gate.rb' + - 'lib/chrono_model/time_machine.rb' + - 'lib/chrono_model/time_machine/history_model.rb' + - 'lib/chrono_model/time_machine/timeline.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: implicit, explicit +Style/RescueStandardError: + Exclude: + - 'lib/chrono_model/adapter/upgrade.rb' + +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: RequireEnglish, EnforcedStyle. +# SupportedStyles: use_perl_names, use_english_names, use_builtin_english_names +Style/SpecialGlobalVars: + Exclude: + - 'lib/chrono_model/adapter/indexes.rb' + +# This cop supports safe autocorrection (--autocorrect). +Style/StderrPuts: + Exclude: + - 'lib/chrono_model/adapter/upgrade.rb' + +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: Mode. +Style/StringConcatenation: + Exclude: + - 'lib/chrono_model/adapter.rb' + - 'lib/chrono_model/json.rb' + - 'lib/chrono_model/time_machine/history_model.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. +# SupportedStyles: single_quotes, double_quotes +Style/StringLiterals: + Exclude: + - 'lib/active_record/connection_adapters/chronomodel_adapter.rb' + - 'lib/active_record/tasks/chronomodel_database_tasks.rb' + - 'lib/chrono_model.rb' + - 'lib/chrono_model/adapter/migrations.rb' + - 'lib/chrono_model/adapter/upgrade.rb' + - 'lib/chrono_model/time_machine/history_model.rb' + - 'lib/chrono_model/time_machine/time_query.rb' + - 'lib/chrono_model/version.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, MinSize. +# SupportedStyles: percent, brackets +Style/SymbolArray: + Exclude: + - 'lib/chrono_model/adapter.rb' + - 'lib/chrono_model/time_machine/timeline.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, AllowSafeAssignment. +# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex +Style/TernaryParentheses: + Exclude: + - 'lib/chrono_model/adapter/tsrange.rb' + +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyleForMultiline. +# SupportedStylesForMultiline: comma, consistent_comma, no_comma +Style/TrailingCommaInHashLiteral: + Exclude: + - 'lib/chrono_model/adapter/tsrange.rb' From 4a2828cdf6b6f6f101d5e593c88c21b828845b65 Mon Sep 17 00:00:00 2001 From: Geremia Taglialatela Date: Sat, 9 Sep 2023 17:23:42 +0200 Subject: [PATCH 2/6] Fix empty line offenses --- .rubocop_todo.yml | 103 ------------------ .../chronomodel_adapter.rb | 3 - lib/chrono_model.rb | 1 + lib/chrono_model/adapter.rb | 7 +- lib/chrono_model/adapter/ddl.rb | 3 +- lib/chrono_model/adapter/indexes.rb | 5 +- lib/chrono_model/adapter/migrations.rb | 9 +- lib/chrono_model/adapter/tsrange.rb | 2 - lib/chrono_model/adapter/upgrade.rb | 8 +- lib/chrono_model/conversions.rb | 2 - lib/chrono_model/json.rb | 3 +- lib/chrono_model/patches/as_of_time_holder.rb | 2 - .../patches/as_of_time_relation.rb | 2 - lib/chrono_model/patches/association.rb | 4 +- lib/chrono_model/patches/join_node.rb | 2 - lib/chrono_model/patches/preloader.rb | 2 - lib/chrono_model/patches/relation.rb | 4 - lib/chrono_model/time_gate.rb | 2 - lib/chrono_model/time_machine.rb | 4 +- .../time_machine/history_model.rb | 3 +- lib/chrono_model/time_machine/time_query.rb | 3 +- lib/chrono_model/time_machine/timeline.rb | 2 - lib/chrono_model/utilities.rb | 2 - 23 files changed, 18 insertions(+), 160 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index b9749e98..9f0e34d6 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -27,67 +27,6 @@ Layout/ElseAlignment: - 'lib/chrono_model/adapter/ddl.rb' - 'lib/chrono_model/time_machine/time_query.rb' -# This cop supports safe autocorrection (--autocorrect). -Layout/EmptyLineAfterGuardClause: - Exclude: - - 'lib/chrono_model.rb' - - 'lib/chrono_model/adapter.rb' - - 'lib/chrono_model/adapter/migrations.rb' - - 'lib/chrono_model/adapter/upgrade.rb' - - 'lib/chrono_model/time_machine.rb' - -# This cop supports safe autocorrection (--autocorrect). -Layout/EmptyLines: - Exclude: - - 'lib/chrono_model/adapter/indexes.rb' - -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: around, only_before -Layout/EmptyLinesAroundAccessModifier: - Exclude: - - 'lib/chrono_model/adapter.rb' - - 'lib/chrono_model/adapter/ddl.rb' - - 'lib/chrono_model/adapter/indexes.rb' - - 'lib/chrono_model/adapter/migrations.rb' - - 'lib/chrono_model/adapter/upgrade.rb' - - 'lib/chrono_model/json.rb' - - 'lib/chrono_model/patches/association.rb' - - 'lib/chrono_model/time_machine/history_model.rb' - - 'lib/chrono_model/time_machine/time_query.rb' - -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: empty_lines, no_empty_lines -Layout/EmptyLinesAroundBlockBody: - Exclude: - - 'lib/chrono_model/adapter/migrations.rb' - - 'lib/chrono_model/adapter/upgrade.rb' - - 'lib/chrono_model/patches/relation.rb' - -# 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: - Exclude: - - 'lib/chrono_model/adapter/ddl.rb' - - 'lib/chrono_model/adapter/indexes.rb' - - 'lib/chrono_model/adapter/migrations.rb' - - 'lib/chrono_model/adapter/tsrange.rb' - - 'lib/chrono_model/adapter/upgrade.rb' - -# This cop supports safe autocorrection (--autocorrect). -Layout/EmptyLinesAroundExceptionHandlingKeywords: - Exclude: - - 'lib/active_record/connection_adapters/chronomodel_adapter.rb' - - 'lib/chrono_model/adapter.rb' - -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines -Layout/EmptyLinesAroundModuleBody: - Enabled: false - # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyleAlignWith, Severity. # SupportedStylesAlignWith: keyword, variable, start_of_line @@ -162,12 +101,6 @@ Layout/LineEndStringConcatenationIndentation: Exclude: - 'lib/active_record/connection_adapters/chronomodel_adapter.rb' -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns. -# URISchemes: http, https -Layout/LineLength: - Max: 197 - # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: symmetrical, new_line, same_line @@ -258,13 +191,6 @@ Layout/SpaceInsideReferenceBrackets: - 'lib/chrono_model/adapter/tsrange.rb' - 'lib/chrono_model/time_machine/timeline.rb' -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: final_newline, final_blank_line -Layout/TrailingEmptyLines: - Exclude: - - 'lib/active_record/connection_adapters/chronomodel_adapter.rb' - # This cop supports safe autocorrection (--autocorrect). Lint/AmbiguousOperator: Exclude: @@ -311,11 +237,6 @@ Naming/MemoizedInstanceVariableName: Exclude: - 'lib/chrono_model.rb' -# Configuration parameters: AllowedPatterns. -# SupportedStyles: snake_case, camelCase -Naming/MethodName: - EnforcedStyle: snake_case - # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. # AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to Naming/MethodParameterName: @@ -324,17 +245,6 @@ Naming/MethodParameterName: - 'lib/chrono_model/adapter/tsrange.rb' - 'lib/chrono_model/time_machine/time_query.rb' -# 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: - - 'lib/chrono_model/adapter.rb' - - 'lib/chrono_model/time_machine.rb' - - 'lib/chrono_model/time_machine/timeline.rb' - # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: PreferredName. Naming/RescuedExceptionsVariableName: @@ -421,19 +331,6 @@ Style/GuardClause: - 'lib/chrono_model/conversions.rb' - 'lib/chrono_model/time_machine.rb' -# This cop supports safe autocorrection (--autocorrect). -Style/IfUnlessModifier: - Exclude: - - 'lib/active_record/tasks/chronomodel_database_tasks.rb' - - 'lib/chrono_model.rb' - - 'lib/chrono_model/adapter.rb' - - 'lib/chrono_model/adapter/ddl.rb' - - 'lib/chrono_model/adapter/migrations.rb' - - 'lib/chrono_model/patches/preloader.rb' - - 'lib/chrono_model/time_machine.rb' - - 'lib/chrono_model/time_machine/timeline.rb' - - 'lib/chrono_model/utilities.rb' - # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle, Autocorrect. # SupportedStyles: module_function, extend_self, forbidden diff --git a/lib/active_record/connection_adapters/chronomodel_adapter.rb b/lib/active_record/connection_adapters/chronomodel_adapter.rb index 60321ad8..f2ae5fe5 100644 --- a/lib/active_record/connection_adapters/chronomodel_adapter.rb +++ b/lib/active_record/connection_adapters/chronomodel_adapter.rb @@ -35,7 +35,6 @@ def chronomodel_connection(config) # :nodoc: adapter.chrono_setup! return adapter - rescue ::PG::Error => error if error.message.include?(conn_params[:dbname]) raise ActiveRecord::NoDatabaseError @@ -43,7 +42,5 @@ def chronomodel_connection(config) # :nodoc: raise end end - end end - diff --git a/lib/chrono_model.rb b/lib/chrono_model.rb index 73562ede..f96bf6d9 100644 --- a/lib/chrono_model.rb +++ b/lib/chrono_model.rb @@ -40,6 +40,7 @@ def self.history_models # def chrono? return false unless connection.respond_to? :is_chrono? + connection.is_chrono?(table_name) end end diff --git a/lib/chrono_model/adapter.rb b/lib/chrono_model/adapter.rb index 4b39a945..b3a247c3 100644 --- a/lib/chrono_model/adapter.rb +++ b/lib/chrono_model/adapter.rb @@ -14,7 +14,6 @@ require 'chrono_model/adapter/upgrade' module ChronoModel - # This class implements all ActiveRecord::ConnectionAdapters::SchemaStatements # methods adding support for temporal extensions. It inherits from the Postgres # adapter for a clean override of its methods using super. @@ -67,6 +66,7 @@ def primary_key(table_name) define_method(method) do |*args| table_name = args.first return super(*args) unless is_chrono?(table_name) + on_schema(TEMPORAL_SCHEMA, recurse: :ignore) { super(*args) } end end @@ -85,6 +85,7 @@ def column_definitions define_method(:column_definitions) do |table_name| return super(table_name) unless is_chrono?(table_name) + on_schema(TEMPORAL_SCHEMA + ',' + self.schema_search_path, recurse: :ignore) { super(table_name) } end @@ -117,7 +118,6 @@ def on_schema(schema, recurse: :follow) yield end - ensure # If the transaction is aborted, any execute() call will raise # "transaction is aborted errors" - thus calling the Adapter's @@ -168,6 +168,7 @@ def valid_table_definition_options end private + # Rails 7.1 uses `@raw_connection`, older versions use `@connection` # def chrono_connection @@ -181,7 +182,6 @@ def count_recursions # yield Thread.current['recursions'] += 1 yield - ensure Thread.current['recursions'] -= 1 end @@ -194,5 +194,4 @@ def chrono_ensure_schemas end end end - end diff --git a/lib/chrono_model/adapter/ddl.rb b/lib/chrono_model/adapter/ddl.rb index 5bd21f4c..c874e8f2 100644 --- a/lib/chrono_model/adapter/ddl.rb +++ b/lib/chrono_model/adapter/ddl.rb @@ -3,9 +3,9 @@ module ChronoModel class Adapter < ActiveRecord::ConnectionAdapters::PostgreSQLAdapter - module DDL private + # Create the public view and its INSTEAD OF triggers # def chrono_public_view_ddl(table, options = nil) @@ -231,6 +231,5 @@ def insert_sequence_sql(pk, current) end # private end - end end diff --git a/lib/chrono_model/adapter/indexes.rb b/lib/chrono_model/adapter/indexes.rb index 26fb8858..7518dba6 100644 --- a/lib/chrono_model/adapter/indexes.rb +++ b/lib/chrono_model/adapter/indexes.rb @@ -1,6 +1,5 @@ module ChronoModel class Adapter < ActiveRecord::ConnectionAdapters::PostgreSQLAdapter - module Indexes # Create temporal indexes for timestamp search. # @@ -74,6 +73,7 @@ def timeline_consistency_constraint_name(table) end private + # Creates indexes for a newly made history table # def chrono_create_history_indexes_for(table, p_pkey) @@ -191,9 +191,6 @@ def chrono_alter_constraint(table_name, options) yield end end - - end - end end diff --git a/lib/chrono_model/adapter/migrations.rb b/lib/chrono_model/adapter/migrations.rb index f8e8ec43..26b6fa3c 100644 --- a/lib/chrono_model/adapter/migrations.rb +++ b/lib/chrono_model/adapter/migrations.rb @@ -1,6 +1,5 @@ module ChronoModel class Adapter < ActiveRecord::ConnectionAdapters::PostgreSQLAdapter - module Migrations # Creates the given table, possibly creating the temporal schema # objects if the `:temporal` option is given and set to true. @@ -65,7 +64,6 @@ def rename_table(name, new_name) # def change_table(table_name, **options, &block) transaction do - # Add an empty proc to support calling change_table without a block. # block ||= proc { } @@ -86,7 +84,6 @@ def change_table(table_name, **options, &block) super table_name, **options, &block end - end end @@ -138,6 +135,7 @@ def rename_column(table_name, *) # def change_column(table_name, column_name, type, **options) return super unless is_chrono?(table_name) + drop_and_recreate_public_view(table_name) { super } end @@ -145,6 +143,7 @@ def change_column(table_name, column_name, type, **options) # def change_column_default(table_name, *) return super unless is_chrono?(table_name) + on_temporal_schema { super } end @@ -152,6 +151,7 @@ def change_column_default(table_name, *) # def change_column_null(table_name, *) return super unless is_chrono?(table_name) + on_temporal_schema { super } end @@ -161,10 +161,12 @@ def change_column_null(table_name, *) # def remove_column(table_name, column_name, type = nil, **options) return super unless is_chrono?(table_name) + drop_and_recreate_public_view(table_name) { super } end private + # In destructive changes, such as removing columns or changing column # types, the view must be dropped and recreated, while the change has # to be applied to the table in the temporal schema. @@ -247,6 +249,5 @@ def rename_table_and_pk(name, new_name) # private end - end end diff --git a/lib/chrono_model/adapter/tsrange.rb b/lib/chrono_model/adapter/tsrange.rb index 82d4b7d3..05794c6d 100644 --- a/lib/chrono_model/adapter/tsrange.rb +++ b/lib/chrono_model/adapter/tsrange.rb @@ -1,6 +1,5 @@ module ChronoModel class Adapter < ActiveRecord::ConnectionAdapters::PostgreSQLAdapter - module TSRange # HACK: Redefine tsrange parsing support, as it is broken currently. # @@ -52,6 +51,5 @@ def initialize_type_map(m = type_map) end end end - end end diff --git a/lib/chrono_model/adapter/upgrade.rb b/lib/chrono_model/adapter/upgrade.rb index b8dbb931..ee2910c6 100644 --- a/lib/chrono_model/adapter/upgrade.rb +++ b/lib/chrono_model/adapter/upgrade.rb @@ -1,6 +1,5 @@ module ChronoModel class Adapter < ActiveRecord::ConnectionAdapters::PostgreSQLAdapter - module Upgrade def chrono_upgrade! chrono_ensure_schemas @@ -9,6 +8,7 @@ def chrono_upgrade! end private + # Locate tables needing a structure upgrade # def chrono_tables_needing_upgrade @@ -16,6 +16,7 @@ def chrono_tables_needing_upgrade on_temporal_schema { self.tables }.each do |table_name| next unless is_chrono?(table_name) + metadata = chrono_metadata_for(table_name) version = metadata['chronomodel'] @@ -49,9 +50,7 @@ def chrono_upgrade_warning # def chrono_upgrade_structure! transaction do - chrono_tables_needing_upgrade.each do |table_name, desc| - if desc[:version].blank? logger.info "ChronoModel: Upgrading legacy PG 9.0 table #{table_name} to #{VERSION}" chrono_upgrade_from_postgres_9_0(table_name) @@ -61,7 +60,6 @@ def chrono_upgrade_structure! chrono_public_view_ddl(table_name) logger.info "ChronoModel: #{table_name} upgrade complete" end - end end rescue => e @@ -114,7 +112,5 @@ def chrono_upgrade_from_postgres_9_0(table_name) end # private end - end - end diff --git a/lib/chrono_model/conversions.rb b/lib/chrono_model/conversions.rb index 78187138..a85a8442 100644 --- a/lib/chrono_model/conversions.rb +++ b/lib/chrono_model/conversions.rb @@ -1,5 +1,4 @@ module ChronoModel - module Conversions extend self @@ -18,5 +17,4 @@ def time_to_utc_string(time) [time.to_formatted_s(:db), sprintf('%06d', time.usec)].join '.' end end - end diff --git a/lib/chrono_model/json.rb b/lib/chrono_model/json.rb index e4d52f97..30ec118d 100644 --- a/lib/chrono_model/json.rb +++ b/lib/chrono_model/json.rb @@ -1,5 +1,4 @@ module ChronoModel - module Json extend self @@ -18,6 +17,7 @@ def drop end private + def sql(file) File.dirname(__FILE__) + '/../../sql/' + file end @@ -26,5 +26,4 @@ def adapter ActiveRecord::Base.connection end end - end diff --git a/lib/chrono_model/patches/as_of_time_holder.rb b/lib/chrono_model/patches/as_of_time_holder.rb index aa349279..867fb550 100644 --- a/lib/chrono_model/patches/as_of_time_holder.rb +++ b/lib/chrono_model/patches/as_of_time_holder.rb @@ -1,6 +1,5 @@ module ChronoModel module Patches - # Added to classes that need to carry the As-Of date around # module AsOfTimeHolder @@ -18,6 +17,5 @@ def as_of_time @_as_of_time end end - end end diff --git a/lib/chrono_model/patches/as_of_time_relation.rb b/lib/chrono_model/patches/as_of_time_relation.rb index 3b29789c..60a1e187 100644 --- a/lib/chrono_model/patches/as_of_time_relation.rb +++ b/lib/chrono_model/patches/as_of_time_relation.rb @@ -1,6 +1,5 @@ module ChronoModel module Patches - # This class is a dummy relation whose scope is only to pass around the # as_of_time parameters across ActiveRecord call chains. # @@ -14,6 +13,5 @@ def initialize(klass, table: klass.arel_table, predicate_builder: klass.predicat end end end - end end diff --git a/lib/chrono_model/patches/association.rb b/lib/chrono_model/patches/association.rb index 8022c446..806ac93d 100644 --- a/lib/chrono_model/patches/association.rb +++ b/lib/chrono_model/patches/association.rb @@ -1,6 +1,5 @@ module ChronoModel module Patches - # Patches ActiveRecord::Associations::Association to add support for # temporal associations. # @@ -34,6 +33,7 @@ def scope end private + def _chrono_record? owner.class.include?(ChronoModel::Patches::AsOfTimeHolder) && owner.as_of_time.present? end @@ -45,8 +45,6 @@ def _chrono_target? @_target_klass.chrono? end - end - end end diff --git a/lib/chrono_model/patches/join_node.rb b/lib/chrono_model/patches/join_node.rb index 2de21ff3..c6773ef6 100644 --- a/lib/chrono_model/patches/join_node.rb +++ b/lib/chrono_model/patches/join_node.rb @@ -1,6 +1,5 @@ module ChronoModel module Patches - # This class supports the AR 5.0 code that expects to receive an # Arel::Table as the left join node. We need to replace the node # with a virtual table that fetches from the history at a given @@ -27,6 +26,5 @@ def initialize(join_node, history_model, as_of_time) super(virtual_table) end end - end end diff --git a/lib/chrono_model/patches/preloader.rb b/lib/chrono_model/patches/preloader.rb index 853e5888..ab367646 100644 --- a/lib/chrono_model/patches/preloader.rb +++ b/lib/chrono_model/patches/preloader.rb @@ -1,6 +1,5 @@ module ChronoModel module Patches - # Patches ActiveRecord::Associations::Preloader to add support for # temporal associations. This is tying itself to Rails internals # and it is ugly :-(. @@ -93,6 +92,5 @@ def through_scope end end end - end end diff --git a/lib/chrono_model/patches/relation.rb b/lib/chrono_model/patches/relation.rb index 928f7f7c..a7547c7e 100644 --- a/lib/chrono_model/patches/relation.rb +++ b/lib/chrono_model/patches/relation.rb @@ -1,6 +1,5 @@ module ChronoModel module Patches - module Relation include ChronoModel::Patches::AsOfTimeHolder @@ -39,11 +38,9 @@ def build_arel(*) return super unless @_as_of_time super.tap do |arel| - arel.join_sources.each do |join| chrono_join_history(join) end - end end @@ -98,6 +95,5 @@ def ordered_relation with_hid_pkey { super } end end - end end diff --git a/lib/chrono_model/time_gate.rb b/lib/chrono_model/time_gate.rb index 1adce51a..dcd342e2 100644 --- a/lib/chrono_model/time_gate.rb +++ b/lib/chrono_model/time_gate.rb @@ -1,5 +1,4 @@ module ChronoModel - # Provides the TimeMachine API to non-temporal models that associate # temporal ones. # @@ -24,5 +23,4 @@ def timeline self.class.timeline(self) end end - end diff --git a/lib/chrono_model/time_machine.rb b/lib/chrono_model/time_machine.rb index 9f553830..36577f51 100644 --- a/lib/chrono_model/time_machine.rb +++ b/lib/chrono_model/time_machine.rb @@ -3,7 +3,6 @@ require 'chrono_model/time_machine/history_model' module ChronoModel - module TimeMachine include ChronoModel::Patches::AsOfTimeHolder @@ -169,6 +168,7 @@ def historical? # def destroy raise ActiveRecord::ReadOnlyRecord, 'Cannot delete historical records' if historical? + super end @@ -236,7 +236,5 @@ def changes_against(ref) end end end - end - end diff --git a/lib/chrono_model/time_machine/history_model.rb b/lib/chrono_model/time_machine/history_model.rb index c969c207..d0166518 100644 --- a/lib/chrono_model/time_machine/history_model.rb +++ b/lib/chrono_model/time_machine/history_model.rb @@ -1,6 +1,5 @@ module ChronoModel module TimeMachine - module HistoryModel extend ActiveSupport::Concern @@ -121,6 +120,7 @@ def descends_from_active_record? end private + # STI fails when a Foo::History record has Foo as type in the # inheritance column; AR expects the type to be an instance of the # current class or a descendant (or self). @@ -246,6 +246,5 @@ def with_hid_pkey @primary_key = old_primary_key end end - end end diff --git a/lib/chrono_model/time_machine/time_query.rb b/lib/chrono_model/time_machine/time_query.rb index 536f6c98..03885175 100644 --- a/lib/chrono_model/time_machine/time_query.rb +++ b/lib/chrono_model/time_machine/time_query.rb @@ -1,6 +1,5 @@ module ChronoModel module TimeMachine - # # TODO Documentation # @@ -12,6 +11,7 @@ def time_query(match, time, options) end private + def time_query_sql(match, time, range, options) case match when :at @@ -81,6 +81,5 @@ def build_time_query(time, range, op = '&&') end end end - end end diff --git a/lib/chrono_model/time_machine/timeline.rb b/lib/chrono_model/time_machine/timeline.rb index a5da9495..8bb923b1 100644 --- a/lib/chrono_model/time_machine/timeline.rb +++ b/lib/chrono_model/time_machine/timeline.rb @@ -1,6 +1,5 @@ module ChronoModel module TimeMachine - module Timeline # Returns an Array of unique UTC timestamps for which at least an # history record exists. Takes temporal associations into account. @@ -96,6 +95,5 @@ def quoted_history_fields end end end - end end diff --git a/lib/chrono_model/utilities.rb b/lib/chrono_model/utilities.rb index 685cf8e7..b1abe3d6 100644 --- a/lib/chrono_model/utilities.rb +++ b/lib/chrono_model/utilities.rb @@ -1,5 +1,4 @@ module ChronoModel - module Utilities # Amends the given history item setting a different period. # Useful when migrating from legacy systems. @@ -23,5 +22,4 @@ def amend_period!(hid, from, to) ] end end - end From e10d1c69f974d91183eac56aaaaed9819992ae34 Mon Sep 17 00:00:00 2001 From: Geremia Taglialatela Date: Sat, 9 Sep 2023 17:32:54 +0200 Subject: [PATCH 3/6] Fix other spacing-related issues --- .rubocop_todo.yml | 102 ------------------ .../chronomodel_adapter.rb | 4 +- lib/chrono_model.rb | 4 +- lib/chrono_model/adapter/ddl.rb | 16 +-- lib/chrono_model/adapter/indexes.rb | 8 +- lib/chrono_model/adapter/migrations.rb | 2 +- lib/chrono_model/adapter/tsrange.rb | 6 +- lib/chrono_model/adapter/upgrade.rb | 2 +- lib/chrono_model/patches/relation.rb | 2 +- lib/chrono_model/time_machine.rb | 2 +- .../time_machine/history_model.rb | 2 +- lib/chrono_model/time_machine/time_query.rb | 2 +- lib/chrono_model/time_machine/timeline.rb | 10 +- lib/chrono_model/utilities.rb | 2 +- 14 files changed, 31 insertions(+), 133 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 9f0e34d6..ba2c6e6f 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -6,13 +6,6 @@ # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, IndentationWidth. -# SupportedStyles: with_first_argument, with_fixed_indentation -Layout/ArgumentAlignment: - Exclude: - - 'lib/chrono_model/time_machine/timeline.rb' - # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: leading, trailing @@ -35,22 +28,6 @@ Layout/EndAlignment: - 'lib/chrono_model/adapter/ddl.rb' - 'lib/chrono_model/time_machine/time_query.rb' -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment. -Layout/ExtraSpacing: - Exclude: - - 'lib/chrono_model/adapter/indexes.rb' - - 'lib/chrono_model/adapter/tsrange.rb' - -# 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: - - 'lib/chrono_model/adapter/tsrange.rb' - # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: normal, indented_internal_methods @@ -80,27 +57,6 @@ Layout/IndentationWidth: - 'lib/chrono_model/time_machine/history_model.rb' - 'lib/chrono_model/time_machine/time_query.rb' -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowDoxygenCommentStyle, AllowGemfileRubyComment. -Layout/LeadingCommentSpace: - Exclude: - - 'lib/chrono_model.rb' - - 'lib/chrono_model/time_machine/history_model.rb' - -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: space, no_space -Layout/LineContinuationSpacing: - Exclude: - - 'lib/active_record/connection_adapters/chronomodel_adapter.rb' - -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, IndentationWidth. -# SupportedStyles: aligned, indented -Layout/LineEndStringConcatenationIndentation: - Exclude: - - 'lib/active_record/connection_adapters/chronomodel_adapter.rb' - # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: symmetrical, new_line, same_line @@ -133,64 +89,6 @@ Layout/MultilineOperationIndentation: - 'lib/chrono_model/adapter/indexes.rb' - 'lib/chrono_model/time_machine.rb' -# This cop supports safe autocorrection (--autocorrect). -Layout/SpaceAfterComma: - Exclude: - - 'lib/chrono_model/time_machine/timeline.rb' - -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowForAlignment, EnforcedStyleForExponentOperator. -# SupportedStylesForExponentOperator: space, no_space -Layout/SpaceAroundOperators: - Exclude: - - 'lib/chrono_model.rb' - - 'lib/chrono_model/adapter/indexes.rb' - -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBrackets. -# SupportedStyles: space, no_space, compact -# SupportedStylesForEmptyBrackets: space, no_space -Layout/SpaceInsideArrayLiteralBrackets: - Exclude: - - 'lib/chrono_model/adapter/ddl.rb' - -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters. -# SupportedStyles: space, no_space -# SupportedStylesForEmptyBraces: space, no_space -Layout/SpaceInsideBlockBraces: - Exclude: - - 'lib/chrono_model/adapter/ddl.rb' - - 'lib/chrono_model/adapter/indexes.rb' - - 'lib/chrono_model/adapter/migrations.rb' - - 'lib/chrono_model/patches/relation.rb' - - 'lib/chrono_model/time_machine/time_query.rb' - - 'lib/chrono_model/time_machine/timeline.rb' - - 'lib/chrono_model/utilities.rb' - -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. -# SupportedStyles: space, no_space, compact -# SupportedStylesForEmptyBraces: space, no_space -Layout/SpaceInsideHashLiteralBraces: - Exclude: - - 'lib/chrono_model/adapter/upgrade.rb' - -# This cop supports safe autocorrection (--autocorrect). -Layout/SpaceInsidePercentLiteralDelimiters: - Exclude: - - 'lib/chrono_model/adapter/ddl.rb' - - 'lib/chrono_model/time_machine.rb' - -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBrackets. -# SupportedStyles: space, no_space -# SupportedStylesForEmptyBrackets: space, no_space -Layout/SpaceInsideReferenceBrackets: - Exclude: - - 'lib/chrono_model/adapter/tsrange.rb' - - 'lib/chrono_model/time_machine/timeline.rb' - # This cop supports safe autocorrection (--autocorrect). Lint/AmbiguousOperator: Exclude: diff --git a/lib/active_record/connection_adapters/chronomodel_adapter.rb b/lib/active_record/connection_adapters/chronomodel_adapter.rb index f2ae5fe5..85203092 100644 --- a/lib/active_record/connection_adapters/chronomodel_adapter.rb +++ b/lib/active_record/connection_adapters/chronomodel_adapter.rb @@ -28,8 +28,8 @@ def chronomodel_connection(config) # :nodoc: adapter = ChronoModel::Adapter.new(conn, logger, conn_params, config) unless adapter.chrono_supported? - raise ChronoModel::Error, "Your database server is not supported by ChronoModel. "\ - "Currently, only PostgreSQL >= 9.3 is supported." + raise ChronoModel::Error, "Your database server is not supported by ChronoModel. " \ + "Currently, only PostgreSQL >= 9.3 is supported." end adapter.chrono_setup! diff --git a/lib/chrono_model.rb b/lib/chrono_model.rb index f96bf6d9..8336460f 100644 --- a/lib/chrono_model.rb +++ b/lib/chrono_model.rb @@ -8,7 +8,7 @@ require 'chrono_model/version' module ChronoModel - class Error < ActiveRecord::ActiveRecordError #:nodoc: + class Error < ActiveRecord::ActiveRecordError # :nodoc: end # Performs structure upgrade. @@ -27,7 +27,7 @@ def self.upgrade! # Computed upon inclusion of the +TimeMachine+ module. # def self.history_models - @_history_models||= {} + @_history_models ||= {} end end diff --git a/lib/chrono_model/adapter/ddl.rb b/lib/chrono_model/adapter/ddl.rb index c874e8f2..161d20fa 100644 --- a/lib/chrono_model/adapter/ddl.rb +++ b/lib/chrono_model/adapter/ddl.rb @@ -36,10 +36,10 @@ def chrono_public_view_ddl(table, options = nil) execute "ALTER VIEW #{table} ALTER COLUMN #{quote_column_name(column.name)} SET DEFAULT #{default}" end - columns = self.columns(table).map {|c| quote_column_name(c.name)} + columns = self.columns(table).map { |c| quote_column_name(c.name) } columns.delete(quote_column_name(pk)) - fields, values = columns.join(', '), columns.map {|c| "NEW.#{c}"}.join(', ') + fields, values = columns.join(', '), columns.map { |c| "NEW.#{c}" }.join(', ') chrono_create_INSERT_trigger(table, pk, current, history, fields, values) chrono_create_UPDATE_trigger(table, pk, current, history, fields, values, options, columns) @@ -116,16 +116,16 @@ def chrono_create_UPDATE_trigger(table, pk, current, history, fields, values, op # Columns to be journaled. By default everything except updated_at (GH #7) # journal = if options[:journal] - options[:journal].map {|col| quote_column_name(col)} + options[:journal].map { |col| quote_column_name(col) } elsif options[:no_journal] - columns - options[:no_journal].map {|col| quote_column_name(col)} + columns - options[:no_journal].map { |col| quote_column_name(col) } elsif options[:full_journal] columns else - columns - [ quote_column_name('updated_at') ] + columns - [quote_column_name('updated_at')] end journal &= columns @@ -141,8 +141,8 @@ def chrono_create_UPDATE_trigger(table, pk, current, history, fields, values, op RETURN NULL; END IF; - _old := row(#{journal.map {|c| "OLD.#{c}" }.join(', ')}); - _new := row(#{journal.map {|c| "NEW.#{c}" }.join(', ')}); + _old := row(#{journal.map { |c| "OLD.#{c}" }.join(', ')}); + _new := row(#{journal.map { |c| "NEW.#{c}" }.join(', ')}); IF _old IS NOT DISTINCT FROM _new THEN UPDATE ONLY #{current} SET ( #{fields} ) = ( #{values} ) WHERE #{pk} = OLD.#{pk}; @@ -212,7 +212,7 @@ def chrono_create_DELETE_trigger(table, pk, current, history) end def chrono_drop_trigger_functions_for(table_name) - %w( insert update delete ).each do |func| + %w(insert update delete).each do |func| execute "DROP FUNCTION IF EXISTS chronomodel_#{table_name}_#{func}()" end end diff --git a/lib/chrono_model/adapter/indexes.rb b/lib/chrono_model/adapter/indexes.rb index 7518dba6..48d23ee7 100644 --- a/lib/chrono_model/adapter/indexes.rb +++ b/lib/chrono_model/adapter/indexes.rb @@ -38,7 +38,7 @@ def remove_temporal_indexes(table, range, options = {}) indexes = temporal_index_names(table, range, options) chrono_alter_index(table, options) do - indexes.each {|idx| execute "DROP INDEX #{idx}" } + indexes.each { |idx| execute "DROP INDEX #{idx}" } end end @@ -93,10 +93,10 @@ def chrono_rename_history_indexes(name, new_name) recorded_at timeline_consistency ) old_names = temporal_index_names(name, :validity) + - standard_index_names.map {|i| [name, i].join('_') } + standard_index_names.map { |i| [name, i].join('_') } new_names = temporal_index_names(new_name, :validity) + - standard_index_names.map {|i| [new_name, i].join('_') } + standard_index_names.map { |i| [new_name, i].join('_') } old_names.zip(new_names).each do |old, new| execute "ALTER INDEX #{old} RENAME TO #{new}" @@ -108,7 +108,7 @@ def chrono_rename_history_indexes(name, new_name) # def chrono_rename_temporal_indexes(name, new_name) on_temporal_schema do - temporal_indexes = indexes(new_name) + temporal_indexes = indexes(new_name) temporal_indexes.map(&:name).each do |old_idx_name| if old_idx_name =~ /^index_#{name}_on_(?.+)/ new_idx_name = "index_#{new_name}_on_#{$~['columns']}" diff --git a/lib/chrono_model/adapter/migrations.rb b/lib/chrono_model/adapter/migrations.rb index 26b6fa3c..2d446e21 100644 --- a/lib/chrono_model/adapter/migrations.rb +++ b/lib/chrono_model/adapter/migrations.rb @@ -66,7 +66,7 @@ def change_table(table_name, **options, &block) transaction do # Add an empty proc to support calling change_table without a block. # - block ||= proc { } + block ||= proc {} if options[:temporal] if !is_chrono?(table_name) diff --git a/lib/chrono_model/adapter/tsrange.rb b/lib/chrono_model/adapter/tsrange.rb index 05794c6d..dab4d667 100644 --- a/lib/chrono_model/adapter/tsrange.rb +++ b/lib/chrono_model/adapter/tsrange.rb @@ -25,7 +25,7 @@ def cast_value(value) extracted = extract_bounds(value) from = Conversions.string_to_utc_time extracted[:from] - to = Conversions.string_to_utc_time extracted[:to ] + to = Conversions.string_to_utc_time extracted[:to] [from, to] end @@ -33,8 +33,8 @@ def cast_value(value) def extract_bounds(value) from, to = value[1..-2].split(',') { - from: (value[1] == ',' || from == '-infinity') ? nil : from[1..-2], - to: (value[-2] == ',' || to == 'infinity') ? nil : to[1..-2], + from: (value[1] == ',' || from == '-infinity') ? nil : from[1..-2], + to: (value[-2] == ',' || to == 'infinity') ? nil : to[1..-2], } end end diff --git a/lib/chrono_model/adapter/upgrade.rb b/lib/chrono_model/adapter/upgrade.rb index ee2910c6..df488fb2 100644 --- a/lib/chrono_model/adapter/upgrade.rb +++ b/lib/chrono_model/adapter/upgrade.rb @@ -12,7 +12,7 @@ def chrono_upgrade! # Locate tables needing a structure upgrade # def chrono_tables_needing_upgrade - tables = { } + tables = {} on_temporal_schema { self.tables }.each do |table_name| next unless is_chrono?(table_name) diff --git a/lib/chrono_model/patches/relation.rb b/lib/chrono_model/patches/relation.rb index a7547c7e..49486dea 100644 --- a/lib/chrono_model/patches/relation.rb +++ b/lib/chrono_model/patches/relation.rb @@ -25,7 +25,7 @@ def empty_scope? def load return super unless @_as_of_time && !loaded? - super.each {|record| record.as_of_time!(@_as_of_time) } + super.each { |record| record.as_of_time!(@_as_of_time) } end def merge(*) diff --git a/lib/chrono_model/time_machine.rb b/lib/chrono_model/time_machine.rb index 36577f51..685e972c 100644 --- a/lib/chrono_model/time_machine.rb +++ b/lib/chrono_model/time_machine.rb @@ -106,7 +106,7 @@ def as_of(time) def attribute_names_for_history_changes @attribute_names_for_history_changes ||= attribute_names - - %w( id hid validity recorded_at ) + %w(id hid validity recorded_at) end def has_timeline(options) diff --git a/lib/chrono_model/time_machine/history_model.rb b/lib/chrono_model/time_machine/history_model.rb index d0166518..7416e800 100644 --- a/lib/chrono_model/time_machine/history_model.rb +++ b/lib/chrono_model/time_machine/history_model.rb @@ -203,7 +203,7 @@ def current_version self.class.superclass.find(rid) end - def record #:nodoc: + def record # :nodoc: ActiveSupport::Deprecation.warn '.record is deprecated in favour of .current_version' self.current_version end diff --git a/lib/chrono_model/time_machine/time_query.rb b/lib/chrono_model/time_machine/time_query.rb index 03885175..54e2032f 100644 --- a/lib/chrono_model/time_machine/time_query.rb +++ b/lib/chrono_model/time_machine/time_query.rb @@ -61,7 +61,7 @@ def primitive_type_for_column(column) def build_time_query_at(time, range) time = if time.kind_of?(Array) - time.map! {|t| time_for_time_query(t, range)} + time.map! { |t| time_for_time_query(t, range) } # If both edges of the range are the same the query fails using the '&&' operator. # The correct solution is to use the <@ operator. diff --git a/lib/chrono_model/time_machine/timeline.rb b/lib/chrono_model/time_machine/timeline.rb index 8bb923b1..02678f6e 100644 --- a/lib/chrono_model/time_machine/timeline.rb +++ b/lib/chrono_model/time_machine/timeline.rb @@ -12,11 +12,11 @@ def timeline(record = nil, options = {}) models = [] models.push self if self.chrono? - models.concat(assocs.map {|a| a.klass.history}) + models.concat(assocs.map { |a| a.klass.history }) return [] if models.empty? - fields = models.inject([]) {|a,m| a.concat m.quoted_history_fields} + fields = models.inject([]) { |a, m| a.concat m.quoted_history_fields } relation = self.except(:order). select("DISTINCT UNNEST(ARRAY[#{fields.join(',')}]) AS ts") @@ -47,7 +47,7 @@ def timeline(record = nil, options = {}) end if options.key?(:after) - sql << " AND ts > '#{Conversions.time_to_utc_string(options[:after ])}'" + sql << " AND ts > '#{Conversions.time_to_utc_string(options[:after])}'" end if rid && !options[:with] @@ -80,7 +80,7 @@ def timeline_associations def timeline_associations_from(names) Array.wrap(names).map do |name| reflect_on_association(name) or raise ArgumentError, - "No association found for name `#{name}'" + "No association found for name `#{name}'" end end @@ -91,7 +91,7 @@ def quoted_history_fields connection.quote_column_name('validity') ].join('.') - [:lower, :upper].map! {|func| "#{func}(#{validity})"} + [:lower, :upper].map! { |func| "#{func}(#{validity})" } end end end diff --git a/lib/chrono_model/utilities.rb b/lib/chrono_model/utilities.rb index b1abe3d6..b857cc93 100644 --- a/lib/chrono_model/utilities.rb +++ b/lib/chrono_model/utilities.rb @@ -10,7 +10,7 @@ module Utilities # end # def amend_period!(hid, from, to) - unless [from, to].any? {|ts| ts.respond_to?(:zone) && ts.zone == 'UTC'} + unless [from, to].any? { |ts| ts.respond_to?(:zone) && ts.zone == 'UTC' } raise 'Can amend history only with UTC timestamps' end From 04eb7305cd8590ac555e1c2930327b87fc588ca3 Mon Sep 17 00:00:00 2001 From: Geremia Taglialatela Date: Sat, 9 Sep 2023 17:37:07 +0200 Subject: [PATCH 4/6] Fix indentation --- .rubocop_todo.yml | 29 --- lib/chrono_model/adapter.rb | 40 ++-- lib/chrono_model/adapter/ddl.rb | 206 +++++++++--------- lib/chrono_model/adapter/indexes.rb | 178 +++++++-------- lib/chrono_model/adapter/migrations.rb | 108 ++++----- lib/chrono_model/adapter/upgrade.rb | 164 +++++++------- lib/chrono_model/patches/association.rb | 18 +- lib/chrono_model/patches/relation.rb | 8 +- .../time_machine/history_model.rb | 14 +- lib/chrono_model/time_machine/time_query.rb | 104 ++++----- 10 files changed, 420 insertions(+), 449 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index ba2c6e6f..456ad9fc 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -28,35 +28,6 @@ Layout/EndAlignment: - 'lib/chrono_model/adapter/ddl.rb' - 'lib/chrono_model/time_machine/time_query.rb' -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: normal, indented_internal_methods -Layout/IndentationConsistency: - Exclude: - - 'lib/chrono_model/adapter.rb' - - 'lib/chrono_model/adapter/ddl.rb' - - 'lib/chrono_model/adapter/indexes.rb' - - 'lib/chrono_model/adapter/migrations.rb' - - 'lib/chrono_model/adapter/upgrade.rb' - - 'lib/chrono_model/patches/association.rb' - - 'lib/chrono_model/patches/relation.rb' - - 'lib/chrono_model/time_machine/history_model.rb' - - 'lib/chrono_model/time_machine/time_query.rb' - -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: Width, AllowedPatterns. -Layout/IndentationWidth: - Exclude: - - 'lib/chrono_model/adapter.rb' - - 'lib/chrono_model/adapter/ddl.rb' - - 'lib/chrono_model/adapter/indexes.rb' - - 'lib/chrono_model/adapter/migrations.rb' - - 'lib/chrono_model/adapter/upgrade.rb' - - 'lib/chrono_model/patches/association.rb' - - 'lib/chrono_model/patches/relation.rb' - - 'lib/chrono_model/time_machine/history_model.rb' - - 'lib/chrono_model/time_machine/time_query.rb' - # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: symmetrical, new_line, same_line diff --git a/lib/chrono_model/adapter.rb b/lib/chrono_model/adapter.rb index b3a247c3..22b7ca92 100644 --- a/lib/chrono_model/adapter.rb +++ b/lib/chrono_model/adapter.rb @@ -169,29 +169,29 @@ def valid_table_definition_options private - # Rails 7.1 uses `@raw_connection`, older versions use `@connection` - # - def chrono_connection - @chrono_connection ||= @raw_connection || @connection - end + # Rails 7.1 uses `@raw_connection`, older versions use `@connection` + # + def chrono_connection + @chrono_connection ||= @raw_connection || @connection + end - # Counts the number of recursions in a thread local variable - # - def count_recursions # yield - Thread.current['recursions'] ||= 0 - Thread.current['recursions'] += 1 + # Counts the number of recursions in a thread local variable + # + def count_recursions # yield + Thread.current['recursions'] ||= 0 + Thread.current['recursions'] += 1 - yield - ensure - Thread.current['recursions'] -= 1 - end + yield + ensure + Thread.current['recursions'] -= 1 + end - # Create the temporal and history schemas, unless they already exist - # - def chrono_ensure_schemas - [TEMPORAL_SCHEMA, HISTORY_SCHEMA].each do |schema| - execute "CREATE SCHEMA #{schema}" unless schema_exists?(schema) - end + # Create the temporal and history schemas, unless they already exist + # + def chrono_ensure_schemas + [TEMPORAL_SCHEMA, HISTORY_SCHEMA].each do |schema| + execute "CREATE SCHEMA #{schema}" unless schema_exists?(schema) end + end end end diff --git a/lib/chrono_model/adapter/ddl.rb b/lib/chrono_model/adapter/ddl.rb index 161d20fa..0d435b68 100644 --- a/lib/chrono_model/adapter/ddl.rb +++ b/lib/chrono_model/adapter/ddl.rb @@ -6,79 +6,79 @@ class Adapter < ActiveRecord::ConnectionAdapters::PostgreSQLAdapter module DDL private - # Create the public view and its INSTEAD OF triggers - # - def chrono_public_view_ddl(table, options = nil) - pk = primary_key(table) - current = [TEMPORAL_SCHEMA, table].join('.') - history = [HISTORY_SCHEMA, table].join('.') + # Create the public view and its INSTEAD OF triggers + # + def chrono_public_view_ddl(table, options = nil) + pk = primary_key(table) + current = [TEMPORAL_SCHEMA, table].join('.') + history = [HISTORY_SCHEMA, table].join('.') - options ||= chrono_metadata_for(table) + options ||= chrono_metadata_for(table) - # SELECT - return only current data - # - execute "DROP VIEW #{table}" if data_source_exists? table - execute "CREATE VIEW #{table} AS SELECT * FROM ONLY #{current}" + # SELECT - return only current data + # + execute "DROP VIEW #{table}" if data_source_exists? table + execute "CREATE VIEW #{table} AS SELECT * FROM ONLY #{current}" - chrono_metadata_set(table, options.merge(chronomodel: VERSION)) + chrono_metadata_set(table, options.merge(chronomodel: VERSION)) - # Set default values on the view (closes #12) - # - columns(table).each do |column| - default = if column.default.nil? - column.default_function - else - quote(column.default) - end + # Set default values on the view (closes #12) + # + columns(table).each do |column| + default = if column.default.nil? + column.default_function + else + quote(column.default) + end - next if column.name == pk || default.nil? + next if column.name == pk || default.nil? - execute "ALTER VIEW #{table} ALTER COLUMN #{quote_column_name(column.name)} SET DEFAULT #{default}" - end + execute "ALTER VIEW #{table} ALTER COLUMN #{quote_column_name(column.name)} SET DEFAULT #{default}" + end - columns = self.columns(table).map { |c| quote_column_name(c.name) } - columns.delete(quote_column_name(pk)) + columns = self.columns(table).map { |c| quote_column_name(c.name) } + columns.delete(quote_column_name(pk)) - fields, values = columns.join(', '), columns.map { |c| "NEW.#{c}" }.join(', ') + fields, values = columns.join(', '), columns.map { |c| "NEW.#{c}" }.join(', ') - chrono_create_INSERT_trigger(table, pk, current, history, fields, values) - chrono_create_UPDATE_trigger(table, pk, current, history, fields, values, options, columns) - chrono_create_DELETE_trigger(table, pk, current, history) - end + chrono_create_INSERT_trigger(table, pk, current, history, fields, values) + chrono_create_UPDATE_trigger(table, pk, current, history, fields, values, options, columns) + chrono_create_DELETE_trigger(table, pk, current, history) + end - # Create the history table in the history schema - def chrono_history_table_ddl(table) - parent = "#{TEMPORAL_SCHEMA}.#{table}" - p_pkey = primary_key(parent) + # Create the history table in the history schema + def chrono_history_table_ddl(table) + parent = "#{TEMPORAL_SCHEMA}.#{table}" + p_pkey = primary_key(parent) - execute <<-SQL + execute <<-SQL CREATE TABLE #{table} ( hid BIGSERIAL PRIMARY KEY, validity tsrange NOT NULL, recorded_at timestamp NOT NULL DEFAULT timezone('UTC', now()) ) INHERITS ( #{parent} ) - SQL + SQL - add_history_validity_constraint(table, p_pkey) + add_history_validity_constraint(table, p_pkey) - chrono_create_history_indexes_for(table, p_pkey) - end + chrono_create_history_indexes_for(table, p_pkey) + end - def add_history_validity_constraint(table, pkey) - add_timeline_consistency_constraint(table, :validity, id: pkey, on_current_schema: true) - end + def add_history_validity_constraint(table, pkey) + add_timeline_consistency_constraint(table, :validity, id: pkey, on_current_schema: true) + end - def remove_history_validity_constraint(table, options = {}) - remove_timeline_consistency_constraint(table, options.merge(on_current_schema: true)) - end + def remove_history_validity_constraint(table, options = {}) + remove_timeline_consistency_constraint(table, options.merge(on_current_schema: true)) + end - # INSERT - insert data both in the temporal table and in the history one. - # - # The serial sequence is invoked manually only if the PK is NULL, to - # allow setting the PK to a specific value (think migration scenario). - # - def chrono_create_INSERT_trigger(table, pk, current, history, fields, values) - execute <<-SQL.strip_heredoc + # INSERT - insert data both in the temporal table and in the history one. + # + # The serial sequence is invoked manually only if the PK is NULL, to + # allow setting the PK to a specific value (think migration scenario). + # + def chrono_create_INSERT_trigger(table, pk, current, history, fields, values) + execute <<-SQL.strip_heredoc CREATE OR REPLACE FUNCTION chronomodel_#{table}_insert() RETURNS TRIGGER AS $$ BEGIN #{insert_sequence_sql(pk, current)} INTO #{current} ( #{pk}, #{fields} ) @@ -96,41 +96,41 @@ def chrono_create_INSERT_trigger(table, pk, current, history, fields, values) CREATE TRIGGER chronomodel_insert INSTEAD OF INSERT ON #{table} FOR EACH ROW EXECUTE PROCEDURE chronomodel_#{table}_insert(); - SQL - end - - # UPDATE - set the last history entry validity to now, save the current data - # in a new history entry and update the temporal table with the new data. - # - # If there are no changes, this trigger suppresses redundant updates. - # - # If a row in the history with the current ID and current timestamp already - # exists, update it with new data. This logic makes possible to "squash" - # together changes made in a transaction in a single history row. - # - # If you want to disable this behaviour, set the CHRONOMODEL_NO_SQUASH - # environment variable. This is useful when running scenarios inside - # cucumber, in which everything runs in the same transaction. + SQL + end + + # UPDATE - set the last history entry validity to now, save the current data + # in a new history entry and update the temporal table with the new data. + # + # If there are no changes, this trigger suppresses redundant updates. + # + # If a row in the history with the current ID and current timestamp already + # exists, update it with new data. This logic makes possible to "squash" + # together changes made in a transaction in a single history row. + # + # If you want to disable this behaviour, set the CHRONOMODEL_NO_SQUASH + # environment variable. This is useful when running scenarios inside + # cucumber, in which everything runs in the same transaction. + # + def chrono_create_UPDATE_trigger(table, pk, current, history, fields, values, options, columns) + # Columns to be journaled. By default everything except updated_at (GH #7) # - def chrono_create_UPDATE_trigger(table, pk, current, history, fields, values, options, columns) - # Columns to be journaled. By default everything except updated_at (GH #7) - # - journal = if options[:journal] - options[:journal].map { |col| quote_column_name(col) } + journal = if options[:journal] + options[:journal].map { |col| quote_column_name(col) } - elsif options[:no_journal] - columns - options[:no_journal].map { |col| quote_column_name(col) } + elsif options[:no_journal] + columns - options[:no_journal].map { |col| quote_column_name(col) } - elsif options[:full_journal] - columns + elsif options[:full_journal] + columns - else - columns - [quote_column_name('updated_at')] - end + else + columns - [quote_column_name('updated_at')] + end - journal &= columns + journal &= columns - execute <<-SQL.strip_heredoc + execute <<-SQL.strip_heredoc CREATE OR REPLACE FUNCTION chronomodel_#{table}_update() RETURNS TRIGGER AS $$ DECLARE _now timestamp; DECLARE _hid integer; @@ -175,16 +175,16 @@ def chrono_create_UPDATE_trigger(table, pk, current, history, fields, values, op CREATE TRIGGER chronomodel_update INSTEAD OF UPDATE ON #{table} FOR EACH ROW EXECUTE PROCEDURE chronomodel_#{table}_update(); - SQL - end - - # DELETE - save the current data in the history and eventually delete the - # data from the temporal table. - # The first DELETE is required to remove history for records INSERTed and - # DELETEd in the same transaction. - # - def chrono_create_DELETE_trigger(table, pk, current, history) - execute <<-SQL.strip_heredoc + SQL + end + + # DELETE - save the current data in the history and eventually delete the + # data from the temporal table. + # The first DELETE is required to remove history for records INSERTed and + # DELETEd in the same transaction. + # + def chrono_create_DELETE_trigger(table, pk, current, history) + execute <<-SQL.strip_heredoc CREATE OR REPLACE FUNCTION chronomodel_#{table}_delete() RETURNS TRIGGER AS $$ DECLARE _now timestamp; BEGIN @@ -208,27 +208,27 @@ def chrono_create_DELETE_trigger(table, pk, current, history) CREATE TRIGGER chronomodel_delete INSTEAD OF DELETE ON #{table} FOR EACH ROW EXECUTE PROCEDURE chronomodel_#{table}_delete(); - SQL - end + SQL + end - def chrono_drop_trigger_functions_for(table_name) - %w(insert update delete).each do |func| - execute "DROP FUNCTION IF EXISTS chronomodel_#{table_name}_#{func}()" - end + def chrono_drop_trigger_functions_for(table_name) + %w(insert update delete).each do |func| + execute "DROP FUNCTION IF EXISTS chronomodel_#{table_name}_#{func}()" end + end - def insert_sequence_sql(pk, current) - seq = pk_and_sequence_for(current) - return 'INSERT' if seq.blank? + def insert_sequence_sql(pk, current) + seq = pk_and_sequence_for(current) + return 'INSERT' if seq.blank? - <<-SQL.strip + <<-SQL.strip IF NEW.#{pk} IS NULL THEN NEW.#{pk} := nextval('#{seq.last}'); END IF; INSERT - SQL - end + SQL + end # private end end diff --git a/lib/chrono_model/adapter/indexes.rb b/lib/chrono_model/adapter/indexes.rb index 48d23ee7..63c9c854 100644 --- a/lib/chrono_model/adapter/indexes.rb +++ b/lib/chrono_model/adapter/indexes.rb @@ -74,123 +74,123 @@ def timeline_consistency_constraint_name(table) private - # Creates indexes for a newly made history table - # - def chrono_create_history_indexes_for(table, p_pkey) - add_temporal_indexes table, :validity, on_current_schema: true + # Creates indexes for a newly made history table + # + def chrono_create_history_indexes_for(table, p_pkey) + add_temporal_indexes table, :validity, on_current_schema: true - execute "CREATE INDEX #{table}_inherit_pkey ON #{table} ( #{p_pkey} )" - execute "CREATE INDEX #{table}_recorded_at ON #{table} ( recorded_at )" - execute "CREATE INDEX #{table}_instance_history ON #{table} ( #{p_pkey}, recorded_at )" - end + execute "CREATE INDEX #{table}_inherit_pkey ON #{table} ( #{p_pkey} )" + execute "CREATE INDEX #{table}_recorded_at ON #{table} ( recorded_at )" + execute "CREATE INDEX #{table}_instance_history ON #{table} ( #{p_pkey}, recorded_at )" + end - # Rename indexes on history schema - # - def chrono_rename_history_indexes(name, new_name) - on_history_schema do - standard_index_names = %w( - inherit_pkey instance_history pkey - recorded_at timeline_consistency ) + # Rename indexes on history schema + # + def chrono_rename_history_indexes(name, new_name) + on_history_schema do + standard_index_names = %w( + inherit_pkey instance_history pkey + recorded_at timeline_consistency ) - old_names = temporal_index_names(name, :validity) + - standard_index_names.map { |i| [name, i].join('_') } + old_names = temporal_index_names(name, :validity) + + standard_index_names.map { |i| [name, i].join('_') } - new_names = temporal_index_names(new_name, :validity) + - standard_index_names.map { |i| [new_name, i].join('_') } + new_names = temporal_index_names(new_name, :validity) + + standard_index_names.map { |i| [new_name, i].join('_') } - old_names.zip(new_names).each do |old, new| - execute "ALTER INDEX #{old} RENAME TO #{new}" - end + old_names.zip(new_names).each do |old, new| + execute "ALTER INDEX #{old} RENAME TO #{new}" end end + end - # Rename indexes on temporal schema - # - def chrono_rename_temporal_indexes(name, new_name) - on_temporal_schema do - temporal_indexes = indexes(new_name) - temporal_indexes.map(&:name).each do |old_idx_name| - if old_idx_name =~ /^index_#{name}_on_(?.+)/ - new_idx_name = "index_#{new_name}_on_#{$~['columns']}" - execute "ALTER INDEX #{old_idx_name} RENAME TO #{new_idx_name}" - end + # Rename indexes on temporal schema + # + def chrono_rename_temporal_indexes(name, new_name) + on_temporal_schema do + temporal_indexes = indexes(new_name) + temporal_indexes.map(&:name).each do |old_idx_name| + if old_idx_name =~ /^index_#{name}_on_(?.+)/ + new_idx_name = "index_#{new_name}_on_#{$~['columns']}" + execute "ALTER INDEX #{old_idx_name} RENAME TO #{new_idx_name}" end end end + end - # Copy the indexes from the temporal table to the history table - # if the indexes are not already created with the same name. - # - # Uniqueness is voluntarily ignored, as it doesn't make sense on - # history tables. - # - # Used in migrations. - # - # Ref: GitHub pull #21. - # - def chrono_copy_indexes_to_history(table_name) - history_indexes = on_history_schema { indexes(table_name) }.map(&:name) - temporal_indexes = on_temporal_schema { indexes(table_name) } + # Copy the indexes from the temporal table to the history table + # if the indexes are not already created with the same name. + # + # Uniqueness is voluntarily ignored, as it doesn't make sense on + # history tables. + # + # Used in migrations. + # + # Ref: GitHub pull #21. + # + def chrono_copy_indexes_to_history(table_name) + history_indexes = on_history_schema { indexes(table_name) }.map(&:name) + temporal_indexes = on_temporal_schema { indexes(table_name) } - temporal_indexes.each do |index| - next if history_indexes.include?(index.name) + temporal_indexes.each do |index| + next if history_indexes.include?(index.name) - on_history_schema do - # index.columns is an Array for plain indexes, - # while it is a String for computed indexes. - # - columns = Array.wrap(index.columns).join(', ') + on_history_schema do + # index.columns is an Array for plain indexes, + # while it is a String for computed indexes. + # + columns = Array.wrap(index.columns).join(', ') - execute %[ + execute %[ CREATE INDEX #{index.name} ON #{table_name} USING #{index.using} ( #{columns} ) ], 'Copy index from temporal to history' - end end end + end - # Returns a suitable index name on the given table and for the - # given range definition. - # - def temporal_index_names(table, range, options = {}) - prefix = options[:name].presence || "index_#{table}_temporal" + # Returns a suitable index name on the given table and for the + # given range definition. + # + def temporal_index_names(table, range, options = {}) + prefix = options[:name].presence || "index_#{table}_temporal" - # When creating computed indexes - # - # e.g. ends_on::timestamp + time '23:59:59' - # - # remove everything following the field name. - range = range.to_s.sub(/\W.*/, '') + # When creating computed indexes + # + # e.g. ends_on::timestamp + time '23:59:59' + # + # remove everything following the field name. + range = range.to_s.sub(/\W.*/, '') - [range, "lower_#{range}", "upper_#{range}"].map do |suffix| - [prefix, 'on', suffix].join('_') - end + [range, "lower_#{range}", "upper_#{range}"].map do |suffix| + [prefix, 'on', suffix].join('_') end + end - # Generic alteration of history tables, where changes have to be - # propagated both on the temporal table and the history one. - # - # Internally, the :on_current_schema bypasses the +is_chrono?+ - # check, as some temporal indexes and constraints are created - # only on the history table, and the creation methods already - # run scoped into the correct schema. - # - def chrono_alter_index(table_name, options) - if is_chrono?(table_name) && !options[:on_current_schema] - on_temporal_schema { yield } - on_history_schema { yield } - else - yield - end + # Generic alteration of history tables, where changes have to be + # propagated both on the temporal table and the history one. + # + # Internally, the :on_current_schema bypasses the +is_chrono?+ + # check, as some temporal indexes and constraints are created + # only on the history table, and the creation methods already + # run scoped into the correct schema. + # + def chrono_alter_index(table_name, options) + if is_chrono?(table_name) && !options[:on_current_schema] + on_temporal_schema { yield } + on_history_schema { yield } + else + yield end + end - def chrono_alter_constraint(table_name, options) - if is_chrono?(table_name) && !options[:on_current_schema] - on_temporal_schema { yield } - else - yield - end + def chrono_alter_constraint(table_name, options) + if is_chrono?(table_name) && !options[:on_current_schema] + on_temporal_schema { yield } + else + yield end + end end end end diff --git a/lib/chrono_model/adapter/migrations.rb b/lib/chrono_model/adapter/migrations.rb index 2d446e21..9e83453b 100644 --- a/lib/chrono_model/adapter/migrations.rb +++ b/lib/chrono_model/adapter/migrations.rb @@ -167,48 +167,48 @@ def remove_column(table_name, column_name, type = nil, **options) private - # In destructive changes, such as removing columns or changing column - # types, the view must be dropped and recreated, while the change has - # to be applied to the table in the temporal schema. - # - def drop_and_recreate_public_view(table_name, opts = {}) - transaction do - options = chrono_metadata_for(table_name).merge(opts) + # In destructive changes, such as removing columns or changing column + # types, the view must be dropped and recreated, while the change has + # to be applied to the table in the temporal schema. + # + def drop_and_recreate_public_view(table_name, opts = {}) + transaction do + options = chrono_metadata_for(table_name).merge(opts) - execute "DROP VIEW #{table_name}" + execute "DROP VIEW #{table_name}" - on_temporal_schema { yield } + on_temporal_schema { yield } - # Recreate the triggers - chrono_public_view_ddl(table_name, options) - end + # Recreate the triggers + chrono_public_view_ddl(table_name, options) end + end - def chrono_make_temporal_table(table_name, options) - # Add temporal features to this table - # - if !primary_key(table_name) - execute "ALTER TABLE #{table_name} ADD __chrono_id SERIAL PRIMARY KEY" - end + def chrono_make_temporal_table(table_name, options) + # Add temporal features to this table + # + if !primary_key(table_name) + execute "ALTER TABLE #{table_name} ADD __chrono_id SERIAL PRIMARY KEY" + end - execute "ALTER TABLE #{table_name} SET SCHEMA #{TEMPORAL_SCHEMA}" - on_history_schema { chrono_history_table_ddl(table_name) } - chrono_public_view_ddl(table_name, options) - chrono_copy_indexes_to_history(table_name) + execute "ALTER TABLE #{table_name} SET SCHEMA #{TEMPORAL_SCHEMA}" + on_history_schema { chrono_history_table_ddl(table_name) } + chrono_public_view_ddl(table_name, options) + chrono_copy_indexes_to_history(table_name) - # Optionally copy the plain table data, setting up history - # retroactively. - # - if options[:copy_data] - chrono_copy_temporal_to_history(table_name, options) - end + # Optionally copy the plain table data, setting up history + # retroactively. + # + if options[:copy_data] + chrono_copy_temporal_to_history(table_name, options) end + end - def chrono_copy_temporal_to_history(table_name, options) - seq = on_history_schema { pk_and_sequence_for(table_name).last.to_s } - from = options[:validity] || '0001-01-01 00:00:00' + def chrono_copy_temporal_to_history(table_name, options) + seq = on_history_schema { pk_and_sequence_for(table_name).last.to_s } + from = options[:validity] || '0001-01-01 00:00:00' - execute %[ + execute %[ INSERT INTO #{HISTORY_SCHEMA}.#{table_name} SELECT *, nextval('#{seq}') AS hid, @@ -216,36 +216,36 @@ def chrono_copy_temporal_to_history(table_name, options) timezone('UTC', now()) AS recorded_at FROM #{TEMPORAL_SCHEMA}.#{table_name} ] - end + end - # Removes temporal features from this table - # - def chrono_undo_temporal_table(table_name) - execute "DROP VIEW #{table_name}" + # Removes temporal features from this table + # + def chrono_undo_temporal_table(table_name) + execute "DROP VIEW #{table_name}" - chrono_drop_trigger_functions_for(table_name) + chrono_drop_trigger_functions_for(table_name) - on_history_schema { execute "DROP TABLE #{table_name}" } + on_history_schema { execute "DROP TABLE #{table_name}" } - default_schema = select_value 'SELECT current_schema()' - on_temporal_schema do - if primary_key(table_name) == '__chrono_id' - execute "ALTER TABLE #{table_name} DROP __chrono_id" - end - - execute "ALTER TABLE #{table_name} SET SCHEMA #{default_schema}" + default_schema = select_value 'SELECT current_schema()' + on_temporal_schema do + if primary_key(table_name) == '__chrono_id' + execute "ALTER TABLE #{table_name} DROP __chrono_id" end + + execute "ALTER TABLE #{table_name} SET SCHEMA #{default_schema}" end + end - # Renames a table and its primary key sequence name - # - def rename_table_and_pk(name, new_name) - seq = pk_and_sequence_for(name).last.to_s - new_seq = seq.sub(name.to_s, new_name.to_s).split('.').last + # Renames a table and its primary key sequence name + # + def rename_table_and_pk(name, new_name) + seq = pk_and_sequence_for(name).last.to_s + new_seq = seq.sub(name.to_s, new_name.to_s).split('.').last - execute "ALTER SEQUENCE #{seq} RENAME TO #{new_seq}" - execute "ALTER TABLE #{name} RENAME TO #{new_name}" - end + execute "ALTER SEQUENCE #{seq} RENAME TO #{new_seq}" + execute "ALTER TABLE #{name} RENAME TO #{new_name}" + end # private end diff --git a/lib/chrono_model/adapter/upgrade.rb b/lib/chrono_model/adapter/upgrade.rb index df488fb2..21139759 100644 --- a/lib/chrono_model/adapter/upgrade.rb +++ b/lib/chrono_model/adapter/upgrade.rb @@ -9,77 +9,77 @@ def chrono_upgrade! private - # Locate tables needing a structure upgrade - # - def chrono_tables_needing_upgrade - tables = {} + # Locate tables needing a structure upgrade + # + def chrono_tables_needing_upgrade + tables = {} - on_temporal_schema { self.tables }.each do |table_name| - next unless is_chrono?(table_name) + on_temporal_schema { self.tables }.each do |table_name| + next unless is_chrono?(table_name) - metadata = chrono_metadata_for(table_name) - version = metadata['chronomodel'] + metadata = chrono_metadata_for(table_name) + version = metadata['chronomodel'] - if version.blank? - tables[table_name] = { version: nil, priority: 'CRITICAL' } - elsif version != VERSION - tables[table_name] = { version: version, priority: 'LOW' } - end + if version.blank? + tables[table_name] = { version: nil, priority: 'CRITICAL' } + elsif version != VERSION + tables[table_name] = { version: version, priority: 'LOW' } end - - return tables end - # Emit a warning about tables needing an upgrade - # - def chrono_upgrade_warning - upgrade = chrono_tables_needing_upgrade.map do |table, desc| - "#{table} - priority: #{desc[:priority]}" - end.join('; ') - - return if upgrade.empty? - - logger.warn "ChronoModel: There are tables needing a structure upgrade, and ChronoModel structures need to be recreated." - logger.warn "ChronoModel: Please run ChronoModel.upgrade! to attempt the upgrade. If you have dependant database objects" - logger.warn "ChronoModel: the upgrade will fail and you have to drop the dependent objects, run .upgrade! and create them" - logger.warn "ChronoModel: again. Sorry. Some features or the whole library may not work correctly until upgrade is complete." - logger.warn "ChronoModel: Tables pending upgrade: #{upgrade}" - end + return tables + end - # Upgrades existing structure for each table, if required. - # - def chrono_upgrade_structure! - transaction do - chrono_tables_needing_upgrade.each do |table_name, desc| - if desc[:version].blank? - logger.info "ChronoModel: Upgrading legacy PG 9.0 table #{table_name} to #{VERSION}" - chrono_upgrade_from_postgres_9_0(table_name) - logger.info "ChronoModel: legacy #{table_name} upgrade complete" - else - logger.info "ChronoModel: upgrading #{table_name} from #{desc[:version]} to #{VERSION}" - chrono_public_view_ddl(table_name) - logger.info "ChronoModel: #{table_name} upgrade complete" - end + # Emit a warning about tables needing an upgrade + # + def chrono_upgrade_warning + upgrade = chrono_tables_needing_upgrade.map do |table, desc| + "#{table} - priority: #{desc[:priority]}" + end.join('; ') + + return if upgrade.empty? + + logger.warn "ChronoModel: There are tables needing a structure upgrade, and ChronoModel structures need to be recreated." + logger.warn "ChronoModel: Please run ChronoModel.upgrade! to attempt the upgrade. If you have dependant database objects" + logger.warn "ChronoModel: the upgrade will fail and you have to drop the dependent objects, run .upgrade! and create them" + logger.warn "ChronoModel: again. Sorry. Some features or the whole library may not work correctly until upgrade is complete." + logger.warn "ChronoModel: Tables pending upgrade: #{upgrade}" + end + + # Upgrades existing structure for each table, if required. + # + def chrono_upgrade_structure! + transaction do + chrono_tables_needing_upgrade.each do |table_name, desc| + if desc[:version].blank? + logger.info "ChronoModel: Upgrading legacy PG 9.0 table #{table_name} to #{VERSION}" + chrono_upgrade_from_postgres_9_0(table_name) + logger.info "ChronoModel: legacy #{table_name} upgrade complete" + else + logger.info "ChronoModel: upgrading #{table_name} from #{desc[:version]} to #{VERSION}" + chrono_public_view_ddl(table_name) + logger.info "ChronoModel: #{table_name} upgrade complete" end end - rescue => e - message = "ChronoModel structure upgrade failed: #{e.message}. Please drop dependent objects first and then run ChronoModel.upgrade! again." - - # Quite important, output it also to stderr. - # - logger.error message - $stderr.puts message end + rescue => e + message = "ChronoModel structure upgrade failed: #{e.message}. Please drop dependent objects first and then run ChronoModel.upgrade! again." + + # Quite important, output it also to stderr. + # + logger.error message + $stderr.puts message + end - def chrono_upgrade_from_postgres_9_0(table_name) - # roses are red - # violets are blue - # and this is the most boring piece of code ever - history_table = "#{HISTORY_SCHEMA}.#{table_name}" - p_pkey = primary_key(table_name) + def chrono_upgrade_from_postgres_9_0(table_name) + # roses are red + # violets are blue + # and this is the most boring piece of code ever + history_table = "#{HISTORY_SCHEMA}.#{table_name}" + p_pkey = primary_key(table_name) - execute "ALTER TABLE #{history_table} ADD COLUMN validity tsrange;" - execute """ + execute "ALTER TABLE #{history_table} ADD COLUMN validity tsrange;" + execute """ UPDATE #{history_table} SET validity = tsrange(valid_from, CASE WHEN extract(year from valid_to) = 9999 THEN NULL ELSE valid_to @@ -87,29 +87,29 @@ def chrono_upgrade_from_postgres_9_0(table_name) ); """ - execute "DROP INDEX #{history_table}_temporal_on_valid_from;" - execute "DROP INDEX #{history_table}_temporal_on_valid_from_and_valid_to;" - execute "DROP INDEX #{history_table}_temporal_on_valid_to;" - execute "DROP INDEX #{history_table}_inherit_pkey" - execute "DROP INDEX #{history_table}_recorded_at" - execute "DROP INDEX #{history_table}_instance_history" - execute "ALTER TABLE #{history_table} DROP CONSTRAINT #{table_name}_valid_from_before_valid_to;" - execute "ALTER TABLE #{history_table} DROP CONSTRAINT #{table_name}_timeline_consistency;" - execute "DROP RULE #{table_name}_upd_first ON #{table_name};" - execute "DROP RULE #{table_name}_upd_next ON #{table_name};" - execute "DROP RULE #{table_name}_del ON #{table_name};" - execute "DROP RULE #{table_name}_ins ON #{table_name};" - execute "DROP TRIGGER history_ins ON #{TEMPORAL_SCHEMA}.#{table_name};" - execute "DROP FUNCTION #{TEMPORAL_SCHEMA}.#{table_name}_ins();" - execute "ALTER TABLE #{history_table} DROP COLUMN valid_from;" - execute "ALTER TABLE #{history_table} DROP COLUMN valid_to;" - - execute "CREATE EXTENSION IF NOT EXISTS btree_gist;" - - chrono_public_view_ddl(table_name) - on_history_schema { add_history_validity_constraint(table_name, p_pkey) } - on_history_schema { chrono_create_history_indexes_for(table_name, p_pkey) } - end + execute "DROP INDEX #{history_table}_temporal_on_valid_from;" + execute "DROP INDEX #{history_table}_temporal_on_valid_from_and_valid_to;" + execute "DROP INDEX #{history_table}_temporal_on_valid_to;" + execute "DROP INDEX #{history_table}_inherit_pkey" + execute "DROP INDEX #{history_table}_recorded_at" + execute "DROP INDEX #{history_table}_instance_history" + execute "ALTER TABLE #{history_table} DROP CONSTRAINT #{table_name}_valid_from_before_valid_to;" + execute "ALTER TABLE #{history_table} DROP CONSTRAINT #{table_name}_timeline_consistency;" + execute "DROP RULE #{table_name}_upd_first ON #{table_name};" + execute "DROP RULE #{table_name}_upd_next ON #{table_name};" + execute "DROP RULE #{table_name}_del ON #{table_name};" + execute "DROP RULE #{table_name}_ins ON #{table_name};" + execute "DROP TRIGGER history_ins ON #{TEMPORAL_SCHEMA}.#{table_name};" + execute "DROP FUNCTION #{TEMPORAL_SCHEMA}.#{table_name}_ins();" + execute "ALTER TABLE #{history_table} DROP COLUMN valid_from;" + execute "ALTER TABLE #{history_table} DROP COLUMN valid_to;" + + execute "CREATE EXTENSION IF NOT EXISTS btree_gist;" + + chrono_public_view_ddl(table_name) + on_history_schema { add_history_validity_constraint(table_name, p_pkey) } + on_history_schema { chrono_create_history_indexes_for(table_name, p_pkey) } + end # private end end diff --git a/lib/chrono_model/patches/association.rb b/lib/chrono_model/patches/association.rb index 806ac93d..1df67a55 100644 --- a/lib/chrono_model/patches/association.rb +++ b/lib/chrono_model/patches/association.rb @@ -34,17 +34,17 @@ def scope private - def _chrono_record? - owner.class.include?(ChronoModel::Patches::AsOfTimeHolder) && owner.as_of_time.present? - end + def _chrono_record? + owner.class.include?(ChronoModel::Patches::AsOfTimeHolder) && owner.as_of_time.present? + end - def _chrono_target? - @_target_klass ||= reflection.options[:polymorphic] ? - owner.public_send(reflection.foreign_type).constantize : - reflection.klass + def _chrono_target? + @_target_klass ||= reflection.options[:polymorphic] ? + owner.public_send(reflection.foreign_type).constantize : + reflection.klass - @_target_klass.chrono? - end + @_target_klass.chrono? + end end end end diff --git a/lib/chrono_model/patches/relation.rb b/lib/chrono_model/patches/relation.rb index 49486dea..20c23dc5 100644 --- a/lib/chrono_model/patches/relation.rb +++ b/lib/chrono_model/patches/relation.rb @@ -89,11 +89,11 @@ def last(*) private - def ordered_relation - return super unless try(:history?) + def ordered_relation + return super unless try(:history?) - with_hid_pkey { super } - end + with_hid_pkey { super } + end end end end diff --git a/lib/chrono_model/time_machine/history_model.rb b/lib/chrono_model/time_machine/history_model.rb index 7416e800..e671fe84 100644 --- a/lib/chrono_model/time_machine/history_model.rb +++ b/lib/chrono_model/time_machine/history_model.rb @@ -121,13 +121,13 @@ def descends_from_active_record? private - # STI fails when a Foo::History record has Foo as type in the - # inheritance column; AR expects the type to be an instance of the - # current class or a descendant (or self). - # - def find_sti_class(type_name) - super(type_name + "::History") - end + # STI fails when a Foo::History record has Foo as type in the + # inheritance column; AR expects the type to be an instance of the + # current class or a descendant (or self). + # + def find_sti_class(type_name) + super(type_name + "::History") + end end # The history id is `hid`, but this cannot set as primary key diff --git a/lib/chrono_model/time_machine/time_query.rb b/lib/chrono_model/time_machine/time_query.rb index 54e2032f..470b9695 100644 --- a/lib/chrono_model/time_machine/time_query.rb +++ b/lib/chrono_model/time_machine/time_query.rb @@ -12,74 +12,74 @@ def time_query(match, time, options) private - def time_query_sql(match, time, range, options) - case match - when :at - build_time_query_at(time, range) + def time_query_sql(match, time, range, options) + case match + when :at + build_time_query_at(time, range) - when :not - "NOT (#{build_time_query_at(time, range)})" + when :not + "NOT (#{build_time_query_at(time, range)})" - when :before - op = options.fetch(:inclusive, true) ? '&&' : '@>' - build_time_query(['NULL', time_for_time_query(time, range)], range, op) + when :before + op = options.fetch(:inclusive, true) ? '&&' : '@>' + build_time_query(['NULL', time_for_time_query(time, range)], range, op) - when :after - op = options.fetch(:inclusive, true) ? '&&' : '@>' - build_time_query([time_for_time_query(time, range), 'NULL'], range, op) + when :after + op = options.fetch(:inclusive, true) ? '&&' : '@>' + build_time_query([time_for_time_query(time, range), 'NULL'], range, op) - else - raise ChronoModel::Error, "Invalid time_query: #{match}" - end + else + raise ChronoModel::Error, "Invalid time_query: #{match}" end + end - def time_for_time_query(t, column) - if t == :now || t == :today - now_for_column(column) - else - quoted_t = connection.quote(connection.quoted_date(t)) - [quoted_t, primitive_type_for_column(column)].join('::') - end + def time_for_time_query(t, column) + if t == :now || t == :today + now_for_column(column) + else + quoted_t = connection.quote(connection.quoted_date(t)) + [quoted_t, primitive_type_for_column(column)].join('::') end + end - def now_for_column(column) - case column.type - when :tsrange, :tstzrange then "timezone('UTC', current_timestamp)" - when :daterange then "current_date" - else raise "Cannot generate 'now()' for #{column.type} column #{column.name}" - end + def now_for_column(column) + case column.type + when :tsrange, :tstzrange then "timezone('UTC', current_timestamp)" + when :daterange then "current_date" + else raise "Cannot generate 'now()' for #{column.type} column #{column.name}" end + end - def primitive_type_for_column(column) - case column.type - when :tsrange then :timestamp - when :tstzrange then :timestamptz - when :daterange then :date - else raise "Don't know how to map #{column.type} column #{column.name} to a primitive type" - end + def primitive_type_for_column(column) + case column.type + when :tsrange then :timestamp + when :tstzrange then :timestamptz + when :daterange then :date + else raise "Don't know how to map #{column.type} column #{column.name} to a primitive type" end + end - def build_time_query_at(time, range) - time = if time.kind_of?(Array) - time.map! { |t| time_for_time_query(t, range) } - - # If both edges of the range are the same the query fails using the '&&' operator. - # The correct solution is to use the <@ operator. - time.first == time.last ? time.first : time - else - time_for_time_query(time, range) - end + def build_time_query_at(time, range) + time = if time.kind_of?(Array) + time.map! { |t| time_for_time_query(t, range) } - build_time_query(time, range) + # If both edges of the range are the same the query fails using the '&&' operator. + # The correct solution is to use the <@ operator. + time.first == time.last ? time.first : time + else + time_for_time_query(time, range) end - def build_time_query(time, range, op = '&&') - if time.kind_of?(Array) - Arel.sql %[ #{range.type}(#{time.first}, #{time.last}) #{op} #{table_name}.#{range.name} ] - else - Arel.sql %[ #{time} <@ #{table_name}.#{range.name} ] - end + build_time_query(time, range) + end + + def build_time_query(time, range, op = '&&') + if time.kind_of?(Array) + Arel.sql %[ #{range.type}(#{time.first}, #{time.last}) #{op} #{table_name}.#{range.name} ] + else + Arel.sql %[ #{time} <@ #{table_name}.#{range.name} ] end + end end end end From 4569cb2ef18432cf38b5cbe1ef68181200d9f61e Mon Sep 17 00:00:00 2001 From: Geremia Taglialatela Date: Sat, 9 Sep 2023 17:53:55 +0200 Subject: [PATCH 5/6] Fix else/end alignment --- .rubocop_todo.yml | 14 -------------- lib/chrono_model/adapter/ddl.rb | 20 ++++++++++---------- lib/chrono_model/time_machine/time_query.rb | 6 +++--- 3 files changed, 13 insertions(+), 27 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 456ad9fc..75cb7d01 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -14,20 +14,6 @@ Layout/DotPosition: - 'lib/chrono_model/patches/join_node.rb' - 'lib/chrono_model/time_machine/timeline.rb' -# This cop supports safe autocorrection (--autocorrect). -Layout/ElseAlignment: - Exclude: - - 'lib/chrono_model/adapter/ddl.rb' - - 'lib/chrono_model/time_machine/time_query.rb' - -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyleAlignWith, Severity. -# SupportedStylesAlignWith: keyword, variable, start_of_line -Layout/EndAlignment: - Exclude: - - 'lib/chrono_model/adapter/ddl.rb' - - 'lib/chrono_model/time_machine/time_query.rb' - # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: symmetrical, new_line, same_line diff --git a/lib/chrono_model/adapter/ddl.rb b/lib/chrono_model/adapter/ddl.rb index 0d435b68..b53810d8 100644 --- a/lib/chrono_model/adapter/ddl.rb +++ b/lib/chrono_model/adapter/ddl.rb @@ -27,9 +27,9 @@ def chrono_public_view_ddl(table, options = nil) columns(table).each do |column| default = if column.default.nil? column.default_function - else - quote(column.default) - end + else + quote(column.default) + end next if column.name == pk || default.nil? @@ -118,15 +118,15 @@ def chrono_create_UPDATE_trigger(table, pk, current, history, fields, values, op journal = if options[:journal] options[:journal].map { |col| quote_column_name(col) } - elsif options[:no_journal] - columns - options[:no_journal].map { |col| quote_column_name(col) } + elsif options[:no_journal] + columns - options[:no_journal].map { |col| quote_column_name(col) } - elsif options[:full_journal] - columns + elsif options[:full_journal] + columns - else - columns - [quote_column_name('updated_at')] - end + else + columns - [quote_column_name('updated_at')] + end journal &= columns diff --git a/lib/chrono_model/time_machine/time_query.rb b/lib/chrono_model/time_machine/time_query.rb index 470b9695..970acd3c 100644 --- a/lib/chrono_model/time_machine/time_query.rb +++ b/lib/chrono_model/time_machine/time_query.rb @@ -66,9 +66,9 @@ def build_time_query_at(time, range) # If both edges of the range are the same the query fails using the '&&' operator. # The correct solution is to use the <@ operator. time.first == time.last ? time.first : time - else - time_for_time_query(time, range) - end + else + time_for_time_query(time, range) + end build_time_query(time, range) end From 910eae8a8a5ff2768ce78cd98b6876ca024e71c9 Mon Sep 17 00:00:00 2001 From: Geremia Taglialatela Date: Sat, 9 Sep 2023 17:57:22 +0200 Subject: [PATCH 6/6] Fix multiline indentation offenses --- .rubocop_todo.yml | 16 ---------------- lib/chrono_model/adapter/indexes.rb | 4 ++-- lib/chrono_model/patches/join_node.rb | 2 +- lib/chrono_model/time_machine.rb | 2 +- lib/chrono_model/time_machine/timeline.rb | 4 ++-- 5 files changed, 6 insertions(+), 22 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 75cb7d01..fbb0611f 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -30,22 +30,6 @@ Layout/MultilineMethodCallBraceLayout: - 'lib/chrono_model/adapter.rb' - 'lib/chrono_model/patches/relation.rb' -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, IndentationWidth. -# SupportedStyles: aligned, indented, indented_relative_to_receiver -Layout/MultilineMethodCallIndentation: - Exclude: - - 'lib/chrono_model/patches/join_node.rb' - - 'lib/chrono_model/time_machine/timeline.rb' - -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, IndentationWidth. -# SupportedStyles: aligned, indented -Layout/MultilineOperationIndentation: - Exclude: - - 'lib/chrono_model/adapter/indexes.rb' - - 'lib/chrono_model/time_machine.rb' - # This cop supports safe autocorrection (--autocorrect). Lint/AmbiguousOperator: Exclude: diff --git a/lib/chrono_model/adapter/indexes.rb b/lib/chrono_model/adapter/indexes.rb index 63c9c854..6972938e 100644 --- a/lib/chrono_model/adapter/indexes.rb +++ b/lib/chrono_model/adapter/indexes.rb @@ -93,10 +93,10 @@ def chrono_rename_history_indexes(name, new_name) recorded_at timeline_consistency ) old_names = temporal_index_names(name, :validity) + - standard_index_names.map { |i| [name, i].join('_') } + standard_index_names.map { |i| [name, i].join('_') } new_names = temporal_index_names(new_name, :validity) + - standard_index_names.map { |i| [new_name, i].join('_') } + standard_index_names.map { |i| [new_name, i].join('_') } old_names.zip(new_names).each do |old, new| execute "ALTER INDEX #{old} RENAME TO #{new}" diff --git a/lib/chrono_model/patches/join_node.rb b/lib/chrono_model/patches/join_node.rb index c6773ef6..7a2430e1 100644 --- a/lib/chrono_model/patches/join_node.rb +++ b/lib/chrono_model/patches/join_node.rb @@ -21,7 +21,7 @@ def initialize(join_node, history_model, as_of_time) @as_of_time = as_of_time virtual_table = history_model. - virtual_table_at(@as_of_time, table_name: @table_alias || @table_name) + virtual_table_at(@as_of_time, table_name: @table_alias || @table_name) super(virtual_table) end diff --git a/lib/chrono_model/time_machine.rb b/lib/chrono_model/time_machine.rb index 685e972c..bbed57e6 100644 --- a/lib/chrono_model/time_machine.rb +++ b/lib/chrono_model/time_machine.rb @@ -106,7 +106,7 @@ def as_of(time) def attribute_names_for_history_changes @attribute_names_for_history_changes ||= attribute_names - - %w(id hid validity recorded_at) + %w(id hid validity recorded_at) end def has_timeline(options) diff --git a/lib/chrono_model/time_machine/timeline.rb b/lib/chrono_model/time_machine/timeline.rb index 02678f6e..681a297b 100644 --- a/lib/chrono_model/time_machine/timeline.rb +++ b/lib/chrono_model/time_machine/timeline.rb @@ -19,7 +19,7 @@ def timeline(record = nil, options = {}) fields = models.inject([]) { |a, m| a.concat m.quoted_history_fields } relation = self.except(:order). - select("DISTINCT UNNEST(ARRAY[#{fields.join(',')}]) AS ts") + select("DISTINCT UNNEST(ARRAY[#{fields.join(',')}]) AS ts") if assocs.present? assocs.each do |ass| @@ -35,7 +35,7 @@ def timeline(record = nil, options = {}) end relation = relation. - order('ts ' << (options[:reverse] ? 'DESC' : 'ASC')) + order('ts ' << (options[:reverse] ? 'DESC' : 'ASC')) relation = relation.from(%["public".#{quoted_table_name}]) unless self.chrono? relation = relation.where(id: rid) if rid