How to save form params in the hasMany side of a one to many relationship in grails - forms

I have one to many relationship between a Post which has many comments of the domain Comment. In my gsp I´m showing a blog post with it´s comments below, at the end, there is form a user can fill out in order to create a new comment. So I´m passing the params filled in the form to a controller in order to save the new comment, but I´m not sure if I have to do it in the PostController (one side) or in the CommentController (many side). And second how exactly should I save the new comment, I used this, CommentController:
def save() {
def p = new Comment(params)
p.save()
redirect(action: 'blog', controller: 'Post', params: params)
}
Which at the end redirects to the PostController where I render the post view with the all the content including the new comment, PostController
def blog()
{
def post = Post.get(params.id)
def entra = Post.findById(params.id)
[post: post, articulos: entra]
}

" but I´m not sure if I have to do it in the PostController (one side)
or in the CommentController (many side)."
Controllers are not domain objects and are not involved in the relationship between Post and Comment. You can create a controller called PoopyCakaController and do the logic there. It is really irrelevant. Given that info, in my opinion, I guess it depends on whether multiple objects can have comments. If post owns those comments and no other objects have comments, do it in the post controller, otherwise do it in the comment controller.
"And second how exactly should I save the new comment, I used this,
CommentController:"
Is that working for you? If so, that's fine. If it is not working for you, post what the problem is including any errors you are getting.

Related

Custom XML response in sails.js blueprint for a model?

I am new to sails.js and I have a simple blueprint model set up. Right now, my controller and model are pretty much empty except for attribute definitions on the model.
After the model is created via POST, I would like the response to be a custom XML response (some plain text I generate essentially), not the standard JSON response. I figured that I could overwrite the entire create method on the controller, essentially copy-and-pasting the code from the default and just overwriting the response, but that seems really heavy too me.
There must be a better way to do this?
Note that I am only attempting to do this for this specific model, not generally.
Thanks!
The best way is to simply add the header as DigitalDesignDj mentioned.
/**
* TestController
*/
module.exports = {
create: function(res, req) {
// get your data
var xml = 'some xml string';
res.setHeader( "Content-type", "text/xml" );
res.send(xml);
}
}
To change headers for a specific response.
response.setHeader( "Content-type", "text/xml" );
When you already have some XML for the response.send()
If your result was to do this for all actions on that single model you could simply overwrite the toJSON method to generate XML instead of JSON in the model itself. Then if your running blueprints, it will spit out XML instead of json when you hit those endpoints.
However your question is specific to the create action. In this instance, I would ask if your running alternate view files for non ajax requests. And if not, just drop an view files into the create action that views/foo/create.[ejs,jade,ect...] with your xml layout. The response will see the view file and override the json output with that file. This means you have to change no code just add that single file.
Their are a dozen ways to accomplish this, and your question would need more detail (as mentioned on the comments) for a specific answer to your use case.

RESTfull implementation and general informatino

I have been reading a lot lately, and even more experimenting with web Development. There are some things that I simply cant understand, therefore any help is appreciated.
I am not trying to get my homework done for me. I have some holes in my knowledge, that I desire to fill. Please, help me out with your views :)
REST questions:
Reading documentation this is perfectly understandable (NODE.JS / Express) example:
EXAMPLE ONE (get):
app.get('/', function(req, res) {
res.send('please select a collection, e.g., /collections/messages')
})
My explanation: When the root of the server is hit, send thie following message
EXAMPLE TWO (get):
app.get('/collections/:collectionName/:id', function(req, res) {
req.collection.findOne({name: req.collection.id(req.params.id)},
function(e, result){
if (e) return next(e)
res.send(result)
})
})
My explanation: When the url in hit, take id from the URL (that is located in params.id) and make search based on it (that is MongoDB).
EXAMPLE THREE (post):
app.post('/collections/:collectionName', function(req, res) {
req.collection.insert(req.body, {}, function(e, results){
if (e) return next(e)
res.send(results)
})
})
My explanation: When the URL is hit, take the payload(JSON in this case) that is located in req.body, and insert it as a new document.
Questions:
Are example one and two both RESTfull?
I am now totally confused with params.id. I do understand that POST is transmitted in rew.body... what is params.id? Is it containing URL variables, such as :ID?
My explanations... are they correct?
Example three is also REST, regardless of the fact that POST is used?
Example three, '/collections/:collectionName. Why is the ':collectionName' passed in URL, I could have placed it in req.body as a parameter (along with new data) and take it from there? What is the benefit of doing it?
Thank you
An API must be using HATEOAS to be RESTful. On first example, if / is the entry point of your API, the response should contain links for the available collections, not a human readable string like that. That's definitely not RESTful.
Exactly.
They're OK, except that there's nothing in the third example implying it's a JSON body. It should check for a Content-Type header sent by the client.
REST isn't dependent on HTTP. As long as you're using the HTTP methods as they were standardized, it's fine. POST is the method to use for any action that isn't standardized, so it's fine to use POST for anything, if there isn't a method specific for that. For instance, it's not correct to use POST for retrieval, but it's fine to use it for creating a new resource if you don't have the full representation.
POST means the data body is subordinated to the resource at the target URI. If collectionName were in the POST body, this would mean you were POSTing to /collections, which would make more sense to create a new collection, not a new item of a collection.

