Mongoid query with where clause on an association of an embeded document - mongoid

I have a Rails app using Mongoid with the classes User, ContractAgreement and ContractVersions.
The relationships are the following: User embeds ContractAgreement, and ContractAgreement belong to ContractVersions, like so:
User:
class User
include Mongoid::Document
include Mongoid::Stateful
include Mongoid::Timestamps
[...]
embeds_many :contract_agreements
ContractAgreement:
class ContractAgreement
include Mongoid::Document
include Mongoid::Timestamps
embedded_in :user
belongs_to :contract_version
field :date_of_agreement, type: DateTime
ContractVersion
class ContractVersion
include Mongoid::Document
include Mongoid::Timestamps
field :version, type: String
field :description, type: String
field :status, type: String
has_one :post, autosave: true
has_one :post, autosave: true
#has_many :contract_agreements
As you can see, #has_many :contract_agreements is commented out as Mongoid didn't like the association to an embeded document.
Is there a way of getting the list of Users that have agreed to a specified contract?
I've tried both doing $elemMatch all the way:
[64] pry(main)> reload!;
u = User.all.select{|u| u.contract_agreements.count > 0}.first ;
cv = u.contract_agreements.first.contract_version ;
User.where(contract_agreements: {'$elemMatch' => {contract_version: {'$elemMatch' => {_id: cv._id}}}}).count
Reloading...
=> 0
As well as the compressed single query notation:
[64] pry(main)> reload!;
u = User.all.select{|u| u.contract_agreements.count > 0}.first ;
cv = u.contract_agreements.first.contract_version ;
User.where("contract_agreements.contract_version._id" => cv._id).count
Reloading...
=> 0
I know the contract version id I am asking for exists since I explicitly select a user that has one.
Is such a query even possible or do I need to de-embed ContractAgreement? If it is possible, what am I doing wrong?

Referring to the foreign key worked:
[73] pry(main)> reload!;
u = User.all.select{|u| u.contract_agreements.count > 0}.first ;
cv = u.contract_agreements.first.contract_version ;
User.where("contract_agreements.contract_version_id" => cv._id).count
Reloading...
=> 1

Related

Validating relationships invalids in mongoid

class A
include Mongoid::Document
field :value, type: String
validates :value, presence: true
has_and_belongs_to_many :cs
end
class B
include Mongoid::Document
belongs_to :a
embedded_in :c
end
class C
include Mongoid::Document
embeds_many :bs
end
:
c = C.create #<C _id: 53c96d1f05dfd40943000001, >
c.valid? # true
a = A.create #<A _id: 53c96d8305dfd4b6e1000002, value: nil, c_ids: nil>
a.valid? # false
invalid_b = c.bs.create(a: a) #<B _id: 53c96dac05dfd4b6e1000004, a_id: "53c96d8305dfd4b6e1000002">
# Invalid object has created !!!!!
# a not been persisted but the c saved his id.
invalid_b.reload
invalid_b.a # nil
invalid_b.a_id # 53c96d8305dfd4b6e1000002
The "a" field is not valid yet "b" is being created.
How can I solve this problem?
So that the class "B" to validate the field before saving?
if you used
invalid_b = c.bs.create!(a: a)
instead of
invalid_b = c.bs.create(a: a)
the invalid record won't create and the create! will raise Mongoid::Errors::Validations exception
check http://mongoid.org/en/mongoid/docs/persistence.html for reference

Have foreign_key on mongoid

Well I'm have a PerformerSource and MonthlyEarning documents which has a field called performer_id
class PerformerSource
....
field :performer_id,:type => Integer
....
....
end
class MonthlyEarning
....
field :performer_id,:type => Integer
....
....
end
Now all I want to set a has_many relationships between the two documents with performer_id in mind i.e
performer_source has_many monthly_earnings
monthly_earning belongs_to performer_source
I think the following isn't allowed in Mongoid because apparently when I set the relationships
it just does not return anything
But if it does then please let me know
Apparently this work so the idea was to have relations through performer_id field present in both document so all that is need is
to set this
class PerformerSource
....
field :performer_id,:type => Integer
....
....
has_many :earnings ,:class_name => "MonthlyEarning",:primary_key => :performer_id,:foreign_key => :performer_id
end
class MonthlyEarning
....
field :performer_id,:type => Integer
....
....
belongs_to :performer,:class_name => "PerformerSource",:primary_key => :performer_id,:foreign_key => :performer_id
end
The way it works over here is the :primary_key i.e(performer_id) when firing the request through association
This is exactly what I want

Elastic Search equivalent of "Scoping (Scalar Fields)" in sunspot/solr

I'm exploring various options for a search engine for our rails-app/data. I was able to make sunspot/solr work and am currently exploring ElasticSearch as an alternative but couldn't get the same thing(scoping/filtering) to work under ES.
I would like to filter/scope objects as described in the "Scoping" section in 'https://github.com/sunspot/sunspot'.
I have an active record class 'Product'.
class Product < ActiveRecord::Base
...
include Tire::Model::Search
include Tire::Model::Callbacks
tire.mapping do
indexes :name, :type => :string
indexes :categories do
indexes :id, :type => :integer
end
end
end
Once I imported products into ES,
the following query works and gives results
Product.tire.search { query { string '*', default_operator: "AND", default_field: "name" } }.results
How do I get products of a particular category given a category id ?
Product.tire.search { query { string '*', default_operator: "AND", default_field: "name" }; filter(:term, 'categories.id' => 38) }.results
I'm basically looking for the tire equivalent for the following sunspot call:
Product.search do
with(:category_ids, 38)
end
with the following in the Product class
searchable :auto_index => true, :auto_remove => true do
text :name
integer :category_ids, :multiple => true do
self.categories.map &:id
end
end

How do you define an array field when using create in mongoid?

I'm trying to create a seed file to populate my mongo database. The following syntax creates a nil value when I try to define the array field value. I'm using mongoid v3.0.9. What am I doing wrong?
These following examples do not work when I put them in the seed file:
User.create(name:'name', test_array_field:'[123,123]')
User.create(name:'name', test_array_field:[123,123])
User.create(name:'name', test_array_field:[123,123].to_a)
I've defined the field in my class like so:
field :test_array_field, type: Array
Your second syntax works for me.
class User
field :roles, type: Array, default: []
end
u = User.create roles: ['superadmin']
u.new_record? # => false
u.roles # => ["superadmin"]
Try this:
class Foo
include Mongoid::Document
field :bar, :type => Array, :default => []
field :baz, :type => Hash, :default => {}
end

mongoid, embedy_many, simple_form

i m looking for a way to manage multiple embedded objects in a form.
found a solution for formtastic by bowsersenior
Formtastic with Mongoid embedded_in relations
but i wasnt able to do the same for simple_form
formtastic:
= semantic_form_for #team do |form|
= #team.players.each do |player|
= form.inputs :for => [:players, player] do |player_form|
= player_form.input :name
best regards
sample
class Team
include Mongoid::Document
field :name, :type => String
embeds_many :players
end
class Player
include Mongoid::Document
embedded_in :team, :inverse_of => :players
field :name, :type => String
field :active, :type=> Boolean # checkboxes
end
Not sure if this would work but you might want to try something like this:
= simple_form_for #team do |form|
= f.input :name
= f.simple_fields_for #team.players do |player_form|
= player_form.input :name
Just keep in mind that you will have to create a new player in the team before the form will show up.
In your controller(controller):
def new
#team = Team.new
8.times { #team.players.new } #for 8 players
end

Resources