Publish fields of Meteor.user to the client - coffeescript

I'm trying to add a custom balance field to the meteor.user collection, but I'm having problem accessing it from the client.
Event if I create a fresh project with autopublish and insecure it doesnt work. Let's say I want to publish the createdAt field of the user collection:
# server
if Meteor.isServer
Meteor.publish "userData", ->
console.log #userId
if #userId
Meteor.users.find
_id: #userId
,
fields:
createdAt: 1
else
#ready()
return
# client
if Meteor.isClient
Meteor.subscribe "userData"
/project/collections/user.coffee
Anyhow when I type Meteor.user() in the console of the broswer I still cant read the createdAt field. What am I doing wrong?

In the success case, your function needs to return a cursor in the client. The explicit return is preventing this. I'd write it like this:
Meteor.publish 'userData', ->
return #ready() unless #userId
Meteor.users.find #userId, fields: createdAt: 1

Related

CloudKit Bad Request on Users Record Update with Web Services API

I added a custom field to the default Users record type in CloudKit, and I'm trying to push a value to that new field.
Here's how my request is structured in Node JS:
var query = {
operations :[{
operationType: 'forceUpdate',
record:{
recordType: 'Users',
fields:{
myCustomField: { value: 'stuff' }
},
recordName: '_abc123'
}
}]
}
I'm getting this response from CloudKit:
records: [{
recordName: '_abc123',
reason: 'invalid id string, id=_abc123',
serverErrorCode: 'BAD_REQUEST'
}]
If I put that same custom field on another, custom Record Type (like if I make my own User (without the "s") type) that also has myCustomField on it, the update works fine. So there must be something special I have to do to update the system Users type.
Does anyone know how to update a field on a Users record with the web services API?

Mongoose $push to array inside subdocument

I have a companies model which has payment info stored like this:
let paymentSchema = new Schema({
date: Date,
chargeId: String
amount: Number,
receipt_url: String,
currency: String,
type: String
});
paymentInfo: {
lastPayment: {type: paymentSchema},
paymentHistory: [{type: paymentSchema}],
paymentMethod: paymentMethod,
customerId: customerId
}
)};
The paymentInfo is a subdocument and I am using schema there for some validation purposes.
While trying to update the a company's info using the following query, it updates everything except the paymentHistory :
Companies.updateOne(
{_id: companyId},
{
paymentInfo: {
paymentMethod: paymentMethod,
customerId: customerId,
lastPayment : paymentObject,
$push: {paymentHistory: paymentObject }
}
One could say why save the same paymentObject in lastPayment and also push it to paymentHistory - that's required for a feature we need and that's not causing any trouble.
I also tried the following update query and it gives a conflict error - updates in the following code is a valid object and without $push it works fine
{$set: updates, $push: {'paymentInfo.paymentHistory': paymentObject}}
Conflict Error :
{"driver":true,"name":"MongoError","index":0,"code":40,"errmsg":"Updating the path 'paymentInfo' would create a conflict at 'paymentInfo'"}
What do I want?
I want to update the company document in a single database call - looking at that error it seems like I am supposed to make 2 calls, one for $set and other for $push? Is there anything wrong with the first update query??
Possible Solution
One way to solve this is to take out the paymentHistory out of paymentInfo so that it's part of main company schema - that solves the issue but I want to keep all payment related stuff inside paymentInfo.
Any help would be appreciated. Thanks

Autoincrement a meteor simpleschema member

Here is what I'm trying to do:
SimpleSchema.FaqSchema = new SimpleSchema
order:
type: Number
autoValue: ->
# somehow increment this by 1
updatedAt:
type: Date
autoValue: ->
new Date
updatedBy:
type: String
autoValue: ->
Meteor.userId()
question: type: String
answer: type: String
Unfortunately, there is nothing in Meteor documentation or simpleschema docs for this matter which explains how to do it. There is mongo docs here : http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/
However, this doesn't really help.
Any help is appreciated. The schema is in coffeescript but can be converted using http://js2.coffee/
Create a Meteor method on the server side that increments the order field by 1 during inserts. This method uses the meteor-mongo-counter package which implements the "Counters Collection" technique described in the MongoDB documentation Create an Auto-Incrementing Sequence Field:
Server
Meteor.methods
"insertDocument": (doc) ->
doc.order = incrementCounter "order"
MyCollection.insert doc
doc.order
Client
doc =
question: "Question 1"
answer: "Answer 1"
# Instead of inserting with Collection.insert doc, use Meteor.call instead
Meteor.call "insertDocument", doc, (err, result) ->
if result console.log "Inserted order number #{result}"

Meteor.users adding additional fields to documents not working properly

I'm not sure what's wrong but following the documentation on how to grab additional fields from the server here:
return Meteor.users.find({_id: this.userId}, {fields: {'other': 1, 'things': 1}});
What ends up happening is that it only publishes the two fields other and things instead of the default fields of emails, profile, username and other, things.
This is what I have return Meteor.users.find({username: username}, {fields: {'status': 1});
So what ends up happening is that the client is only receiving two fields _id, and status. I don't want to manually add all the 'default' fields to each and every publish function, what am I doing wrong?
If you want to apply DRY principle then simply create defaultInclusionFields:
var defaultInclusionFields = function() {
return {
emails:1,
profile:1,
username:1
};
}
and extend defaultInclusionFields() using underscore with your custom fields ('other', 'status', ... ):
Meteor.users.find(
{username: username},
{fields: _.extend(defaultInclusionFields(),{"other":1,"status":1})
);
Note that you can not mix inclusions and exclusions.

How can I upsert using Mongoose based on _id?

When I do this:
client_id = req.param("client_id") ? null
client =
name: req.param "clientName"
status: 'active'
Client.update {_id: client_id}, client, {upsert: true}, (err, updRes) ->
if err
res.json
error: "Couldn't create client"
else
res.json client
It will create a new client record, except with a null _id field. I assume that's because the insert part of the upsert looks to the query to create the document. How can I do it so that if no doc is found, then insert a new ObjectId?
Not sure if you have figured this one out yet, but in case you don't want to run into trouble with unique key constraints like Mustafa mentioned above, the way I've done it is by using mongoose's findByIdAndUpdate:
// require mongoose
client_id = req.param("client_id") ? new mongoose.Types.ObjectId
client =
name: req.param "clientName"
status: 'active'
Client.findByIdAndUpdate client_id, client, {upsert: true}, (err, updRes) ->
if err
res.json
error: "Couldn't create client"
else
res.json client
I've never written CoffeeScript, so forgive me if some of that syntax is wrong, but I think it should be fairly obvious what I'm trying to do.
One thing to notice is that you need to make sure client_id is neither an empty string (as that would cause an 'Invalid ObjectID' error) nor null (because mongoose seems infer the new document's id from the one you're querying for). In case it is, I create a new ObjectId, which will cause the query to miss and therefore create a new document with that ID since I pass {upsert: true}.
This seems to have solved the problem for me.
All you have to do with Mongoose is to call save on the client, Mongoose will figure out on its own if it's an update or an insert:
client_id = req.param("client_id") ? null
client_data =
name: req.param "clientName"
status: 'active'
_id: client_id
client = new Client(client_data)
client.save (err) ->
if err
res.json
error: "Couldn't save client"
else
res.json client
Note: Client is a Mongoose model.