Rails remote form, replace after create - ruby-on-rails

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 %>
...

Related

How to POST to the external sites form from rails controller with redirecting to this external site at the same time?

I heve mysite.com (rails app) and there is not mine site other.site.com
There is the form on the other.site.com to which I want to put some data. The data is not sensitive (not a login/pass/...) but it is not working via GET.
So I need to gather data in my controller and redirect user to the form at the other.site.com filling this form at the same time.
I do not need to submit this form, I just need to fill it and leave it up to user to submit the form or not.
Use form_tag helper:
<%= form_tag 'url_where_you_want_to_POST' %>
... your form controls
<% end %>
More information about this helper you can read in the rails api reference.
you can use JSON to send data:
site 1:
inside controller
def action1
#say you want send a #data
respond_to do |format|
format.json { render :json => #data }
end
end
site 2:
now get this data and generate a form
def action2
#data_from_site1 = Net::HTTP.get(URI.parse("http://example.com/action1.json")) #or you can use html format
#parse_data = JSON.parse #data_from_site1
# now use this #parse_data inside the View of this action
end
I hope you are looking for this.

rails multiple forms in one view

I have index method that displaying two forms Sign in and Sign up, that means user can create an account and a log in from same place.
so I have users controller with index method that displaying a view with Sign in and Sign up form with two partials one is _signin.html.erb and _signup.html.erb in index.html.erb.
Any Idea How can I handle new and create methods from users and sessions controllers (may be I can ignore new method)?
As long as each form is being rendered with the correct model object and/or the correct value to the :url option, each form should send the expected request (assuming you're rendering your forms with form_for).
For example, your sign in form should start with something like this::
<%= form_for :session, :url => sessions_path %>
#...
<% end %>
As long as a POST request (the default from form submissions) is sent to a "collections" resource (i.e. /sessions) it will route the request to the create action in your SessionsController or whatever you named your controller.
For signing up, you probably have something like this:
<%= form_for #user do |f| %>
# ...
<% end %>
The #user model object will assume the request should go to /users. Again this will call your create action in your UsersController.
Of course, all this is also assuming your config/routes.rb file is just declaring each resource with something like:
resources :users
resources :sessions, :only => [:create, :destroy]
You usually have each form in separate views such as
match 'sign_in', :to => 'sessions#new'
match 'sign_up', :to => 'users#new'
But if you only want to display these forms in an index.html.erb view then these routes are no longer necessary.
<%= form_for :signin,:url=>{:controller=>"yourcontroller",:action=>"signin"},:html=>{:id=>"signin_form"} do |f|%>
...
<%end%>
<%= form_for :signup,:url=>{:controller=>"yourcontroller",:action=>"signup"},:html=>{:id=>"signup_form"} do |f|%>
...
<%end%>
One simple workaround that I found was that if the two forms have at least one uniquely named parameter, then you can simply route the POST request to a single action. Then within the action check which parameter exists and execute the corresponding code. You end up having essentially two actions within one action in your controller.
def create
if params[:username] and !params[:name]
# You know that the user pressed submit on whichever form
# has a field that fills params[:username].
# So do the action with that form's parameters here
# i.e, login an existing user
respond_to do |format|
format.html {redirect_to '/home', notice: "Login successful"}
end
elsif params[:name] and !params[:username]
# You know that the user pressed submit on whichever form
# has a field that fills params[:username].
# So do the action with that form's parameters here
# i.e, create a new user
respond_to do |format|
format.html {redirect_to '/onboard', notice: "Thanks for signing up"}
end
end
end
Just be sure to have it configured in your routes.rb so that when a POST request comes from the page the two forms are on, it will direct to this action in this controller.
Hope this helps!

render :new not going to the right place after a validation

I have a 'new' form that gets validated in a post model. When the validator kicks in, it renders incorrectly.
The new post page path is at '/posts/new'
On validation, the new post page path is at '/posts' .. I need it to go back to '/posts/new'.
This is my controller:
def create
#post = current_user.posts.build(params[:post])
if #post.save
redirect_to public_post_page_path(#post.public_url)
else
render :action => :new
end
end
I have a feeling it might have to do with my form. So here is the formtastic first line:
<%= semantic_form_for [:student, post], :html => {:id => "post_form"} do |form| %>
This is the correct behavior from rails.
In the create action it simply renders the "new" view file. As such the url will be /posts but the view will correctly display the form. There is nothing wrong with this behavior; and in general rails convention is good form. Also the built in rails errors work if you just render new; however if you redirect they won't display.
If you really feel like you want to go back to that url you need to use:
redirect_to
instead of render.
If validation fails, user should see the form with the errors and stay at /posts/new. That's what you want, right?
There's a simple way to achieve this.
Set remote: true on the form to prevent the url from advancing. Handle ajax:success to replace the form on the page with the newly rendered one.
$('form[data-remote=true]').on 'ajax:success', (e, data, status, xhr) ->
if isHTML(data)
thisForm = "form[id=#{#getAttribute('id')}]"
$(thisForm).replaceWith $(data).find(thisForm)
isHtml() function is from this question.

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.

What to render on error in a Rails controller

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

Resources