Configure Mongoid relation to return objects sorted - ruby

I have two classes with a 1-n relationship. Like so:
class Band
include Mongoid::Document
has_many :members
end
class Member
include Mongoid::Document
field :name, type: String
field :joined, type: Date
belongs_to :band
end
Now when I call band.members I get the member objects. What I want is that if I call band.members.last to get the member who joined the last. I achieve this by defining the <=> method for Member and sort based on joined:
band.members.sort.last
How can I make this behavior default? I don't want to avoid the extra call to sort. Is this possible and if yes, how?

class Band
include Mongoid::Document
has_many :members, :order => :joined.asc
end

Related

Issues with Polymorphic/STI in Ruby

We're having a problem with polymorphism & STI in Ruby
Our database has two tables: 'account' and 'list'. 'list' has columns 'account_id', 'type', 'description'.
Our classes look like so:
class Account < ActiveRecord::Base
has_many :lists
has_many :subscription_lists
has_many :email_lists
end
class List < ActiveRecord::Base
belongs_to :account
end
class SubscriptionList < List
end
class EmailList < List
end
Inside Account, methods email_lists and subscription_lists work exactly as expected. Our goal is we want to be able to call lists which will return an array of all lists. Currently, that doesn't work, nor does self.lists
Oddly, Account.find(self.id).lists DOES give us an array of all the lists associated.
What gives? How do we fix this?
You can use List.all which will return an ActiveRecord::Relation of all List objects, regardless of type.
Additionally, you can use #instance_variable.lists on any instance variable of Account
What's more, you could use a query on a class method to accomplish the job, like so, which will also return an ActiveRecord::Relation:
List.where('account_id = ?', id)
Lastly, your Account association with List should not include the children of List:
class Account < ActiveRecord::Base
has_many :lists, inverse_of: :account, dependent: :destroy
end

How to query unique documents for a given field where there is a referenced 1-N relationship in Mongoid?

class User
include Mongoid::Document
has_many :foos
end
class Foo
include Mongoid::Document
include Mongoid::Timestamps
field :group_id, type:String
belongs_to :user
end
Each Foo belongs to a group with a group_id. However, there is no Group model.
What is an efficient way to get the single latest (highest created_at) Foo for each group_id?

Activerecord checking if association exist

I have two ActiveRecord models:
class Class < ActiveRecord::Base
(...)
has_many :class_to_teacher, dependent: :destroy
end
class Teacher < ActiveRecord::Base
has_many :classes,
through: :class_to_teacher
end
class ClassToTeacher < ActiveRecord::Base
belongs_to :klass
belongs_to :teacher
end
When I remove Class I don't remove it completly only I remove record from ClassToTeacher record. I need to keep this data:
def leave(class, teacher)
teacher.klasses.delete(class)
end
Now I have to get all associated classes (classes which contains record in ClassToTeacher). How to do this the best? Thanks for all answers.
You should try something like that:
Class.includes(:class_to_teacher).where('class_to_teacher.id is not null').references(:class_to_teacher).all
Assuming that you have an 'id' field in your database for the ClassToTeacher
I guess there's a lot of ways to get there but the simplest one is probably this:
Klass.where(id: KlassToTeacher.select(:klass_id))
This will result in a single query with a sub-query. Note that I changed the names of the models because Class is already defined in Ruby and you're just asking for trouble.

Mongoid: Retrieves all embedded documents

Suppose we have these models:
class Person
include Mongoid::Document
embeds_many :albums
end
class Album
include Mongoid::Document
embeds_many :photos
end
class Photo
include Mongoid::Document
end
What I want is to retrieves all Photo of a particular Person. Is there a mongoid/mongodb shortcuts or the only way is to iterate over person.albums and store all album.photos in a new array?
Thanks.
You have 2 ways to do this, one is through Mongoid, which, AFAIK, will inflate all objects.
Something like:
Person.only("albums.photos").where(id: '1').albums.map(&:photos).flatten
Or you can do it in Moped(driver) which will return only an array of photos.
Person.collection.find(id: "1").select("albums.photos" => 1).
first["albums"].map { |a| a["photos"] }.flatten
On the DB load, both dont make any difference, as they will yield the same query, only difference is that the first one will create way more objects than the second one.

Mongoid Relations 1..*

Consider the following:
class Picture
include Mongoid::Document
field :data, :type => String
end
class Cat
include Mongoid::Document
has_one :picture, :autosave => true
field :name, :type => String
end
class Dog
include Mongoid::Document
has_one :picture, :autosave => true
field :name, :type => String
end
Now, is it possible to do the following:
dog = Dog.new
dog.picture = Picture.new
dog.save!
Without having to edit the Picture class to the following:
class Picture
include Mongoid::Document
belongs_to :cat
belongs_to :dog
field :data, :type => String
end
I don't need pictures to know about it's Dog or Cat. Is this possible?
I believe you could do this if you put the belongs_to :picture in your dog and cat classes. The side of the relation that has belongs_to is the side that will store the foreign key. That would put a picture_id field in each of Dog and Cat, instead of having to store a whatever_id for each type of think you want to link on your Picture class.
No it is not. You need to have cat_id or dog_id or some polymorphic obj_id for all of them to store information about belonging of this picture.
Or how do you know wich Picture belongs to current Dog or Cat?

Resources