How to modify the create & update method in RoR? - ruby-on-rails

I know that the after the create or update methods is done, they have the method like this
respond_to do |format|
format.js
end
Since I change my form from remote form to non remote form, so I won't use the format.js anymore, I just want to refresh the page, after the user create/update a product, so I have this code:
respond_to do |format|
page.reload
end
But it don't work, so I try not to use respond_to do, I only have the page.reload. But it also show me the site like this:
http://localhost:3000/products/50
I just want to reload the page after I create/update, why I can't do it in this way?

The reload method reloads the browser's current location using JavaScript. I would suggest that you probably want to do a server-side redirect after creating or updating your resource. Something like one of these alternatives:
redirect_to product_path(#product) # Redirect to the 'show' page for the product
redirect_to products_path # Redirect to the products' index page

How can I assign the product_path? in routes.rb?
in routes.db you can either:
map.product 'products/:id', :controller => 'products', :action => 'view'
map.resources :product
map.resource :product
1) will give you product_path(123) and product_url
2) will give you product_path, new_product_path, edit_product_path and so on
HTH

Related

Ruby on Rails 6. Using Ajax after redirection

Say, I have users list on the '/users' page and 2 actions for the 'user' entity: 'index' (with using of Ajax) and 'destroy'.
def index
...
respond_to do |format|
format.html
format.js
end
end
def destroy
...
redirect_to users_url
end
I want to destroy a user (right from the '/users' page) and use Ajax of the 'index' action after that ('index.js.erb' file) in order to render only a part of the opened '/users' page.
Is it possible to do that?
My current solution right now is to use Ajax for 'destroy' action (a separate 'destroy.js.erb' file) and duplicate needed changes for 'index' page there. But, first of all, it's a code duplication, and second, in this case my pagination links are broken (I use 'Kaminari' gem and looks like it works fine only with 'get' requests, at least by default).
There is a 'view' part of updating with Ajax, if necessary:
<div id="users_table">
<table class="table table-hover table-borderless">
...
<tbody>
<%= render #users %>
</tbody>
</table>
<div><%= paginate #users, remote: true %></div>
</div>
If you want the destroy action to render the index.js.erb:
def destroy
...
respond_to do |format|
format.js { render action: :index}
format.html { redirect_to users_url}
end
end
But, to render index.js you will need to, in your destroy action, rebuild the #users object and ensure you're rebuilding it for the correct page. So, when you call the destroy action you'll need to pass the ID(s) of the user(s) you want to destroy, as well as the page you are on.
Your destroy.js.erb should (on successful destruction) remove the destroyed element from the index by deleting a part of the HTML. I don’t expect that the code to do that duplicates the code you have in the index view.
Post your current destroy.js.erb as well as the relevant part of index.html.erb for more help though.
You can also use redirect within a respond_to so your HTML call will redirect while the Ajax uses destroy.js.erb
respond_to do |format|
format.js
format.html { redirect_to users_url}
You could also hack your way to your answer by calling render :index for the js response. But, if you were to try to render the index view here you’ll definitely get duplication of code, along with an extra DB call and probably some broken pagination. So, I’d recommend that you take the approach I first suggested (use destroy.js.erb to remove that user from the HTML)
Finally, more generally, when you’re trying to avoid duplication of view code; a partial might be the answer

Allow method to accept an :id param

