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

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.

Related

Form_for namespaced route for a resource with multiple states

I have a Blog model which has different states. In order to keep a skinny controller and follow the convention of only having CRUD operations per controller, I followed DHH's namespacing controllers pattern and namespaced out the Blog controller.
Now I have a Blogs::NewDraft controller, a Blogs::AwaitingApproval controller, and a Blogs::Active controller.
I have the following in my _form.html.erb for creating a new draft for a blog. It works for creating a new record, but it does not work for updating an existing record:
# app/views/blogs/new_drafts/_form.html.erb
<%= form_for #blog, url: :blogs_new_drafts do |f| %>
...
<% end %>
When I go to update the draft it throws this error:
No route matches [PATCH] "blogs/new_drafts"
I'm having trouble figuring out why it is saying there is a routing error when I update here because when I run rake routes it does have a route for a PATCH to blogs/new_drafts#update
Change your URL:
<%= form_for #blog, url: :blogs_new_draft(#blog) do |f| %>
...
<% end %>
The URL for your create action will differ from the update. The update action URL needs to know which blog you are trying to update.
That said, if you are trying to share _form with the new and edit views, having a single form won't work, since you are providing custom URLs which will differ between those two actions. There's ways to make it work (pass in the URL to the partial / instantiate the URL in your controller as a variable / add the form tag directly to your new/edit views / etc), but something will need to be done.

Example of form_for custom REST action and .haml?

