Restful Rails Edit vs Update - ruby-on-rails

I was trying to redirect to a different page after editing an entry, I assumed that it was using the update code because you are updating the database. It took me some time to realise that I was using the wrong action in the controller. Can someone please explain how edit and update work. Why are there two different actions? what are the differences between them?

edit action is responsible for rendering the view
update action is responsible for interacting with the model (db updates etc)
If you run rake routes you will see the difference between the verb and the action. Typically, the create/update actions are used when submitting a form. This differs from the new and edit actions as these are used to render the view (that displays the form to be submitted).

Another perspective - a bit redundant to highlight similarities and differences:
New is the precursor action to render a form, that upon submitting, runs the Create action.
(the view is typically redirected back to the index view showing a list of similar items you already created)
Edit is the precursor action to render a form, that upon submitting, runs the Update action.
(the view is typically redirected back to the index view showing a list of similar items you already created)

Related

My page isn't showing the the intended UI Ina given route in Ruby on Rails app

I got the image below when I try to perform a get request on the articles.
Need to create the corespondent page for the action
so in the views folder create a new one called articles then create the page for the index action
views/articles/index.html.erb

Why does the object id change following failed validations in a rails controller?

I've generated a simple rails app using scaffolding. In the user model I have added a validation for the presence of name. I am using debug(#user.object_id) and showing at the top of my user edit page in edit.html.erb
I've purposefully left the name blank and tried to submit the form. The usual errors are rendered but every time I submit the form, the #user's object id changes. Could someone please explain why the object_id is changing? My assumption was that the #user is still the same object (since we're in the same page, just adding errors and re-rendering the edit.html.erb on failed update)
You probably confused by the fact, that render :edit in the update method just renders the edit template, but doesn't redirect to the edit page - that's right.
But, actually this is what happens in your scenario:
edit page is visited, #user assigned in the edit method of UsersController
form is submitted, update action is called and found #user is assigned in the update method and renders edit template
Thus, on submitting a form different method is called and the state changes
No, your assumption is not correct. HTTP calls are stateless, meaning that state does not persist between calls (i.e. every call is independent of each other). Every time your form is submitted, a new object is created and assigned to the variable #user. Since a new (and different) object is created during each call, their object_ids will be different.

Render a form in a modal(bootstrap) and make it available on another controller's view

It's been a while since I've used Rails and I think I've gotten a little rusty. Is there a way to do this?
I'm trying to make a messaging feature that allows one user type to message another. I want the button to display on the User index page and the user show page. When the button is clicked a modal will popup with a form contained therein.
Currently I've made a Message model with three columns: user_type1_id, user_type2_id and message_body.
Should I make a distinct controller for this new model? Or should I put the logic in the controller of user_type1 (the usertype that will be messaged)?
Any other suggestions would be welcome.
Controllers are there primarily to get data from the database and get it ready for the views. So if you have user#index and user#show pages, then you should use the UsersController for all the logic associated with those views, even though it uses other modals. It really is the "Rails Way". If, however, you were to create a message#index page, then you should create the associated MessagesController.
Also, there is nothing wrong with creating a partial and sticking in the messages view directory (the filename would be, say, messages/_form.html.erb). Then, whenever you needed that form (throughout the entire site), all you would need to do was type:
<%= render 'messages/form' %>

Is there any harm in using a typical GET action for a PUT? (RESTfully speaking)

I have an action that doesn't require a form. So it really only needs the one 'edit' method instead of the RESTful 'edit' --> 'update'. Is there any reason not to do this or a better way?
def edit
#Do a POST(PUT)
end
The harm is that a user could easily navigate to that url and perform a potentially destructive action.
/noform/edit #URL typed by user => Action Performed
/noform/update #URL typed by user => Error is thrown, No Action Performed
A normal browsing experience generates GET requests to the server. The assumption is, any page you can easily navigate to (or type into your address bar) will not perform any data changing functions.
A POST request, generated via a form submission or a AJAX request expects the result that data is changed on the server.
Similarly the two rails "faked" versions of PUT and DELETE also are not actions you could simply navigate to using a browser.
The solution
The solution is to have only the update action and where you originally would have linked to edit use something like the following:
button_to "Add new tracker", noform_path, :method => :put
If there is any type of error, you may still need an edit path to show the user so they can correct something. But from what you have described, a single update action should do the trick.
Gets should always be idempotent -- that is they should not perform any action that will alter the state of the application, database, etc.
Just as an aside -- in true RESTful form an edit would be performed by an HTTP Update action, but Rails simulates this with a post and a hidden value on the form, since browsers don't have HTTP Updates.
It's still not clear to me why you need an update without an input field. Perhaps a little more detail would be helpful.

