Meteor jagi:astronomy .save function is not working - javascript

For some reason, i get a "post.save is not a function" on using the .save() function on astronomy v2. i tried to call the .save() on inserting a new doc in the db using a meteor methods call from the client side.
Here's some code :
import { Class } from 'meteor/jagi:astronomy';
import { Mongo } from 'meteor/mongo';
const Posts = new Mongo.Collection("Posts");
const Post = Class.create({
name: 'Post',
Collection : Posts,
secured: true,
fields: {
title: String,
published: Boolean,
/* ... */
},
methods: {
rename(title) {
// Check if a given user can rename this post.
if (this.ownerId !== Meteor.userId()) {
throw new Meteor.Error(403, 'You are not an owner');
}
this.title = this;
this.save();
},
publish() {
// Check if a given user can publish this post.
if (this.ownerId !== Meteor.userId()) {
throw new Meteor.Error(403, 'You are not an owner');
}
if (this.published) {
throw new Meteor.Error(403, 'Post is already published');
}
this.published = true;
this.save();
}
}
});
Meteor.methods({
"newPost"(){
const post = new Post();
post.title = "test";
post.save();
},
"renamePost"(postId, title) {
const post = Post.findOne(postId);
post.rename(title);
},
"publishPost"(postId) {
const post = Post.findOne(postId);
post.publish();
}
});
As you can see im using the samples on the astronomy documentation with an additional methods called newPost.
calling on those functions all resulted in an Exception
TypeError: post.save is not a function
Have tried the following tries on resolving the error with no success
Removing and re adding astronomy
Rebuild meteor project
Updating to latest 2.1.2 version
Thx for the answers !

It looks like method dont know about Astronomy.Class.
You export your class?

Related

JHipster Blueprint | Yeoman Generator - Using a user's answer to a prompt for templating with EJS

I am developping a JHipster blueprint and I need to use EJS to template the files I want to generate. Since this is my first time using EJS, all I am trying to do for now is use an answer from one of the generated question and create a java interface with its name.
This is the template I got:
public interface <%= databaseURL %> {
}
prompts.js:
function askForDatabaseURL(meta) {
const applicationType = this.applicationType;
const prompts = [
{
type: 'string',
name: 'databaseURL',
message:
'Quel est l\'URL de votre base de données ?',
default: 'URL'
}
];
if (meta) return PROMPTS;
const done = this.async();
this.prompt(prompts).then(prompt => {
this.log(this.databaseURL);
this.databaseURL = prompt.databaseURL;
this.log(this.databaseURL);
done();
});
}
module.exports = {
askForDatabaseURL
};
index.js:
const chalk = require('chalk');
const AppGenerator = require('generator-jhipster/generators/app');
const prompts = require('./prompts');
module.exports = class extends AppGenerator {
constructor(args, opts) {
super(args, { fromBlueprint: true, ...opts }); // fromBlueprint variable is important
this.databaseURL = "Hello";
}
get initializing() {
return super._initializing();
}
_prompting() {
return {
askForDatabaseURL: prompts.askForDatabaseURL
}
}
get prompting() {
const defaultPhaseFromJHipster = super._prompting();
const myPrompting = this._prompting();
return Object.assign(defaultPhaseFromJHipster, myPrompting);
}
get configuring() {
return super._configuring();
}
get default() {
return super._default();
}
_writing() {
this.fs.copyTpl(
this.templatePath(`src/main/java/package/repository/JOOQRepository.java.ejs`),
this.destinationPath(`${this.databaseURL}.java`),
{ databaseURL : this.databaseURL}
)
}
get writing() {
const defaultPhaseFromJHipster = super._writing();
const myWriting = this._writing()
return Object.assign(defaultPhaseFromJHipster, myWriting);
}
get install() {
return super._install();
}
get end() {
return super._end();
}
};
The problem is, after the prompting phase, this.databaseURL always has a value of "Hello" which is the default value in the constructor, meaning the file generated is always Hello.java.
I tried to add this.log(this.databaseURL); before and after this.databaseURL = prompt.databaseURL so I'd get an idea if this line does what it's supposed to and it does:
I am fairly new to JavaScript so I might have missed something very basic, but I don't understand why this.databaseURL returns "Hello" after assigning it the user's answer to it.
Any help is welcomed!