I'm redeveloping a .haml form_for for an #edit_profile view to accommodate a controller where the #edit and #update methods have already been claimed. I had the form working before with the standard methods, but apparently Rails was doing a lot behind the scenes that I must now specify and I'm stuck.
I'm the sort who learns by mimicry and breaking things, so I need an example. I've googled around without any luck, so I'm hoping someone here can point me at one. Specifically: where do I put the method::patch and update_profile paths?
I just need the haml. I've established that the controller works with the new methods (#edit_profile and #update_profile), so all I have to do is connect the form to the controller.
Here's the repository if anybody needs that:
https://github.com/sidhene/MetPlus_PETS/blob/Update_CompanyPerson-%23146/app/views/company_people/edit_profile.html.haml
Thanks in advance,
A
The url argument needs to be to the update_profile action instead of the update action. Change update_company_person_path(#company_person) to update_profile_company_person_path(#company_person)
Edit: Your config/routes looks correct, but run rake routes just ot be sure. You should see a line with update_profile_company_person and PATCH in it.
form_for takes a value and populates its other HTML attributes from it (action / method etc):
form_for generates an appropriate form tag and yields a form builder object that knows the model the form is about.
As you see, the HTML reflects knowledge about the resource in several spots, like the path the form should be submitted to, or the names of the input fields.
The whole point of form_for is that you're meant to pass a resource / object to it.
Populated from the model, this object / resource will contain an array of data, such as the Class name etc, which Rails then uses to populate the form.
As per the docs:
...to create a new person you typically set up a new instance of Person in the PeopleController#new action, #person, and in the view template pass that object to form_for:
<%= form_for #person do |f| %>
The HTML generated for this would be (modulus formatting):
<form action="/people" class="new_person" id="new_person" method="post">
Thus, if you wanted to infer a different path / url for your form, you'll need to explicitly define it:
= form_for #profile, url: profile_update_path(#profile) do |f|
--
In your case, you're using a nested resource, which means that you have to pass both parts of the route as an array:
= form_for [:company_person, #company_person] do |f|
This should work fine for you.

undefined method `pushes_path' for #<#<Class:0x007f85a15c6c90>

i'v been trying to resolve this error for the past 5 hours and I'm gonna burn my computer if I can't solve this.
undefined method `pushes_path' for #<#:0x007f859d605250> this is the error code I'm getting but i don't understand why.
this is my index.html.erb file inside of the interaction
<%= simple_form_for #push do |f| %>
<%= f.input :payload, as: :text %>
<%= f.input :segment, as: :radio_buttons %>
<%= submit_tag "start the campaign" %>
<% end %>
and this is my interaction controller
class InteractionController < ApplicationController
def index
#push =Push.new
end
end
Push is my table in the database and i'll get the inputs and write them in the database to use them for later one.
and this is my routes file
devise_for :partners
get 'home/index'
get 'segmentation/index'
get 'interaction/index'
root to: "home#index"
i really don't know why its looking for pushes_path, what am i doing wrong?
form_for
The problem you have is that your form_for method is going to try and generate a route based off your #path object. And as such, if you don't have a path created for it, you'll receive the error you're getting:
:url- The URL the form is to be submitted to. This may be represented
in the same way as values passed to url_for or link_to. So for example
you may use a named route directly. When the model is represented by a
string or symbol, as in the example above, if the :url option is not
specified, by default the form will be sent back to the current url
(We will describe below an alternative resource-oriented usage of
form_for in which the URL does not need to be specified explicitly).
The bottom line is that as Rails is object orientated, its built around the assumption that you'll have routes set up to handle the creation of individual objects.
Every time you use form_for, Rails will attempt to construct your routes from your object -- so if you're trying to do the following, it will treat the routes as photo_path etc:
#app/views/pushes/new.html.erb
<%= form_for #push do |f| %>
...
<% end %>
--
Fixes
As #mandeep suggested, there are several fixes you can employ to get this to work:
Firstly, you can just create a route for your push objects:
#config/routes.rb
resources :pushes
Secondly, as you're using a different controller, you'll want to do the following:
#config/routes.rb
resources :interactions
#app/views/pushes/new.html.erb
<%= form_for #push, url: interaction_path do |f| %>
...
<% end %>
This will route your form submission to the interactions controller, rather than the pushes controller that you'll get by default!
Objects
Something to consider when creating Rails-based backends is the object-orientated nature of the framework.
By virtue of being built on Ruby, Rails is centered on objects - a term for a variable, which basically encompasses much more than just a piece of data. Objects, in the case of Rails, are designed to give the application:
Once you understand this, the entire spectrum of Rails functionality becomes apparent. The trick is to realize that everything you do in Rails should be tied to an object. This goes for the controllers too:
--
Ever wondered why you call resources directive in your routes, for a controller? It's because you're creating a set of resourceful routes based for it:
Do you see how it's all object orientated?
This gives you the ability to define the routes for specific controllers etc. The most important thing to note is how this will give you the ability to determine which routes / controller actions your requests should go
--
There's nothing wrong in using the controller setup as you have - the most important thing is to ensure you're able to define the custom URL argument, as to accommodate the non-object based structure
In your index action you have
def index
#push =Push.new
end
and your form has
<%= simple_form_for #push do |f| %>
so your form is looking for /pushes with post verb or pushes_path and you don't have that route in your routes.rb file so to fix this you need to add this in routes.rb:
resources :pushes
Update:
when you add resources :push rails basically creates seven different routes for you. One of which is
POST /pushes pushes#create create a new push
and if you look at the html generated by your form it would be something like:
<form action="/pushes" class="new_push" id="new_push" method="post">
// your fields
</form>
notice the action and verb so when you submit your form your routes are checked for them and since you didn't define them in your routes you were getting this error
And how will i be able to use the params i m getting from this form with this new resource addition?
Your form will take you to pushes_controller create action so first of all you'll have to define them. You can access them simply by params[:pushes] in your controller action but since you want to create a new record so you'll have to permit those attributes, checkout strong parameters
If you are using rails >= 4 then you can do
class PushesController < ApplicationController
def create
#push =Push.new(push_params)
if #push.save
redirect_to #push
else
render 'interaction/index'
end
end
private
def push_params
params.require(:push).permit(:attributes)
end
end
If you are using rails < 4 then instead of permitting these attributes(because strong parameters feature came from rails 4) you'll have to tell rails that these attributes are accessible by writing this in your pushes.rb
attr_accessible :attribute_name
Why it is assuming that its pushes controller?Because of the Push.new creation?
That's because if you look at your index action #push = Push.new so #push contains a push object with nil values(as you have just initialized it) so this is where rails magic comes, rails automatically tries to figure out url of your form and since your #push is only an initialized variable so rails takes you to create action for it. For details you should checkout rails polymorphic urls If you want your form to go to interaction_controller or some other url then you'll have to specify the url option for it
<%= form_for #push, url: "your_url_for_custom_method" %>
// other fields
<% end %>
And in the end you should really read docs

rails g scaffold needs explanation - form_for submits to index?

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

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.

Resources