Rails best practice for having same form on multiple pages

I am developing an Rails 2.3.1 Web site. Throughout the Web site, I need to have a form for creating Posts on various pages (Home page, Create Posts page, Post listing page, Comment listing page, etc. -- suffice to say this form needs to be on many pages served by a variety of controllers). Each of these pages displays a wide variety of other information that is retrieved in the corresponding controller/action. Ex, the home page lists latest 10 posts, content pulled from the DB, etc.
So, I've moved the Post creation form into its own partial, and included this partial on all the necessary pages. Note that the form in the Partial POSTs to /questions (which routes to PostsController::create -- this is default rails behavior).
The problem I am running into is when the the Posts form is not completed correctly, by default the PostsController::create method render's questions/new.html.erb, even if the form was submitted from the home page (/home/index.html.erb).
I tried changing the form in the partial to submit the "submitting_controller" and "submitting_action", and in PostsController::create, when #post.save? == false, I render action => "../submitting_controller/submitting_action" (Which is slightly hacky, but lets you render actions from non-PostsController's).
This seemed to work OK on the surface. The incomplete form was rendered in the view that submitted it with all the correct #post.errors message, etc. The problem was ALL the other data on the pages didnt show up, because the actual submitting_controller/submitting_action methods weren't called, just the associated view. (Remeber, I did a render which preserves instance objects, rather than a redirect_to which does not preserve the #post instance object which has all the error messages and submitted values.)
As far as I can see I have two options:
1) I can store the #post object in the session when #post.save? fails in PostsController::create, redirect_to submitting_controller/submitting_action, at which point i pull the #post object out of the session and use it to re-populate the form/error messages. (As far as I understand, storing objects in the session is BAD practice in rails)
2) I can move all the logic used to pull non-post creation form data from the various submitting_controller/submitting_action, put it in the ApplicationController, create a giant switch statement in PostsController::create for submitting_controller/submitting_action and call the methods in the ApplicationController to grab all the extra data needed for each submitting page's render.
Thoughts on the best way to do this within Rails?
By any chance is your Post model in a belongs_to relationship with each model who's controller you'll be using to render your form? Are you doing any special processing in the Post controller beyond Post.create(params[:post])?
If you answered yes to the first question and no to the second, you could get by with minimal mangling by adding accepts_nested_attributes_for to each of the controllers on which a user can create a post.
Regardless, Robertpostill is correct in that this is probably when to start looking at AJAX, to just replace the section of the page. The only problem is what to do if a user has javascript disabled. Personally I like to do design for the non-javascript case and add convenience methods.
As for thoughts on what you consider your two options,
1) I've used this method to store a shallow copy of an object in the flash hash. Preserving it across redirects. However this might not work for you given the variable nature of posts. As you can only send about 4K worth of data, and that includes other information in addition to your shallow copy.
2) See robertpostill's response
This is about the point that you move from full page updates to updating sections of a page through the use of AJAX. There are a bunch of things you should consider but the most rails-esque approach would be to split the response between an AJAX response and a plain HTML response. Check out this ONLamp article, this register article or the awesome agile web development with rails book. Essentially your controller renders a new div replacing the old div containing the result of submitting the partial.
In your question you mention two approaches and so I'll try and give you some pointers on why and why not here:
Option 1) Ths option is not so bad with a couple of tweaks. The main tweak is is to store the object in a serialized form in the DB. Then simply pass around the ID of the serialized object. Your upsides are that the session data gets persisted so recovering a a session is neater and your session stays light. The downside of this is that having a bucket of session cruft in your DB will pollute your app and you'l need to do some thinking as to how you expire unused session cruft from the DB. I've never seen this end well...
Option2) Eeek not inside the application_controller! :) Seriously, keep that as your weapon of last resort. You can pop things insde the helpers though and get access to those methods inside your controllers and views. However the testing of that stuff is not so easy so be careful before choosing that route. Switch statements can be replaced in OO apps with a little thinking, certainly in his case you can use option hashes to get a railsy way of having some smarts about the state of the app at the time the request is made.

Resources