simple_form undefined method model_name 3 classes error - ruby-on-rails

So I just Nested some resources that weren't Nested before and since I have been trying to fix all of the path references. The biggest issue I have been having is with the fact that there are 2 nested resources within a larger nested resource like so:
Users->Photos->Comments
On my form, it keeps giving me the following error
undefined method `model_name' for "/users/2/photos/2/comments/new":String
The error page says that the source is around line #1 of the following (my comments/_form partial):
= simple_form_for ([#comment, new_user_photo_comment_path(#user,#photos,#comment)]) do |f|
= f.input :content, label: "Reply to thread"
=f.button :submit, class: "button"
This is my Comments controller:
class CommentsController < ApplicationController
before_action :authenticate_user!
def new
#photo=Photo.find(params[:photo_id])
end
def create
#photo =Photo.find(params[:photo_id])
#comment=Comment.create(params[:comment].permit(:content, :id, :photo_id))
#comment.user_id= current_user.id
#comment.photo_id= #photo.id
#user= User.find_by(params[:id])
if #comment.save
redirect_to user_photo_path(#photo, #user)
else
render 'comments/new'
end
end
end

At first, it is not preferably to nest resources deeper than two times.
You should consider to nest comments within only photos. It`s ok to do like so in routes.rb:
resources :users do
resources :photos
end
resources :photos do
resources :comments
end
And you errors is because
= simple_form_for ([#comment, new_user_photo_comment_path(#user,#photos,#comment)]) do |f|
gives for method simple_form_for as parameters:
1 - model Comment
2 - String /users/2/photos/2/comments/new
to set proper path (form action) form builders need models as all arguments.
Maybe something like
= simple_form_for ([#user,#photos,#comment]) do |f|
should work

Related

Following Rails tutorial, undefined method 'create' for nil:NilClass, with nested resource

I'm following the Rails tutorial and making changes where appropriate, with the intention that my tutorial project will become a full-fledged production app after the completion of the tutorial.
I've run into a snag with the second model portion of the tutorial. Here is how I've written my second model.
In my policy.rb:
class Policy < ApplicationRecord
has_one :insured
end
In my insured.rb:
class Insured < ApplicationRecord
belongs_to :policy
end
In my routes.rb:
resources :policies do
resource :insured
end
In my insureds_controller.rb:
def create
#policy = Policy.find(params[:policy_id])
# next line is raising the error
#insured = #policy.insured.create(insured_params)
redirect_to #insured
end
private
def insured_params
params.permit(:name, :address, :phone, :email)
end
I've inspected the #policy object with render plain: #policy.inspect and can confirm that ActiveRecord is retrieving the policy correctly. When I inspect the attributes of #policy, using render plain: #policy.attribute_names.inspect, I don't see an insured attribute, which I thought Rails was supposed to automatically manage for me. In the tutorial, an article has_many :comments, and a comment is supposedly easily created and associated with the parent article with this call: #article.comments.create(comment_params). I also noticed that the tutorial uses params.require(:comment).permit(...) while I have to use params.permit(...), after inspecting the params hash I saw that the :insured attributes existed in the top-level of the hash, instead of being tied to an :insured key within the hash.
I tried manually saving and assigning the #insured object like so:
def create
#policy = Policy.find(params[:policy_id])
#insured = Insured.new(insured_params)
if #insured.save
#policy.insured = #insured
redirect_to #insured
end
end
Only to run into the following error in my .../insureds/new.html.erb:
<h1>New Insured</h1>
<h1><%= #policy.policy_number %></h2>
<%= render 'form' %>
<%= link_to 'Cancel', policy_path(#policy) %>
Which derives from my partial form .../insureds/_form.html.erb:
# the following line raises the error
<%= form_with model: #insured, local: true do |form| %>
# html omitted for brevity
<% end %>
Error: 'undefined method insureds_path'. This is weird because when I inspect the HTML I can see the form action for this view is /policies/[:id]/insured.
Sorry for the massive wall of text, I wanted to show you guys that I did try to figure out what is going wrong.
There is an error in your config/routes.rb file:
resources :policies do
# change it for:
collection do
get 'insured', to: 'policies#show_insured', as: 'show_policy_insured'
# maybe unnecessary to be here
# get 'insured/new', to: 'insureds#new', as: 'new_policy_insured'
# post 'insured/create', to: 'insureds#create', as: 'create_policy_insured'
# delete 'insured/delete', to: 'insureds#delete', as: 'delete_policy_insured'
end
end
# add resources here
resources :insureds
In policy_controller.rb:
def show_insured # 'policy/:id/insureds/
end
In insureds_controller.rb:
def show # '/insureds/:id'
end
def create
...
redirect_to show_policy_insured && return if #insured_policy
end
# before_filter or before_action
#policy = Policy.find(params[:id])
#insured_policy = #policy.insured
Check it and run this to see your routes:
$ bundle exec rake routes
get /policies/:id/insured => 'policies_controller#show_insured'
get /insureds/:id => 'insureds_controller#show'
get /insured/new => 'insureds_controller#new'
post /insureds/create => 'insureds_controller#create'
delete /insureds/:id/delete => 'insureds_controller#delete'
#maguri, that's not all necessary. The stumbling block I was running into was that Rails couldn't automatically determine the correct routes. When I provided my own urls in the form_with declarations, everything went smoothly.
Observe the following change in my _form.html.erb for the Insured model, which belongs_to Policy, which has_one Insured.
<%= form_with model: #insured, url: policy_insured_path(#policy) local: true do |form| %>
In my updated insureds_controller.rb file, using #Phlip's suggestion:
def create
#policy = Policy.find(params[:policy_id])
#insured = #policy.create_insured(insured_params)
if #policy.insured.save
redirect_to policy_insured_path(params[:policy_id])
else
render 'new'
end
end
This allows me to keep routes.rb clean and simple:
resources :policies do
resource: insured
end
Thank you for your answer, it helped me discover the problem was with my routes.

Odd Rails Routing errors

I am getting an undefined method stripe_managed_accounts_path when trying to create a new resource via typical rails forms. Below is my code, I am dumbfounded, cannot figure it out.
Controller
class StripeManagedAccountsController < ApplicationController
before_action :authenticate_printer!
def new
#stripe_managed_account = StripeManagedAccount.new(printer_id: current_printer.id)
end
end
model
class StripeManagedAccount < ActiveRecord::Base
belongs_to :printer
end
views/new
<h1>Create New Stripe Managed Account</h1>
<%= render 'form' %>
view/form
<h5>inside the form</h5>
<%= form_for #stripe_managed_account do |f| %>
<% end %>
routes
resources :printers, only: [:show, :edit, :update] do
resources :stripe_managed_accounts
end
error
`undefined method 'stripe_managed_accounts_path' for #<#<Class:0x007fc627d342b8>:0x007fc62b36e108>`
routes
printer_stripe_managed_accounts GET /printers/:printer_id/stripe_managed_accounts(.:format) stripe_managed_accounts#index
POST /printers/:printer_id/stripe_managed_accounts(.:format) stripe_managed_accounts#create
new_printer_stripe_managed_account GET /printers/:printer_id/stripe_managed_accounts/new(.:format) stripe_managed_accounts#new
edit_printer_stripe_managed_account GET /printers/:printer_id/stripe_managed_accounts/:id/edit(.:format) stripe_managed_accounts#edit
printer_stripe_managed_account GET /printers/:printer_id/stripe_managed_accounts/:id(.:format) stripe_managed_accounts#show
PATCH /printers/:printer_id/stripe_managed_accounts/:id(.:format) stripe_managed_accounts#update
PUT /printers/:printer_id/stripe_managed_accounts/:id(.:format) stripe_managed_accounts#update
DELETE /printers/:printer_id/stripe_managed_accounts/:id(.:format) stripe_managed_accounts#destroy
and it is highliting this line <%= form_for #stripe_managed_account do |f| %>
I have grepped the entire code base for stripe_managed_accounts_path and it is no where. I am at odds end...
UPDATE:::
If I add that route it disappears??? Why is it looking for that route. Is it becasue of how I named my fodlers, etc??
You're nesting stripe_managed_accounts inside printers on your routes file. If you take a look at the output of rake routes, you can see that there isn't a path for stripe_managed_accounts_path.
You can either use the shallow option on the stripe_managed_accounts resource or adjust your form to include the printer which the managed account will belong to.
#controller
class StripeManagedAccountsController < ApplicationController
before_action :authenticate_printer!
def new
#stripe_managed_account = current_printer.build_stripe_managed_account
end
def create
current_printer.stripe_managed_accounts.create stripe_managed_account_params
# handle response
end
def stripe_managed_account_params
params.require(:stripe_managed_account).permit([list of attributes])
end
end
#form
<h5>inside the form</h5>
<%= form_for [current_printer, #stripe_managed_account] do |f| %>
<% end %>
That will generate the proper url, nesting the stripe_managed_account inside the current printer.
For has_one association reference http://guides.rubyonrails.org/association_basics.html#has-one-association-reference

Form_for is giving me a No Method Error when trying to create a new object

So as it stands I have a form partial which starts off as:
<%= form_for(#merchandise) do |f| %>
It works perfectly for editing the data that I have already assigned in the rails console. When I try to use it for a "new" form that creates new merchandise (in this case the singular form of merchandise, I don't have nested resources, multiple models etc.), I get a no Method error that states
"undefined method 'merchandises_path' for #<#<Class:0x64eaef0>:0x95d2370>".
When I explicitly state the URL in the form_for method:
<%= form_for(#merchandise url:new_merchandise_path) do |f| %>
I get it to open and I finally have access to the form, however in this case I get a routing error that states
"No route matches [POST] "merchandise/new"".
I decided to write out that route in my routes file which previously just had:
root "merchandise#index" resources :merchandise
After I add the route it literally does nothing. I click submit and it takes me to the form but there is no new data in the database. I am at a complete loss and have been at this for hours googling and stack overflowing and I just don't know what to do anymore. All help is seriously appreciated. I'm adding a pastebin with all my code in the following url:
http://pastebin.com/HDJdTMDt
I have two options for you to fix it:
Option 1:
Please try to do this for best practice in Rails:
routes.rb
change your routes use plural
resources :merchandises
merchandises_controller.rb
Rename your file controller and class into MerchandisesController
class MerchandisesController < ApplicationController
def index
#merchandise = Merchandise.all
end
def new
#merchandise = Merchandise.new
end
def create
#merchandise = Merchandise.new(merchandise_params)
if #merchandise.save
redirect_to merchandises_path
else
render :new
end
end
def show
#merchandise = Merchandise.find(params[:id])
end
def edit
#merchandise = Merchandise.find(params[:id])
end
def update
#merchandise = Merchandise.find(params[:id])
if #merchandise.update(merchandise_params)
redirect_to #merchandise, notice: "The movie was updated"
else
render :edit
end
end
def merchandise_params
params.require(:merchandise).permit(:shipper, :cosignee, :country_arrival_date, :warehouse_arrival_date, :carrier, :tracking_number, :pieces, :palets, :width, :height, :length, :weight, :description, :cargo_location, :tally_number, :customs_ref_number, :released_date, :updated_by, :country_shipped_to, :country_shipped_from)
end
end
Option 2:
If you want to not change many code
/merchandise/_form.html.erb
in partial file
/merchandise/new.html.erb
<%= render 'form', url: merchandise_path, method: 'post' %>
/merchandise/edit.html.erb
<%= render 'form', url: category_path(#merchendise.id), method: 'put' %>

Undefined method 'model_name' when attempting to use Simple Form in Rails

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.

form for nested resource

I have gone through tons of the form_for nested resource questions and can't get any of the solutions to work for me. I figured its time to ask a personalized question.
I have two models, jobs and questions, jobs has_many questions and questions belong_to jobs.
I used scaffolding to create the controllers and models then nested the resources in the routes.rb.
root :to => "pages#home"
resources :jobs do
resources :questions
end
get "pages/home"
get "pages/about"
get "pages/contact"
class Job < ActiveRecord::Base
has_many :questions
end
class Question < ActiveRecord::Base
belongs_to :job
end
Right now I am trying to access '/jobs/1/questions/new' and keep getting the
NoMethodError in Questions#new
I started with the error No route matches {:controller=>"questions"} when the code was
<%= form_for(#question) do |f| %>
I know this is wrong, so I started to try other combos and none of them worked.
I've tried
<%= form_for([#job.questions.build ]) do |f| %>
that
<%= form_for([#job, #job.questions.build ]) do |f| %>
that
<%= form_for(#job, #question) do |f| %>
Among a bunch of other combinations and that are not working.
Here is a link to my rake routes : git clone https://gist.github.com/1032734
Any help is appreciated and let me know if you need more info, thanks.
I just pass the URL as an extra option:
<%= form_for(#question, :url => job_questions_path(#job)) do %>
EDIT:
Also try:
form_for([#job, #question])
This is how I solved mine :)
In your questions/_form.html.erb
<%= form_for [#job, #question] do %>
For this to work, you need the job's id. You'll pass it as follows:
In the questions_controller.rb
def new
#job = Job.find(params[job_id])
#question = #job.questions.build
end
Build(.build) is similar to using new(.new) in the code above, with differences only in older versions of rails; rails 2 down.
Now for the create action (still in questions_controller.rb)
def create
#job = Job.find(params[:job_id])
#question = #job.questions.build(question_params)
end
If you only use these, the job_id and user_id field in the question model will be empty. To add the ids, do this:
In your questions_controller.rb add job_id to job_params like so:
def question_params
params.require(:question).permit(:ahaa, :ohoo, :job_id)
end
Then to pass the user's id (if you are using Devise), do:
def create
#job = Job.find(params[:job_id])
#question = #job.questions.build(question_params)
#question.user_id = current_user.id
end

Resources