From within a controller function, how do you delete all the models in an Alloy Collection. The collection is using properties sync adapter. I think the backbone reset method is the way to go but I could not make it work.
The quickest way for me was to run destroy() on every model. To do this quickly you can use underscore (build in) like this:
_.invoke(Alloy.Collections.library.toArray(), 'destroy');
or even extend the model.js
extendCollection: function(Collection) {
_.extend(Collection.prototype, {
// extended functions and properties go here
dump: function() {
// get all models
return this.models;
},
clear: function() {
// remove/destroy all models
_.invoke(this.toArray(), 'destroy');
}
});
return Collection;
}
and run Alloy.Collections.library.clear();
Pro Tip: you can always search for things like delete all models in backbone and use most of the results right away since it is using backbone in the background.
Related
good day, I am using Tucker-Eric/EloquentFilter Laravel.
I want to filter it by relationship using Models
I want to automate it, instead of using the following:
public function users($users)
{
// dd($users);
return $this->r('users', $users);
}
public function user($user)
{
// dd($user);
return $this->r('user', $user);
}
public function owner($owner)
{
// dd($owner);
return $this->r('owner', $owner);
}
I want to make it one function that based on the relationship
so that I want to add another relationship on the model I don't need anymore to add another function.
Thanks!
We specifically stayed away from the type of implicit functionality you're looking for and opted for explicit filter methods to avoid security issues if/when new relations/properties were added to a model they wouldn't implicitly be available to filter against.
With that, what you're looking for isn't recommended because of the security concerns above but it can still exist if you implement it.
It sounds like the setup method would be the best place to implement it since it would be called first every time ->filter() is called.
public function setup()
{
foreach($this->input() as $key => $val) {
if($this->getModel()->$key() instanceof \Illuminate\Database\Eloquent\Relations\Relation) {
// Your logic here
}
}
}
I have an Ember app that, rather than using Ember Data, uses our own custom AJAX data layer to talk to an API.
We're able to load two models at once using RSVP - one is a Project object via our API wrapper, the second is an object representing the logged in user. Both are passed into the controller and templates and work just fine.
But I have a need to load a second model, based on a value in the returned Project object.
Once I've loaded a model in my route like this...
App.ProjectUpdateRoute = Ember.Route.extend({
setupController: function(controller, model) {
controller.set('model', model);
},
model: function(params) {
return Ember.RSVP.hash({
// Load Project from API - /myapi/v1/Project/:ProjectID
Project : App.Project.create().findById(params.ProjectID),
// Load current user from local object
User : App.AuthUser,
});
},
});
...I have a Project object (or rather model.Project) with various properties including the ID of the User that owns the project.
Now I'd like to make a second API call to /myapi/v1/User/:UserID to get the User's details.
Everything I've tried - including adding further App.User.create().findById(UserID) calls into the route's setupController function and the controller - results in the correct API call, but it's asyncronous, so Ember carries on rendering the page and I can't show the result of the API call on the page.
So - how, and where in the Ember structure, do I load a second model based on data from the first? How can I get ember to wait for the resolved promise of this second AJAX call?
UPDATE
I've also tried using afterModel:function() which is almost what I need - it makes the second API call in the right place in the app flow, but I still need to add the result into my existing model array:
afterModel: function(model, tranistion, params) {
// Returns the promise but doesn't update 'model'
return Ember.RSVP.hash({
ProjectOwner : App.User.create().findById(model.Project.UserID)
});
}
Chain the promise, and Ember will take the final resultant (from the model hook)
model: function(params) {
return Ember.RSVP.hash({
// Load Project from API - /myapi/v1/Project/:ProjectID
Project : App.Project.create().findById(params.ProjectID),
// Load current user from local object
User : App.AuthUser,
}).then(function(results){
return App.User.create().findById(results.Project.UserID).then(function(user){
results.projectUser = user;
return results;
});
});
},
I'm writing a front-end to my RESTful API using Backbone... and I'm really enjoying it so far. Learning this framework continues to be super interesting. However, I am now stumped on something that seems like, to me at least, that it should be straight forward.
I now have a single (and only) html page where the main application resides that lists one or more products. And, lets say it resides here: http://localhost/index.html
I would like to be able to switch from the product list view to the new product view (via click event on a button at the top). And that, from what I understand, I need to begin using a router for switching using the pattern described in How to switch views using Backbone.js.
Is view-switching what I need to be doing to achieve this behavior?
This looks hokey: http://localhost/index.html#product/newAnd, since I'm using [tornado](http://tornadoweb.org) as my web server for both my API and static content, I can't just implement a rewrite rule easily. I may switch to using nginx for static content in the near future, but I haven't yet. If I'm to use a router to switch views like when going from Review to Create (of CRUD operations), how do I change the URL/URI to look something more along the lines of thishttp://localhost/product/new
In order to receive hashless url changes, your browser has to support pushstate. If I am not mistaken, Backbone will fallback to using hashes if your browser does not support pushstate. You would initialize your router with the following in order to use pushstate in your application:
Backbone.history.start({pushState: true})
I like #alexanderb's use of view switching. Just MAKE sure when you are changing views, you dispose of them properly. Otherwise you will run into some complex problems that are difficult to debug. Read more here.
Yes, you need 2 things - Router and ApplicationViewManager (some class, that is responsible for changing the view).
define(function () {
var ViewManager = function () {
return {
show: _showView
};
};
function _showView(view) {
if (this.currentView) {
this.currentView.close();
}
this.currentView = view;
this.currentView.render();
$("#app").html(this.currentView.el);
}
return ViewManager;
});
In router, you do something like:
// router
var ApplicationRouter = Backbone.Router.extend({
initialize: function () {
this.viewManager = new ViewManager();
},
routes: {
'': 'dashboard',
'configure/sites/:id': 'configure'
},
dashboard: function () {
var app = require('./apps/DashboardApp');
app.run(this.viewManager);
},
configure: function (id) {
var app = require('./apps/ConfigureApp');
app.run(id, this.viewManager);
}
});
Some code examples, you can take from this repository.
I have a FormView which handles such events as save and cancel. I also have an AjaxFormView that handles save, cancel and get form by ajax. I have an AssetFormView that handles save, cancel, get by ajax, delete, and print.
So on and so forth. there is considerable repitition.
I found a post this post http://kalimotxocoding.blogspot.com/2011/03/playing-with-backbonejs-views.html
where he shows you can extend views. However, I'm finding that when i have multiple versions of views on the page there are properties cross pollinating. Is there no built in way to inherit views in backbone, that is safe?
Thanks,
Raif
* hmmm well, this stuff is pretty thick and my current cross pollination issue may be ( probably is ) the result of some error on my part, but the question still stands, is there not and would it not be an important feature to have, some way to inherit views?
I'd like to see what you mean when you say that your properties are cross-pollenating.
The View.extend mechanism works quite well. Do be aware, though, that you are extending one prototype with new functions. With prototypical inheritance, the prototype shares it's objects with the new instances.
I am guessing that when you say that your properties are "cross-pollenating", you are actually doing something like this:
var baseModel = Backbone.Model.extend({
defaults: {
foo: { bar: "baz" }
}
});
Since the objects are shared, every instance of baseModel ends up having the same object for foo, giving the feeling of cross-pollination.
If instead, you define your defaults as a function, then each instance will get it's own copy of the foo object and your cross-pollination goes away.
var baseModel = Backbone.Model.extend({
defaults: function() { return {
foo: { bar: "baz" }
} }
});
Of course, without code, we can't be certain to what your problem is. Just know that this mechanism has been well-used among the community without trouble. It is safe. You just need to understand what is going on.
I'm not sure if this is the same problem you're having but I wanted to have some events defined in the parent class and then have the child class extend the property without overriding it.
If I did it like this, I was overriding what the parent defined:
App.parent = Backbone.View.extend({
events: {
'click #button-add': 'onAddButtonClicked'
'click #button-delete': 'onDeleteButtonClicked'
}
onAddButtonClicked: function() {
console.log('onAddButtonClicked');
},
onDeleteButtonClicked: function() {
console.log('onDeleteButtonClicked');
}
});
App.child = App.parent.extend({
initialize: function() {
// This looks redundant but it seems to protect App.parent::events
this.events = _.extend({}, this.additionalEvents, this.events);
// THIS IS WRONG and results in errors when I have multiple childdren:
_.extend(this.events, this.additionalEvents); // <-- this seems to change the parent
}
additionalEvents: {
'click #button-additional': 'onOtherButtonClicked'
},
onOtherButtonClicked: function() {
console.log('child:onOtherButtonClicked');
}
});
When extending the parent's events like this:
_.extend(this.events, this.additionalEvents);
I'd get "Uncaught Error: Method 'onOtherButtonClicked' does not exist" because I was modifying App.parent's events field. App.child2 was blowing up because it couldn't see the events that were put there by App.child.
By changing it to:
this.events = _.extend({}, this.additionalEvents, this.events);
I was able to protect the parent.
I have a web site I'm converting to Codeigniter and I want to simplify and decouple. I like what I've read about the Observer pattern for things like "new survey created" (which triggers a new help ticket, which triggers an email, etc).
But how do I implement such a thing in Code Igniter? I see the Symfony component but at this point I'm not concerned about understanding the system as much as figuring out how to use it in controllers and models. I have extended both CI_Model and CI_Controller already for other reasons. Would putting Observer pattern code there be the best?
I imagine a point like this: someone hits the web site and spawns a request which gets routed to a controller/action: http://localhost/test/save_changes
// warning, pseudo-code!
class Test extends MY_Model
{
public function __construct ()
{
// do I put this here?!? - or maybe in MY_Model?
// Should it be a singleton?
$this->load->library('dispatcher');
// where do I attach what I want... here?
$this->load->library('emailer');
$this->dispatcher->attach($this->emailer);
// what if I have 50 possible things that might happen
// based on any given event, from adding a user to
// deleting a survey or document? There has got to be a
// way to attach a bunch of observers that trickle
// down to each object, right?
}
public function save_changes ()
{
$this->load->model('user');
$this->user->init($this->session->userdata('user.id'))->save();
}
}
class User extends MY_Model
{
public function __construct ()
{
parent::__construct ();
// do I put this here?!?
$this->load->library('dispatcher'); // just something to call it
}
public function init($id)
{
if($this->_loadUser ($id))
{
$this->dispatcher->notify($this, 'user.loaded');
}
}
public function save($id)
{
if(parent::save())
{
$this->dispatcher->notify($this, 'user.saved');
}
}
}
class Emailer
{
public function update ($caller,$msg)
{
switch ($msg)
{
case 'user.saved':
// send user an email
// re-cache some stuff
// other things that we might want to do, including more of these:
$this->dispatch->notify('user-saved-email-sent');
break;
}
}
}
class Dispatcher
{
public function notify ($caller, $msg) { ...foreach attached do $obj->update($caller,$msg) ...}
public function attach ($obj) { ... }
public function detach ($obj) { ... }
}
I can see how powerful that would be. But I'm not sure how to simplify the setup and attaching of all of these listener/observers.
Maybe I should have a factory to create them all? It just seems like yes, they would be decoupled from the way it currently works, but it seems managing all the different objects that I'd have to 'attached' in each controller or method would become coupled in a different way.
Thanks,
Hans
Your proposed structure would have to be something like:
$this->load->library('observer_factory', 'of'); // factory for creating observers
// Observer_factory would have knowledge/access to different classes which relate
// to the pattern.
$ync = $this->of->getNotifier( $some_variable ) );
$ync->attach( $this->of->getObserver( $some_other_variable ) );
$ync->attach( $this->of->getObserver( $some_final_variable ) );
$ync->someMethod(); // someMethod calls notify
But I wonder about it. You'd have a factory class that slowly becomes all-knowing. It starts usurping the functionality of the Loader. Why load a library when my Observer_factory can handle it by doing exactly the same thing?
I think you're better off with a library or a model that knows what it is supposed to do and is well designed, then adding this class structure. I do not see the gains outweighing the costs.