facultycreative / ngactiveresource Goto Github PK
View Code? Open in Web Editor NEWConnects business objects and REST web services for Angular.js
Connects business objects and REST web services for Angular.js
The following comes to mind, assuming a model called Sensor
Sensor.all(); // alternate way to write Sensor.where({})
Sensor.show(1); // alternate way to write Sensor.find(1)
What other methods would be good to add?
Currently the find
methods limitation to a single object and lack of show
method hinder proper API integration.
The following API schema is expected:
GET /resource Index page, lists all resources, returns array
POST /resource Create a new resource
GET /resource/{id} Get a single resource by id, returns object
PUT /resource/{id} Update a single resource by id
DELETE /resource/{id} Delete a single resource by id
GET /resource/find Finds many resources that match query params, returns array
However ngActiveResource deviates from this pattern which creates the following limitations:
id
from query params, rather then getting id
from the url itself.find()
, which you would expect to return an array in some cases, always returns a single object. This limits queries such as posts/?published=true
.This would require refactoring the methods find()
and where()
which would need to be discussed.
Active-support.js is ~236kb (> active-resource.js ~115kb) and is not commonly used in apps.
Is it possible to have a leaner replacement for active-support? (inflectionjs)
I'm using lodash and async in other parts of my app so having it as a dependency for active-resource is not much of an issue.
Overall, this is an amazing plugin. Love the functionality it provides to an angular app.
I would love to use this library but I'm have a lot of issues working with it. One of the biggest problems is the inconsistency between the README and the example code.
For starters, the only dependency mentioned is lodash
, yet it also seems to require active-support
and async
to run, and also downloads meld
(though it doesn't appear to require this).
The README also shows a completely different syntax for declaring models from the example code. I'm finding I can get one way to work at runtime but fails at testing and the other works for testing but fails at runtime.
There are a lot of desirable features in this library but right now it's a bit messy to use and that's holding me back from actively working with it. If you have some time please give the docs and examples some love, thanks!
Hey @brettshollenberger,
I have made some contributions & pull requests regarding the addition of new features and think this may have been a mistake, at least for the time being, because I've been very busy at work and haven't had the chance to follow these up yet. That's not the only reason I think they were a mistake, I also think time would be better spent standardising and polishing off existing features while improving the documentation as well. Anyway, if you don't mind I'm going to put the sideload and custom serializer issues to the side temporarily (anybody else is welcome to work on them). Instead I was thinking a few PRs regarding simplifying code and adding documentation/comments where
neccessary.
What do you think? Feel free to tell me to gtfo, I just feel solidifying existing features is better than adding new ones that could break things. If you're game then maybe we can create a issue listing all the things relating to a tidy up.
Is there a way to force the .hasMany() relationship to use URL parameters and not query strings?
My Rest API wants the parameters in the form:
/API/Incident/Activity/:ProblemID
which resolves to...
/API/Incident/Activity/2
I can correctly call the model directly by passing in the correct named parameter, but the automatic association of parent-to-child is always called with the query string like:
/API/Incident/Activity?problem_id=2
I'm trying to recreate the Post/Comment sample in a codepen but I'm getting the error "Uncaught TypeError: Cannot read property 'downcase' of undefined". And I can't find the cause. I want to know if i'm doing something wrong?
The error happens on line 278 in active-support.js because the string is empty (""). I think it has something to do with the relations because when I comment out this.hasMany('comments')
the error doesn't occur.
Because I don't see it in the API class definition; and using e.g. Node.all() to return all resources for the model Node gets a 404 error.
The "Problem" model (see code below) works when it is stand-alone, but as soon as i attempt to establish a "this.hasMany" relationship with the "Activity" model I get the following error.
TypeError: Cannot set property 'problem' of undefined
at Function.<anonymous> (http://localhost:8000/lib/js/ngActiveResource/ng-active-resource.js:1669:50)
at http://localhost:8000/lib/js/lodash/lodash.js:912:25
at Function.forEach (http://localhost:8000/lib/js/lodash/lodash.js:3307:15)
at Function._this.new (http://localhost:8000/lib/js/ngActiveResource/ng-active-resource.js:1667:13)
at Function.Associations.get (http://localhost:8000/lib/js/ngActiveResource/ng-active-resource.js:698:20)
at transformSearchTermsToForeignKeys (http://localhost:8000/lib/js/ngActiveResource/ng-active-resource.js:1194:41)
at generateGET (http://localhost:8000/lib/js/ngActiveResource/ng-active-resource.js:1242:32)
at Function._this.where (http://localhost:8000/lib/js/ngActiveResource/ng-active-resource.js:1709:18)
at Scope.$scope.load (http://localhost:8000/js/controllers.js:113:17)
at http://localhost:8000/lib/js/angular/angular.js:10347:21
Please can you guide me as what the problem might be (API?, primaryKey?)
This is my model definition.
angular.module('opsCentralApp.models', ['ActiveResource'])
.factory('Problem', ['ActiveResource', function (ActiveResource) {
function Problem(data) {
this.number('ProblemID');
this.number('PortalID');
this.string('Title');
this.string('Status');
this.string('Priority');
this.string('CreatedDate');
this.string('ProblemStart');
this.string('ProblemResolved');
this.string('Category');
this.string('Service');
this.string('SubService');
this.hasMany('activity');
}
Problem.inherits(ActiveResource.Base);
Problem.primaryKey = "ProblemID";
Problem.api.set('http://myurl/API/Incident');
Problem.api.indexURL = 'http://myurl/API/Incident/Problem';
return Problem;
}])
.factory('Activity', ['ActiveResource', function (ActiveResource) {
function Activity(data) {
this.ActivityID = data.ActivityID;
this.ProblemID = data.ProblemID;
this.UserName = data.UserName;
this.UpdateTime = data.UpdateTime;
this.Description = data.Description;
this.belongsTo('problem');
}
Activity.inherits(ActiveResource.Base);
Activity.primaryKey = "ProblemID";
Activity.api.set('http://myurl/API/Incident');
Activity.api.indexURL = 'http://myurl/API/Incident/Activity/[:ProblemID]';
return Activity;
}]);
Saving individual instance is good for one set of applications. But data heavy applications would benefit from saving multiple rows at once rather than one at a time. Any plans of doing this?
Since Sensor.cached.length
doesn't work as expected, let's create a method that abstracts Object.keys whatever.
Love the project, not sure if anyone is actively working on issues. I am seeing that this library does not work with IE at all due to the use of the ECMAScript6 function.name which is not supported at all by IE. I see 17 instances of klass.name in the source code.
Any plans on updating this so that it will work with IE?
Cheers
I keep getting the following error:
ReferenceError: djson is not defined
Any idea why? Is there a dependency that I haven't included somewhere?
Hey,
I've been digging through base.js and I can't seem to find anything related to registering a custom serializer.
I'm asking because my model's data is within the data key of the following response example:
// multiple resources
{
"data": [
{
"id": 1,
...
},
{
"id": 2,
...
}
]
}
// single resource
{
"data": {
"id": 1,
...
}
}
Does this feature already exist? If so how can one override the default behaviour? If not I'd be more than happy to help if you think it's possible.
Where is the hyphenate method supposed to be defined on the string? What lib are you guys using that I have forgotten to include?
I was wondering if any of you know how ngActiveResource compares to restangular?
https://github.com/mgonto/restangular
It seems like a pretty robust solution to the same problem? Any thoughts would be appreciated.
Is it possible to create an association from one model to another but leave out the reverse?
For example I have an Analysis
and a Frame
.
(1) Each Analysis
hasOne
(or belongsTo
a) Frame
.
(2) Each Frame
hasMany
Analyses
.
I don't want to create the second association where each Frame
hasMany
Analyses
. Can I accomplish this?
I love this project, but there has not been any changes since september. Starting a new, long-term project and don't want to use ActiveResource if it is no longer maintained...
Our rails API returns a root element in the response:
{ user: { id: 1, username: "user1" } }
Is there a way to tell ngActiveResource to parse the data correctly?
Sorry, I tried to figure this one out by searching through your sourcecode but I had no luck.
Any idea what I've forgotten to get this error.
The way the function mixinProp is currently being defined in the provider ARMixin doesn't work with firefox.
Firefox isn't hoisting mixinProp() as its being defined within a for loop and it is causing the following error:
Error: mixinProp is not defined
Please see gist and plunkr(open in firefox vs. open in chrome) to see the differences in hoisting
https://gist.github.com/jamesjtong/10272048
http://plnkr.co/edit/qrEuUUzDcwWjQFYILsaC?p=preview
Hi,
Is there a facility to add a custom server connection method to an ngActiveResource Entity?
for instance a more robust /search endpoint that could accept JSON POST payload of parameters (instead of the built-in where() call)?
Also is there a way to push into the ngActiveResource object cache entities that were loaded with a different $http call?
thanks
Consider the following case:
GET
request to findURL which is getSensorList.do?id=1
.id === 1
because the API didn't recognize that the query params and incorrectly returned the complete list.In the above case, YES the API should be a bit smarter. However ngActiveResource could be smarter itself and intervene between step 3 and 4:
3a. find()
attempts to match from the new cache that was created by the GET request.
Basically, by doing one more check after a GET request which generates a new cache we could provider a more consistent interface.
Is there currently a way to set custom headers for the API requests?
This is a nice project. I am really hoping I can use it.
If you append a trailing slash to the url like you do in this function:
function appendSlashForQueryString(url) {
if (url.slice(-1) == '/') return url;
return url + '/';
};
It seems to prevent developers from using custom query string parameters like so.
Dashboard.api.showURL = 'http://localhost:8000/api/dashboards/:id/?embed=:embed';
Dashboard.find({
id: $routeParams.id,
embed: 'widgets,users'
}).then(function (dashboard) {
// ...
});
Which results in the following http://localhost:8000/api/dashboards/1/?embed=widgets,users/
I can't speak for others but I sometimes need to pass query string parameters to my server, maybe to paginate results or to define what resources to embed. If the trailing slash isn't necessary I can send a pull request your way.
How come you're removing :
from the url here? It only seems to remove my port number.
url = url.replace(/\:\w+/, '');
I didn't want to make a pull request because I don't know why it's there in the first place.
ngActive GET requests should use the following syntax:
$http.get(url, {params: paramObj})
In the above example we pass in the paramObj
as params
to the request config. Angular then handles stringifying them and appending the the url. This eliminates the need to do this within ngAactiveResource. More importantly, it gives us access to the params within our interceptors within the request(config) provider as config.params
. This allows us to manipulate the params before sending them off - for example we could change the request to POST, delete the params, and add them instead to data.body
.
What about working and querying on cache explicitly? Sometimes there are needs to work in "offline" mode and then sync data after some period of time.
Update:
What's a good place to store metadata from each request if I'm paginating data?
EDIT: I realize I actually probably don't need to store it in the model I'd just like to figure out a mechanism for returning it so I can know out how many requests need to be made. I'll try to explore a custom $http interceptor.
EDIT2: I created an $http interceptor and can modify the data to work properly with ngActiveResource but I then lose the metadata. I need to modify the promise returned by active-resource's "where" function to return an object with data and metadata.
EDIT3: Figured it out. Sorry for all the notifications!
View Diff Here: https://github.com/AlJohri/ngActiveResource/commit/1e68e3cb0e4875e1c1627727f40ea431e97d7a4b
base.js in _this.where function
// Generate a GET request for all instances matching the given params, deserialize each
// into the appropriate class, and return the found collection
return GET(_this, url, terms, options).then(function(json) {
data = json.data;
meta = json.meta;
var results = [];
for (var i in data) {
var instance = _this.new(data[i]);
results.push(instance);
serializer.deserialize(data[i], instance, options);
}
// Watch all collections that get assigned out as variables
_this.watchedCollections.push(results);
_this.emit('where:complete', {instance: results, data: data, meta: meta});
return {data: results, meta: meta};
});
I found that "addValidations" get call multiple times within the code and for each time a validation function get added which make it to run same function multiple times.
Hey guys,
First off, this library is totally awesome and also badly needed in the angular community. I'm incredibly happy to see it!
Secondly, I have the following coffeescript model:
angular.module('models').
factory 'Account', [\
"ActiveResource"
(ActiveResource) ->
Account = (data) ->
@number 'id'
@string 'phone_number'
@hasMany 'orders'
Account.inherits ActiveResource.Base
Account.api.set('/accounts').format 'json'
Account
]
Part of the code that makes associations work in your library fails because Account.name returns "" instead of "Account". I can use the class
keyword to get the right behavior but that won't survive minification. (I think)
Can you guys support a .className
property that gets set explicitly?
For reference here is an example using the name property in your code:
function nameOfBelongsToModel(model) {
if (!model)
return;
if (!model.klass && !model.name)
return;
if (!model.klass)
return model.name.camelize();
return model.klass.name.camelize();
}
Making a http request per resource isn't always desired. Any chance sideloading is on your roadmap?
Take the following data structure for example:
{
"title": "example post",
"body": "...",
"comments": [/* embedded comments */]
}
I can envision two possible apis for this to work.
Model.api.embedable({
'comments': 'comments'
});
Is this worth investigating further?
I'm currently looking to implement ngActiveResource, but am unable to make it communicate with our API because ours greatly deviates from the conventions assumed in the docs. Which would basically force me to fork the repo and change the code to comply with the structure we're using.
Some kind of Adapter & Serializer base class would be an ideal situation. This would allow developers to write a minimal amount of code to make their APIs work with ngActiveResource. These would essentially be the same concept used in Ember Data, see Adapter & Serializer from the Ember docs.
with util methods like
angular.bind
angular.copy
angular.equals
angular.extend
angular.forEach
angular.fromJson
angular.isArray
angular.isDate
angular.isDefined
angular.isElement
angular.isFunction
angular.isNumber
angular.isObject
angular.isString
angular.isUndefined
angular.lowercase
angular.toJson
angular.uppercase
is there really a need for lodash dep?
don't get me wrong - I ❤️ me some lodash, but i just find it a bit weird to include yet another lib
I followed the installation instructions and received nothing but errors. Looks like the name to include ngActiveResource is now 'ActiveResource', even though the read me says ngActiveResource. After changing it I am now receiving the error 'has no method 'hyphenate''.
Currently .find()
will return a blank model if nothing is found. It would be more ideal if this method returned false, null, an empty array, or something similar.
Currently I've worked around this by using:
// find sensor and redirect if not found
Sensor.find({
id: sensorId
}).then(function(response) {
if(!response.id) $redirect('settings_sensors_path');
$scope.sensor = response;
});
But obviously checking for .id
is not ideal.
If a resource has an ID == 0, then it fails to initialize.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.