Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
<strong>Q&A by the community, for the community</strong>
</div>
<br>
<p align="center">
<a href="https://github.com/codidact/qpixel/actions/workflows/ci-cd.yml"><img src="https://github.com/codidact/qpixel/actions/workflows/ci-cd.yml/badge.svg" alt="Pipeline status" /></a>
<a href="https://codecov.io/gh/codidact/qpixel"><img src="https://codecov.io/gh/codidact/qpixel/graph/badge.svg?token=RM60WJLP1V" alt="Coverage Status"/></a>
<a href="https://zenodo.org/badge/latestdoi/237078806"><img src="https://zenodo.org/badge/237078806.svg" alt="DOI"></a>
</p>
<div align="center">

[![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)
</div>

Rails-based version of our core software, powering [codidact.com](https://codidact.com). Currently under active development towards MVP.

Expand Down
2 changes: 1 addition & 1 deletion app/helpers/abilities_helper.rb
Original file line number Diff line number Diff line change
@@ -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
Expand Down
36 changes: 0 additions & 36 deletions app/models/application_record.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# rubocop:disable Style/OneClassPerFile
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true

Expand Down Expand Up @@ -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
1 change: 1 addition & 0 deletions app/models/audit_log.rb
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion app/models/comment_thread.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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<CommentThread>]
def self.accessible_to(user, post)
if user&.at_least_moderator? || user&.post_privilege?('flag_curate', post)
Expand Down
27 changes: 27 additions & 0 deletions app/models/concerns/user_sortable.rb
Original file line number Diff line number Diff line change
@@ -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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not super-familiar with how all this is wired together, but should this have turned into doc at https://docs.dev.codidact.org/docs/UserSortable? Or am I looking in the wrong place?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No clue, those are concerns with class_methods instead of included - that's likely a limitation of yardoc. I can take a look just in case, but pretty sure that's not an issue on our side

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, different type of method. I don't think we need to fuss over it; I was just trying to figure out if there was an error in either the content or the build setup that we were tripping over. Not that, so fine with me.

# 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
1 change: 1 addition & 0 deletions app/models/post.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class Post < ApplicationRecord
include PostValidations
include SoftDeletable
include Timestamped
include UserSortable

belongs_to :user, optional: true
belongs_to :post_type
Expand Down
1 change: 0 additions & 1 deletion app/models/subscription.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion lib/namespaced_env_cache.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
4 changes: 2 additions & 2 deletions lib/redis_cache_hash_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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<String>] Keys to retrieve
# @return [Hash] Keys and values from the hash
def hmget(hash_key, *keys)
with_redis do |rd|
Expand All @@ -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<String>] 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|
Expand Down
Loading