NoMethodError In Rails Page - ruby-on-rails

Here's the page template I've got:
<h1>Editing user</h1>
<% form_for(#user) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :forename %><br />
<%= f.text_field :forename %>
</p>
<p>
<%= f.label :surname %><br />
<%= f.text_field :surname %>
</p>
<p>
<%= f.label :address %>
<%= f.text_field :address %>
</p>
<p>
<%= f.label :postcode %>
<%= f.text_field :postcode %>
</p>
<p>
<%= f.label :contact_number %>
<%= f.text_field :contact_number %>
</p>
<% end %>
<%= link_to 'Show', #user %> |
<%= link_to 'Back', users_path %>
The controller is actually sub-typed from the AdminController as there's a separate section as the following class declaration shows:
class Admin::UsersController < ApplicationController
with the edit method as follows:
def edit
#user = User.find(params[:id])
end
With the error as follows:
undefined method `user_path' for #<ActionView::Base:0x104369fe8>
and the following in my routes:
map.namespace(:admin) do |admin|
admin.resources :pages
admin.resources :treatments
admin.resources :users
admin.resources :finances
end
So I'm a bit stuck, because it's the form_for(#user) that's doing it. I've seen this before but have no idea how to diagnose it unfortunately.

Since you are using a name spaced routes, you have to specify the name space in the form_for invocation.
<% form_for([:admin, #user]) do |f| %>
Refer to the documentation for more details.(Hint: Read the end of the Resource-oriented style section)

Doesn't the name-spacing change the named paths so maybe to need to be explicit it in the form like this?
form_for (#user, :url => admin_user_path) do |f|

For the namespace you are using....the link would be
<% form_for #user, edit_admin_user_path(#user.id) do |f|%>
.....
<% end %>
Do a rake routes to look at how routes look like for a namespaced controller

Related

Ruby on Rails - No route matches [POST] "/setor/update"

i'm new to ruby on rails and I keep getting this error when trying to update an object.
here's my controller:
class SetorController < ApplicationController
def index
#setor = Setor.all
end
def new
end
def show
#setor = Setor.find(params[:id])
end
def create
#setor = Setor.new(setor_params)
#setor.save
redirect_to #setor
end
def edit
#setor = Setor.find(params[:id])
end
def update
#setor = Setor.find(params[:id])
if (#setor.update(setor_params))
redirect_to #post
else
render 'edit'
end
end
private def setor_params
params.require(:setor).permit(:nome, :sigla, :cnpj)
end
end
this is the index page - where I link to edit the object:
<%= #setor.each do |s| %>
<%= s.nome %> |
<%= s.sigla %> |
<%= s.cnpj %> |
<%= link_to "edit", edit_setor_path(s.id) %> <br>
<% end %>
and this is the update form:
<h1> Editar Setor </h1>
<%= form_for :setor, url: setor_path(:update) do |f| %>
<p>
<%= f.label :nome %>
<%= f.text_field :nome %> <br>
<%= f.label :sigla %>
<%= f.text_field :sigla %> <br>
<%= f.label :cnpj %>
<%= f.text_field :cnpj %> <br>
</p>
<%= f.submit %>
<% end %>
what am I missing?
Thanks!
First, make sure you have a route that matches edit_setor_path. You can do this by running rails routes in your terminal or by going to the url localhost:3000/rails/info/routes in your browser.
On your index page, you have the following:
<%= link_to "edit", edit_setor_path(s.id) %> <br>
You do not need to pass in the id of the s object. Rails will figure this out on its own. Instead, just pass in the object:
<%= link_to "edit", edit_setor_path(s) %> <br>
Change #setor in the index action of your SetorController to #setors and change #setor in your index.html.erb file to #setors.
Change the :sector in your edit.html.erb to #setor. You can also remove url: setor_path(:update) from the edit.html.erb form.
These changes follow Rails conventions. You should try to follow Rails conventions as much as possible, especially when just learning Rails.
Try to mention #setor object in the form code:
<%= form_for #setor do |f| %>
How about trying something like this:
Rename your controller to setors_controller.rb and change the class name to SetorsController -- this is to follow the typical Rails naming convention.
Then make sure you have a route:
# config/routes.rb
Rails.application.routes.draw do
resources :setors
end
Update your view's form_for tag to use the instance variable set up in the controller:
# app/views/setors/edit.html.erb
# NOTE: folder path above... "setor" is now "setors" to follow the Rails convention
<%= form_for #setor do |f| %>
<p>
<%= f.label :nome %>
<%= f.text_field :nome %> <br>
<%= f.label :sigla %>
<%= f.text_field :sigla %> <br>
<%= f.label :cnpj %>
<%= f.text_field :cnpj %> <br>
</p>
<%= f.submit %>
<% end %>

Instance variable in _form.html.erb not working for new_path

I receive this error: NoMethodError in Admin::SuperCategories#new, undefined method `super_categories_path'. My path are well defined and the whole logic works with the admin edit path. For some reason it doesn't work for the admin new action. Not sure what I am doing wrong here.
admin/super_categories/index.html.erb
<%= link_to "Create a new Super Category",
new_admin_super_category_path, class: "button success right" %>
admin/super_categories_controller.rb
def new
#super_category = SuperCategory.new
end
admin/super_categories/new.html.erb
<%= render 'form' %>
admin/super_categories/_form.html.erb
<%= form_for(#super_category) do |f| %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_area :description, rows: 6 %>
</div>
<div class="actions">
<%= f.submit class: "button success medium" %>
</div>
<% end %>
routes.rb
namespace :admin do
resources :super_categories
end
resources :super_categories, only: [:show]
You're forgetting the admin portion of your path. You need to let form_for know about it, or it looks for super_categories_path instead of admin_super_categories_path:
<%= form_for [:admin, #super_category] do |f| %>

Ruby on Rails, instead of update make new entry to model

I made a simple demo site, with an model for the patients name (name:string) and another model with the treatment (content:text). I created this "project" to learn more about the accepts_nested_attribute for tag and the fields_for tag.
Now my problem is that on the patient show page i created an nested formula for the treatment , like you can see here:
<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
<%= #patient.name %>
</p>
<ol>
<% for treatment in #patient.treatments %>
<li><%= treatment.content %></li>
<% end %>
</ol>
<%= form_for(#patient) do |f| %>
<%= f.fields_for :treatments do |builder| %>
<div class="field">
<%= builder.label :content %><br />
<%= builder.text_field :content %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<%= link_to 'Edit', edit_patient_path(#patient) %> |
<%= link_to 'Back', patients_path %>
So my problem is that in the builder.text_field :content better called the input shows up the last saved treatment from <%= builder.content %>, but i want that he does not update it instead i want to add new treatments! Hopefully somebody understands me! Thanks
I would create separate controller for creating only the treatment, eg.
# treatments_controller.rb
class TreatmentsController < ApplicationController
def create
#patient = Patient.find(params[:patient_id])
#treatment = #patient.treatments.new(params[:treatment])
if #treatment.save
redirect_to #patient
else
# handle unsuccessful treatment save
end
end
end
# routes.rb:
resources :patients do
resources :treatments, only: :create
end
# form:
<%= form_for #patient, #treatment do |f| %>
<div class="field">
<%= f.label :content %><br />
<%= f.text_field :content %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
You should also set #treatment variable in the patient#show action, like this:
#treatment = #patient.treatments.new

How to use If,else in form_for helper to extract specific field

I have following code in my edit view:
<%= form_for #content do |f|%>
<% if f.text_field :home %>
<%= f.label :Home %>
<%= f.text_field :home %>
<% elsif f.text_field :aboutus %>
<%= f.label :Abouts %>
<%= f.text_field :aboutus %>
<% end %>
<%= f.submit%>
Here #content contain following information:
id: "1", home: "staticcontent", aboutus: "staticcontent"
so i wants that if someone wants to edit home page he can see only home submission form and if he choose aboutus, he can see edit form page for only about us.suggest me whats correct way to use if,else in this block?
You could pass a URL param and work with that. For example:
# in some view
<%= link_to "Edit Homepage", edit_content_path(page: "home")
# this will link to /contents/:id/edit?page=home
Then in your form:
<%= form_for #content do |f|%>
<% if params[:page] == "home" %>
<%= f.label :home %>
<%= f.text_field :home %>
<% else %>
<%= f.label :about_us %>
<%= f.text_field :about_us %>
<% end %>
<%= f.submit%>
Notice I downcased the labels, and changed aboutus to about_us so that the label displays correctly.

Routing Sub-Controllers

My route looks like the following:
map.namespace(:admin) do |admin|
admin.resources :pages
end
and my controller name looks like the following:
class Admin::PagesController < ApplicationController
and my new.html.erb file looks like the following:
<% form_for(#page) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :title %>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :body %>
<%= f.text_area :body %>
</p>
<p>
<%= f.submit "Create" %>
</p>
<% end %>
<%= link_to 'Back', :action => "index" %>
Yet I keep on getting the following error:
NoMethodError in Admin/pages#new
Showing app/views/admin/pages/new.html.erb where line #1 raised:
undefined method `pages_path' for #<ActionView::Base:0x104528000>
Extracted source (around line #1):
1: <% form_for(#page) do |f| %>
2: <%= f.error_messages %>
3: <p>
4: <%= f.label :title %>
I can't figure out why as I'm assuming the route is correct. If I try other routes then it will work until I try submitting the form, then it thinks it should be taking me back to site.com/pages which it shouldn't.
Any ideas?
Your model #page isn't aware that it's being used in a namespace like that. You can use rake routes to see all your routes for your admin namespace. You need to manually change your url path:
<% form_for(#page) do |f| %>
to
<% form_for(#page, :url => admin_pages_path) do |f| %>
Another example for when you're updating a page:
admin_page_path(#page)

Resources