Im using the sane stack with mongo db. I'm fairly new to emberjs. I'm using ember 0.2.5 and sails 0.11.0 and mongodb.
I have a game route, controller and model that I can properly access from the game template. I also have a separate player route, controller, model, template setup that I can also access and manipulate properly.
A game has two players, and the player has a logo. Given I have the game data which contains each player id, I basically want to do get the player logo using the player id and display that in the game template.
Ive tried a few things, this is my last attempt to put that logic in the game controller.
//model/game.js
import DS from 'ember-data';
export default DS.Model.extend({
home_player: DS.attr('string'),
away_player: DS.attr('string'),
players: DS.hasMany('players'),
});
//Here's the logic of what I want to achieve
playerLogo: function(playerName){
for (player in players)
if player.name == playerName
return player.logo_url);
}
I've searched a bit I don't see an straight forward answer to this (or a solution I understand).
Thanks
Your model definition of Game has set relationship players: DS.hasMany('players') without setting { async: true }. I assume that you are familiar with the consequences and you set your backend to send game object with nested players relationship. If not, I'll get to it back later.
Assuming that your backend is sending the data properly you can do it like this:
game.get('players').findBy('id', idYouHave).get("logo_url"); # you can find by 'name' also
Remember to always use #set and #get when working with Ember/DS objects. You cannot query or set properties directly.
Ok, but if it's not a problem, but you rather defined the relationship without knowledge what async means, let's take a look. async means that Ember should fetch the related models by ids when they will be needed. Thus, all you get from backend is game object with player_ids table (e.g. player_ids: [1, 2]). These related players are not accessible initially - they still need to be fetched by ember, but only when explicitly needed. Therefore you would have to change your logic to use promises:
game.get('players').then(function(players) {
players.findBy('id', idYouHave).get("logo_url");
});
Remember though, that changing to async is a huge change that in case of big application can take some work to perform. You need to change your API too. However, it is more intuitive and more easy in maintenance than not using async. In long term, when you get a lot of related models, it has better performance.
Related
I'm looking for an answer to what is the best practice to customize default sails.js CRUD blueprints. The simple example of what I mean is let's say I need to create SomeModel, using standard blueprint POST \someModel action, and also I want to get information about authenticated user from req object and set this property to req.body to use values.user.id in beforeCreate function:
module.exports = {
attributes: {
// some attributes
},
beforeCreate: function (values, cb) {
// do something with values.user.id
}
};
I'm very new to sails.js and don't want to use anti-patterns, so I'm asking for inputs on what is the right way to handle such cases. Also it would be great to have some good resources on that topic.
There are a few options open to you which you've identified, and as usual, it depends on your use case. Here are some thoughts on the three options you listed in your comment:
Override controller/create - Of the three, this is the best option because it doesn't clog up code in routes or policies for a single instance.
Write controller/action and add to config/routes.js - While this works, it defeats the purpose of using blueprints, and you have to do all the code in option 1 plus making your routes code messier.
Apply a policy for a single create action - To do this, you will not only have to clutter up your /policies folder but also your policies.js file. This is more code AND it puts the logic for one controller method in two separate places, neither of which is the controller.
Out of these three, option 1 is the best because it contains the code to its context (the controller) and minimizes written code. This is assuming that you only want to alter the create method for one model.
Side note:
As an example of how your use case determines your implementation, here is how I've set my Sails app up which has a few REST routes, each of which responds differently based on the user calling the route (with a valid Facebook token):
Only uses blueprint action routes (not blueprint REST routes)
First goes through the policies:
'*': ['hasFBToken', 'isTokenForMyApp', 'extractFBUser', 'extractMyAppUser'] which store fbuser, myappuser, and other variables in req.body
At this point, my controller function (e.g. controller.action()) is called and can access information about that user and determine if it has the correct permissions to do CRUD.
Pros of this system:
All code for each CRUD operation is contained within its controller function
Minimal to no code in routes.js (no code) or policies.js (one line) or /policies
Works well with API Versioning (e.g. controllers/v1.0/controller.js), which is much easier to do with versioned controllers than versioned models. That means that I can create a new API version and simply by creating a controller in /v2.0 with a function action(), calls such as POST /v2.0/controller/action will exist with no extra routing needed.
Hopefully this example helps illustrate how design decisions were made to offer functionality like API versioning and consolidate code in its specific context.
I would like to create multiple game instances.
Currently, on the client side a game template is rendered
Template.game.rendered = function () {
graph = new Graph("#graph", nodes);
};
//
function Graph(selector, nodes) { //code here };
This give me a single game instance. Now I would like to create more game instances, hosted in a 'lobby'.
For this I have a collection.lobby.
id,
host,
players,
status,
invitedplayers,
url
This functionality works: I can set the collection values and retrieve them under the assigned url.
Now I need to create a new game instance with this.
I think that I need a Meteor.method that 'renders' a new game container at the specified url. Is this correct ?
How do I have to combine these elements ?
There is enough sample code on github, but everyone does this a little different, so that I have not been able to analyze and understand how to do it.
The answer seem so be here Loading templates with iron router
Ed Die,
If you take a look through the full api documentation for Meteor, and search for the keyword "chat", you'll find examples of chat-room instances being created, which seems very similar to what you're trying to accomplish.
You may or may not need to have a unique url routed, for example www.mygame.com/game/MONGO_ID_HERE or a different generated ID.
The approach could be that each game url or session id get's stored into the database, that game's session data get's stored into that document, and when someone is playing the game, they get assigned that session's id until the game is over.
I hope this helps.
I was wondering what the best practice or convention is when creating stores in Flux when working with an API
Let's say we have a list of 'projects', the API call would eventually fill a Store called ProjectStore in _projects
Then, when a user selects a project, you want to load the Project specific data. Would you add this to the same ProjectStore as _activeProject, or create a seperate Store for it?
Same for when you load the Todo's within that Project. It would make sense to put these in a TodoStore, but what about a specific Todo within the Todos within the Project?
I hope the above makes sense :)
I would use the ProjectStoreto store both _projectsand _activeProject.
I have done as a rule in my React projects to create a new store for each model.
For instance: Let's say that I have an application that serves messages and accounts. I would then have a MessageStoreand an AccountStore. Then use these accordingly to their domain.
E.g., when I want to get some messages from the backend (through an API), I store them in the MessageStore. The same goes for the AccountStore.
As your project becomes larger and larger, you would probably have to reconsider refactoring something into a new store. For instance, if you want to add advertisement to your site, you could create an AdsStore.
My rule of thumb is to try to separate stores by their domain, but don't make the structure more complex than it has to be.
Hope that helped.
I'm having a tricky issue with my models and Sails' automatic blueprint matching.
When I post to one of my endpoints, /answer/create, I get a 500 response with validation errors for a different model entirely (the event model).
That endpoint for the event model would be at /event/create, but when I post to that I get a 404.
All of my files were generated with sails generate [model] and don't contain any custom Controller routes.
Has anyone seen this before?
It turned out this was a result of following this screencast:
http://irlnathan.github.io/sailscasts/blog/2013/09/15/sailscasts-answers-ep1-question-about-using-a-service-to-allow-inheritance-in-a-model/
I was inheriting a baseModel via services into more than one other model, so when I ran _.merge(), the changes it made would persist across them both, rendering inconsistencies.
If you want to do this, make sure you use the _.cloneDeep method to clone the base model, otherwise _.merge will affect it and your blueprints/actions won't work as expected.
In the screencast above, this would make line 12 in the user model look like this:
module.exports = _.merge(_.cloneDeep(baseModel) { ... });
I am writing a module based javascript website, backed by a Mysql DB.
Each module talks with the DB through PHP.
On the UI, for simplicity, the module on the left will display all relevant rows, with edit(write) functionality. The module on the right display the data from the same DB, with write access too.
So each would affect the other in each update.
I'm told backbone would be a good framework. Then, I have read the todos example, and understand how there are item->itemList, view->viewList, etc...
But now, the question is, how do I apply it to this situation?
Which is an item, a view in this situation?
The module on the left and the module on the right are Views, each of which can be made up of other views.
Within the model don't store a reference to the view (as I've seen done in some of the examples):
this.view = view; //view being passed in as an arg
The reverse (a view storing a reference to a model) is okay. Your views should be doing most of the work, listening to and responding to model events. Thus, in the view initialize method you might:
model.bind("interesting-event", function(){
//the view updates/reacts to the model.
});
Also, never add a model to two collections (just one ever). When a model is assigned to a collection, Backbone sets a reference on the model that points to the owning collection.
Incidentally, the a-model-cannot-belong-to-two-collections issue is the reason why you don't want a model referencing its view. A model can have many views on one screen.
Backbone is perfect for your needs. Start with a very basic version of your app and keep fleshing it out. All the while keep reading about Backbone online. I read everything I could find (there's not a whole lot, not really). The key concept is simply event based programming (much like you'd use in VB or lots of other platforms). It's a lot of trial and error, but you'll make sense of it with practice.