Mongoid timestamp is missing - ruby

I'm trying to use mongoid timestamps in my model class to update the created_at and updated_at fileds. However, these fields are missing in DB for all inserts and updates.
That's how I'm upserting documents:
update_hash = { :$set => some_hash_1, :$setOnInsert => some_hash_2}
application = Application.where(external_id: external_id)
application.update(update_hash, upsert: true)
However, when I'm trying to update this way, it works:
application = Application.find_or_initialize_by(external_id: external_id)
application.update_attributes!(update_hash)
I don't want to use the second method as it makes 2 calls to the DB. How can I make the first one working? Am I doing something wrong or it could be some mongoid bug?
This is how my model class looks like:
class Application
include Mongoid::Document
include Mongoid::Timestamps
field :external_id, type: String
...
end
mongoid version is 7.0.4.

Related

Is there a way to serialize nested attributes outside of the parent with ActiveModel Serializer?

I upgraded activemodel serializer and now the output is different than what it once was. I'm trying to get the JSON output to match what it previously was. Specifically, I'd like an objects nested attributes to be on the same level as the main object.
For example, let's say my serializer is as follows:
class DishesSerializer < ActiveModel::Serializer
has_many :ingredients
end
This would be the current output:
{
"dish": {
"dish_stuff_1": "dish_stuff_1",
"dish_stuff_2": "dish_stuff_2",
"dish_stuff_3": "dish_stuff_3",
"ingredients": {
"ingredients_stuff_1": "ingredients_stuff_1"
}
}
}
And what I'd like is something like this:
{
"dish": {
"dish_stuff_1": "dish_stuff_1",
"dish_stuff_2": "dish_stuff_2",
"dish_stuff_3": "dish_stuff_3"
}
"ingredients": {
"ingredients_stuff_1": "ingredients_stuff_1"
}
}
I am currently doing this in the controller using multiple serializers, but it takes some additional querying and feels wrong. I feel like there should be some hacky way to do it in AMS.
I tried something like this:
def attributes
hash = super
hash.merge!(:dishes => dishes)
end
but that ends up in the same layer.
Any help would be greatly appreciated.
In this case, can't you just create a new serializer that has all the data you need - say a menu serializer:
class MenuSerializer < ActiveModel::Serializer
has_one :dish
has_many :ingredients
end
Not sure having a serializer that returns 2 root elements is a good idea, as that would make it hard to reuse in the future.

EmbeddedDocument field never optional in Django Mongoengine REST framework

I am using Django REST framework with Mongoengine. When I attempt serialize an optional field on an embedded document, the framework still requires the field and returns the error message that the field cannot be left blank. How do I make fields optional on an EmbeddedDocument? It works fine for standard Document model objects, just not for EmbeddedDocument objects.
My model:
class Event(EmbeddedDocument):
id = ObjectIdField(required=True, default=ObjectId())
status = StringField(required=True, max_length=50)
note = StringField(required=False, max_length=2000)
created = DateTimeField(required=True, default=timezone.now())
My serializer:
class EventSerializer(EmbeddedDocumentSerializer):
class Meta:
model = Event
depth = 2
def validate(self, data):
return data
Note that the field "note" is set to required=False. When I serialize the document, however, I still get an error message that the field can't be left blank. Thank you!
I came across the same problem, I think you can mark the fields as blank=True and it should allow you to place nothing in those fields.

Mocking mongomapper document inside helper

I am creating a simle application with ruby and mongo mapper and I want to test it with rspec, the setup is like this:
class Entry
include MongoMapper::Document
key :things, Array
key :date_created, Date
end
And the service (thinking in changing it to helper) looks like this:
class EntryService
def save_entry (date, items)
entry = Entry.new(:date_created => date, :things => items )
entry.save!
return 'success'
end
end
My question is, how do I test the save_entry method of the EntryService class without hitting the Database?

Mongoid find by embedded document

I have the following embedded structure
class CbAuthor
include Mongoid::Document
embeds_many: cb_bylines
field :name, type: String
end
class CbByline
include Mongoid::Document
embedded_in :cb_author
has_many :cb_articles
field :byline, type: String
end
class CbArticle
include Mongoid::Document
belongs_to :cb_byline
end
This is because there are many bylines or pseudonyms the authors publish under and that is will be attached to their analytics reports. So when I have a byline, how do I find the author? This will be necessary because They will have dashboards that should list all the articles they wrote under all their respective bylines.
I tried CbAuthor.cb_bylines but that gives me a no method error. or CbAuthor.where(cb_bylines["byline"]: bylineInQuestion) but that also gives errors.
Essentially the goal is to have one author name to find all his bylines and the articles associated with those bylines
embeds_many :cb_bylines is just a fancy way of saying "add an array of hashes called cb_bylines" (at least as far as storage is concerned). That means that your CbAuthors look like this inside MongoDB:
{
_id: '...',
name: '...',
cb_bylines: [
{ _id: '...', byline: '...' },
...
]
}
MongoDB will unroll the array for simple queries for you so you can simply look for 'cb_bylines.byline' as though you were querying a hash inside the collection:
authors_by_lined_as_pancakes = CbAuthor.where('cb_bylines.byline' => 'Pancakes McGee')
or if you know there is just one:
pancakes_mcgee = CbAuthor.find_by('cb_bylines.byline' => 'Pancakes McGee')
Don't be afraid to bypass Rails and Mongoid to look at what your data really looks like inside MongoDB.

How to access Users in Mongo db console

I'm using Mongoid for Ruby. I have queried in my Mongo database before, but forget how it works with Mongo. I have a user model like so:
class User
include Mongoid::Document
field :email, type String
field :crypted_password, type String
...
end
How would I grab all the users or a specific user in my console? Thanks to anyone who can help
use *database
This returns a specific user:
db.getUser("*user")
This returns all users
db.getUsers()
If your class is called User then the underlying MongoDB collection will be users. So you'd say things like:
> db.users.find() // All users
> db.users.find({ field: value }) // Users that match certain conditions
> db.users.findOne({ _id: ObjectId('...') }) // Find one user with a specific id
...
See the find and findOne documentation for further details.

Resources