Sail.js - routing to methods, custom policies & PATCH method

I have a few questions that I couldn't find answers anywhere online.
Does sails.js framework support HTTP PATCH method? If not - does anyone know if there is a planned feature in the future?
By default if I create method in a controller it is accessible with GET request is it the routes.js file where I need to specify that method is accessible only via POST or other type of methods?
How would you create a policy that would allow to change protected fields on entity only for specific rights having users. I.e: user that created entity can change "name", "description" fields but would not be able to change "comments" array unless user is ADMIN?
How would you add a custom header to "find" method which specifies how many items there are in database? I.e.: I have /api/posts/ and I do query for finding specific items {skip: 20; limit: 20} I would like to get response with those items and total count of items that would match query without SKIP and LIMIT modifiers. One thing that comes to my mind is that a policy that adds that that custom header would be a good choice but maybe there is a better one.
Is there any way to write a middle-ware that would be executed just before sending response to the client. I.e.: I just want to filter output JSON not to containt some values or add my own without touching the controller method.
Thank you in advance
I can help with 2 and 5. In my own experience, here is what I have done:
2) I usually just check req.method in the controller. If it's not a method I want to support, I respond with a 404 page. For example:
module.exports = {
myAction: function(req, res){
if (req.method != 'POST')
return res.notFound();
// Desired controller action logic here
}
}
5) I create services in api/services when I want to do this. You define functions in a service that accept callbacks as arguments so that you can then send your response from the controller after the service function finishes executing. You can access any service by the name of the file. For example, if I had MyService.js in api/services, and I needed it to work with the request body, I would add a function to it like this:
exports.myServiceFunction = function(requestBody, callback){
// Work with the request body and data access here to create
// data to give back to the controller
callback(data);
};
Then, I can use this service from the controller like so:
module.exports = {
myAction: function(req, res){
MyService.myServiceFunction(req.body, function(data){
res.json(data);
});
}
}
In your case, the data that the service sends back to the controller through the callback would be the filtered JSON.
I'm sorry I can't answer your other questions, but I hope this helps a bit. I'm still new to Sails.js and am constantly learning new things, so others might have better suggestions. Still, I hope I have answered two of your questions.

Angular JS: Full example of GET/POST/DELETE/PUT client for a REST/CRUD backend?