I have created a method called verify in a controller (events_controller.rb), and I want to allow that page (verify.html.erb) to accept an object (#event), and show of that objects parameters. I'm creating a show page in essence, but I need to build some special logic into this page that I don't want to build into the show page. I have created the route, but I still get an error when I tell it to find an Event by params[:id]. The actual url it is going to is /verify.(event :id) and I believe it should be routing to events/verify/(event :id).
My error
Couldn't find Event without an ID.
routes.rb
get "verify", to: 'events#verify'
resources :events
events_controller.rb
def verify
#event = Event.find(params[:id])
respond_to do |format|
format.html # verify.html.erb
format.json { render json: #event }
end
end
Thanks Stack!
get "verify/:id", to: 'events#verify', as: "verify"
in browser go to url for example:
localhost:3000/verify/1

Redirecting and routing Ruby on Rails

I'm still new to Ruby on Rails and I'm currently having a issue with routing and redirecting.
I have two controllers "candidate" and "survey". I'm currently viewing "canidate/editEmail.html"
http://www.otoplusvn.com/TherapistSurvey/candidates/editEmail/2
Once the submit button is clicked, the candidate's method for updating the email is executed:
def updateEmail
#candidate = Candidate.find(params[:id])
respond_to do |format|
if #candidate.update_attributes(params[:candidate])
flash[:notice] = 'Candidate email was successfully updated.'
format.html { redirect_to :controller => "survey", :action => "end" }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #candidate.errors, :status => :unprocessable_entity }
end
end
end
This code will update the Candidate's email in the database and redirect it. I want to redirect it to an html page called end.html.erb that is located under the view/Survey/end.html.erb. However, With the present code it will give me a
Unknown action
No action responded to show. Actions: download and lastPage
where download and lastPage are the only methods in the Survey controller. "end" is not a method defined in the survey_controller.rb, but I assumed that it would automatically jump to the end.html.erb located under views/survey
On my local machine, I'm able to get this to work with this updated code:
format.html { redirect_to :controller => "survey/end" }
But this doesn't work on the site that I loaded the ruby on rail application on. In either case, I think there is probably an easier way to do this and i'm doing this incorrectly.
I think it has to deal with the route.rb file or permission that I'm unaware of when you port a local ruby on rail application to a host.
Normally I would think that if i went directly to the file
http://www.otoplusvn.com/TherapistSurvey/survey/end
I would be able to see the page like I was able on my local machine, but I'm not able to with what I have hosted.
In general, I just want to be able to redirect (jump) to another html page indicating that the email update was done correctly and that the survey is over. This is all triggered by hitting a submit button that result in an update to the database being called an a redirect to another page. The problem being how to do the redirect correctly.
BTW: in my routes.rb I have
map.resources :survey
Any Advice Appreciated. Thanks!
D
You need add all other action you want.
map.resources add only route need by ressources browsing.
So add in collection option your method end in your case
map.resources :survey, :collection => {:end => :get}
Add this to routes.rb
map.resources :survey, :collection => {:end => :get}
Run rake routes from terminal in the route of your application to see your routes.
Use named routes:
redirect_to survey_end_path

rails: specify the HTTP verb in a redirect_to

Here's a basic overview of my domain:
a user has a list of courses
the user can "select" a course. The corresponding action is invoked with
the PUT verb, stores the course_id in
a session variable and redirects to
the "show" action of the selected
course.
when the user has only 1 course available, I want to redirect him
directly to the only course available (and
invoke the "select" method before, of
course).
From there, i see 2 options:
Keep the "select" action when the user clicks the link and add a new action for when the selection is automatic... but that doesn't look very DRY (even if I could refactor some code)
call the PUT action from the controller itself... but I haven't found how (is it even possible)?
Any alternative is welcome :)
Thanks for your help.
P.
In the courses controller:
def index
#courses = Course.all
if #courses.length == 1 #if only one course
#course = #courses[0] #get that course
session[:course_id] = #course.id #set the session
redirect_to :action => "show", :param => "#{#course.id}" #redirect
end
respond_to do |format|
format.html
format.xml { render :xml => #line_items }
end
end

How do I use redirect_to if I've got multiple controllers in different subdirectories?

I've created a small application to learn RoR. (Book database) It consists of a read-only area and a read-write admin area.
After I've got the admin functionality working first, I've moved the controller into a subdirectory and created the read-only controller.
Now when I'm updating a book in the admin area, the redirect_to function redirects to the read-only area.
What am I missing?
Here's the code I'm using:
class Admin::BooksController < ApplicationController
<snip>
def update
#book = Book.find params[:id]
respond_to do |format|
if #book.update_attributes params[:book]
flash[:notice] = "Book updated"
format.html { redirect_to #book }
format.xml { head :ok }
else
<snip>
end
end
end
<snip>
end
This update itself works but it redirects me to /books/1, but I'd want it to redirect to /admin/books/1. I could just hardcode the correct path, but I guess that's not very good style.
What would be the proper way?
PS: Please comment if you need further information.
You are telling it to redirect to book because you are using rails' built in magical recognition of what it should do with the #book object (which is build a url to show the book using the book controller.
format.html { redirect_to #book }
If you want it to go elsewhere you need to be explicit about where you want it to go using a hash for url_for
format.html { redirect_to :controller => 'admin/book', :action => 'show', :id => #book }
or use the paths like klew points out.
so for more detail -
redirect_to (#book) or
redirect_to book_path(#book)
are both shortcuts for this:
redirect_to :controller => book, :action => 'show', :id => #book.id
Rails creates for you url helpers based on your routes.rb. If you have namespace then you can use this:
admin_book_path(#book) # admin/books/2
admin_books_path # admin/books
edit_admin_book_path(#book) # admin/books/2/edit
and so on.
The other way is to use resource_controller it creates for you controller automaticaly and provides some ways to modify it if it's needed. It also gives you some useful url helpers
collection_path # admin/books
object_path # admin/books/2
When you use above helpers in views, than it generates url with namespace if you are in one, or without namespace otherwise.
resource_controller isn't perfect, but in most cases it works good and saves a lot of work.
You can also pass an array to redirect where the first element is a symbol representing the namespace, and the second the element the object.
redirect_to [:admin_book, #book]
You can also use this for form_for, link_to and any other helpers that require a path.

Resources