Combine two ActiveRecord results and sort by a shared joined table attribute
You can try the following:
(@convos + @group_meetings).sort_by { |item| item.msgs.minimum(:created_at) }
Combine active_record models and sort by shared properties
The issue is that nil
is only comparable with nil
:
nil <=> nil # => 0 # -1, 0, 1 are good
"priority" <=> nil # => nil # `nil` means not comparable
# and you get an error from `sort_by`
Solution is to avoid comparing nil
with anything else or explicitly handle the comparison.
You can use sort
and sort the nil
s yourself:
ary = (Author.all + Photographer.all)
ary.sort do |a, b|
if a.priority && b.priority # priority <=> priority
a.priority <=> b.priority
elsif a.priority # priority <=> nil
-1 # nil is lower
elsif b.priority # nil <=> priority
1 # priority is higher
else # nil <=> nil
a.name <=> b.name # break the tie
end
end
You can split array in two, with priority and without priority, and sort each one. That way priority
is compared to priority
; nil
is compared to nil
, which is 0, and it falls back to comparing name
(like the sort
above, but elsif's never match):
ary.partition(&:priority).flat_map do |part|
part.sort_by { |i| [i.priority, i.name] }
end
Or a dumber way of doing this (it's also faster) is to make nil
be something last:
ary.sort_by { |i| [i.priority||"zzz", i.name] }
Combine two ActiveRecord::Relation objects
If you want to combine using AND
(intersection), use merge
:
first_name_relation.merge(last_name_relation)
If you want to combine using OR
(union), use or
†:
first_name_relation.or(last_name_relation)
† Only in ActiveRecord 5+; for 4.2 install the where-or backport.
Combining two different ActiveRecord collections into one
Well, assuming that the result of querying both Hire
and Deal
models is an array of objects (collection), then you just use +
to concatenate them into a new array and sort items by date
with sort_by
:
combined = ( Hire.all + Deal.all ).sort_by(&:date)
or use concat
to concatenate one collection with another:
combined = Hire.all.concat( Deal.all ).sort_by(&:date)
Combine Two Database Columns to Order Data
For MySQL:
User.order('CONCAT(`first_name`, `last_name`)')
How to merge multiple objects from different models into one object in Rails?
You can create a PORO (plain old ruby object) to represent the combined object so something like:
class Stream
attr_accessor :product, :post, :member, :selection
def initialize(attrs)
assign_attributes(attrs)
end
end
Then just initialize and create as many stream
objects as you need using Stream.new(attrs)
. You can create an array of stream
objects and loop through them to render or show multiple stream
data.
For sorting an array of objects by its attributes you can use
objects.sort_by {|obj| obj.attribute}
Can I merge two Set objects in Ruby?
Why This Question is Useful
While the OP has been criticized for lack of research effort, it should be pointed out that the Ruby documentation for Set#merge is not friendly for new Rubyists. As of Ruby 2.3.0, it says:
Merges the elements of the given enumerable object to the set and returns self.
It offers merge(enum)
as the signature, but no useful examples. If you need to know what classes mix in Enumerable, it can be difficult to grok from just this one piece of documentation what kind of duck-typed ducks can be merged in. For example, set.merge {foo: 'bar'}.to_enum
will raise SyntaxError despite the fact that it is enumerable:
{foo: 'bar'}.to_enum.class
#=> Enumerator
{foo: 'bar'}.to_enum.class.include? Enumerable
#=> true
Merging Sets
If you're thinking of Set#merge as creating a set union, then yes: you can merge sets. Consider the following:
require 'set'
set1 = Set.new [1, 2, 3]
#=> #<Set: {1, 2, 3}>
set2 = Set.new [3, 4, 5]
#=> #<Set: {3, 4, 5}>
set1.merge set2
#=> #<Set: {1, 2, 3, 4, 5}>
Merging Other Enumerable Objects Like Arrays
However, you can also merge other Enumerable objects (like arrays) into a set. For example:
set = Set.new [1, 2, 3]
#=> #<Set: {1, 2, 3}>
set.merge [3, 4, 5]
#=> #<Set: {1, 2, 3, 4, 5}>
Using Array Union Instead
Of course, you may not need sets at all. Compare and contrast Set to array unions (Array#|). If you don't need the actual features of the Set class, you can often do similar things directly with arrays. For example:
([1, 2, 3, 4] | [3, 4, 5, 6]).uniq
#=> [1, 2, 3, 4, 5, 6]
Related Topics
How to Access the Current Node from a Library in a Chef Cookbook
Version Sort (With Alphas, Betas, etc.) in Ruby
Converting a Unique Seed String into a Random, Yet Deterministic, Float Value in Ruby
Sass Variables Not Parsing Correctly - Undefined Variable: "$Ct-White"
Wrapping Text into Lines at Word Boundaries
Keyword Arguments Unpacking (Splat) in Ruby
Encoding::Undefinedconversionerror: "\Xe4" from Ascii-8Bit to Utf-8
How to Set a Variable from a Helper Method for Inclusion in a SASS SCSS Stylesheet
Using Phonegap as a Native Container for a Rails 3 App
Ruby-Rails Serve Ftp File Direct to Client
Ruby 2.7 Says Uri.Escape Is Obsolete, What Replaces It