How to fake a user in unit tests in Meteor using practicalmeteor:mocha?

I'm having a difficult time trying to test a methods in meteor that requires a connected user. Basically I need to test if a user of the app can add an article to it's cart. The methods will tests if a user is connected and, in order to test that will use Meteor.userId(). This seems to be a problem in unit testing as I get the error:
"Meteor.userId can only be invoked in method calls or publications."
So far, I tried to do what's proposed in this post: How to unit test a meteor method with practicalmeteor:mocha but I don't understand what the solution is doing.
Here is my testing method:
import { Meteor } from 'meteor/meteor';
import { Random } from 'meteor/random';
import { assert } from 'meteor/practicalmeteor:chai';
import { sinon } from 'meteor/practicalmeteor:sinon';
import { Carts } from '/imports/api/carts/carts.js';
import { Articles } from '/imports/api/articles/articles.js';
import '/imports/api/carts/carts.methods.js';
import { SecurityEnsurer } from '/lib/security/security.js';
function randomInt (low, high) {
return Math.floor(Math.random() * (high - low) + low);
}
if (Meteor.isServer) {
describe('Carts', () => {
describe('methods', () => {
let currentUser;
beforeEach(() => {
Factory.define('user', Meteor.users, {
name: "userTest",
currentUser: {
email: 'user#shop.info',
password: '123456',
}
});
currentUser = Factory.create('user');
sinon.stub(Meteor, 'user');
Meteor.user.returns(currentUser);
Articles.remove({});
articleId = Articles.insert({
name : "azerty",
description : "descTest",
modelNumber : "wxcvbn",
categoryName : "CatTest",
price : 1,
advisedPrice: 2,
supplierDiscount : 0,
brandId : "BrandTest",
isAvailable: true,
restockingTime: 42,
color: "Yellow",
technicals: [
{
name : "GPU",
value : "Intel"
},
],
});
Carts.insert({
owner: currentUser,
entries: [],
});
});
afterEach(() => {
Meteor.user.restore();
Articles.remove({});
Carts.remove({});
});
it('can add article', () => {
let quantity = randomInt(1,50);
const addArticleToCart = Meteor.server.method_handlers['carts.addArticle'];
const invocation = {};
addArticleToCart.apply(invocation, [articleId, quantity]);
assert.equal(Cart.find({owner: currentUser, entries: {$elemMatch: {articleId, quantity}}}).count(), 1);
});
});
});
}
If anyone can help me find out how to create my test, this would realy help me.
To fake a user when calling a Meteor Method, the only way I found is to use the mdg:validated-method package which provide a framework around Meteor methods. This framework seems to be the standard now (see the Meteor guide), but it requires to re-write your methods and the in-app calls.
After describing the methods using this framework, you are able to call them with the userId parameter when testing, using this kind of code (which verifies that my method is returning a 403 error):
assert.throws(function () {
updateData._execute({userId: myExternalUserId}, {
id: dataId,
data: {name: "test"}
});
}, Meteor.Error, /403/);
FYI, here are the packages I add when I do automated testing (Meteor 1.6 used):
meteortesting:mocha
dburles:factory
practicalmeteor:chai
johanbrook:publication-collector
Here's how I set up a fake logged in user for testing publish and methods:
1) create a user
2) stub i.e. replace the Meteor.user() and Meteor.userId() functions which return the current logged in user in methods
3) provide that user's _id to PublicationsCollector, which will send it in to your publish function.
Here's how I did it, I hope you can adapt from this:
import { Meteor } from 'meteor/meteor';
import { Factory } from 'meteor/dburles:factory';
import { PublicationCollector } from 'meteor/johanbrook:publication-collector';
import { resetDatabase } from 'meteor/xolvio:cleaner';
import faker from 'faker';
import { Random } from 'meteor/random';
import { chai, assert } from 'meteor/practicalmeteor:chai';
import sinon from 'sinon';
// and also import your publish and collection
Factory.define('user', Meteor.users, {
'name': 'Josephine',
});
if (Meteor.isServer) {
describe('Menus', () => {
beforeEach(function () {
resetDatabase();
const currentUser = Factory.create('user');
sinon.stub(Meteor, 'user');
Meteor.user.returns(currentUser); // now Meteor.user() will return the user we just created
sinon.stub(Meteor, 'userId');
Meteor.userId.returns(currentUser._id); // needed in methods
// and create a Menu object in the Menus collection
});
afterEach(() => {
Meteor.user.restore();
resetDatabase();
});
describe('publish', () => {
it('can view menus', (done) => {
const collector = new PublicationCollector({ 'userId': Meteor.user()._id }); // give publish a value for this.userId
collector.collect(
'menus',
(collections) => {
assert.equal(collections.menus.length, 1);
done();
},
);
});
});
});
}
You can also write a test for calling a Meteor method that relies on Meteor.userId():
expect(() => { Meteor.call('myMethod'); }).to.not.throw(Meteor.Error);

