Nested routes and dot in url in Rails - ruby-on-rails-3

I'm building a simple todo app for some practice. I have projects which has_many tasks and tasks belongs_to projects.
So that I can display url/projects/1/tasks I'm nesting the route:
routes.rb
resources :projects do
resources :tasks
end
In my project show view I have the following form:
Add a task:
<%= form_for [#project, #task] do |f| %>
<%= f.label :Task_name %>
<%= f.text_field :name, :placeholder => "Task Name" %>
<%= f.submit 'Create Task' %>
<% end %>
In my tasks controller I'm doing the following:
def create
#project = Project.find(params[:project_id])
#task = #project.tasks.new(params[:task])
if #task.save
redirect_to projects_path(#project)
else
redirect_to projects_path(#project)
end
end
It seems on task.save when I redirect and pass in the project instance variable it redirects me to http://todoapp.dev/projects.5 (5 being the id of the project) instead of http://todoapp.dev/projects/5.
Could the problem be in my controller with the redirect_to method or possibly the nested route?
I have a basic understanding of Rails routing but could use some advice.

Looks like in the redirect_to in my controller I was using the pluralized version of the path. projects_path(#project) instead of project_path(#project).
def create
#project = Project.find(params[:project_id])
#task = #project.tasks.new(params[:task])
if #task.save
redirect_to project_path(#project)
else
redirect_to project_path(#project)
end
end
This ended up working.

Related

Best steps for trouble shooting rails app

What's the best (simplest) way to walk through MVC and check if everything is set up right?
I get a bit frazzled and I feel like there must be a really simple fix to error messages like these:
undefined method `invitations_path' for #<#<Class:0x00000105ad5cb8>:0x00000105820b30>
After adding small amounts of code to my app things break and I want to trouble shoot them myself.
Thanks for the tips!
EDIT
Perhaps troubleshooting the specific issue will lead way to a generalized approach,
Link_to is not linking Used <%= %> instead of <% %>.
The above error is generated when visting localhost:3000/invitation/new
view (in home/index.erb.html)
<% if #user.invitation_limit > 0 %>
<% link_to 'Send Invitations', new_invitation_path %>
(<%= #user.invitation_limit %> left)
<% end %>
view (in invitation/new.erb.html)
<%= error_messages_for :invitation %>
<% form_for #invitation do |f| %>
<p>
<%= f.label :recipient_email, "Friend's email address" %><br />
<%= f.text_field :recipient_email %>
</p>
<p><%= f.submit "Invite!" %></p>
<% end %>
controller
class InvitationController < ApplicationController
def new
#invitation = Invitation.new
end
def create
#invitation = Invitation.new(params[:invitation])
#invitation.sender = current_user
if #invitation.save
if logged_in?
Mailer.deliver_invitation(#invitation, signup_url(#invitation.token))
flash[:notice] = "Thank you, invitation sent."
redirect_to projects_url
else
flash[:notice] = "Thank you, we will notify when we are ready."
redirect_to root_url
end
else
render :action => 'new'
end
end
end
model
class Invitation < ActiveRecord::Base
belongs_to :sender, :class_name => 'User'
has_one :recipient, :class_name => 'User'
attr_accessible :recipient_email, :sender_id, :sent_at, :token
end
routes.rb
resources :home, :only => :index
resources :invitation
You can create request specs for each of your controller actions. Request specs follow the request all the way from the controller to rendering the view, and if there is an error it will show up in the request spec.
This may take time to set up, but will save you lots of time in the future, as you don't have to manually test every page when you want to roll out a new version of your website.

Rails Undefined Method 'model_name'

I have the following model:
class Contact
attr_accessor :name, :emails, :message
def initialize(attrs = {})
attrs.each do |k, v|
self.send "#{k}=", v
end
end
def persisted?
false
end
end
I am calling to a contact form in my view like so:
<div class="email_form">
<%= render 'form' %>
</div>
Here is the controller:
class ShareController < ApplicationController
layout "marketing_2013"
respond_to :html, :js
def index
#contact = Contact.new
end
end
Here is the Form:
<%= form_for(#contact) do |f| %>
<%= f.label :name, "Your Name" %>
<%= f.text_field :name %>
<%= f.label :text, "Send to (separate emails with a comma)" %>
<%= f.text_field :emails %>
<%= f.label :message, "Email Text" %>
<%= f.text_area :message %>
<%= f.submit %>
<% end %>
For some reason I keep getting this error:
undefined method model_name for Contact:Class
Any reason why what I have currently wouldn't work?
Besides the correct route in your config/routes.rb, you will also need these two instructions on your model:
include ActiveModel::Conversion
extend ActiveModel::Naming
Take a look at this question: form_for without ActiveRecord, form action not updating.
For the route part of these answer, you could add this to your config/routes.rb:
resources :contacts, only: 'create'
This will generate de following route:
contacts POST /contacts(.:format) contacts#create
Then you can use this action (contacts#create) to handle the form submission.
add include ActiveModel::Model to your Contact file
your route probably doesn't go where you think it's going and therefore #contact is probably nill
run "rake routes" and check the new path.. if you are using defaults, the route is
new_contact_path.. and the erb should be in file: app/views/contacts/new.html.erb
def new
#contact = Contact.new
end

Rails 310 Redirect Loop

I'm going back to write a basic app with projects that have tasks. In my show view of a project I want to list the tasks and also include a form. When I wire this all up I get 310 Redirect loop. It's been a while since I've written anything from scratch so would appreciate some help looking at my code.
controller code:
def show
#project = Project.find(params[:id])
#task = #project.tasks.new(params[:task])
if #task.save
redirect_to #project, :notice => "Task added"
else
render action: :show
end
end
view code:
<%= #project.project_name %>
<%= form_for(#task) do |m| %>
<%= m.label :Task %>
<%= m.text_field :task_name %>
<%= m.button :submit %>
<% end %>
<% #project.tasks.each do |t| %>
<%= t.task_name %>
<% end %>
project.rb
has_many :tasks
task.rb
belongs_to :project
You are redirecting to #project, which is interpreted as meaning, redirect to the show page for #product. But you are calling redirect from the show page, hence the redirect loop:
request routed to show page
find project
task instantiated
task saved
redirect to show (loop back to 2)
Normally you don't create records in show, you do it in create. Any reason you're doing it this way?

Rails Routing Redirects to wrong path

I have a view called, "clients" which shows a list of calls from the Call database. That works fine. However when I added a new button with a form behind it the call will be created but it redirects to calls_path instead of clients_path.
I have no idea why it's doing this, my only theory is that I'm working with actions that touch data outside of the clients_controller and somehow Rails is defaulting to the calls_path. The same thing happens on my delete action. Can someone help me make sense of this?
calls_controller
def new
#call = Call.new :call_status => "open"
respond_with #call
end
def create
#call = Call.new(params[:call])
if #call.save
redirect_to clients_path, notice: "Call was successfully created."
else
render :new
end
end
def destroy
#call = Call.find(params[:id])
#call.destroy
respond_to do |format|
format.html { redirect_to clients_index_path }
format.json { head :no_content }
end
end
_form.html.erb
<%= form_for(#call) do |f| %>
<%= f.label :caller_name %>
<%= f.text_field :caller_name %>
<%= f.label :caller_phone %>
<%= f.text_field :caller_phone, :placeholder => 'xxx-xxx-xxxx' %>
<%= f.label :caller_email %>
<%= f.text_field :caller_email %>
<%= f.button :submit %>
<% end %>
routes.rb
devise_for :users
match 'mdt' => 'mdt#index'
get "home/index"
resources :medics
resources :clients
resources :users
resources :units
resources :mdt do
collection do
put "in_service"
put "en_route"
put "to_hospital"
put "at_hospital"
put "on_scene"
put "out_of_service"
put "at_station"
put "staging"
put "at_post"
put "man_down"
end
end
resources :calls do
member do
post 'close'
end
end
root :to => 'home#index'
devise_scope :user do
get "/login" => "devise/sessions#new"
delete "/logout" => "devise/sessions#destroy"
end
The problem I had was with routes. I needed a post method for a new calls. After creating two actions (one for create and one for destroy) along with their routes everything started working. It looks like it was trying to use the default routes and actions which would re-route to the wrong URL for my purposes.
resources :clients do
collection do
post "calls"
end
member do
delete "cancel"
end
end
def calls
#call = Call.new(params[:call])
if #call.save
redirect_to clients_path, notice: "Call was successfully created."
else
render :new
end
end
def cancel
#call = Call.find(params[:id])
#call.destroy
respond_to do |format|
format.html { redirect_to clients_path }
format.json { head :no_content }
end
end

Trying to create user with membership using Devise - Need help with controller

I have a standard devise installation, and I'm trying to add in functionality to add a user with a gym membership from an admin panel.
routes.rb
devise_for :users
resources :users
I am creating the user from the gym controller, so this is my gym action
def members
#gym = Gym.find(params[:id])
#user = User.new
#user.gym_users.build
#roles = Role.all
end
The gym_user is accepted in the user model
accepts_nested_attributes_for :gym_users
Then here is a portion of my form
<%= form_for #user do |f| %>
<%= f.label :email %><br />
<%= f.text_field :email %>
<% f.fields_for :gym_users do |builder| %>
<%= builder.label :item_id, "Membership Level" %><br />
<%= builder.collection_select(:item_id, #gym.membership_items, :id, :name, {:include_blank => true}) %>
<% end %>
<% end %>
What I'm having trouble with is my user controller where I actually create the user. This is the route for the membership page where the user is created
match 'gyms/:id/members' => 'gyms#members'
Finally, here's the create method on my users_controller
def create
#user = User.new(params[:user])
if #user.save
:notice => "User created successfully"
render :new
else
render :new
end
end
What I'm not sure is how to send back to that url when there is an error so that my model errors go with it, or redirect when it completes correctly.
I resolved this by making it an ajax call which eliminated the need for a redirect.