diff --git a/README.md b/README.md index 774efdd62..583ad0ee6 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,12 @@ Q&A by the community, for the community
-

- Pipeline status - Coverage Status - DOI -

+
+ + [![Pipeline status](https://github.com/codidact/qpixel/actions/workflows/ci-cd.yml/badge.svg)](https://github.com/codidact/qpixel/actions/workflows/ci-cd.yml) + [![Coverage status](https://codecov.io/gh/codidact/qpixel/graph/badge.svg?token=RM60WJLP1V)](https://codecov.io/gh/codidact/qpixel) + [![DOI](https://zenodo.org/badge/237078806.svg)](https://zenodo.org/badge/latestdoi/237078806) +
Rails-based version of our core software, powering [codidact.com](https://codidact.com). Currently under active development towards MVP. diff --git a/app/helpers/abilities_helper.rb b/app/helpers/abilities_helper.rb index cf8bcedb1..30094bc62 100644 --- a/app/helpers/abilities_helper.rb +++ b/app/helpers/abilities_helper.rb @@ -1,6 +1,6 @@ module AbilitiesHelper # Gets a maybe_ability to the specified ability - # @param ability [Ability, String] ability or its internal id to link to + # @param maybe_ability [Ability, String] ability or its internal id to link to # @return [ActiveSupport::SafeBuffer] def ability_link(maybe_ability) ability = maybe_ability.is_a?(String) ? Ability.find_by(internal_id: maybe_ability) : maybe_ability diff --git a/app/models/application_record.rb b/app/models/application_record.rb index fcdb164f3..24d4ef204 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -1,4 +1,3 @@ -# rubocop:disable Style/OneClassPerFile class ApplicationRecord < ActiveRecord::Base self.abstract_class = true @@ -158,38 +157,3 @@ def self.useful_err_msg end # rubocop:enable Metrics/MethodLength end - -module UserSortable - # Sort a collection according to a user selection, by mapping user selectable values to column names. - # SQL injection safe. - # @param term_opts Hash of search term options - # @param field_mappings Hash of user-selectable values to column names: +{ age: :created_at, rep: :threshold }+ - # @option term_opts :term [String] A user-provided search term to apply - usually from +params+, e.g. +params[:sort]+. - # Should be one of the keys in +field_mappings+. - # @option term_opts :default [Symbol] A column name to apply as the default sort ordering. - # @return [ActiveRecord::Relation] A relation of the current type, with the sort ordering applied. - def user_sort(term_opts, **field_mappings) - default = term_opts[:default] || :created_at - requested = term_opts[:term] - direction = term_opts[:direction] || :desc - if requested.nil? || field_mappings.exclude?(requested.to_sym) - $active_search_param = default - default.is_a?(Symbol) ? order(default => direction) : order(default) - else - requested_val = field_mappings[requested.to_sym] - $active_search_param = requested_val - requested_val.is_a?(Symbol) ? order(requested_val => direction) : order(requested_val) - end - end -end - -klasses = [ActiveRecord::Relation] -klasses << if defined? ActiveRecord::Associations::CollectionProxy - ActiveRecord::Associations::CollectionProxy - else - ActiveRecord::Associations::AssociationCollection - end - -ActiveRecord::Base.extend UserSortable -klasses.each { |klass| klass.send(:include, UserSortable) } -# rubocop:enable Style/OneClassPerFile diff --git a/app/models/audit_log.rb b/app/models/audit_log.rb index dfecac249..024d1515f 100644 --- a/app/models/audit_log.rb +++ b/app/models/audit_log.rb @@ -1,6 +1,7 @@ class AuditLog < ApplicationRecord include CommunityRelated include Timestamped + include UserSortable belongs_to :related, polymorphic: true, optional: true belongs_to :user, optional: true diff --git a/app/models/comment_thread.rb b/app/models/comment_thread.rb index 05f81d6ed..7d5b5fcbc 100644 --- a/app/models/comment_thread.rb +++ b/app/models/comment_thread.rb @@ -19,7 +19,7 @@ class CommentThread < ApplicationRecord # Gets threads appropriately scoped for a given user & post # @param user [User, nil] user to check - # @para post [Post] post to check + # @param post [Post] post to check # @return [ActiveRecord::Relation] def self.accessible_to(user, post) if user&.at_least_moderator? || user&.post_privilege?('flag_curate', post) diff --git a/app/models/concerns/user_sortable.rb b/app/models/concerns/user_sortable.rb new file mode 100644 index 000000000..4552963d4 --- /dev/null +++ b/app/models/concerns/user_sortable.rb @@ -0,0 +1,27 @@ +module UserSortable + extend ActiveSupport::Concern + + class_methods do + # Sort a collection according to a user selection, by mapping user selectable values to column names. + # SQL injection safe. + # @param term_opts Hash of search term options + # @param field_mappings Hash of user-selectable values to column names: +{ age: :created_at, rep: :threshold }+ + # @option term_opts :term [String] A user-provided search term - usually from +params+, e.g. +params[:sort]+. + # Should be one of the keys in +field_mappings+. + # @option term_opts :default [Symbol] A column name to apply as the default sort ordering. + # @return [ActiveRecord::Relation] A relation of the current type, with the sort ordering applied. + def user_sort(term_opts, **field_mappings) + default = term_opts[:default] || :created_at + requested = term_opts[:term] + direction = term_opts[:direction] || :desc + if requested.nil? || field_mappings.exclude?(requested.to_sym) + $active_search_param = default + default.is_a?(Symbol) ? order(default => direction) : order(default) + else + requested_val = field_mappings[requested.to_sym] + $active_search_param = requested_val + requested_val.is_a?(Symbol) ? order(requested_val => direction) : order(requested_val) + end + end + end +end diff --git a/app/models/post.rb b/app/models/post.rb index 60a4505d7..2327df5b8 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -4,6 +4,7 @@ class Post < ApplicationRecord include PostValidations include SoftDeletable include Timestamped + include UserSortable belongs_to :user, optional: true belongs_to :post_type diff --git a/app/models/subscription.rb b/app/models/subscription.rb index 2cb0376f9..a3a52e155 100644 --- a/app/models/subscription.rb +++ b/app/models/subscription.rb @@ -48,7 +48,6 @@ def questions end # Is the subscription's type qualified (bound to an entity)? - # @param type [String] type to check # @return [Boolean] check result def qualified? QUALIFIED_TYPES.include?(type) diff --git a/lib/namespaced_env_cache.rb b/lib/namespaced_env_cache.rb index 68473e58f..75fbd1831 100644 --- a/lib/namespaced_env_cache.rb +++ b/lib/namespaced_env_cache.rb @@ -93,7 +93,7 @@ def write_collection(name, value, **opts) # no selects or joins applied. # @param name [String] cache key name # @param opts [Hash] options hash - any unlisted options will be passed to the underlying cache - # @options opts [Boolean] :include_community whether to include the community ID in the cache key + # @option opts [Boolean] :include_community whether to include the community ID in the cache key # @return [ActiveRecord::Relation, nil] def read_collection(name, **opts) namespaced = construct_ns_key(name, include_community: include_community(opts)) diff --git a/lib/redis_cache_hash_methods.rb b/lib/redis_cache_hash_methods.rb index c75ec35a1..8b9bd8716 100644 --- a/lib/redis_cache_hash_methods.rb +++ b/lib/redis_cache_hash_methods.rb @@ -41,7 +41,7 @@ def hget(hash_key, key) ## # Get multiple hash values. # @param hash_key [String] The name of the hash - # @param *keys [String] Keys within the hash to retrieve + # @param keys [Array] Keys to retrieve # @return [Hash] Keys and values from the hash def hmget(hash_key, *keys) with_redis do |rd| @@ -63,7 +63,7 @@ def hgetall(hash_key) ## # Delete a hash value, or the entire hash. # @param hash_key [String] The name of the hash - # @param *keys [String] Keys within the hash to delete. If none are provided, the entire hash is deleted. + # @param keys [Array] Keys to delete. If none are provided, the entire hash is deleted. # @return [Integer] The number of keys that were removed from the hash def hdel(hash_key, *keys) with_redis do |rd|