Parse JS SDK: Cannot use the Master Key, it has not been provided

I need to use masterKey inside my angular2 app, but I can't pass it to initialize function and I can't google out why.
From package.json: "parse": "~1.9.2".
Initialization:
import {Parse} from '~/node_modules/parse/dist/parse';
#Injectable()
export class TFCloudService {
constructor() {
this.parse = Parse;
Parse.initialize(appConfig.parse.appId, null, appConfig.parse.masterKey);
Parse.serverURL = appConfig.parse.clientServerUrl;
Parse.liveQueryServerURL = appConfig.parse.liveQueryServerURL;
}
}
Error source:
this.edittedUser.save(null, {useMasterKey: true})
.then((user) => {
console.log(user);
});
Error text:
Error: Cannot use the Master Key, it has not been provided.
appConfig.parse.masterKey works fine, I checked that line with hard-coded key too, but got the same result.
Actually guessed the right way to pass that key:
Parse.initialize(appConfig.parse.appId);
Parse.masterKey = appConfig.parse.masterKey;

How to find a record both by id and query parameters in Ember

I'm trying to use ember-data to send a request via id and query parameters to an endpoint. The end output of the ajax call would be http://api.example.com/invoices/1?key=value. As far as I know, ember-data's store doesn't have a native way to find by both id and query parameters (neither of the following worked):
// outputs http://api.example/com/invoices/1
this.store.find('invoice', 1);
// outputs http://api.example.com/invoices?id=1&key=value
this.store.find('invoice, {id: 1, key: value});
Instead, I've been attempting to modify the invoice adapter. Our backend is Django, so we're using the ActiveModelAdapter. I want to override the method that builds the url so that if id is present in the query object, it will automatically remove it and append it to the url instead before turning the rest of the query object into url parameters.
The only problem is that I can't figure out which method to override. I've looked at the docs for ActiveModelAdapter here, and I've tried overriding the findRecord, buildUrl, urlForFind, and urlForQuery methods, but none of them are getting called for some reason (I've tried logging via console.log and Ember.debug). I know the adapter is working correctly because the namespace is working.
Here's my adapter file:
import DS from 'ember-data';
import config from '../config/environment';
export default DS.ActiveModelAdapter.extend({
namespace: 'v1',
host: config.apiUrl,
// taken straight from the build-url-mixin and modified
// very slightly to test for logging
urlForFindRecord: function(id, modelName, snapshot) {
Ember.debug('urlForFindRecord is being called');
if (this.urlForFind !== urlForFind) {
Ember.deprecate('BuildURLMixin#urlForFind has been deprecated and renamed to `urlForFindRecord`.');
return this.urlForFind(id, modelName, snapshot);
}
return this._buildURL(modelName, id);
},
// taken straight from the build-url-mixin and modified
// very slightly to test for logging
findRecord: function(store, type, id, snapshot) {
Ember.debug('findRecord is being called');
var find = RestAdapter.prototype.find;
if (find !== this.find) {
Ember.deprecate('RestAdapter#find has been deprecated and renamed to `findRecord`.');
return this.find(store, type, id, snapshot);
}
return this.ajax(this.buildURL(type.modelName, id, snapshot, 'findRecord'), 'GET');
},
// taken straight from the build-url-mixin and modified
// very slightly to test for logging
urlForQuery: function(query, modelName) {
Ember.debug('urlForQuery is being called');
if (this.urlForFindQuery !== urlForFindQuery) {
Ember.deprecate('BuildURLMixin#urlForFindQuery has been deprecated and renamed to `urlForQuery`.');
return this.urlForFindQuery(query, modelName);
}
return this._buildURL(modelName);
},
// taken straight from the build-url-mixin and modified
// very slightly to test for logging
_buildURL: function(modelName, id) {
Ember.debug('_buildURL is being called');
var url = [];
var host = get(this, 'host');
var prefix = this.urlPrefix();
var path;
if (modelName) {
path = this.pathForType(modelName);
if (path) { url.push(path); }
}
if (id) { url.push(encodeURIComponent(id)); }
if (prefix) { url.unshift(prefix); }
url = url.join('/');
if (!host && url && url.charAt(0) !== '/') {
url = '/' + url;
}
return url;
},
});
Is there an easier way to accomplish what I'm trying to do without overriding adapter methods? And if not, what method(s) do I need to override?
Thanks in advance for your help!
You can use this.store.findQueryOne('invoice', 1, { key: value });
https://github.com/emberjs/data/pull/2584

