I am having problem with routing when using simple_form_for. I understand it is something to do with pluralizing but the same form is working perfectly for edit/update method.
undefined method `companies_path'
Did you mean? companys_path
company_path
companys_controller
def new
#company = Company.new
end
def create
#company = Company.new(company_params)
if #company.save
redirect_to #company
else
render 'new'
end
end
_form.html.haml
= simple_form_for #company do |f|
= f.input :name
= f.input :description
= f.input :website
= f.button :submit
rake routes
companys GET /companys(.:format) companys#index
POST /companys(.:format) companys#create
new_company GET /companys/new(.:format) companys#new
edit_company GET /companys/:id/edit(.:format) companys#edit
company GET /companys/:id(.:format) companys#show
PATCH /companys/:id(.:format) companys#update
PUT /companys/:id(.:format) companys#update
DELETE /companys/:id(.:format) companys#destroy
I guess the problem is, Edit/update is going for 'companys_path' and new/create is going for 'companies_path'. Any help is appreciated.
Controller name should be plural so in your case it should be companies_controller
Follow these steps to change it
Rename controller to companies_controller.rb
Change controller class name to
class CompaniesController < ActionController::Base
# controller code
end
Change in routes.rb
resources :companies
Edit
Controller naming conventions
link in comments by Greg
First thing, you should follow rails naming convention and rename your controller from companys_controller.rb to companies_controller.rb.
Your issue will be fixed after renaming.
Simple form taking assumption that you have followed rails naming convention and making request at companies_path which is not present in your routes.
Related
In my rails app I'm trying to use a form partial to display the same quiz on the new and edit views. I can see the new view page, but when I hit <%= f.submit "Submit Answers" %> I get an error saying No route matches [POST] "/flex_quiz/new".
Here is the form for line in my partial:
<%= form_for #flex_quiz, url: url do |f| %>
And here's how the locals stand in my new view:
<%= render partial: "quiz", locals: { url: new_flex_quiz_path, method: :post } %>
And my edit view:
<%= render "quiz", url: edit_flex_quiz_path(#flex_quiz), method: :put %>
Here are the route paths:
Prefix Verb URI Pattern Controller#Action
...
flex_quiz_index GET /flex_quiz(.:format) flex_quiz#index
POST /flex_quiz(.:format) flex_quiz#create
new_flex_quiz GET /flex_quiz/new(.:format) flex_quiz#new
edit_flex_quiz GET /flex_quiz/:id/edit(.:format) flex_quiz#edit
flex_quiz GET /flex_quiz/:id(.:format) flex_quiz#show
PATCH /flex_quiz/:id(.:format) flex_quiz#update
PUT /flex_quiz/:id(.:format) flex_quiz#update
DELETE /flex_quiz/:id(.:format) flex_quiz#destroy
Can anyone suggest how to fix this? I have looked at several similar posts (like this and this) but since I'm using partials the solution here is going to have to be a bit different.
EDIT
Here are my definitions in my flex_quiz_controller:
class FlexQuizController < ApplicationController
before_action :require_sign_in
def show
#flex_quiz = FlexQuiz.find(params[:id])
end
def new
#flex_quiz = current_user.build_flex_quiz
end
def create
#flex_quiz = FlexQuiz.new
#flex_quiz.flex01 = params[:flex_quiz][:flex01]
#flex_quiz.flex02 = params[:flex_quiz][:flex02]
#flex_quiz.flex03 = params[:flex_quiz][:flex03]
#flex_quiz.flex04 = params[:flex_quiz][:flex04]
#flex_quiz.flex05 = params[:flex_quiz][:flex05]
#flex_quiz.flex06 = params[:flex_quiz][:flex06]
#flex_quiz.flex07 = params[:flex_quiz][:flex07]
#flex_quiz.flex08 = params[:flex_quiz][:flex08]
#flex_quiz.flex09 = params[:flex_quiz][:flex09]
#flex_quiz.flex10 = params[:flex_quiz][:flex10]
#flex_quiz.user = current_user
if #flex_quiz.save
flash[:notice] = "Quiz results saved successfully."
redirect_to user_path(current_user)
else
flash[:alert] = "Sorry, your quiz results failed to save."
redirect_to welcome_index_path
end
end
def edit
#flex_quiz = FlexQuiz.find(params[:id])
end
def update
#flex_quiz = FlexQuiz.find(params[:id])
#flex_quiz.assign_attributes(flex_quiz_params)
if #flex_quiz.save
flash[:notice] = "Post was updated successfully."
redirect_to user_path(current_user)
else
flash.now[:alert] = "There was an error saving the post. Please try again."
redirect_to welcome_index_path
end
end
private
def flex_quiz_params
params.require(:flex_quiz).permit(:flex01, :flex02, :flex03, :flex04, :flex05, :flex06, :flex07, :flex08, :flex09, :flex10)
end
end
If you want to create new flex_quiz objects, then you're going to want to POST to flex_quiz_index_path.
Notice in your route paths, if you look at new_flex_quiz, the HTTP verb is a GET.
It may be slightly unintuitive, but the new action is actually a GET request.
The action in which the object is supposed to be created in is the create action.
So to solve your problem this should do the trick:
<%= render partial: "quiz", locals: { url: flex_quiz_index_path, method: :post } %>
EDIT:
Instead of defining locals, you can simply define your forms in form_for as such:
You will also have to define #flex_quiz in your controller actions as well (in your case new and edit) form_for will automatically infer the appropriate URL.
From documentation:
However, further simplification is possible if the record passed to
form_for is a resource, i.e. it corresponds to a set of RESTful
routes, e.g. defined using the resources method in config/routes.rb.
In this case Rails will simply infer the appropriate URL from the
record itself.
You'll also need to change the naming from singular form to plural.
The rails to do resuable forms is:
app/views/flex_quiz/_form.html.erb:
<%= form_for(#flex_quiz) do |f| %>
# ...
<% end %>
app/views/flex_quiz/new.erb:
<h1>Create a new quiz</h1>
<%= render 'form' %>
app/views/flex_quiz/edit.erb:
<h1>Edit a quiz</h1>
<%= render 'form' %>
While using locals can often be a good idea its not needed here. Note we just pass the resource and not a URL to form_for - that is convention over configuration in action and is what makes Rails awesome.
Rails figures out all by itself what URL to use for the action attribute and what method to use based on if the resource has been saved.
However for this to work you to actually follow the conventions. Make sure you are using the proper plural forms (the plural of quiz is quizzes):
resources :flex_quizzes
class FlexQuizzesController < ApplicationController
end
Unfortunately when it comes to rest of your setup you need to revisit the drawing board. Its not very realistic to think that you can do this with a single model. You would usually have several models with relations:
class Quiz
has_many :questions
end
class Question
belongs_to :quiz
has_many :answers
end
class Answer
belongs_to :question
end
class UserQuiz
belongs_to :user
belongs_to :quiz
end
class UserAnswer
belongs_to :question
belongs_to :answer
end
You would use one or several controllers to let admins create the quizes and a separate controller to let users answer the quiz. Its a quite common domain so you should be able to find plenty of examples.
I'm trying to make a form that will post to a database, I'm really struggling at the moment and i'm getting this error.
NameError in AddController#index
uninitialized constant AddController::Newevents
Could you advise what i would need to do?
Heres all the code i have
Form
<%= simple_form_for(#newevent) do |f| %>
<%= f.input :eventname, required: true %>
<%= f.input :eventdate %>
<%= f.input :eventimage %>
<%= f.button :submit %>
<% end %>
controller
class AddController < ApplicationController
def index
#newevent = Newevent.new
end
end
Model
class Newevent < ActiveRecord::Base
def event_params
params.require(:Newevent).permit(:eventname, :eventdate, :eventimage)
end
end
Routes
resources :add
Edit
i now have this error undefined methodnewevents_path'` after changing this
#newevents = Newevent.new
It seems that you miscopied your code here. The error message indicates that your index method actually looks like this
def index
#newevent = Newevents.new
end
Remove the s from the end of Newevent and it should work.
RE: your edit
Your routes declare that you have a resource named add, if you want to show and create your Newevent objects, then you should create a controller for that. Declare resources :newevents in your routes and create a controller to handle it.
You should research RESTful routes, because that's what Rails's resource routing works best with. The form to create a new object should be displayed by the new action and not index.
You should be using create method instead of index if you are using POST http method. index will be called if you are using GET method and it shouldn't be used to post the form data. Refer this link for more information on rails routing.
class AddController < ApplicationController
def create
#newevent = Newevent.new
end
end
I've been stuck on this for a bit and can't figure out the exact reason why I'm getting the following error:
undefined method `entries_path' for <%= form_for(#entry) do |f| %>
entry_controller:
class EntryController < ApplicationController
def index
end
def new
#entry = Entry.new
end
def create
#entry = Entry.new(user_params)
if #entry.save
redirect_to #entry
else
render 'new'
end
end
private
def user_params
params.require(:entry).permit(:comment, :flag)
end
end
routes has:
resources :entry
and the new page where the error occurs:
<%= form_for(#entry) do |f| %>
<%= f.label :comment %>
<%= f.text_field :comment %>
<%= f.label :flag %>
<%= f.text_field :flag %>
<% end %>
I can't figure out why I'm getting this error.
form_for needs to reference the path associated with #entry (i.e. entries_path), but your routes.rb file uses the singular form of the resource (:entry) rather than the required plural form (:entries), so the proper path names don't exist.
Rails models use the singular form, but the Rails database, controllers, views use the plural form and this is reflected in the routes file. One way to remember this is that a model is describing a single class that each object belongs to. Everything else, pretty much, is responsible for managing multiple instances, so while they themselves are singular (e.g. Controller), they refer to the objects they manage in the plural form (e.g. EntriesController, controller/entries directory).
See Ruby on Rails plural (controller) and singular (model) convention - explanation for more discussion of this.
Controller and views should always be treated in plural form. For example, if you have an object Book, then the controller declaration should be
class BooksController < ApplicationController
and the views( new, edit, show, index ) should be inside a folder named
/books
Also, the declaration of routes should be in plural form. In this case, the routes should be declared as
resources :books
You could try to generate the controller and view folder by running in your terminal:
rails generate controller name_of_object_in_plural_form( for sample, books)
The script will generate a controller named books_controller.rb and /books folder under /views
I am attempting to get a form generated by simple-form in my modal, however I keep running into the following error upon loading the page.
undefined method 'model_name' for NilClass:Class
Here is the simple code I was using to try to generate the form
_header.html.erb (under the view_pages_controller)
<%= simple_form_for #update do |f| %>
<%= f.input :lang %>
<%= f.input :book %> #temp, just for testing simpform
<%= f.button :submit %>
<% end %>
I am pretty sure the problem lies with my controller code
updates_controller.rb
class UpdatesController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
def create
#update = current_user.updates.build(params[:update])
if #update.save
flash[:success] = "Update successful"
redirect_to root_path
else
flash[:error] = "Failed to update, please try again"
redirect_to root_path
end
end
end
update.rb
class Update < ActiveRecord::Base
attr_accessible :book, :user_id, :lang, :round_id
belongs_to :user
end
Any help/tips would be greatly appreciated. I know my code sucks.
The problem is that #update is null in your view. You should clarify which action renders this view, and set value to #update. The create action only sets it based on the params, and then redirects to root.
I believe you are using some kind of RESTfull controller, and you are rendering your form on action :new. So, to solve your trouble, add
#update = current_user.updates.build(params[:update])
to your new action
Have you tried putting a debugger in above the line in your controller where you declare #update.
You could then see your current_user object and what methods are available using something like current_user.methods
Have you included resource:'updates' or resources:'updates' in routes.rb.This may solve the problem.
I am trying to get a basic form to work and am struggling because I keep getting the error
undefined method `profiles_index_path' for #<#<Class:0x4fe1ba8>:0x4fccda0>
I have checked through and can't seem to work out where I am going wrong.
In my view (new.html.erb) I have:
<%= form_for #profile do |f| %>
<%= f.text_field :name %>
<%= f.text_field :city %>
<%= f.text_field :country %>
<%= f.text_field :about %>
<%= f.submit "Create Profile" %>
<% end %>
In my profiles controller I have:
class ProfilesController < ApplicationController
def new
#title = "New Profile"
#profile = Profiles.new
end
def create
#user = current_user
#profile = #user.profiles.new(params[:profile])
if #profile.save
redirect_to profile_path, :notice => "Welcome to your new profile!"
else
render "profiles#new"
end
end
def edit
#user = current_user
#profile = #user.profiles.find(params[:id])
end
def update
#title = "Update Profile"
#user = current_user
#profile = #user.profiles.find(params[:id])
if #profile.update_attributes(params[:profile])
redirect_to profile_path
else
render action: "edit"
end
end
def index
#user = current_user
#profile = #user.profiles.all
#title = "Profile"
end
end
And finally in my profiles model I have
class Profiles < ActiveRecord::Base
belongs_to :user
end
Any help people can offer really would be much appreciated because I am stumped. :)
Sorry forgot to include routes:
controller :profiles do
get "newprofile" => "profiles#new"
get "updateprofile" => "profiles#update"
get "profile" => "profiles#home"
end
resources :profiles, :controller => 'profiles'
The problem is indeed the way you've pluralized your model name. Don't do that. It should be a Profile, not a Profiles. There my be some work around to allow you to use a plural model name, but the answer is to stick to Rails convention rather than fighting the framework. Rename your model to Profile and the url_for helpers will understand how to correctly turn a new Profile object into a /profiles URL.
If you run "rake routes" command, do "profiles_index" appear in your routes? Usually for the index page of a model, the work 'index' is left out so the route is profiles_path
You error probably comes from a view where you've used profiles_index_path instead of profiles_path
I think it's failing due to the convention not being followed with your model name.
So I think you're problem is mostly around that you aren't following the convention on the model name, which would classically be singular, since each instance represents one profile. I think the form_for helper is trying to figure out what to do with it and failing as a result. So you have two options to try and resolve. Refactor the model name to singular (I'm not clear exacly how difficult that would be) or pass the :url paramater to form_for so it knows where to post to.
<% form_for #profile, :url => path_to_create_action do |f| %>
more information here:
I'm working with Rails 5 and I got the same error and it was specific using the word Media as my model and RoR used Medium as the plural so I got different routes when executing rake routes.
What I did to fix it was:
Delete the model I just have created.
rails d scaffold Media
Edit config/initializers/inflections.rb with:
ActiveSupport::Inflector.inflections(:en) do |inflect|
# Here you can put the singular and plural form you expect
inflect.irregular 'media', 'medias'
end
Now execute the scaffold again:
rails g scaffold Media
Now you must have everything in the way you expected. Because you have overwritten the Pluralizations and Singularizations (Inflections) in Ruby on Rails.
I hope it could be useful.
Have you tried to replace your form_for tag with the following?
<%= form_for #profile, :as => :post do |f| %>
It looks like it's trying to treat it as a GET request to "/profile". And, since it is not finding the index action, it craps out. I think forcing it to do a POST will fix this issue.