In my code I have a user class:
class User
include Mongoid::Document
has_and_belongs_to_many :person_record_bookmarks, inverse_of: nil, :class_name => "PersonRecord"
end
now it will generate person_record_bookmarks_ids in my document. This name is too long, is there any way to store it as shorter name in the database? In embed documents we can use store_as:, but seems it doesn't work for references.
foreign_key is what you are looking for
class User
include Mongoid::Document
has_and_belongs_to_many :person_record_bookmarks, inverse_of: nil, :class_name => "PersonRecord", foreign_key :shorter_name
end
then your user will be:
{...shorter_name:[ObjectId("..."),ObjectId("...")]...}
You can user user.shorter_name to retrieve the list of ids or user.person_record_bookmarks to retrieve all PersonRecordBookmarks.where({_id: {$in: shorter_name})
Related
Foo, Bar and Baz are all Mongoid collection models. There are the only collections in the DB.
Is there a more efficient way to get all the data in the DB?
Foo.all + Bar.all + Baz.all
I don't know a way of querying several collections at the time, and I believe that if one try to do that will defeat the purpose of using a NONSQL DB like MongoDB.
However, there is one way of archiving this behaviour in MongoDB. Using embedded documents. For example:
class Everything
include Mongoid::Document
include Mongoid::Timestamps
embeds_many :foos, class_name: 'Foo', inverse_of: :everything
embeds_many :bars, class_name: 'Bar', inverse_of: :everything
embeds_many :bazs, class_name: 'Bazs', inverse_of: :everything
end
class Foo
include Mongoid::Document
field :foo, type: String
embedded_in :everything, class_name: 'Everything', inverse_of: :foos
end
class Bar
include Mongoid::Document
field :bar, type: String
embedded_in :everything, class_name: 'Everything', inverse_of: :bars
end
class Bazs
include Mongoid::Document
field :baz, type: String
embedded_in :everything, class_name: 'Everything', inverse_of: :bazs
end
Doing Everything.all will retrieve all documents in Everything along with all the embedded documents in one call.
I am trying to store messages and I want to store to and from User reference as below:
class Message
include Mongoid::Document
include Mongoid::Timestamps
field :from, type: Moped::BSON::ObjectId
field :to, type: Moped::BSON::ObjectId
end
class User
include Mongoid::Document
field :username, type: String
end
Is the above the correct way of doing so? I can imagine one way is to create User as a custom type, but that seems a lengthy direction to take. Ideally I want to be able to reference the User directly as so: message.from.username or message.from['username'] and be able to validate the presence of the from and to fields.
Any help would be much appreciated.
class Message
belongs_to :from, class_name: 'User', inverse_of: nil
belongs_to :to, class_name: 'User', inverse_of: nil
...
Message.where(from: my_user)
How do I go about validating the presence of an item defined as belongs_to? In other words:
class Temp
include Mongoid::Document
include Mongoid::Timestamps
belongs_to :user
end
and I wish to make sure a user was input.
Thanks in advance!
From the fine manual:
The parent document of the relation should use the has_many macro to indicate is has n number of referenced children, where the document that is referenced uses belongs_to.
class Band
include Mongoid::Document
has_many :members
end
class Member
include Mongoid::Document
field :name, type: String
belongs_to :band
end
[...]
# The parent band document.
{ "_id" : ObjectId("4d3ed089fb60ab534684b7e9") }
# The child member document.
{
"_id" : ObjectId("4d3ed089fb60ab534684b7f1"),
"band_id" : ObjectId("4d3ed089fb60ab534684b7e9")
}
Take note of the band_id that represents the belongs_to :band relationship. So saying:
belongs_to :user
implicitly adds a field :user_id to your Temp. That means that you can simply:
validates_presence_of :user_id
to make sure that a :user_id has been given. If you want to ensure that the :user_id is valid then you could:
validates_presence_of :user
and the validation will make sure that temp.user (i.e. User.find(temp.user_id)) finds something.
In the following "department store pattern" I have three models:
class Store
has_many :items, inverse_of: :store, autosave: true
has_many :departments, inverse_of: :store, autosave: true
accepts_nested_attributes_for :departments, allow_destroy: true
class Department
belongs_to :store, inverse_of: :departments
has_many :items, autosave: true, inverse_of: department
accepts_nested_attributes_for :items, allow_destroy: true
class Item
belongs_to :store, inverse_of: :items
belongs_to :department, inverse_of: :items
When I try the following:
store = Store.new
department = store.departments.build
item = department.items.build
store.save
Then the item does not associate with the store.
My solution to the problem was to add the following to the Item model:
class Item
before_validation :capture_store_info
def capture_store_info
self.store = self.department.store
end
I added it to the before_validation callback because in my non-trivial code I have a bunch of validations, including one that checks for the presence of the store model.
Question: My solution works, but is it the correct (ie. Rails conventional) way of solving this problem? Is there a better solution. This feels kinda dirty, and every time I have done something in Rails that felt "kinda dirty" it has come back to bite me later.
Thanks,
JB
I have belongs_to :provider in my model, and provider_id is set, but association is still blank:
irb(main):095:0> o2.provider_id
=> BSON::ObjectId('4e0472f36d40ec0004000001')
irb(main):096:0> o2.provider
=> nil
Also, model has provider_id= method with "write_attribute(:provider_id, provider_id)" inside.
What could be wrong here?
Mongoid version is 2.4.0
Thank you!
I believe you need a has_one or has_many association in your other model.
class Foo
include Mongoid::Document
belongs_to :bar
end
class Bar
include Mongoid::Document
has_one :foo
end