@@ -416,6 +416,8 @@ def inherited(subclass)
416416
417417 subclass . _allowed_filters = ( _allowed_filters || Set . new ) . dup
418418
419+ subclass . _allowed_sort = _allowed_sort . dup
420+
419421 type = subclass . name . demodulize . sub ( /Resource$/ , '' ) . underscore
420422 subclass . _type = type . pluralize . to_sym
421423
@@ -537,7 +539,7 @@ def model_name_for_type(key_type)
537539 end
538540
539541 attr_accessor :_attributes , :_relationships , :_type , :_model_hints
540- attr_writer :_allowed_filters , :_paginator
542+ attr_writer :_allowed_filters , :_paginator , :_allowed_sort
541543
542544 def create ( context )
543545 new ( create_model , context )
@@ -583,6 +585,10 @@ def attribute(attribute_name, options = {})
583585 define_method "#{ attr } =" do |value |
584586 @model . public_send ( "#{ options [ :delegate ] ? options [ :delegate ] . to_sym : attr } =" , value )
585587 end unless method_defined? ( "#{ attr } =" )
588+
589+ if options . fetch ( :sortable , true ) && !_has_sort? ( attr )
590+ sort attr
591+ end
586592 end
587593
588594 def attribute_to_model_field ( attribute )
@@ -669,6 +675,15 @@ def filter(attr, *args)
669675 @_allowed_filters [ attr . to_sym ] = args . extract_options!
670676 end
671677
678+ def sort ( sorting , options = { } )
679+ self . _allowed_sort [ sorting . to_sym ] = options
680+ end
681+
682+ def sorts ( *args )
683+ options = args . extract_options!
684+ _allowed_sort . merge! ( args . inject ( { } ) { |h , sorting | h [ sorting . to_sym ] = options . dup ; h } )
685+ end
686+
672687 def primary_key ( key )
673688 @_primary_key = key . to_sym
674689 end
@@ -689,7 +704,7 @@ def creatable_fields(_context = nil)
689704
690705 # Override in your resource to filter the sortable keys
691706 def sortable_fields ( _context = nil )
692- _attributes . keys
707+ _allowed_sort . keys
693708 end
694709
695710 def sortable_field? ( key , context = nil )
@@ -759,11 +774,7 @@ def verify_filter(filter, raw, context = nil)
759774 strategy = _allowed_filters . fetch ( filter , Hash . new ) [ :verify ]
760775
761776 if strategy
762- if strategy . is_a? ( Symbol ) || strategy . is_a? ( String )
763- values = send ( strategy , filter_values , context )
764- else
765- values = strategy . call ( filter_values , context )
766- end
777+ values = call_method_or_proc ( strategy , filter_values , context )
767778 [ filter , values ]
768779 else
769780 if is_filter_relationship? ( filter )
@@ -774,6 +785,14 @@ def verify_filter(filter, raw, context = nil)
774785 end
775786 end
776787
788+ def call_method_or_proc ( strategy , *args )
789+ if strategy . is_a? ( Symbol ) || strategy . is_a? ( String )
790+ send ( strategy , *args )
791+ else
792+ strategy . call ( *args )
793+ end
794+ end
795+
777796 def key_type ( key_type )
778797 @_resource_key_type = key_type
779798 end
@@ -890,6 +909,10 @@ def _allowed_filters
890909 defined? ( @_allowed_filters ) ? @_allowed_filters : { id : { } }
891910 end
892911
912+ def _allowed_sort
913+ @_allowed_sort ||= { }
914+ end
915+
893916 def _paginator
894917 @_paginator ||= JSONAPI . configuration . default_paginator
895918 end
@@ -963,6 +986,10 @@ def _allowed_filter?(filter)
963986 !_allowed_filters [ filter ] . nil?
964987 end
965988
989+ def _has_sort? ( sorting )
990+ !_allowed_sort [ sorting . to_sym ] . nil?
991+ end
992+
966993 def module_path
967994 if name == 'JSONAPI::Resource'
968995 ''
0 commit comments