You can use Enumerable#sort_by using an array to keep the groups you want and sorting by name without lose those groups.
For example:
[[0,0,1], [1,1,1], [0,1,0], [1,0,0], [0,1,1]].sort_by &:itself
# => [[0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 1, 1]]
Using this, you can set an array with length 2. Using index 0 to "group" by the elements you want and index 1 to sort by name.
OR = "OR"
AND = "AND"
_NOT_PRESENT = "_NOT_PRESENT"
array_group = [
{ operator: OR, name: "z string", status: false },
{ operator: AND, name: "a string", status: false },
{ operator: AND, name: "z string", status: true },
{ operator: OR, name: "a string", status: true },
{ operator: _NOT_PRESENT, name: "d string", status: true },
{ operator: _NOT_PRESENT, name: "b string", status: true },
{ operator: _NOT_PRESENT, name: "c string", status: false },
{ operator: _NOT_PRESENT, name: "a string", status: false }
]
# Types of "groups" you want to keep. Greater values will be at the end
BY_NOT_PRESENT = 2
BY_STATUS_FALSE = 1
BY_STATUS_TRUE = 0
array_group.sort_by do |a|
group = if a[:operator] == _NOT_PRESENT
BY_NOT_PRESENT
else
a[:status] ? BY_STATUS_TRUE : BY_STATUS_FALSE
end
[group, a[:name]]
end
#=> [{:operator=>"OR", :name=>"a string", :status=>true},
# {:operator=>"AND", :name=>"z string", :status=>true},
# {:operator=>"AND", :name=>"a string", :status=>false},
# {:operator=>"OR", :name=>"z string", :status=>false},
# {:operator=>"_NOT_PRESENT", :name=>"a string", :status=>false},
# {:operator=>"_NOT_PRESENT", :name=>"b string", :status=>true},
# {:operator=>"_NOT_PRESENT", :name=>"c string", :status=>false},
# {:operator=>"_NOT_PRESENT", :name=>"d string", :status=>true}]
I am doing this way, because if just sort_by an array like [status, not_present, name] then status will have precedence on sort, overriding the name sort, resulting this:
#=> [{:operator=>"OR", :name=>"a string", :status=>true},
# {:operator=>"AND", :name=>"z string", :status=>true},
# {:operator=>"AND", :name=>"a string", :status=>false},
# {:operator=>"OR", :name=>"z string", :status=>false},
# {:operator=>"_NOT_PRESENT", :name=>"b string", :status=>true},
# {:operator=>"_NOT_PRESENT", :name=>"d string", :status=>true},
# {:operator=>"_NOT_PRESENT", :name=>"a string", :status=>false},
# {:operator=>"_NOT_PRESENT", :name=>"c string", :status=>false}]
statuscan have a value other thanTrueorFalse. Is that correct?"other string"'sstatusswitch fromtruetofalse? Why is"another string"not first in the sorted array, consider that it ties with"other string"on the value of:statusand is the only one of the two to have_NOT_PRESENTas the value of:operator?