I am making a rails MVC style application.
When I am loading the pages, the controller gets the data from the model and forwards it to the view and the view renders itself.
However, I am wondering what the appropriate way is to interact between javascript and my database.
Say the user is playing a game and he has a bunch of clues on the screen. Clicking a clue will move it to his clue box and needs to update the UserClues model to add the clue.
The user also needs to be able to remove clues where the clue gets removed etc...
This needs to happen via AJAX.
I am wondering what the appropriate approach is.
Say he got his page from /Investigation which loaded the page using the InvestigationController.
Should the InvestigationController be the one calling the model to add/remove the clues, or should some sort of data controller do it.
For example:
/Investigation/AddClue
or another controller
/User/Clues/Add
The reason I am asking is I have a lot of data on my pages that is created/added/modified and I am wondering if my routes/controllers should be separate for data manipulation and pages, or if I should have a controller for each page and it also manages what the user can do on that page (like add / remove clues to and from a ClueBox)
Thanks
Ideally you will want to have a separate controller for each resource. Even though your current view is in the context of the Investigations, controller, dealing with clues should have its own resource. Otherwise things can get complex. If the clues are investigation specific, then you can scope them under the Investigation URL.
resources :investigations do
resources :clues
end
This will give you something like /investigations/1/clues/1, but this maybe not be necessary, and I would avoid nesting unless required.
The controller can then respond in the correct format. In this case Rails UJS provides you with the tools you need. You can render a create.js.erb or destroy.js.erb templates to handle user actions. The templates would have the required JavaScript and dynamic code to update the screen state.
If at all possible, try to use Rails' RESTful routes. In this case, that probably means line in your routes file that looks something like:
resources users do
resources clues
end
In your users/clues_controller.rb file, put in actions for the different AJAX requests, like create to add a clue to a user (via a POST request), destroy action to remove a clue from user (via a DELETE request, might need to simulate with POST + "_method=delete" parameter).
Related
I have a system with a web UI that works as normal, and an API endpoint at /receiver_api. Users send emails which are parsed by Mailgun, who then submit a POST to this endpoint. There are a lot of possible actions that we may want to take, depending on the values of these params (create new post, create new reply, add subscription, delete subscription etc.), and when writing the handler it felt like we were doing a kind of routing again!
So we would like to choose the controller that we direct the request to based on what the POST params are. We are directing /receiver_api to a ReceiverApi#receiver controller/method at the moment, which inherits from ApplicationController. It currently effectively routes requests to other "fake" controllers that don't inherit from ApplicationController (since redirecting from one Rails controller to another wouldn't work). We would like to be ultimately routing to Rails controllers so we can use before_filter and all the other magic in them.
Anyway, one possibility that springs to mind is a method in routes.rb that accesses the POST params and returns the Rails controller/method that should be directed to. 2 questions:
Is this possible? Can you access POST params in routes.rb?
Is there a better way of doing this? We had thought about moving up a level into Rack, and will probably do this at some point, but would rather just get something out of the door if this will take a while.
Thanks!
Choosing a controller based on params is not a good thing to do.
A better alternative is to refactor your code (in those fake controllers) to methods in your model, and call model methods based on the params from your controller.
You cannot access params in your routes.rb, because it is run at initialization.
If you really want to call controllers based on params, there is a way of doing this, by redirecting to another controller. This is explained in http://www.railsonwave.com/2008/10/25/how-to-call-a-controller-s-action-from-a-different-controller/ [bad link], but do note that it is very much a hack.
this is kind of a newbie question, sorry but...if a model has no controllers, how could i perform a
flash[:notice]?
for example in
https://github.com/tute/merit
i noticed that it just has models and no controllers. i know that it would be wise to put the flash message inside a controller as opposed to the methods that get executed in the models, but.... how can i do this if there is no controller?
i could try to create one but then doesn't each action in the controller correspond to a page in the view?
certain methods are being executed in the models and i want to be able to add a flash[:notice] whenever they get executed but...how would i do this?
thank you
You would still set flash messages in a controller (or anywhere else the session can be accessed, technically). Merit is just an add-on for Rails, not a replacement. You would still use controllers in your application to handle requests from the user.
since I am only going to be showing that one item, do I just have (example)
/the_thing/23
or do I still go with the /the_group/1/the_thing/23
I know I need to appropriately nest and have associations for forms and using nested routes for links, but for a show page is my link to it nested or not?
i.e. should I still show it within the context of its master or just on it's own. In this case the resource cannot be updated without the nesting i.e. on it's own.
Will a main intent be to show links back to the group?
This question is ONLY about the show page.
This is just a matter of choice, you can even create both routes depending on the context.
You should just ask yourself if it makes more sense for the user to see one url or the other: it's sheer user experience here.
It's true that it's only a matter of choice.
But consider a case, you have a Post model and Comment model, and Comment is a nested resource of Post. It does not make sense to have a separate route for show action of Comment, as showing comments without the relevant post makes no sense.
Hence, it's case specific as well.
I'm learning RoR, I've read some tutorials (railstutorial for the first one),
but I've a problem to define the logic layout of the my first simple website.
The structure is:
When you go to mysite.com you see a welcome page with the signup form or the link for login.
If you signup or you login into the site, you are at mysite.com/dashboard and you see a list of your messages.
You can go to mysite.com/$username and you see a page with a form where you can write a message for the $username.
Stop. That's it. It's very simple, I know, but is for learning.
The problem is this: I'm new to MVC paradigm and I don't know how structure the logic layout of my app. Of course there'll two models: User and Message. But for controllers? And which functions in any controllers? Should I use scaffolding?
Please give me a help, I'm very confused.
Thank you.
Controllers are the logic for the data, so to login/sign-up is really validating/creating a user, if you need to view the users dash board, well that's a look up on the user data so he goes there as well.
The messages, that will be a separate controller that can create/view messages!
As others have pointed out, your controllers contain the logic for your code and invoke views based on that logic by rendering or redirecting to pages. You can define whatever actions you want in your controllers, and then use routes to map a particular URL to a controller action. That being said, Rails gets a lot easier if you "go with the flow" and make some simple assumptions about the actions that could happen. Both your users and your messages represent rows in their respective database tables. There's no much you can do to a row in a database table - you can Create it, Read it, Update it, or Delete it (CRUD). If you define your actions in terms of these four logical actions, Rails lets you generate some easy routes.
You can back into any URL schema that you want, but what you are describing is:
Read the messages that are for a user on the dashboard
Create a message for a user when you go to another page (mysite/username)
Each of these maps to a CRUD action that you should be defining in your controllers.
Agreed also with other advice to simply do a few more tutorials that will probably clear this up.
If you haven't already, read Getting Started with Rails. Look out for the discussion on MVC and scaffolding. Playing around with scaffolding can help you learn where things go and is a great place to start for beginners.
Also, I highly recommend this book: Agile Web Development with Rails. It is very hands on and an easy read.
I have a very fundamental understanding problem with Rails page caching mechanism.
On a rails 2.0.5 application, I use a lot of full page caching, everything's working fine, pages are served at great speed by apache.
So far all the content was handled in an admin section, the cache sweepers are working well.
But I have now opened the edition of some sections to the users, who don't go through the "admin" namespace, but the regular routes.
the problem is that it seems when the updates are performed, they don't go to mongrel with the "put" action, instead I just get the cached page (no action in the database, no flash message, no nothing....)
I feel like I missed something here, is it possible to use page caching with regular REST routes ? or do I have a problem with my mongrel/apache configuration ?
EDIT:
thanks for your answer, but it is not what I meant, the full page cache mechanism works fine, I have dedicated sweepers in the admin controllers that refresh the pages.
my problem is (or I think it is) that when the models are updated through the regular controllers, the form is submitted to the cached page and not to the appropriate action.
in the form
/pages/1-hello/edit
form should be posted with "put" method on "/pages/1-hello"
but I believe it goes to the cached page '/pages/1-hello.html' and is treated as a regular get....
When I submit the form, I just see the show action, no flash message, nothing updated.
then I erase the cached file in my public directory, submit the form again and suddenly everything works....
I read the cache section in "the rails way" and the tutorial on railsenvy.com but I never seen anything mentionned about cached pages that would bring such problems....
You're probably caching too much of the page. If you're caching the entire page and then altering the contents of that page via a put action, the page won't register the change unless you clear the cache explicitly.
If you have a copy 'The Rails Way', some great examples are given to expire pages so that they are reloaded on the next load.
More or less, you have to do something like the following within your create action:
expire_page :action => 'index'
You can also create an observer to observe your model and expire the cache without needing to explicitly call it after a create or update action.
Hope that helps.