What to render on error in a Rails controller - ruby-on-rails

In my rails application, I've got a partial view with an entry form on it. The form gets included on multiple pages across my app. The form in the partial posts to a RidesController to save with a create method like this:
RidesController.rb
def create
#ride = current_user.rides.build(params[:ride])
if #ride.save
flash[:success] = "Ride created!"
redirect_to root_path
else
#rides = current_user.rides.paginate(:page => params[:page])
render 'pages/home' # <---- WHAT GOES HERE?
end
end
I've commented the line where my question is. When we have an error, I need to present the same view that the user is presently on. But because this controller is being invoked from a partial instead of a full view, I don't know how to tell what context it's coming from.
Right now if there's an error on /rides/new, the user ends up redirected to the homepage which also has the form.

One way you could do this is pass the template path in with the form.
Add this to each main view that includes the form partial (e.g. pages/home, rides/new, etc):
<% #current_page_template = __FILE__ %>
In your form partial:
<%= form_for ... do |f| %>
<%= hidden_field_tag 'current_page_template',
#current_page_template.sub(File.join(Rails.root, 'app', 'views'), '') %>
In your controller:
def create
...
if #ride.save
...
else
...
render params[:current_page_template]
end
end

Related

Getting 'form_for(#something)' to work outside of new.html.erb

I want to place my <%= form_for(#something) do |f| %> which is currently located in app/views/something/new.html -- inside multiple pages, so maybe in app/views/layouts/application.html.erb
How do I get the #something variable and the form to work properly there, or somewhere else -- since it's defined in the controller #new action of SomethingController, it only seems to be available in the appropriate new.html.erb view..
You can put the form anywhere, just provide an instance variable of #something in controller
The basic usage is here.
ThisThingsController
def show
#this_thing = foo
#that_thing = bar
end
end
# View
<%= #this_thing %>
<%= form_for #that_thing %>
Of course you can use partial to render the form, as long as you feed it with variable it needs.
Try
<%= form_for SomeThing.new do |f| %>
Without fully understanding what you are trying to accomplish, I'll make this suggestion.
Add a before filter to your ApplicationController (alternatively you could create a module and mix it in where needed). Then call the before_filter when needed. This example will always run the before filter:
class ApplicationController
before_filter :set_something
private
def set_something
#something = ... # Fill in the logic here
end
end
Then add your form where needed. You can even make it appear conditionally depending on whether #something is set.
<% if #something %>
# Form goes here
<% end %>

Rails remote form, replace after create

I have a typical "create" form action, that's set to be a remote call.
What I want to do is after the form is submitted, replace the form with the "edit" view with an additional form field, so that once they submit that second form, it updates instead of creating a new record.
So basically, the form would change from "create" to "edit"...but all via ajax calls.
I'm running Rails 3.2.
You make an AJAX POST to /resources
Controller
def create
...
# you set #resource to be used in edit form
#resource = Resource.create params[:resource]
respond_to do |format|
# tell controller to respond to requests with JS format
format.js
end
...
end
Actually if you want just that behaviour you can remove anything in your controller.
def create
...
# you set #resource to be used in edit form
#resource = Resource.create params[:resource]
...
end
Be sure to make the POST with JS format:
<%= form_for #resource, format: :js %>
View
file create.js.erb is served by controller, and run by browser.
$(selector).html("<%= escape_javascript( render 'edit') %>")
You have to define selector according what you have in page with form for new items.
file _edit.html.erb is rendered inline in previous file
<%= form_for #resource, remote: true do %>
...

form_tag action not working in rails

I have this form in my application.html.erb.
<%= form_tag(:action=>"index", :controller=>"posts") %>
<p>
// code here
</p>
I dont understand why is this getting directed to posts->create instead of posts->index?
Thanks.
Basically, Rails observes and obeys "RESTful" web service architecture. With REST and Rails, there are seven different ways to interact with a server regarding a resource. With your current code, specifying the form's action as index doesn't make sense: Rails' form helpers can either POST, PUT or DELETE.
If you wanted to create a post, then redirect to the index, you can do so in the applicable controller action:
class PostsController < ApplicationController
...
def create
#post = Post.new
respond_to do |format|
if #post.save
format.html { redirect_to(:action => 'index') }
end
end
While your form would look like:
<% form_for #post do |f| %>
# put whatever fields necessary to create the post here
<% end %>
You seem to be a little mixed up with respect to the uses for each action. Here's a quick summary of typical RESTful usage:
Index -> view a list of items
New/Edit -> form where items are added or edited
Create/update -> controller action where items are created/updated
The reason your routes file is not taking you to index is because index is not an action where posts are typically created or updated. The best way is to go RESTful. Unless you have a very unusual situation, the best way to set your system up is probably a little like this:
# routes.rb
resources :posts
# application.html.erb (or better: posts/_form.html.erb).
<% form_for #post do |f| %>
<% end %>
# posts controller, whichever action you want to use
def new
#post = Post.new
end
By putting the form in a partial called form you can access it in new, edit, or wherever else you need to manipulate a post in your system.

Rails show views from a different controller

In my Ruby on Rails application
I have a page Aboutus - This has a Controller and View. Has no model.
I have a Comments model (generated by the rails generate scaffold comment) - This has a Controller, view, model
On my Aboutus page, I want to show the "Comments" from the comments model, so I am thinking of using the Comments index action (to list comments) and new action (to create new comments) on my Aboutus page.
I am having trouble getting this right.
This is what I did:
Aboutus controller, I added
redirect_to :controller => "comments", :action => "index"
Aboutus views, I added
<%= render 'comments/index' %>
It doesnt work, gives me Undefined redirect_to and nil object #comments errors.
Could you advise me
1. A proper way to do this
2. Syntax
3. Any thing to do to config.rb ?
you want to create a partial that you use to render the comments in the comments index view, and also in your view for the aboutus page
# in about_us and in 'comments#index'
<%= render :partial 'path/to/_partial' %>
#in the about_us controller, or whatever controller dispatches the about us view
#comments = Comment.all.where(:my_conditions)
#partial view
<% #comments.each do |comment| %>
..
<% end %>

Keep form fields filled after an error (RoR)

After validation, I got an error and I got returned back to :action => :new.
Some field on form already filled, so I want to keep them filled even after error message too.
How it can be done?
Your View (new.html.erb) something like following
<%= error_message_for :user %>
<% form_for :user, :action=>"create" do|f|%>
<%= f.text_field :login %>
<% end %>
Controller Code (create method)
def create
#user=User.new(params[:user])
if #user.save
redirect_to :action=>'index'
else
render :action=>'new' #you should render to fill fields after error message
end
end
Since in my case the form was in the view of another controller I did use flash to store my data and then check if there is data in flash present. If yes take this for default values for your input fields, if not just show whatever you want to show then.
So snippets from my code
flash[:date] = start_date
# in the view where to form resides
start_day = flash[:date].nil? nil : flash[:date].day
# ...
<%= select day start_day ... %>
Hope that helps some of you ;-).

Resources