Slim route groups not working as expected - slim

In my code I am doing something very similar to the following (from the slim docs). My expected behaviour is that groups restrict the route scope to within that group e.g. /library/books is not the same as /books. However, I'm finding in my code that the group method is not restricting the route as expected and for example the route for /admin/tours is being called even when I go to /tours. Is there something I am missing? The docs for group on the homepage (www.slimframework.com) of the slim website are different from the documentation website (http://docs.slimframework.com/routing/groups/).
$app = new \Slim\Slim();
// API group
$app->group('/api', function () use ($app) {
// Library group
$app->group('/library', function () use ($app) {
// Get book with ID
$app->get('/books/:id', function ($id) {
});
// Update book with ID
$app->put('/books/:id', function ($id) {
});
// Delete book with ID
$app->delete('/books/:id', function ($id) {
});
});
});
Further example
$app->group( '/admin', function () use ( $app , $twig) {
$app->get('/tours', function() use ($app){
print_r('do tours admin');
});
});
$app->get('/tours', function() use ($app){
print_r('do tours');
});
my behaviour is that /tours is still routing to /admin/tours

It seems like a bit of a simple solution but ordering the registering of the /tours route before the /admin/tours route sorted it.

Related

MongoDB: can't return random document from collection

I'm working on a word game and am trying to return a random wordpair (my collection) on a page load. I'm using Express and have adapted my code from this tutorial if that's of any use.
A GET request renders my page just fine, and I'm trying to send a random WordPair object alongside the title:
router.get('/', function(req, res, next) {
res.render('play', { title: 'play', random_wordpair: wordpair_controller.wordpair_random});
});
The wordpair_random function is here inside a controller file I've made (which also successfully manages listing the wordpairs and creating new ones etc).
// Get random WordPair
exports.wordpair_random = function() {
WordPair.aggregate(
[{
$sample: {
size: 1
}
}]
)
.exec(function(err, random_wordpair) {
if (err) {
return next(err);
}
console.log(random_wordpair);
return random_wordpair;
});
};
Then inside a play.pug template, I'm simply trying to display this result:
h3 random wordpair selection is: #{random_wordpair}
But all I can see is the function rendered as HTML text. Can anyone tell me what I'm doing wrong?
I also understand looking at the documentation for MongoDB $sample aggregation that I need to be calling my function on the database object, but I've seen various examples and some don't do this. When I try calling db.wordpair.aggregate(...) (or WordPair or wordpairs as it appears in mLab) directly after initializing db in my app.js file, I get undefined errors. My db object doesn't seem to contain the correct data for this request.
Thanks!
I guess you're writing this in Node.JS. A core feature in Node.JS is non-blocking IO model. That means, the code won't wait for a database call to complete to move on.
Another concept you need to get it right is that Node.JS, being a variation of JavaScript, in nature is a functional programming. Assigning a function to a property of a JSON object like below won't cause the function to execute. It simply creates a pointer to the function body, that's why your application prints the function itself.
{ title: 'play', random_wordpair: wordpair_controller.wordpair_random}
To fix this, use a callback
exports.wordpair_random = function(callback) {
WordPair.aggregate([$sample: {size: 1}}]).exec(callback);
};
Then in you web function:
router.get('/', function(req, res, next) {
wordpair_controller.wordpair_random(function(err, result) {
//Handle errors if needed.
res.render('play', { title: 'play', random_wordpair:result });
})
});

Handle different method request in slim framework 3

Hey i am learning slim framework 3 it may be a newbie question,
in the documentation i see a way to kind of group the request using map() like this
$app->map(['GET', 'POST'], '/books', function ($request, $response, $args) {
// Create new book or list all books
});
How do i handle each request, say i wanna handle GET request where do i put the logic in my controller?
i have tried to work around it using this :
//category routes
$app->group('/category', function(){
$this->get('', 'CategoryController:getCategories');
$this->post('', 'CategoryController:insertCategory');
});
and it worked just fine, but still how do i handle it ?
When the GET and POST handling is different, I would prefer your working approach.
With one route for multiple methods you need to manually check for POST/GET (when something different should be done).
$app->map(['GET', 'POST'], '/books', function ($request, $response, $args) {
$method = $request->getMethod();
switch($method) {
case 'POST':
// insert category
break;
case 'GET':
// get categories
break;
default:
return $response->write('Could not handle request');
}
});

How to redirect a user when the published cursor gets emptied?