SignalR IUserIdProvider not invoked for userid and connectionid mapping

I am sending userid from javascript while i am making request to signalr as follows:
var userId = "1";
var connection = $.hubConnection("/signalr", { useDefaultPath: false });
var notificationsHubProxy = connection.createHubProxy('NotificationsHub');
connection.qs = "userId=" + userId;
notificationsHubProxy.on('notify', function (notifications) {
notifyAll(notifications);
});
connection.start()
.done(function() {
notificationsHubProxy.invoke('getNotifications', "1,2,3");
})
.fail(function(reason) {
alert('signalr error');
});
Here is the class for implementing IUserIdProvider that retrieves querystring and returns as userId, i debugged and this class and GetUserId method was not invoked by the framework.
public class RealTimeNotificationsUserIdProvider : IUserIdProvider
{
public string GetUserId(IRequest request)
{
return request.QueryString["userId"];
}
}
Here is my startup class for hooking up IUserId provider with signalR configuration:
var userIdProvider = new RealTimeNotificationsUserIdProvider();
GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => userIdProvider);
app.Map("/signalr", map =>
{
var hubConfiguration = new HubConfiguration
{
EnableDetailedErrors = true,
Resolver = dependencyResolver,
EnableJavaScriptProxies = false
};
map.RunSignalR(hubConfiguration);
});
Now, when i try to send notification to a particular User by accessing Clients.User(userId) its not working:
var userId = "1";
Clients.User(userId).notify("test");
what am i missing? Please help.
What you have looks like it should work. The only thing that looks suspicious is that you are registering your IUserIdProvider with GlobalHost.DependencyResolver, but then you have Resolver = dependencyResolver in your HubConfiguration.
There is no other reference to dependencyResolver anywhere else in your question. If you were to leave out Resolver = dependencyResolver, SignalR would use GlobalHost.DependencyResolver by default.
hier is what I did to solve this problem, form me request.QueryString["userId"] did not return user id that is why it did not work, I change your code like below and it does work I tested t on my project:
using using System.Web;
public class RealTimeNotificationsUserIdProvider : IUserIdProvider
{
public string GetUserId(IRequest request)
{
return HttpContext.Current.User.Identity.GetUserId()
}
}
remove var userIdProvider = new RealTimeNotificationsUserIdProvider() and write it like below:
ConfigureAuth(app);
GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => new RealTimeNotificationsUserIdProvider());
app.Map("/signalr", map =>
{
var hubConfiguration = new HubConfiguration
{
EnableDetailedErrors = true,
EnableJavaScriptProxies = false
};
map.RunSignalR(hubConfiguration);
});

Categories

Resources