Rails : How does new action called create action?
It's not passed to create
action, it's instantiated again with params you pass from the form displayed with new
action.
create
action is called with POST request to the path specified in config/routes.rb, leading to specific controller and action.
How is the 'new' action redirected to 'create' in Rails?
OOP
The bottom line answer to your question is that Rails is object orientated (by virtue of being built on top of Ruby). This is very important, as it means everything inside Rails should be based around objects:
This leads me to the routes - the resourceful
nature of Rails' routes is down to the same idea, that you need to work with objects in your application - hence the resources
directive providing 7 key actions to manipulate those objects
To fully understand Rails, you really need to look into how it works with objects, specifically how they interact with each other
Redirect
To answer your question regarding the redirect
, the simple answer is that Rails doesn't "redirect" to any action specifically
Remember, Rails is stateless - it does not persist data through requests - it only has the data which you either initialize at the time, or have sent it
What you're confused about is how some of the Rails actions seem to be sending your requests to the appropriate "request" action. The answer to this lies in the helpers / methods you use, specifically form_for
form_for
form_for builds forms from their ActiveRecord objects.
Therefore, if you perform the following:
#app/controllers/your_controller.rb
Class YourController < ActiveRecord::Base
def new
@model = Model.new
end
end
This will give Rails the knowledge that it's loading a new
object, and therefore will use the form_for
method to send the request to the create actionIf you used form_tag
, you would not get a redirect to the create
action -- that's the magic of Rails -- it's been built to accommodate objects
How do I create a new/create action for items?
resources :users do
resources :items, only: [:new, :create]
end
This will nest items route inside user. Check rake routes
and you will not get this items_path
You have to define resource :items
to get items_path
So if you want to use nested routes you have to update your form and controller and if not just routes resource :items
<%= form_for [@user, @item] do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.submit "Save" %>
<% end %>
and controllerdef new
@item = Item.new
@user = current_user
end
How are params passed from the New to Create action in Rails?
You are mixing two requests with each other. When you hit the new
action, a view that contains your form
gets rendered. As it gets rendered, the new
action finishes, and now the new
action has nothing to do with create
action.
You need new
action to create a form
through form_for
method in which you actually pass an object, in your case @post
.
The create
action is independent, and params
it receives, they have nothing to do with new
method, those params
are received through form
rendered in the new.html.erb file of views.
You can also invoke the create
method in your controller by sending the data through AJAX or even using cURL or POSTMAN - a chrome extension.
And as you asked:
Rails doesn't channel theseHow does rails channel these params to create despite the page refresh that occurs?
params
, Rails run at back-end, Rails just receives those params
. They are sent through an HTML form, and as I said earlier there are other ways to send params
as well. Rails - How does the show and new action work
Render produces a string that will displayed as the response to the request to the application.
redirect_to produces a response header resulting in a new request to the application.
The render action 'show', location: @product
uses the the file app/views/products/show.html.erb
with @product
as a parameter to produce the html which will be returned.
The reason some of the controller functions are empty is that rails are using defaults. So if you don't tell rails what to render then rails will look for a file in the appropriate location.
Methods ending with redirect_to
are usually post/patch requests saving something in your database and after the requested action has been performed they redirect the user to a method meant for displaying information.
Rails new vs create
Within Rails' implementation of REST new and create are treated differently.
An HTTP GET to /resources/new
is intended to render a form suitable for creating a new resource, which it does by calling the new action within the controller, which creates a new unsaved record and renders the form.
An HTTP POST to /resources
takes the record created as part of the new action and passes it to the create action within the controller, which then attempts to save it to the database.
Rails form going to new action instead of create action
form_for @parent, :url => leads_path, :method => "post"
Also, you don't need the form tag wrapped around the outside, form_for
generates its own form tag Call create action from different controller
Your mistake is inside if-else in the controller. You're checking @room
before you define it, so it is always nil. It should be:
def create
# use find_by here, otherwise you get RecordNotFound error
@room = Room.find_by(id: params[:room_id])
if @room
# use build, because create saves the instance
@booking = @room.bookings.build(booking_params)
if @booking.save
redirect_to room_path(@room)
else
# I suppose you don't want render bookings/new view here
render 'books/show'
end
else
@booking = Booking.new(booking_params)
respond_to do |format|
# redirect and render logic goes here. BTW, do you really need json response format?
end
end
end
end
Also, define in rooms#show action@booking = @room.bookings.build
and use the instance in the form to correctly display validation errorsform_with(model: [@room, @booking], local: true) do |form|
create action in rails
By default scaffolding on form (read here)
When the user clicks the Create Post button on this form, the browser
will send information back to the create action of the controller
(Rails knows to call the create action because the form is sent with
an HTTP POST request; that’s one of the conventions that were
mentioned earlier):
def create
@post = Post.new(params[:post])
respond_to do |format|
if @post.save
format.html { redirect_to(@post,
:notice => 'Post was successfully created.') }
format.json { render :json => @post,
:status => :created, :location => @post }
else
format.html { render :action => "new" }
format.json { render :json => @post.errors,
:status => :unprocessable_entity }
end
end
end
If you want customize an action on new form scaffold, you should add :url => {:action => "YourActionName"}
on your form.Example :
#form
form_for @post, :url => {:action => "YourActionName"}
#controller
def YourActionName
@post = Post.new(params[:post])
respond_to do |format|
if @post.save
format.html { redirect_to(@post,
:notice => 'Post was successfully created.') }
format.json { render :json => @post,
:status => :created, :location => @post }
else
format.html { render :action => "new" }
format.json { render :json => @post.errors,
:status => :unprocessable_entity }
end
end
end
#route
match '/posts/YourActionName`, 'controllers#YourActionName', :via => :post
Rails Call 'Create' Action from Another Controller
Move this method to application_controller.rb and allow to pass params to it.
Then you'll be able to call it from any controller method
Related Topics
Sql Like Operator in Ruby on Rails
What Is The Ruby Equivalent to This Curl Request
Sinatra Not Persisting Session with Redirect on Chrome
Running "Bundle Install" Fails and Asks Me to Run "Bundle Install"
How to Open File in Default Application. Ruby
Binding to Networking Interfaces in Ruby
Error While Starting Puma Server with Workers
How to Convert JSON to Xml in Ruby
Rails How to Create Data Schema Seed Data
Capistrano, Firewalls and Tunnel
How to Make Two Thor Tasks Share Options
Many to Many Table with an Extra Column in Rails
Rails: What's Wrong with This Multiple Join with Conditions on The Associations
Is 'Respond_To_Missing''s Second Argument Useful for Anything