I'm publishing a cursor that outputs just one document inside of it:
Meteor.publish ( 'test', function () {
return MyCollection.find ( 'DocumentMongoDBID' );
}
And I'm subscribing to it from the router (using iron router):
Router.route ( '/thepage', {
...
subscriptions: function () {
this.subscribe ( 'test' ).wait ();
}
}
I want to redirect the user to another page if the document gets deleted, hence if the cursor is empty.
How can I get a function invoked when this happens so that I can redirect the user? All the template's helpers that rely on that subscription gets called, but I'd prefer to have another function called before of them, that will eventually redirect the user.
Maybe try using LocalCursor.observeChanges on the client-side ?
Meteor.startup(() => {
MyCollection.find('DocumentMongoDBID').observeChanges({
removed(){
// redirect the user
Router.go(...);
}
});
});
https://docs.meteor.com/#/full/observe_changes

EmberJS: How to Redirect from Route, Keeping Query Params

I want to redirect from a route, /new, and keep the query params for the new route:
As far as I know, the only place to access queryParams is within the model hook of a route.
But I want to redirect in the beforeModel hook:
import Ember from "ember";
export default Ember.Route.extend({
/**
* ##override
* Implicitly create a new applicant, redirecting to the generated ID at /applications/#{id}
* #param transition
*/
beforeModel: function(transition) {
var emptyApplicant = this.store.createRecord("applicant",
{isPrimary: true}
),
emptyApplication = this.store.createRecord("application");
emptyApplication.set("applicant", emptyApplicant);
emptyApplicant.save().then((savedApplicant) => {
emptyApplication.save().then((savedApplication) => {
this.transitionTo("applications", savedApplication);
});
});
}
});
While the above code works, the transition will complete without preserving the query params. For example, navigating to applicants/new?agent=35 will not preserve agent=35 in the query param, and will simply redirect to applicants/new instead.
How can I access the queryParams object from the beforeModel hook in my Ember app?
You should be able to pass query parameters to the transitionTo, something along the line of:
this.transitionTo("applications", savedApplication, {
queryParams: transition.queryParams
});
In more modern versions of Ember, the transition object has a to property which contains the query params. Transition no longer has a queryParams property
A redirect to the index route in a beforeModel for example, might look like this:
beforeModel(transition){
super.beforeModel(...arguments);
transition.abort();
this.transitionTo('index', {
queryParams: transition.to.queryParams
});
}

$.event.trigger not firing in non-DOM object

var test = { }
$(test).on("testEvent", function (){
console.log("testEvent has fired");
});
$.event.trigger("testEvent");
I am trying to using jQuery to do a publish/subscribe mechanism using events. I need to be able to attach events to non-DOM objects and be able to have them all fire from a single global trigger. I expected the code above to work but it did not result in the testEvent firing for the test object.
Note that there will be multiple objects in which an event will be subscribed to. A single $.event.trigger should fire all of those events.
Do note that this code works fine:
$('#someID').on("testEvent", function () {
console.log('testEvent has fired from DOM element');
})
$.event.trigger("testEvent");
After doing some research it appears as though jQuery 1.7 provides an easy way to introduce a publish/subscribe mechanism. (found here) In order to have a publish/subscribe mechanism the following code can be used:
(function ($, window, undefined) {
var topics = {};
jQuery.Topic = function (id) {
var callbacks, method, topic = id && topics[id];
if (!topic) {
callbacks = jQuery.Callbacks();
topic = {
publish: callbacks.fire,
subscribe: callbacks.add,
unsubscribe: callbacks.remove
};
if (id) {
topics[id] = topic;
}
}
return topic;
};
})
In order to subscribe to an event the following is done:
$.Topic("message").subscribe(function () {
console.log("a publish has occurred");
});
In order to publish a message the following is done:
$.Topic( "message" ).publish(data);
"Message" is the event name. The data argument contains any information you want passed to the subscribers.
In order to unsubscribe you must pass the function that was subscribed:
$.Topic( "message" ).unsubscribe(funcSubscribedToBefore);
In modern browsers (If I've read the source for Underscore.js right) allow you to bind events to non DOM objects natively. Otherwise, you'll have to use something like underscore's .bind function. So it depends upon what browsers you need to support.
Edit:
Ok, nevermind, I was thinking bind in Underscore.js is the same as with Backbone. Backbone has it's own events module that does event binding, apparently.
binding events to dynamic objects in underscore/backbone
I recently used Ben Alman approach, and it worked great!
/* jQuery Tiny Pub/Sub - v0.7 - 10/27/2011
* http://benalman.com/
* Copyright (c) 2011 "Cowboy" Ben Alman; Licensed MIT, GPL */
(function ($) {
var o = $({});
$.subscribe = function () {
o.on.apply(o, arguments);
};
$.unsubscribe = function () {
o.off.apply(o, arguments);
};
$.publish = function () {
o.trigger.apply(o, arguments);
};
}(jQuery));
Usage:
$.subscribe('eventName', function (event) {
console.log(event.value);
});
$.publish({ type: 'eventName', value: 'hello world' });
See https://gist.github.com/addyosmani/1321768 for more information.