So I've dived into Backbone.js framework and I've finally came to the point where I play with models/collections.
Here's the thing. I'm using localstorage as database and my problem is I'm not statisfied to see my ids look like this:
id : "53ec77a0-8b06-c31b-d72c-a350741898d0"
Is there a simple solution to set the id's to a more proper look, like 1, 2, 3 or even like the cid. I've tryed it out with cid but it isn't good either because it changes everytime you fetch the data from localstorage...
Thanks in advance!
/Haris
Hmmm, I am not sure why you'd want to do that, it's really the adapter's job to define the IDs, and ensure their uniqueness, not yours!
If you look at the code of backbone's localstorage, you can see the line that is creating your issues here:
create: function(model) {
if (!model.id) {
model.id = guid();
model.set(model.idAttribute, model.id);
}
...
}
So, two ways to go about that:
Fork backbone localstorage to replace the call to guid() (which just generate random ids, it doesn't try to ensure uniqueness) by something nicer.
Give your own ID before calling save(). For the localstorage, it's kind of acceptable since there are no real constraints on the ids, but then it becomes your job to make it unique, especially across multiple running of your app [closing+reopening the browser] (you can keep the lastId in your local storage and increment it every time, to make it behave like a Primary Key with AutoIncrement in a DB, I guess)
Related
As a laravel user for a couple of months now, I'm trying to better understand advanced use of Eloquent.
I ran into a case where I can't come up with a solution that feels right.
I've got the following structure (simplified)
Mandate
id
status_id
Mandate_user
mandat_id
user_id
link_status
User
id
I declared belongsToMany in both User and Mandat via the pivot table.
on User:
public function mandates(){
return belongsToMany(..)->withPivot('link_status');
}
I'm able to get accepted mandates for a user by using
public function acceptedMandates(){
return $this->mandates()->wherePivot('link_status', MandateUserStatus::Accepted);
}
This works but I'm wondering if there would be a better way by using scopes or other eloquent methods.
And I'm trying to get accepted mandates that also have a status_id lower than 4 (which comes from an enum as well)
I thought of something like :
public function runningMandates(){
return $this->acceptedMandates()->where('status_id','<', 4);
}
Then gathering mandates like so:
$mandates = User::find(1)->runningMandates();
But would the eloquent way be of doing something like:
$mandates = User::find(1)->mandates()->running()->accepted();
Thanks for your time.
It's a very subjective question and hard to give a straight answer to, but hopefully I can stop you from second-guessing yourself: what you're doing is perfectly fine and no less "eloquent-like" than the other.
Personally I like what you're doing now much more than what you present as the "Eloquent way" and have done so before in professional projects, but ultimately there is a difference in the way you design the code for a framework or package, which must be flexible to account for many different scenarios, most of which you cannot even envision when doing version one, versus how you design the code for an app which will only be consumed by itself. If you know the business logic that drives your app and the views it will present to its users (subsequently, the queries it must perform), why wouldn't you create methods that will easily achieve just that?
Eloquent relies on chaining not just because it's cool, but because it does not know (or care to know) what your business logic is. To me, the "Eloquent way" is more about fluent, readable code, and I find that $user->runningMandates is more readable than $user->mandates()->running()->accepted()->get().
I also find that the first approach is easier to get into. If you're constantly forcing yourself to separate methods so they can be chained, it can be harder to grasp which method is doing what and which method relies on which. Query scopes can modify the query as they like (join, alias, etc) so the danger lies in one method requiring another to come first, because you're conditioning based on a table or column that isn't on the original query, so a method will only work in conjunction with another; or maybe two methods are trying to join the same table, or using the same aliases, so they cannot be used together. It may seem far-fetched, but often the effort to keep things separate and tidy will make your code harder to use. But even if things don't blow up code-wise, the deal-breaker to me would be neglecting business logic: in your case, does it make sense to have two separate scopes for running and accepted? Can a mandate be running if it's not accepted? If not, you should try to prevent a less knowledgeable developer from creating that flawed query (logic-wise). And as you said, the structure is simplified so there may be other gotchas lurking around, and many more will come as the app grows in complexity.
If I'm taking over someone else's code, I'd rather have limited, self-contained methods that don't break over simple, decentralized methods that require you to read (often non-existent) documentation in order to prevent the many ways in which to mis-use them.
Basically, scopes add constraints to the query so you may use the scope approach to modify the query by calling scope methods that will eventually give you a chance to make a query dynamically. So, you may declare (as you did) one relationship method where you may do all the query and call that specific method or use scope methods two build the query using method calls where each method adds a constraint. In this case, it'll be more dynamic but still it's a preference and it gives you more flexibility (IMO). So yes, you can use query scopes for that, for example:
// Declare the main relationship
public function mandates()
{
return $this->belongsToMany(..)->withPivot('link_status');
}
Now, declare query scope for accepted (add a constraint on the query returned by mandates method call)
public function scopeAccepted($query)
{
return $query->wherePivot('link_status', MandateUserStatus::Accepted);
}
Now, add another query scope for running, for example:
public function scopeRunning($query)
{
return $query->where('status_id','<', 4);
}
Now, if you call something likethe following:
$user = User::find(1);
Now, call the relationship method (not as property)
$mendates = $user
->mandates() // The method is called and a query object is constructed
->running() // Add another constraint into the query: ->where('status_id','<', 4)
->accepted() // Add another constraint into the query: ...
->get(); // Finally, execute the query to get the result
Probably, it's clear to you now. Notice the method call mandates(), it's a method call on the relation defined which returns the Query Builder and by chaining additional scope method calls, you are just modifying the query by adding some more constraints but you can do all the query in one method without dynamic scopes, so it's up to you. While, scopes gives you more flexibility but it doesn't mean you've to follow this approach always, it depends.
I'm using hood.ie for a web app I'm making. I like the simplicity of it however there's something I'm not too sure about.
When retrieving data from the couchDB there is a method: findAll - which as an example looks like:
hoodie.store.findAll('todo')
.done(function(allTodos) {
//do something with allTodos
})
What I was wondering/don't really like is the fact that I'm getting all the items of type todo then filtering down once I have e.g. todo with todays date.
Instead of getting all of them, is it possible to just get ones I actually want.
I know there is a find method but that requires an id which i won't have.
Or do i simply not need to worry about this - is the call to get all data not that expensive (if i had 1000+ records I feel it may be).
Any guidance would be appreciated.
Thanks.
You don't need to worry about it.
Hoodie stores all data in your browser, from where it also retrieves the data, it does not send any requests to CouchDB in the background when you call hoodie.store.findAll('todo')
In future, this particular call will become more efficient as Hoodie will use indexing by object types, but unless you have thousands of objects per user, you shouldn't even see the the difference
I have an app that tracks and displays various stats for a local athletic league. One of my requirements is to be able to break down stats by game type, league id and location id. The user picks a value for each of those 3 items and then goes off to view various stats with the 3 variables stored in a session. This works fine, but my problem is that users can't link back to whatever stats they were viewing. I know I can extend the life of the session, but I'd rather pass the state of those 3 variables around in the URL so I can have the ability to link back to any specific stats page with any or none of those 3 variables defined.
Query strings seem like an obvious way to do this, but I can't tell if there's any way for me to 'automatically' append the query string to all links generated in the app, or if I manually need to go through and add the querystring parameters wherever I generate a link or do a redirect. That seems like the brute force approach and I feel like there must be a better way to do this sort of persistence that I'm missing. Any help appreciated!
For a number of reasons (linking, SEO...etc), use a URL, not sessions/cookies. And instead of IDs, use slugs instead:
www.mysite.com/league/football/youth/newyork
I'm sure there are many different ways to keep the url vars consistent across the board, but the way I can think to do it would be the following:
You can use Cake's route functionality to set each item to a variable and make nice looking URLs
In your AppController's beforeFilter(), set the Session of each item (type, league, location)
Make a custom MyHtmlHelper
in it, check if your Session for each contains data, and if it does, append to every link that needs it (could use only for specific controllers, actions...etc)
I hope there's a simpler way, but that's all I could think of offhand.
I'm trying to save an object and verify that it is saved right after, and it doesn't seem to be working.
Here is my object
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
#Entity
public class PlayerGroup {
#Id public String n;//sharks
public ArrayList<String> m;//members [39393,23932932,3223]
}
Here is the code for saving then trying to load right after.
playerGroup = new PlayerGroup();
playerGroup.n = reqPlayerGroup.n;
playerGroup.m = reqPlayerGroup.m;
ofy().save().entity(playerGroup).now();
response.i = playerGroup;
PlayerGroup newOne = ofy().load().type(PlayerGroup.class).id(reqPlayerGroup.n).get();
But the "newOne" object is null. Even though I just got done saving it. What am I doing wrong?
--Update--
If I try later (like minutes later) sometimes I do see the object, but not right after saving. Does this have to do with the high replication storage?
Had the same behavior some time ago and asked a question on google groups - objectify
Here the answer I got :
You are seeing the eventual consistency of the High-Replication
Datastore. There has been a lot of discussion of this exact subject
on the Objecify list in google groups , including several links to the
Google documentation on the subject.
Basically, any kind of query which does not include an ancestor() may
return results from a stale view of the datastore.
Jeff
I also got another good answer to deal with the behavior
For deletes, query for keys and then batch-get the entities. Make sure
your gets are set to strong consistency (though I believe this is the
default). The batch-get should return null for the deleted entities.
When adding, it gets a little trickier. Index updates can take a few
seconds. AFAIK, there are three ways out of this: 1; Use precomputed
results (avoiding the query entirely). If your next view is the user's
recently created entities, keep a list of those keys in the user
entity, and update that list when a new entity is created. That list
will always be fresh, no query required. Besides avoiding stale
indexes, this also speeds up your app. The more you result sets you
can reliably manage, the more queries you can avoid.
2; Hide the latency by "enhancing" the query results with the recently
added entities. Depending on the rate at which you're adding entities,
either inject only the most recent key, or combine this with the
solution in 1.
3; Hide the latency by taking the user through some unaffected views
before landing on your query-based view. This strategy definitely has
a smell over it. You need to make sure those extra steps are relevant
to the user, or you'll give a poor experience.
Butterflies, Joakim
You can read it all here:
How come If I dont use async api after I'm deleting an object i still get it in a query that is being done right after the delete or not getting it right after I add one
Another good answer to a similar question : Objectify doesn't store synchronously, even with now
I have a User object that, upon successful authentication, is tucked into the session (sans security info) for easy recall and for determining whether we have an authenticated user or anonymous session. There are several paths by which the user can alter some or all of his or her information and I'd like to keep that session value up to date. The obvious answer is to update the value in the afterSave() callback, but that, of course, violates MVC.
Is there another way of capturing every change in one place so that I don't have to drop session writes all over the place? I can't think of anything, nor have I been able to find any other ideas. Am I the only person trying to do something like this?
Thanks.
Final Solution: I marked neilcrookes' response as the answer, frankly, because there doesn't seem to be the better way. Since this way violates my OCD senses, though, I took a slightly different path. I decided to have my User::authenticate() method return the authenticated user object to the caller so it can do whatever it wants with it. One of the things that the callers "want" to do is to drop that value in the session. It's redundancy, but it's very, very limited. In my mind, that felt better than accessing the session from the model (though it's certainly a damned if you do, damned if you don't scenario).
//in users controller
if ($this->User->save()) {
$this->Auth->login($this->User->read());
$this->Session->setFlash[.. etc]
And for the record, I do not agree with the answer of neilcrooks, but I will refrain from feeding the troll.
Some might disagree but I'd screw MVC, do it in Model::afterSave() and use $_SESSION - test for the session before writing to it, in case it's not started for example you are saving against the model in a shell or something.
MVC is a general pattern - a guideline, you can bang your head against it trying to figure out how to achieve something that doesn't quite fit, or just do it another way and move onto to something more important.
Bring on the flames.
after save
Use Like this
$this->Session->write('Auth.User.mmid', $kinde['Kindle']['id']);
You should be able to just use AppController to create the necessary callback(s) that keep your session data up to date. So, for instance, you could have your User model afterSave() set a property called changed to true. Then in your AppController->afterFilter() you check that property and update the session data as necessary.
Alternatively, you could write a component through which to update your user info and also your session data. Then any controller that needs to change user info just needs to include that component.
There's no need to write redundant code or break MVC.