Querying embedded documents of one given parent document - ruby-on-rails

I have a mongoid model class "Event" embedding many of class "Participant". Participant has a field "email". Now somewhere in the code I get a reference to one specific Event instance named "#event".
How do I now query the participants of ONLY that instance for an participant with email = XYZ?Not all participants in the collection, just the ones of this given instance #event.
Any ideas?
Thx!

This should work
#event.participants.where(email: 'XYZ') # this will help you query what ever you want
#or
#event.participants.find_by_email 'XYZ' #this will get exactly one record

Related

access ActiveRecord Has Many associations

I have a model which has a lot of associations. What I need to do is to check whether one of those associations is not present or all of them are set correctly.
To do so, I created an array which includes all of those needs-to-be-checked fields. And created a loop through each element, but the case is that I can not access has_many related attributes with read_attribute method. It basically returns nil whenever I try to access has many associated fields.
What I am trying to do, I can access all related objects via car.drivers but I can not access the same object with car.read_attribute(:drivers) (because some of them are attributes and some are relations)
I think it's the behavior of read_attribute, so what should I use to access any (attribute or relation) on ActiveRecord object?
Regarding to the comments, it looks like no one understand what I am trying to do. I want to access the relations of one ActiveRecord object such like;
RELATIONS.each do |relation|
puts "#{relation} exists" if #object.relation.present?
end
What I do not know about this, is there any method that I can access the related objects with their string typed name. Similar to, #object.read_attribute(:attribute_name) In that way I can create a for loop, but for relations not for the attributes
To do so, I used dynamical method call. Below is an example of showing it
RELATIONS.each do |relation|
puts "#{relation} exists" unless #object.send('relation').nil?
end

Ruby map unknown parent-child relationship (composition not inheritance) & get parent/child name or object given one known object?

Say I want to map an unknown parent-child relationship where I have a known #object_instance that's could be itself a parent or a child. I'd like to then see if this #object_instance has any parents or children, and get then list the ID(s) appropriately. For example, in pseudo-code:
def map_relationships
if self.has_children
puts "This object has children named #{self.child.class_name} with ID(s) #{self.children.map(&:id)}"
end
if self.has_parent
puts "This object has a parent named #{self.parent.class_name} with ID(s) #{self.parent.id}"
end
end
Let's say Company has_many Sites and a Site has many Offices, and #object_instance is a Site, then the result of the above method would be:
#object_instance.map_relationships
> "This object has children named Desks with ID(s) [5,6,7]"
> "This object has a parent named Company with ID(s) 4"
Isi something like this possible? I skimmed through the public_methods for both a Class and an instance of it, and couldn't see something obvious.
Thanks!
I found a way, essentially you can construct the above method using reflect_on_all_associations, which works like so:
# get parent
#object_instance.class.reflect_on_all_associations(:belongs_to)
# returns an array, like below
# [:company]
# get children
#object_instance.class.reflect_on_all_associations(:has_many)
# returns an array, like below
# [:desks]
Other answers welcome in case there are other nifty ways of doing this

Querying model by attribute of HABTM association

I have an HABTM association between two models, User and Conversation.
I want to be able to query the logged-in user's conversations (current_user.conversations), passing it another user's id, and have it return a conversation that is shared by both users, if one exists.
(an additional perk would be to have the query create one if one doesn't exist.)
The associations are working fine, so I can access the associated objects through instance variables like #user.conversations and #conversation.users, so I could go the long way and loop through each conversation object and search the user associations in each of them... But there must be an efficient way to construct this query.
What I would like to be able to do is something like current_user.conversations.where(conversation.users.exists?(id: #user_id)) or something like Conversation.find(users: {id: #user_id AND current_user.id}).
I imagine there is an obvious answer to this, and I've been searching around here for similar questions but haven't found any. After looking through the Rails API docs, I imagine that the solution I'm looking for involves .includes() in some way, but I can't get it working.
Any advice? Thanks.
Suppose you have two users #sender and #receiver, and there is one (or perhaps more) conversation between them. One possible way to query their shared conversations is by using the merge function in ActiveRecord. merge will select the intersection of conversations between between them:
#shared_conversations = #sender.conversations.merge(#receiver.conversations)
Note that the result will be a collection, not an individual conversation. In SQL this would translate to an INNER JOIN.
If you wanted to amend this query to create the conversation if it didn't exist, then you can use first_or_create. Like its name implies, first_or_create returns the first item in the collection. If the collection is empty, it will create a new object. You can pass it a block for further control over the newly created object:
#shared_conversations = #sender.conversations.merge(#receiver.conversations).first_or_create do |conversation|
conversation.title = "#{#sender.first_name}'s conversation"
end
You can find more details on merge in the Rails docs: http://apidock.com/rails/ActiveRecord/SpawnMethods/merge.
Try
current_user.conversations.includes(:users).where(user.id:current_user.id)

Rails Parent.find method returns object of type Child

I'm seeing an interesting behavior and would like some insight.
I have two models: Person & User. User inherits from Person. There is no users db table, just people.
When I search for a user I've created using Person's find model, I'm expecting to see an object of type person returned. But its type is user.
#person = Person.find(params[:id])
#person.class
# outputs 'User'
Can someone please explain why it wouldn't return a person object.
That is the desired behaviour. The type column of the found person row contains the value "User". Because of that the returned type is User, too.
Remember that User also is a Person, so you can treat any User instance like it was a Person instance.

In Rails, how do you swap a new object for an existing one?

I have the following nested model relationship:
Countries (id, name)
Provinces (id, country_id, name)
Cities (id, province_id, name)
I have validates_uniqueness_of constraint on the name fields for each model in the relationship and a unique index on the name columns in the database.
I want to swap a new object created with the same name as an existing record at some point before it's validated. In other words, if a user attempts to add a city, province, country combination that has already been added, I want to country model to return a reference to the corresponding existing model records instead of failing validation before save.
I'm having trouble using the model callbacks (after_initialize, before_validation, etc.) and I wasn't able to get Country.find_or_initialize_by_name to work with the nested models... any suggestions?
What you are trying to do sounds pretty hard and will probably require you to know a lot of the internal implementation details of ActiveRecord::Base.
Instead, could you do something like this?
#country = Country.find_or_initialize_by_name(params[:name])
...
#country.save
EDIT:
ActiveRecord has find_or_create_by_XXX and find_or_initialize_by_XXX functions built in, so there is no need to add a function to the model. For more info see the "Dynamic attribute-based finders" section of http://api.rubyonrails.org/classes/ActiveRecord/Base.html

Resources