We have a field in our mongodb database called "failed?", including the question mark. Sometimes when I access that field, I get the value in the database, and sometimes I get null. I'm looking to understand what should happen a little bit more in order to debug this. So, can you have a question mark in a field name in a model, like so:
field :failed?, :type => Boolean, :default => nil
or am I in for a world of trouble. Assuming I already have this in the database and have to work with it, how should I get the fields out.
Environment: Rails 3.1, JRuby, Mongoid.
It's most likely a Mongoid bug as question marks in field names are valid in MongoDB. If I had to take a guess, it could be a weird conflict with the automatic <field>? that are created by Mongoid.
The easiest way to work around this would be to try accessing it through the raw hash that is pulled out from MongoDB, you can access it with model.attributes["failed?"]. If you still have issues, then likely it's a MongoDB driver problem.
Related
I am struggling with an issue with a Rails 5.2.4.1 app.
Configuration is the following:
Ruby 2.6.5
Rails 5.2.4.1
attr_encrypted 3.1.0
I have a model called Chicken that has 2 attributes: name - which is attr_encrypted and number - which is a normal integer field. Whenever I perform queries to retrieve any other fields except the attr_encrypted one, that still gets attached to the result and it's alway nil:
Chicken.select(:number) => #<ActiveRecord::Relation [#<Chicken id: nil, number: nil, name: nil>]>
Please keep in mind that this is just a test application and the queries that I am trying to execute on the actual app where I have encountered this initially, are more complex.
Is there a way to prevent attr_encrypted from attaching encrypted fields to queries results? Since the current results mean that I have to re-write all the existing queries in the app or add a filter for these types of fields somehow
This problem was caused by this change to attr_encrypted. As far as I can tell, there isn't any easy way to remove this attribute without modifications to the library but no one actively works on it so that seems unlikely.
The only options as far as I can see are to:
Use another library
Override the models attributes method to exclude the value (may produce undesirable results). It will still show in other methods active record provides.
Deal with it
Something else I haven't been able to find
A few ways you can deal with it:
Use a library to generate JSON responses for the frontend to only include attributes you want
redefine serializable_hash like devise does to remove attributes. (A lot safer than redefining the attributes method itself.
I'm using the active_model_serializers gem for a RoR API. Versions:
Rails: 4.2.8
Ruby: 2.2.5
active_model_serializers: 0.10.0
I'm using a virtual attribute in a serializer. I get it by using a sub query when I retrieve the objects from the database.
You can find the code here: Github Gist
This is the error I'm getting:
undefined method 'number_of_reservations' for DiscountSchedule...
This field isn't defined in the table nor in the model (attr_accessor)
I'm not sure why it doesn't work, I have a very similar serializer and it's working OK.
Any help will be appreciated.
EDIT:
I have another serializer where the virtual/calculated field is working OK. My guess on this is that since AR is making a bunch of LEFT OUTER JOINS and the SELECT list of the query is very big at some point something is getting broke.
The link won't work for me as I don't have access at my work place, however, from the error I can recommend you to check if you have defined the attributes like this in your serializer attributes :number_of_reservations and have an action in the serializer that says
def number_of_reservations
// Your logic goes here.
end
I suspect this question has to be about ActiveRecord, rather than AMS. You're trying to use select and alias to collect some computed (aggregate) attribute along with objects themselves. This, unfortunately, won't work in ActiveRecord, at least not in versions below 4.2.X. And this is why you're observing this behavior, there is no number_of_reservations in your models.
To see what's going on, try to inspect #objects here: https://gist.github.com/LuisDeHaro/ebf92781b449aa1ee7b85f8f552dd672#file-some_controller-rb-L17
Indeed: the issue was by the big amount of LEFT JOINS that the includes(:table_name) is generating. The serializer then does not know what to do.
I found a monkey-patch gem that works for AR (Rails 4 & 5) that fix this.
https://github.com/alekseyl/rails_select_on_includes
So, the virtual field number_of_reservations is picked up by the serializer like a charm.
And, you might be wondering: why do you want to retrieve a field that is not in the table definition in the database. A: well, in some scenarios you will need a calculated field for EVERY row you are retrieving. A SQL sub query is one of the most efficient ways to do so.
It's working now for me.
I'm using Mongoid 4.0.0 with Rails 4. My models map tables in another application, and I have no control over the field names.
One of the models has a field named id, which is getting coerced into Mongo's _id field. For example, when I insert a document with an id value of "something" I get
{_id:"something", id:null}
instead of
{_id:ObjectId("<hexstring>"),id:"something"}
Is there any way to avoid this coercion, make Mongoid not conflate the two fields, and leave my id field alone?
As I said, renaming the id field is not an option.
Thanks!
[edited]
This is definitely not a MongoDB issue. It must be in Moped or (my guess) Mongoid.
I've tried changing the params key from :id to :_rid but this is still happening. I'm going to check out aliases, but from my first pass I don't think they're going to help -- they appear to go the wrong way.
This appears to be hardcoded into Moingoid and a pervasive assumption throughout. It's annoying enough, though, that I might come up with a patch to allow users to override the key field on a per-model basis.
Oh well.
In Mongoid 3.0.21, how to get all model's attributes as a plain Ruby Hash?
Calling either #attributes or #raw_attributes returns Moped::BSON::Document. While it actually extends Hash, several hash method does not work as expected. Particularly #except returns unmodified self, not hash with given keys stripped off.
Update: Moped::BSON::Document properly inherits behavior of Hash. I was trying to name attributes with symbols, not strings, that's why #except didn't work. Shortly: do except('pictures'), not except(:pictures).
Hash[e.attributes]
where e is your model instance
I apologize for bumping something so old, but I wanted to leave this here for myself and all the future people who run into this same issue. I am using the Mongoid ORM for Rails, which uses Moped internally for its interaction with MongoDB.
This gem has now saved me hours and hours of manually converting things to Hash or HashWithIndifferentAccess: https://github.com/mindscratch/mongoid-indifferent-access.
Essentially it seems to have some sort of pre-return hook that automatically converts all documents coming from MongoDB to type HashWithIndifferentAccess.
Not looking for points on this. Just wanted to leave this here because it is the top Google result for this issue and it saved me from going insane.
i am having an issue with updating existing documents composite key fields in rails. the associated mongo query for my update_attributes statement seems to be correct, however the object cannot be found afterwards.
for example with an existing object with first_name "Jane" and last_name "Doe"... with my :key being :first_name, :last_name
i hit my update method with:
{"artist"=>{"last_name"=>"Doe", "first_name"=>"John"}, "commit"=>"Update Artist", "id"=>"jane-doe"}
def update
#artist = Artist.find(params[:id])
if #artist.update_attributes(params[:artist])
redirect_to #artist
end
end
which generates the mongo query: MONGODB app_database['artists'].update({"_id"=>"jane-doe"}, {"$set"=>{"_id"=>"john-doe", "first_name"=>"John"}})
which seems correct to me... but when i am redirected to that new artist, it complains about Document not found for class Artist with id(s) john-doe.
and in fact looking at my db from the mongo console, i still see Jane Doe in there. It is something to do with them being composite key fields, since i can update non-key fields just fine.
what am i missing here?
I tried this in an app of my own, and it looks like MongoDB simply doesn't currently allow you to modify the _id field as part of a $set operation (which is what Mongoid uses to perform updates). This is a strange restriction - I've been using Mongo for a year and a half now and I've never run into it.
So, a few options:
Stop using anything for your _id that might need to be changed later. I'd do this - it's a best practice anyway.
Whenever you need to make one of these _id changes, instead create a new record with the new _id attribute and delete the old one. This might get messy though, especially if you have other models that refer your Artist models by id.
File an issue with 10gen asking for this restriction to be lifted. They're very good about responding to users' concerns, but even if they agree, it'll probably take a while to be done.
File an issue with Mongoid to request support for these types of changes (Mongoid could conceivably handle the create + delete mechanism for you), but honestly, it's the kind of edge case that's probably not worth the extra time and code for them to support. It'd be nice if Mongoid raised an error when you tried to do an update like this, at the very least.