We are using the same action in a controller (called 'residential_springs') to process and render a form
def index
//..code...
if params[:authenticity_token]
if process_post(params)
redirect_to checkout_index_url
end
end
end
def process_post(params)
return true
end
And then in the routes we have
get "residential_springs/index"
post "residential_springs/index"
The form actually points to this action
=form_for #order_garage_door, :url => {:action => 'index'} do |f|
//form stuff...
yet we keep getting the routing error
No route matches "/residential_springs/index"
The crazy thing is we've already set this up a ton in this project and it works fine for other controllers so we know we're missing something crazy small and dumb. But I think everyone on the project has tunnel vision and fresh eyes would be appreciated.
Related
I have a controller action where I'd like to receive form data, execute some business logic, then refresh the form. This works Ok if I save the object in the database then use a redirect_to. I would prefer the controller edit the object in memory and render the response directly.
For example, take a standard rails 5.1.4 generated app generated like so:
rails new turbolinks_example
rails g scaffold Thing name
rails db:migrate
The form, slightly edited for brevity and to enable turbolinks:
<%= form_with(model: thing) do |form| %>
<div class="field">
<%= form.label :name %>
<%= form.text_field :name, id: :thing_name %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
A) Now we edit the controller to change the object. This uses a redirect to edit and works:
ThingsController < ApplicationController
...
def update
if #thing.update(thing_params)
#thing.update name: "#{#thing.name} is OK"
redirect_to edit_thing_path(#thing)
end
end
B) This uses a render and does not work:
class ThingsController < ApplicationController
...
def update
if #thing.update(thing_params)
#thing.name = "#{#thing.name} is OK"
render :edit
end
end
end
With A)
- Update request is received by controller
- Object is modified (& saved)
- Redirect is returned
- Rediredted url is rendered
- DOM is updated
With B)
- Update request is received by controller
- Object is modified (in memory)
- Response is rendered
- Response is received by browser, but ignored
The response received, looks correct. Full HTML, with the changes made to the object. How do I get turbolinks to notice it and replace document.body like normal?
The full project, including development.log is on Github
The problem is that, in Rails 5:
Forms are remote by default: they are sent via AJAX unless local: true provided
When rendering HTML as a response to an AJAX call, nothing happens unless, of course, there is custom javascript in the client handling the response
Turbolinks is enabled by default, which handles redirect_to properly, but does nothing for render
I think this is an inconsistency in Rails that causes much confusion, such as the problem you exposed with your code. I created a gem turbolinks_render to deal with this problem. I also wrote a little post on this very same problem.
I hope that, one way or other, this gets fixed in future Rails versions.
New to rails 3
I would like to create a contact form that people fill out, its saved to the db and then a thank you page comes up.
I would like to do this without scaffold so I can learn better, and I figure that by doing it this way it would be easer to setup so that people cannot try and look at other people's entries by modifying the url.
ideally it would keep their state in the session or cookie so that they would end up on the thanks page if they came back.
Have been trying to do this for about 3 days and reading/googling tons, but between the new routes redirect_to controller stuff in rails3 havn't managed to figure it out.
Routes.rb
Contact::Application.routes.draw do
resources :contactees, :only => [:new, :create]
# to make sure crud doesn't have the routest I don't want
get 'contactees/submitted'
root :to => 'contactees#new'
contactees_controller.rb
ContacteesController < ApplicationControler
def share
end
def new
#contactee = Contactee.new
end
def create
#contactee = Contactee.new(params[:contactee])
if #contactee.save
redirect_to submitted_contactee
else
render action: "new"
end
end
end
Views
contactees
_form.html.erb
new.html.erb
submitted.html.erb
Get rid of the submitted route, you don't need it. Perhaps something like this?
def new
render :submitted if session[:contacted]
end
def create
#contactee = Contactee.new(params[:contactee])
if #contactee.save
session[:contacted] = true
render :submitted
else
render action: "new"
end
end
I am experiencing extremely strange behaviour in Rails 3.2.1
I have some resources that do not have show actions.
For example:
resources :homes, :except => [:show]
In my controller I say:
def update
#domain = Domain.where(:domain => request.domain.split('.').first).first
#home = Home.find(params[:id])
if #home.update_attributes(params[:home])
expire_page :action => :index
redirect_to(admin_path(#domain), :notice => "Updated.")
else
render :action => "edit"
end
end
and all is hunky dory in development.
But in production rails consistently tries to redirect to (the non existent) show action, despite the obvious redirect_to. It's as if this method is ignored totally. In fact I can try and redirect to any path in the app and it will be ignored. As soon as I set perform_caching to false in production.rb the routes begin to behave as expected again! Any ideas why this is happening and how I can make it stop!? Obviously I could turn off caching, but I need the pages to be cached for performance reasons.
Thanks for reading.
I am currently following the Ruby on Rails Tutorial by Michael Hartl. And there is something that has been bugging me for quite some time. I looked it up but I still can't find a good answer.
Anyway, I've noticed is when you have a validation error in the signup page it renders the original signup page and changes the nav bar address. I've matched /signup to the action new, but if I use render it changes from /signup to /users (the default, because of the RESTful standard I guess).
I'll leave some lines of my code:
routes.rb
resources :users
match '/signup', :to => 'users#new'
users_controller.rb
def new
#user = User.new
#title = "Sign up"
end
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Welcome to the Sample App!"
redirect_to user_path(#user)
else
#title = "Sign up"
#user.password = ""
#user.password_confirmation = ""
render 'new'
end
end
So I've tried to work around this by not using the render method but redirect_to instead but I'm having trouble using it. As it is actually sending data to the path provided, #user.errors gets overwritten by creating a new instance of the model and the flash variable cannot show the errors.
_errors.html.erb
<% if #user.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#user.errors.count, "error") %>
prohibited the user from being saved:
</h2>
<p>There were problems with the following fields:</p>
<ul>
<% #user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
My question is: is there any way that by using render I can change the url displayed on the navbar? It's really frustrating if someone makes a mistake in the signup form, presses enter in the navbar and ends up in a totally different place.
The reason why the address changes is because you have performed a POST request to /users/ therefore the browser is doing the correct thing by displaying the different address.
There are a few of ways around this:
Store the invalid User object and redirect back to the Users.new action.
Change the URL of the Users.create action.
Use history.replaceState to change the user's address bar.
The first option keeps the controller more RESTful, however it will need use of the :session or flash to persist the data across the redirect.
The second option keeps the code simpler, but involves fiddling with the routes.rb file.
The third option relies on javascript and support for HTML5 to mess with the user's browser history.
Personally I would leave the URL as is, but if I had a client who insisted on doing this, I would go for the second option.
I have a column in a table called Complete that is a boolean.
How can I (using the Rails 3 / JQuery way) provide a link that will toggle that via AJAX?
Historically, I've simply created my own jquery file, grabbed the click event, and done it by hand. But it really seems like I'm missing something by not doing it the "rails" way. If that makes sense.
I guess I still don't understand how the responds_to JS works, JS with ERB, etc.
Is there a good, up-to-date tutorial on how to do this?
Thanks.
see this post,
Rails 3, Custom Actions, and HTML request methods
and use UJS on top of it.
so you have a fallback, if javascript is disabled
a possible method in the controller looks like that:
# GET /surveys/1/close
def close
#survey.close!
flash[:success] = "Survey successfully closed!"
respond_to do |format|
format.html { redirect_to(surveys_url) }
format.xml { head :ok }
format.js { render :partial => 'list_item', :locals => { :survey => #survey } }
end
end
you could also use a state machine to change the state of your object.