Mongoid: Referencing Same Model More Than Once Through has_many - ruby

I'd like to be able to reference a model (a has_many relationship) more than once in the same model. For example, given the following models:
class MyModel
include Mongoid::Document
field :name, type: String
has_many :main_efforts, :class_name => 'Effort', as: :effortable, dependent: :delete, autosave: true
has_many :secondary_efforts, :class_name => 'Effort', as: :effortable, dependent: :delete, autosave: true
validates_presence_of :name
end
class Effort
include Mongoid::Document
field :name, type: String
belongs_to :effortable, polymorphic: true
validates_presence_of :name
end
As you can see, the Effort model is referenced twice. Originally, my Effort model wasn't polymorphic, but it seemed Mongoid was unable to determine which collection (main_efforts or secondary_efforts) the effort belonged to. As such, I made it polymorphic. After making it polymorphic, however, my main_efforts and secondary_efforts fields are always an empty array.
What is the proper way to reference a polymorphic model more than once in the same model (assuming a polymorphic model is necessary)?

Figured it out:
class MyModel
include Mongoid::Document
field :name, type: String
has_many :main_efforts, :class_name => 'Effort', dependent: :delete, autosave: true, :inverse_of => :main_effort
has_many :secondary_efforts, :class_name => 'Effort', dependent: :delete, autosave: true, :inverse_of => :secondary_effort
validates_presence_of :name
end
class Effort
include Mongoid::Document
field :name, type: String
belongs_to :main_effort, :class_name => 'Conop', :inverse_of => :main_efforts
belongs_to :secondary_effort, :class_name => 'Conop', :inverse_of => :secondary_efforts
validates_presence_of :name
end

Related

Validate uniqueness nested model params

I have three models:
class User < ActiveRecord::Base
has_many :user_countries
accepts_nested_attributes_for :user_countries, reject_if: :all_blank
validate :user_countries
end
class UserCountry < ActiveRecord::Base
belongs_to :user
belongs_to :country
end
class Country < ActiveRecord::Base
has_many :user_countries
has_many :users, :through => :user_countries
end
In a the user creation form I can create user_countries too. How I can validate in server the uniqueness of country_id in user_countries. A user has many countries: France, United State... but not for example: France and France.
I've added this to user_countries.. but it don't work:
validates :user_id, uniqueness: {scope: :country_id, allow_blank: false}
Try this in the user_country model.
class UserCountry < ActiveRecord::Base
belongs_to :user
belongs_to :country
validates_uniqueness_of :user_id, scope: :country_id, allow_blank: false
end
Also, you need to create a migration like below to add unique indexes on database level.
add_index :user_countries, [ :user_id, :country_id ], :unique => true

Trying to figure out what kind of relationships I should use

Sinatra, Mongoid 3
There 4 models: User, Book, FavoriteBooks, ReadBooks, NewBooks. Each user has their list of the favourites, read and new books. A book belongs to a list. But it's also possible to request an information about any book which means books should not be embedded into FavoriteBooks, ReadBooks, NewBooks.
The part of the scheme:
class Book
include Mongoid::Document
belongs_to :favourite_books
belongs_to :read_books
belongs_to :new_books
end
class FavoriteBook
include Mongoid::Document
has_many :books
end
#.... the same for ReadBooks and NewBooks
class User
include Mongoid::Document
# what else?
end
It seems like I missed something.
What should I do to make a user "contain" the lists of FavoriteBooks, ReadBooks, NewBooks? Should I use one-to-one relationship?
I think you should rethink your modeling. IMHO it should be book and user as models, and the favorite_books, read_books and new_books should all be relationhips like so:
class User
include Mongoid::Document
has_many :favorite_books
has_many :read_books
has_many :new_books
has_many :books, :through => :favorite_books
has_many :books, :through => :read_books
has_many :books, :through => :new_books
end
class Book
include Mongoid::Document
has_many :favorite_books
has_many :read_books
has_many :new_books
has_many :users, :through => :favorite_books
has_many :users, :through => :read_books
has_many :users, :through => :new_books
end
class FavoriteBook
include Mongoid::Document
belongs_to :books
belongs_to :users
end
#.... the same for ReadBooks and NewBooks
I think this should be a better approach. =)

Mongoid not saving nested_attributes for 'belongs_to' in a 1:1 relationship

I have two model's Contact, and User. When I create a new user I am trying to create the contact at the same time. But It is not getting created for some reason. Any ideas on why?
class Contact
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::MultiParameterAttributes
include Mongoid::Paranoia
include Mongoid::Versioning
# Attr.
attr_accessible :first_name, :last_name, :birthday, :email_addresses_attributes, :phone_numbers_attributes, :relationships_attributes, :addresses_attributes
#Relationships
belongs_to :firm, validate: true
has_one :user # contact information for user
has_many :relationships, autosave: true
has_many :clients
has_many :notes, dependent: :destroy
...
end
class User
include Mongoid::Document
include ActiveModel::SecurePassword
include Mongoid::Timestamps
# Attr.
attr_accessible :contact_id, :contact_attributes, :password, :password_confirmation, :google_tokens
#Relationships
belongs_to :firm, validate: true
belongs_to :contact, validate: true, autosave: true
has_one :user_type
embeds_many :histories
# Nested Attrs
accepts_nested_attributes_for :contact
...
end
accepts_nested_attributes_for is done on the owner object to allow you to set attributes of objects that belong it.
In your case, User belongs to (or is nested under) Contact. You would have to do accepts_nested_attributes_for :user in your Contact model.
You could switch it around so that User has_one :contact and Contact belongs_to :user. This requires you give Contact a user_id field.

Change name of mongoid relations (embeds_...,belongs_to,has_...)

When you have a relation such as embeds_many :album_items which relates to the AlbumItem model. How can I have it stored in just items. I tried embeds_many :album_items, :as => :items and embeds_many :items, :class_name => AlbumItem. Neither worked.
How can I go about renaming the relation?
Thanks
Does this work(assuming your parent model name is Album)?
In Album:
embeds_many :items, :class_name => "AlbumItem", :inverse_of => :album
and in AlbumItem:
embedded_in :album, :class_name => "Album", :inverse_of => :items

mongoid self to self relationship?

Hi guys I have a class like below for a crawler model:
class Link
include Mongoid::Document
include Mongoid::Timestamps
field :url, type: String
field :links, type: String
index :url
has_many :pages
end
where a link repent a URL and they have many inbound/outbound connections, I would like to have it working, so:
a_link.links # => gives a list of outbound link objects.
How would you do it with mongoid?
You can set up a many-many association using has_and_belongs_to_many on each side of the relationship.
class Link
include Mongoid::Document
has_and_belongs_to_many :links, :class_name => 'Link', :inverse_of => :inbound_links
has_and_belongs_to_many :inbound_links, :class_name => 'Link', :inverse_of => :links
end
As the association is to and from the same class in this case you need to give mongoid a little help with the class_name and inverse_of because it can't infer this from the association name.
a bit cleaner way to archive this using many-many associations
class Link
include Mongoid::Document
has_and_belongs_to_many :links, class_name: 'Link', inverse_of: :links
end

Resources