'no implicit conversion of symbol into Integer' with form_for - ruby-on-rails

I am receiving
no implicit conversion of symbol into Integer
with the following code:
<%= form_for #question, admin_questions_path do |f| %>
<%= f.label :question %>
<%= f.text_area :question %>
<% end %>
But when I change the form_for method as follows; the form renders correctly.
<%= form_for [:admin, #question] do |f| %>
What is the difference between the code? If the incorrect code is routing to the create method of the Admin::QuestionsController with the path admin_questions_path why does it not work? I am new to rails and namespacing, so I may be missing something completely obvious.
Edit:
The questions controller is namespaced under admin.
namespace :admin do
resources :questions, only: [:index, :new, :create]
end

The first example should be syntactic sugar for writing the following (if i'm not mistaken):
form_for [#question, admin_questions_path] do |f|
Where you most likely wanted:
form_for #question, url: admin_questions_path do |f|
Your second form uses polymorphic routing to automatically determine the correct route, this is useful if you want to use the same form for editing and creating. The link Arup provided should be helpful about that topic, as is the guide about routing at: http://guides.rubyonrails.org/routing.html

Related

form_for Ruby On Rails

I'm trying to follow a tutorial on using basic AJAX to add a record to a list in place, and I'm having issues using form form_for.
Here is my code.
<%= form_for ([#product, #product.new]) do |p| %>
<p>
<%= p.label :product_part %>
<%= p.text_field :product_part%>
</p>
<p>
<%= p.submit %>
</p>
<% end %>
The error I am getting is
undefined method `new' for nil:NilClass
I understand why I am getting the error (#products hasn't been "initialized") but I have no idea how to fix this issue (I am sure it's simple). I have seen something about putting a resource in the routes file, but I do not know for sure.
If you're trying to make a form for a new product, you should (in your controller) be setting #product to an instance of a new Product:
# app/controllers/products_controller.rb
def new
#product = Product.new
end
In your view, using [#product, #product.new] makes no sense. You can't invoke new on an instance of a product. It's very unclear why you're not simply using the following, which is the correct use of form_for with a new instance of an ActiveRecord model:
form_for #product do |p|
Do this:
#app/controllers/products_controller.rb
class ProductsController < ApplicationController
def new
#product = Product.new
render :form
end
def edit
#product = Product.find params[:id]
render :form
end
end
#app/views/products/form.html.erb
<%= form_for #product, remote: true do |f| %>
<%= p.label :product_part %>
<%= p.text_field :product_part%>
<%= f.submit %>
<% end %>
This will do everything you need for both the new and edit methods (which you raised concerns about in your comments with #meagar).
This should be corroborated with the following routes (you can see why here):
#config/routes.rb
resources :products
I would say In case you need to look the form_for helper ; to understand the behavior of the method.
The method form_for It accept the argument as record, options = {}. The value of record could be a symbol object or a newly object of respective class in your case Person.new.
Second argument could be
:url, :namespace, :method, :authenticity_token, :remote , :enforce_utf8, :html
Among them :remote => true option is used as the Ajaxify your request.
form_for is a helper that assists with writing forms. form_for takes a :remote option. It works like this:
<%= form_for(#article, remote: true) do |f| %>
....
<% end %>
This will generate the following HTML:
<form accept-charset="UTF-8" action="/articles" class="new_article" data-remote="true" id="new_article" method="post">
...
</form>
Note the data-remote="true". Now, the form will be submitted by Ajax rather than by the browser's normal submit mechanism.
For more info about Form-For helper
Hope this solve your problem!!!.

Re-writing Rails form helper in simple form

Is the following line in Rails Simple form
<% form_for #user :url => {:action => "attempt_login"}, do |f| %>
The same as the following in Rails form helper?
<%= form_tag(:action => 'attempt_login') do %>
If not, can you tell me what it would be? I need to redo some form code and I would like write down the correct syntax before running the app...
For in the case of passing parameters (i.e. :action) the simple form documentation is rather ambiguous.
Thanks!
The form_for is usually used for a specific record in order to update or create it.
Example:
# view in HAML (not ERB)
= form_for #user do |f|
= f.text_field :username
# matched with the routes
resources :users
other example with nested resources:
# routes.rb
resources :users do
resources :posts
end
# view in HAML
= form_for [#user, #post] do |f|
= f.text_field :content
Since you gave a record as an argument to the form_for method, it can "pre-fill" some fields of your record, i.e. if the #user already has a value for username, the field will be populated with that username.
It is true that you can specify an action to the form_for, something like this:
= form_for #user, url: { action: :custom_action } do |f|
The form_tag is used for the "other forms", such as a login form or a specific controller's action to be done.
Example:
# view in HAML
- form_tag action: :login do
= text_field_tag :username
= password_field_tag :password
To conclude, I would (based on my opinion) use the form_for helper if you are actually using a model's instance in the form and trying to modify/create it. So in your case, I would not use the form_for helper but use the form_tag instead (because you want a login form).
I recently migrated my form_tag methods to form_for because form_for was used in a gem that formatted my form using bootstrap. This was for a login form with no model. Here's how I used form_for without a model:
<%= form_for(:login, :action => 'attempt_login') do %>
I assume this works for simple_form as well:
<%= simple_form_for(:login, :action => 'attempt_login') do %>
Instead of using a form_tag, because the gem didn't decorate it, I used a form_for with a :symbol instead of a #model

How to fix undefined method error in rails?

I keep getting an error saying: undefined method `androids_path' for #<#:0x007ff5edcd5330>. It's saying the error is at line 1 in new.html.
The name of the model is Android and is at android.rb. Any advice on how to fix this?
In androidapps_controller.rb:
def new
#android = Android.new
end
In new.html I have:
<%= form_for(#android, validate:true) do |f| %>
<% #android.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %>
</p>
<%= f.submit %>
<% end %>
routes.rb
Grabapp::Application.routes.draw do
root :to => 'iosapps#index'
get "static_pages/home"
get "static_pages/add"
get "static_pages/about"
devise_for :users
resources :iosapps
resources :androidapps
Add to your routes.rb:
resources :android
You're error is because you've asked form_for to do resource based routing!
<%= form_for(#android, validate:true) do |f| %>
But you didn't define the resource based routing required to make it work!
Your model and controller are not matched (Android vs AndroidApp), so need to specify the correct url in your form:
<%= form_for(#android, validate: true, url: androidapps_path) do |f| %>
<%= form_for(#android, validate:true) do |f| %> automatically sets up the correct HTTP method (normally POST or PUT) with the HTML markup for a form. It also assumes you have a url set up called /androids in the case of POST and /androids/:id in the case of PUT. So for this to work you need to tell rails to create the necessary routings. This is done by adding the following line in config/routes.rb namely resources :androids.
This is why is is better to match up your model and controller names, Rails can then automatically infer the correct controller actions based on the model name.
You need to read up a bit more on routing and how it works. Do it here: http://guides.rubyonrails.org/routing.html

form_for [#parent, #child] causes undefined method `parent_child_path' in Child#new

So a user has many colleges (that they have attended), and a college belongs to a user. I call these colleges, college_profile as they are the college attribute of a user's profile.
I am running into the problem when trying to generate a new college. My controller for the college at the moment is very simple:
def new
#user = User.find(params[:id])
#college = current_user.college_profile.build if signed_in?
end
And the view equally as simple: (views/college_profiles/new.html.erb)
<%= form_for [#user, #college] do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<% end %>
And yet, for some reason I get the following error:
NoMethodError in College_profiles#new
Showing .../app/views/college_profiles/new.html.erb where line #4 raised:
undefined method `user_college_profiles_path' for #<#<Class:0x5bf1b68>:0x673aef8>
As I am still learning Rails, I really don't even understand what this error is exactly referring to. A fair amount of Google-ing has given me no luck, or if the answer is out there I simply don't know enough to realize I was looking at it. Any help would be greatly appreciated!
If it is relevant, seeing as we're talking about paths, here's an excerpt from my routes file:
resources :users, :only => [:index, :new, :create, :destroy, :update, :edit] do
resources :college_profiles, :only => [:new, :create]
end
If any more info is needed, just let me know. Thanks!
The thing about form_for is that its URL is based on the model that you passed in. In your case, it's:
<%= form_for [#user, #college] do |f| %>
Rails automatically looks for user_college_profiles_path because you assigned User to #user, and current_user.college_profile to #college.
Fortunately, Rails provides a way to override the default URL the form will go to on submit:
<%= form_for([#user, #college], :url => your_custom_route_path) do |f| %>
All you need to do is create your_custom_route in your routes.rb
Source: Ruby on Rails Guides: Rails Form Helpers
Rails is trying to create a path that will be used to post data from the form to your controller. The action that it's looking for is create, but you only have new defined in your routes. If your controller is called CollegeProfiles, then you will need to change your nested route to:
resources :college_profiles, :only => [:new, :create]

Rails 3 routing not generating proper paths for new vs edit views

I'm getting some funkiness that is absolutely confounding me with Rails 3. I can't seem to get the routing to generate the proper path using the (mostly) standard _form style of the scaffold.
First off, I'm doing everything within an "admin" namespace. I'm finding that the form partial throws a routing error if I use admin_team_path(#team) to generate the path when creating a new Team, but then submitting the form when editing, it throws an error unless I use admin_teams_path.
admin_team_path(#team) where #team = Team.new throws this error:
No route matches {:controller=>"admin/teams", :action=>"show", :id=>#}
Meanwhile...
admin_teams_path(#team) where #team = throws this error:
The action 'edit' could not be found for TeamsController
In the latter case, it seems to be directing to the URL: http://localhost:3000/teams/1/edit - it's not recognizing the namespace properly.
Here's my full _form.html:
<%= semantic_form_for(#team, :url => admin_teams_path(#team)) do |f| %>
<%= f.semantic_errors %>
<%= f.inputs do %>
<%= f.input :user_id %>
<%= f.input :league_id %>
<%= f.input :name %>
<% end %>
<%= f.buttons do %>
<%= f.commit_button :button_html =>{:class => "primary"} %>
<% end %>
<% end %>
What gives? What's the right way to create this form partial so it works for both new and edit actions?
Namespaces seem to be such a mess to work with.
Presuming you have defined your routes in a RESOURCEful manner, like so:
namespace :admin do
resources :teams
end
Then, in your _form partial you can let rails take care of the action like so:
<%= semantic_form_for(["admin", #team]) do |f| %>
.... #rest of the code
<% end %>

Resources