rails g scaffold needs explanation - form_for submits to index? - ruby-on-rails

I am trying to understand the stuff going on during the creation of an object using the pages generated by the command rails g scaffold ModelName.
What I don't understand is that given a model Location, the _form.html.erb form-tag looks like this:
<%= form_for(#location) do |f| %>
This would, if I understand it correctly, point the form submission to location_path, which is like the index (or list) of all locations stored in the database.
Why is the form not pointing to create or update? Where on the way are the objects actually created? I'd be really grateful if someone could describe the flow here, like
_form.html.erb submits to
create in locations_controller.rb which redirects to
index in locations_controller.rb, which renders
sometemplate.html.erb

Where the form submits depends on #location.new_record?.
If it’s a new record, it will POST to locations_path: /locations. That maps to LocationsController#create.
If it’s an existing record, it will PUT (or PATCH on newer versions of Rails) to location_path(#location): /locations/:id. That maps to LocationsController#update.
As #Pavan suggests in the comment, a look at the existing routes can help with understanding routing:
rake routes

Related

Rails Modify Scaffold Form

Using rails 5.0.0 for building a simple timecard module for a web application. My question is how do I go about modifying a form which is automatically being rendered by rails scaffold
rails g scaffold Timesheet user:string clock:string time:datetime
=== new.html.erb file ===
<%= render 'form', timesheet: #timesheet %>
In the user string want to add <%= current_user.email %> and in clock string want to add a drop-down? What is the best way to do this? Already have database table in place etc...
Illustration below
Thanks in advance!
The form is in an automatically generated partial, located in app/views/timesheets/_form.html.erb.
Ok, in: app/views/timesheets - you should find your form. If you change something in form, check it with your 'new' merhod (or with last method - if you didn't change/add anything: this method will get your params) in controller.
When you run
$rails generate scaffold <name>
you will auto-generate a ready to use controller, model, and views with a full CRUD (Create, Read, Update, Delete) web interface.
You can modify each of the CRUD operations to your liking, in your case timesheets view which is located in app/views/timesheets/.

ruby on rails 4.2 - ActionController::UrlGenerationError in Prodotti#new

I'm following the tutorial http://guides.rubyonrails.org/getting_started.html but i'm stuck on section 5.2 'the first form'
The error is after i put prodotti_path
<%= form_for :prodotto, url: prodotti_path do |f| %>
my rake routes:
Prefix Verb URI Pattern Controller#Action
welcome_index GET /welcome/index(.:format) welcome#index
prodotti_index GET /prodotti(.:format) prodotti#index
POST /prodotti(.:format) prodotti#create
new_prodotti GET /prodotti/new(.:format) prodotti#new
edit_prodotti GET /prodotti/:id/edit(.:format) prodotti#edit
prodotti GET /prodotti/:id(.:format) prodotti#show
PATCH /prodotti/:id(.:format) prodotti#update
PUT /prodotti/:id(.:format) prodotti#update
DELETE /prodotti/:id(.:format) prodotti#destroy
root GET / welcome#index
but when i refresh the page http://localhost:3000/prodotti/new/ the rails say:
ActionController::UrlGenerationError in Prodotti#new
Why? i'm new to ruby and ror, sorry !
Firstly, welcome to the Rails community!
Here's what you need to do:
#app/controllers/prodottis_controller.rb
class ProdottisController < ApplicationController
def new
#prodotti = Prodotti.new
end
def create
#prodotti = Prodotti.new prodotti_params
end
private
def prodotti_params
params.require(:prodotti).permit(:x, :y, :z)
end
end
Then in your view:
#app/views/prodotti/new.html.erb
<%= form_for #prodotti do |f| %>
<%= f.text_field :attribute_name %>
<%= f.submit %>
<% end %>
OOP
The problem you have is you're using a symbol in your form_for. Whilst this does work, it is not the best way to get it working, especially for a beginner.
Without going into too much detail, I'll explain that form_for is what's known as a helper method. If you pass this certain credentials, it will construct an HTML form for you:
Typically, a form designed to create or update a resource reflects the
identity of the resource in several ways: (i) the url that the form is
sent to (the form element's action attribute) should result in a
request being routed to the appropriate controller action (with the
appropriate :id parameter in the case of an existing resource), (ii)
input fields should be named in such a way that in the controller
their values appear in the appropriate places within the params hash,
and (iii) for an existing record, when the form is initially
displayed, input fields corresponding to attributes of the resource
should show the current values of those attributes.
In Rails, this is usually achieved by creating the form using form_for
and a number of related helper methods. form_for generates an
appropriate form tag and yields a form builder object that knows the
model the form is about. Input fields are created by calling methods
defined on the form builder, which means they are able to generate the
appropriate names and default values corresponding to the model
attributes, as well as convenient IDs, etc.
This basically means that you're meant to pass objects to the form_for helper - objects which have been built in your model and assigned in your controller.
The objects in Ruby are used by Rails throughout your application. Indeed, as Ruby is object orientated, all the things you do with the language, and frameworks, are meant to revolve around objects too.
Rails is object orientated in its own way. Remember, Rails is a framework which sits on top of Ruby. Thus, anything you do has to have objects at the center of the flow:
Models construct the objects in Rails.
Everything from your routes to controller actions take the idea that your models will be invoking data objects -- making it that each "helper" method in Rails (such as form_for) can be used with the corresponding objects you've built.
This is why I recommended setting the appropriate variable and passing it to your form helper. This will tie into your routes and controller actions, and should work for you.

Rails naming convention issue

My question pertains to a Rails naming convention conundrum. My application has sign up, sign in, sign out features.
For the sign up page, I used form_for(#user) helper.
For the sign in page I used a form_for(:session, url: sessions_path). But in my routes.rb file I have included the resources :sessions instead of the singular as mentioned in the argument of form_for helper in the sign in page.
If someone could:
1.) Solve this particular form_for issue
2.) More importantly point me in the direction where I can learn/read about Rails naming conventions, I would be highly indebted.
I bet that #user has been initialized with User.new - this is a new user. When you sign up you want to create a new user so you can translate form_for(#user) as "form for a new user". Note that in this case you provide form_for an ActiveRecord User instance, which is the way it was meant to be used.
When you give form_for a symbol and not an instance of an ActiveRecord model, it uses the symbol to nest the inputs inside the form. For example, if you put <%= f.text :name %> in your form it will generate <input name="session[name]" type="text">. Also, when an existing user signs in you do not want to create a new user(like in step 1), you just want to create a new session for an existing user, thus posting to sessions_path looks very intuitive.
You can type the command rake routes in your terminal and get all the named routes set for your application, this will give you a very good insight of how rails converts the resources command into named routes.
For further info read the following:
Rails Routing Guide
form_for ApiDock documentation

Understanding function form_for() in Rails

I'm currently reading Beginning Rails 3. I'm coming from PHP and trying to learn Ruby and Rails. I'm looking at a _form partial and I have a few questions. Specifically about the line:
<%= form_for(#article) do |f| %>
What is the purpose of having the #article object in there as well as what is the function of variable f?
thanks,
mike
form_for accepts a model so that it can do a few things for you under the covers:
It will read any current values off of that model and populate them in the fields you specify
It will generate the proper URL for that resource (assuming you're following conventions, otherwise you still have to specify it)
It can display any validation errors on the model if you're displaying after a POST.
If you just want the tag helpers, there's also form_tag and friends
The #article is what the form is for (in this case).
The f is for creating individual form elements; it's a builder object yielded by form_for's block.

How to pass a param from one view to another in Ruby on Rails, using POST

I feel like this should be an easy thing to figure out, but I'm stumped.
I have a value in a Project's instance variable called ID. I want to pass that value to a new Photos page to associate each photo that is created with that specific project, but I don't want the Project's ID to show up in the visible query string.
I've tried using link_to and button_to, but (I suspect) since I'm using "resources :photos" in my routes, all of the requests that come to photo#new are being interpreted as GET instead of POST.
Helllllllllllllllp!
Thanks to anyone that can give me some insight, I'v been killing myself over this for the past hour or two already.
--Mark
The usual way to do this in Rails is to create a route that matches urls like this: /projects/4/photos/new. Doing something else is up to you, but Rails makes it really easy to do stuff like this. See more on routes in Rails 3.
Your entry in routes.rb should look something like this:
resources :projects do
resources :photos
end
Then in app/controllers/photos_controller.rb you'd have this for the "New Photo" form page:
def new
#project = Project.find_by_id(params[:project_id])
end
and this for the action that the form in app/views/photos/new.html.erb submits to:
def create
#project = Project.find_by_id(params[:project_id])
#photo = #project.photos.create(params[:photo])
end
Of course you'll want to have error handling and validation in here, but this is the gist of it. And remember, use GET for idempotent (non state-changing) actions (e.g. GET /projects/4/photos), POST for creating a new thing (e.g. POST /projects/4/photos), and PUT for updating an existing thing (e.g. PUT /projects/4/photos/8).

Resources