I've implemented a REST/CRUD backend by following this article as an example: http://coenraets.org/blog/2012/10/creating-a-rest-api-using-node-js-express-and-mongodb/ . I have MongoDB running locally, I'm not using MongoLabs.
I've followed the Google tutorial that uses ngResource and a Factory pattern and I have query (GET all items), get an item (GET), create an item (POST), and delete an item (DELETE) working. I'm having difficulty implementing PUT the way the backend API wants it -- a PUT to a URL that includes the id (.../foo/) and also includes the updated data.
I have this bit of code to define my services:
angular.module('realmenServices', ['ngResource']).
factory('RealMen', function($resource){
return $resource('http://localhost\\:3000/realmen/:entryId', {}, {
query: {method:'GET', params:{entryId:''}, isArray:true},
post: {method:'POST'},
update: {method:'PUT'},
remove: {method:'DELETE'}
});
I call the method from this controller code:
$scope.change = function() {
RealMen.update({entryId: $scope.entryId}, function() {
$location.path('/');
});
}
but when I call the update function, the URL does not include the ID value: it's only "/realmen", not "/realmen/ID".
I've tried various solutions involving adding a "RealMen.prototype.update", but still cannot get the entryId to show up on the URL. (It also looks like I'll have to build the JSON holding just the DB field values myself -- the POST operation does it for me automatically when creating a new entry, but there doesn't seem to be a data structure that only contains the field values when I'm viewing/editing a single entry).
Is there an example client app that uses all four verbs in the expected RESTful way?
I've also seen references to Restangular and another solution that overrides $save so that it can issue either a POST or PUT (http://kirkbushell.me/angular-js-using-ng-resource-in-a-more-restful-manner/). This technology seems to be changing so rapidly that there doesn't seem to be a good reference solution that folks can use as an example.
I'm the creator of Restangular.
You can take a look at this CRUD example to see how you can PUT/POST/GET elements without all that URL configuration and $resource configuration that you need to do. Besides it, you can then use nested resources without any configuration :).
Check out this plunkr example:
http://plnkr.co/edit/d6yDka?p=preview
You could also see the README and check the documentation here https://github.com/mgonto/restangular
If you need some feature that's not there, just create an issue. I usually add features asked within a week, as I also use this library for all my AngularJS projects :)
Hope it helps!
Because your update uses PUT method, {entryId: $scope.entryId} is considered as data, to tell angular generate from the PUT data, you need to add params: {entryId: '#entryId'} when you define your update, which means
return $resource('http://localhost\\:3000/realmen/:entryId', {}, {
query: {method:'GET', params:{entryId:''}, isArray:true},
post: {method:'POST'},
update: {method:'PUT', params: {entryId: '#entryId'}},
remove: {method:'DELETE'}
});
Fix: Was missing a closing curly brace on the update line.
You can implement this way
$resource('http://localhost\\:3000/realmen/:entryId', {entryId: '#entryId'}, {
UPDATE: {method: 'PUT', url: 'http://localhost\\:3000/realmen/:entryId' },
ACTION: {method: 'PUT', url: 'http://localhost\\:3000/realmen/:entryId/action' }
})
RealMen.query() //GET /realmen/
RealMen.save({entryId: 1},{post data}) // POST /realmen/1
RealMen.delete({entryId: 1}) //DELETE /realmen/1
//any optional method
RealMen.UPDATE({entryId:1}, {post data}) // PUT /realmen/1
//query string
RealMen.query({name:'john'}) //GET /realmen?name=john
Documentation:
https://docs.angularjs.org/api/ngResource/service/$resource
Hope it helps

GET and POST request in one action. Playframework. Scala

Action create shows form:
def create = Action {
Ok(html.post.create(postForm))
}
How can i modify this action so that for GET request it would give out form and for the POST request it would process user input data, as if it were a separate action:
def newPost = Action { implicit request =>
postForm.bindFromRequest.fold(
errors => BadRequest(views.html.index(Posts.all(), errors)),
label => {
Posts.create(label)
Redirect(routes.Application.posts)
}
)
}
Wthat i mean is i want to combine this two actions.
UPDATE1: I want a single Action that serves GET and POST requests
It is recommended not to merge both actions, but modify routes to get the behavior you are expecting. For instance:
GET /create controllers.Posts.create
POST /create controllers.Posts.newPost
In case you have several kind of resources (post and comments, for instance), just add
a prefix to the path to disambiguate:
GET /post/create controllers.Posts.create
POST /post/create controllers.Posts.newPost
GET /comment/create controllers.Comments.create
POST /comment/create controllers.Comments.newComment
I tried once to accomplish similar thing, but I realized that I wasn't using framework like it was meant to be used. Use separate GET and POST methods like #paradigmatic showed and in cases like you specified "If we take adding comments to another action, we wouldn't be able to get infomation on post and comments in case an error occured (avoding copy-paste code)." - just render the page at the end of controller method with the view you like? and for errors etc. you can always use flash scope too? http://www.playframework.org/documentation/2.0.2/ScalaSessionFlash you could also render this form page with two or more beans and send them to controller side to catch related error messages and data.?