Good afternoon!
I can't seem to find what the problem is here on my Tickets and I thought maybe getting another eye on it would help :). Also it is greatly appreciated for using your time to help me out.
All pages for my Tickets work correctly except for the Create action. The redirection even works correctly by going to the tickets_path after I hit Create Ticket for the New. However, it keeps flashing to Unable to submit ticket. and does not create the record in the table.
There are no errors however, the console shows the Parameters of the form in the log below.
# Controller
class TicketsController < ApplicationController
before_filter :authenticate_user!
before_action :set_ticket, only: [:show, :edit, :update, :create]
respond_to :html
def index
#tickets = Ticket.includes(:category, :user, :ticket_status)
#authorize User
end
def show
#ticket = Ticket.find(params[:id])
#authorize #user
end
def new
#ticket = Ticket.new
#ticket.ticket_status = TicketStatus.find_by_name("Open")
end
def edit
#ticket = Ticket.find(params[:id])
end
def create
#ticket = Ticket.new(ticket_params)
if #ticket.save
redirect_to tickets_path, :notice => "Ticket Submitted."
else
redirect_to tickets_path, :alert => "Unable to submit ticket."
end
end
def update
#ticket = Ticket.find(params[:id])
if #ticket.update(ticket_params)
redirect_to tickets_path, :notice => "Ticket updated."
else
redirect_to edit_ticket_path, :alert => "Unable to update ticket."
end
end
def destroy
#ticket = Ticket.find(params[:id])
#ticket.destroy
redirect_to tickets_path, :notice => "Ticket deleted."
end
private
def set_ticket
#ticket = Ticket.find(params[:id])
end
def ticket_params
params[:ticket].permit(:ticket_status_id, :user_id, :category_id, :title, :description)
end
end
# Model
class Ticket < ActiveRecord::Base
belongs_to :user
belongs_to :category
belongs_to :ticket_status
validates_presence_of :title, presence: true
validates_presence_of :description, presence: true
validates_presence_of :user_id, presence: true
validates_presence_of :category_id, presence: true
validates_presence_of :ticket_status_id, presence: true
end
# Ticket _form partial
<div class="container">
<div class="row">
<hr>
<h3><%= content_for?(:title) ? content_for(:title) : "Progressor Admin" %>
<span><%= link_to current_user.email, edit_user_registration_path, :class => 'glyphicon glyphicon-user btn btn-primary btn-sm pull-right', id: 'tooltip-profile', data: {toggle: 'tooltip', placement: 'right'}, :'data-original-title' => 'View Profile' %></span>
</h3>
<hr>
<%= render 'sidebar' %>
<div class="col-sm-9">
<%= form_for #ticket do |f| %>
<% if #ticket.errors.any? %>
<div class="alert alert-error">
<b><%= pluralize(#ticket.errors.count, "error") %> prohibited this ticket from being saved:</b>
<ul>
<% #ticket.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<table class="table panel">
<tbody>
<tr>
<td><%= f.label :user_id, "User Name" %></td>
<td><%= f.label current_user.name %></td>
</tr>
<tr>
<td><%= f.label :category_id, "In which area are you having an issue?" %></td>
<td><%= f.select(:category_id, Category.order("name ASC").map { |c| [c.name, c.id] }, {}, {:class => 'form-control'}) %></td>
</tr>
<tr>
<td><%= f.label :ticket_status_id %></td>
<td><%= f.select(:ticket_status_id, TicketStatus.order("position ASC").map{|c[c.name, c.id] }, {}, {:class => 'form-control'}) %></td>
</tr>
<tr>
<td><%= f.label :title, "Ticket Title" %></td>
<td><%= f.text_field :title, :class => 'form-control' %></td>
</tr>
<tr>
<td><%= f.label :description, "Ticket Description" %></td>
<td><%= f.text_area :description, :class => 'form-control', :rows => "10"%></td>
</tr>
</tbody>
</table>
<div class="form-actions">
<% if #ticket.id %>
<%= link_to 'Cancel', #ticket, :class => "btn btn-danger" %>
<% else %>
<%= link_to 'Cancel', tickets_path, :class => "btn btn-danger" %>
<% end %>
<%= f.submit :class => "btn btn-success pull-right" %>
</div>
<% end %>
</div> <!-- col-sm-9 -->
# Development Log
Started POST "/tickets" for ip-address at 2014-11-22 13:41:59 -0600
Processing by TicketsController#create as HTML
Parameters: {"utf8"=>"✓","authenticity_token"=>"N9rBPw6v+T2OMnn7dQp8NsFC5saYuUQsP5pcXe5gfhQ=", "ticket"=> {"category_id"=>"5", "ticket_status_id"=>"8", "title"=>"asdf", "description"=>"asdf"}, "commit"=>"Create Ticket"}
[1m[36mUser Load (0.5ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = 13 ORDER BY "users"."id" ASC LIMIT 1[0m
[1m[35m (0.2ms)[0m BEGIN
[1m[36m (0.1ms)[0m [1mROLLBACK[0m
Redirected to /tickets
Completed 302 Found in 30ms (ActiveRecord: 5.3ms)
You're missing the user_id attribute when making the POST request
And it's because of this line:
<td><%= f.label :user_id, "User Name" %></td>
you meant to write
<td><%= f.hidden_field :user_id, value: current_user.id %></td>
Related
I'm new to Rails and I have no idea what's going on here. The app I am building is an online store. The current functionality works, but the change I am trying to implement isn't working. As a starting point, I will show the working version that I have now. Here is my carts/show.html.erb file:
<p id="notice"><%= notice %></p>
<h2>My Cart</h2>
<table class="table table-responsive table-striped">
<thead>
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Total Price in Galleons</th>
<th>Total Price in Muggle Currency</th>
</tr>
<tbody>
<%= render(#cart.line_items) %>
<tr>
<td>Total</td>
<td><%= number_to_currency(#cart.total_price * 7.35) %></td>
<td></td>
<td></td>
</tr>
</tbody>
</thead>
</table>
<br>
<div class="row">
<div class="col-md-3">
<div class="row">
<div class="col-md-4">
<%= link_to 'Back', products_path, :class => 'btn btn-primary whiteText' %>
</div>
<div class="col-md-4">
<%= link_to "Checkout", new_charge_path, :class => 'btn btn-success whiteText' %>
</div>
<div class="col-md-4">
<%= link_to 'Empty Cart', #cart, method: :delete, data: {confirm: 'Are you sure you want to empty your cart?'}, :class => 'btn btn-danger whiteText' %>
</div>
</div>
</div>
<div class="col-md-9"></div>
</div>
However, I am wanting to change the workflow a bit so that it uses my Order scaffold to redirect the user to an address confirmation page (orders/new.html.erb) after clicking "Checkout" on the Cart show page. Once the address is confirmed, it should then route the customer to the payments page, which is what the new_charge_path in my current Checkout link redirects to already.
So to start with, I am replacing the Checkout link and turning it from this:
<%= link_to "Checkout", new_charge_path, :class => 'btn btn-success whiteText' %>
to this:
<%= link_to "Checkout", new_order_path, method: :get, :class => 'btn btn-success whiteText' %>
This redirect functions as expected, and takes me to orders/new.html.erb, which contains the following:
<h1>Order Information</h1>
<br>
<%= render 'form', order: #order %>
<%= link_to 'Back', products_path %>
The form it renders contains the following code:
<%= form_for(order) do |f| %>
<% if order.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(order.errors.count, "error") %> prohibited this order from being saved:</h2>
<ul>
<% order.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="row">
<div class="col-md-6">
<div class="field">
<%= f.label :first_name %>
<%= f.text_field :first_name, size: 20, :value => current_user.first_name, :class => "form-control" %>
</div>
<div class="field">
<%= f.label :last_name %>
<%= f.text_field :last_name, size: 20, :value => current_user.last_name, :class => "form-control" %>
</div>
<div class="field">
<%= f.label :address %>
<%= f.text_area :address, size: 40, :value => current_user.address, :class => "form-control" %>
</div>
<div class="field">
<%= f.label :city %>
<%= f.text_area :city, size: 20, :value => current_user.city, :class => "form-control" %>
</div>
<div class="field">
<%= f.label :state %>
<%= f.text_area :state, size: 2, :value => current_user.state, :class => "form-control" %>
</div>
<div class="field">
<%= f.label :email %>
<%= f.text_field :email, size: 40, :value => current_user.email, :class => "form-control" %>
</div>
<div class="field">
<%= f.label :pay_type %>
<%= f.select :pay_type, Order.pay_types.keys, prompt: 'Select a payment method', :class => "form-control" %>
</div>
</div>
<div class="col-md-6">
<%= form_tag(payments_path, class: "form-inline") do %>
<%= hidden_field_tag(:purchase_amount_cents, #cart.total_price) %>
<div class="form_group">
<%= label_tag(:credit_card_number, "Credit Card Number", class: "sr-only") %>
<%= text_field_tag(:credit_card_number, "", class: "form-control", placeholder: "Credit Card #") %>
</div>
<br>
<div class="form_group">
<%= label_tag(:expiration_month, "Month", class: "sr-only") %>
<%= text_field_tag(:expiration_month, "", class: "form-control", placeholder: "Month") %>
<br>
<%= label_tag(:expiration_year, "Year", class: "sr-only") %>
<%= text_field_tag(:expiration_year, "", class: "form-control", placeholder: "Year") %>
<br>
<%= label_tag(:cvc, "Year", class: "sr-only") %>
<%= text_field_tag(:cvc, "", class: "form-control", placeholder: "CVC #") %>
</div>
<br>
<div class="form_group">
<%= submit_tag("Purchase Cart", class: "btn btn-default", id: "purchase") %>
</div>
<% end %>
</div>
</div>
<hr>
<div class="actions">
<%= f.submit 'Proceed to Payment' %>
</div>
<% end %>
The payment options are credit card (Stripe) or Paypal. I will eventually add the Paypal functionality but Stripe API is all I have for now.
Here is my Order Controller:
class OrdersController < ApplicationController
include CurrentCart
before_action :set_cart, only: [:new, :create]
before_action :ensure_cart_isnt_empty, only: :new
before_action :set_order, only: [:show, :edit, :update, :destroy]
# GET /orders
# GET /orders.json
def index
#orders = Order.all
end
# GET /orders/1
# GET /orders/1.json
def show
end
# GET /orders/new
def new
#order = Order.new
end
# GET /orders/1/edit
def edit
end
# POST /orders
# POST /orders.json
def create
#order = Order.new(order_params)
#order.add_line_items_from_cart(#cart)
respond_to do |format|
if #order.save
format.html { redirect_to new_charge_path}
else
format.html { render :new }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /orders/1
# PATCH/PUT /orders/1.json
def update
respond_to do |format|
if #order.update(order_params)
format.html { redirect_to #order, notice: 'Order was successfully updated.' }
format.json { render :show, status: :ok, location: #order }
else
format.html { render :edit }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# DELETE /orders/1
# DELETE /orders/1.json
def destroy
#order.destroy
respond_to do |format|
format.html { redirect_to orders_url, notice: 'Order was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_order
#order = Order.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def order_params
params.require(:order).permit(:first_name, :last_name, :address, :city, :state, :email, :pay_type)
end
def ensure_cart_isnt_empty
if #cart.line_items.empty?
redirect_to products_path, notice: 'Your cart is empty!'
end
end
end
Here is my Charge Controller:
class ChargesController < ApplicationController
include CurrentCart
before_action :set_cart, only: [:new, :create]
def new
end
def create #METHOD IS CALLED AFTER PAYMENT IS MADE
# Amount in cents
#amount = #cart.total_price
customer = Stripe::Customer.create(
:email => params[:stripeEmail],
:source => params[:stripeToken]
)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => #amount,
:description => 'Customer',
:currency => 'usd'
)
Cart.destroy(session[:cart_id])
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to new_charge_path
end
end
Here's the problem. While the redirects work as expected, the #amount in the Charge controller is set to $0.00 if the order controller is used. If, however, the Cart links directly to the Charge controller, then the correct dollar amount is used. So, I am assuming that somehow the cart object is being lost or having its value reset.
Here is my set_cart method:
def set_cart
#cart = Cart.find(params[:id])
end
And here is my CurrentCart module:
module CurrentCart
private
def set_cart
#cart = Cart.find(session[:cart_id])
rescue ActiveRecord::RecordNotFound
#cart = Cart.create
session[:cart_id] = #cart.id
end
end
My idea you need to passing forward the value #cart.total_price from cart show form to order controller here some steps to do
inside your link (you pass the value as params)
<%= link_to "Checkout", new_order_path(total_price: #cart.total_price), method: :get, :class => 'btn btn-success whiteText' %>
inside order_controller (you get the params and put in instance variabel)
# GET /orders/new
def new
#order = Order.new
#temp_total_price = params[:total_price]
end
inside order_form insert between your form_for tag, we need to put this in the form as hidden value, so it can be passing to create method for charge
<%= hidden_field_tag 'total_price', #temp_total_price %>
inside your class ChargesController create method you can get the total_price
#total_price = params[:total_price]
I know it's little bit log but probably this can help
I am learning RoR and trying to setup an association between a User model and Department model. Currently, I am able to choose a department from a dropdown field and then save it. However, when showing the user or presenting the user in a list, the department shows the id number and not the department name. I cant figure out what I am doing wrong. Any help would be greatly appreciated!
Here are the models:
class User < ActiveRecord::Base
belongs_to :departments
end
class Department < ActiveRecord::Base
has_many :users
end
Here are the controllers:
class UsersController < ApplicationController
before_action :logged_in_user, only: [:edit, :update, :destroy]
before_action :admin_user, only: [:index, :destroy]
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
log_in #user
flash[:success] = "Account created!"
redirect_to root_path
else
render 'new'
end
end
def index
#filterrific = initialize_filterrific(
User,
params[:filterrific],
select_options:
{
sorted_by_name: User.options_for_name,
department_select: Department.options_for_select
},
) or return
#users = #filterrific.find.page(params[:page])
respond_to do |format|
format.html
format.js
end
end
def show
#user = User.find(params[:id])
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
flash[:success] = "Profile successfully updated."
redirect_to edit_user_path
else
render 'edit'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted."
redirect_to users_url
end
private
def user_params
params.require(:user).permit(:name, :email, :work_phone, :department, :cell_phone, :password, :password_confirmation)
end
# Before filters
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Please log in first."
redirect_to login_url
end
end
# Confirms an admin user.
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
class DepartmentsController < ApplicationController
def create
#department = Department.new(department_params)
if #department.save
redirect_to(:action => 'index')
else
render 'new'
end
end
def index
#department = Department.all
end
def show
#department = Department.find(params[:id])
end
def edit
#department = Department.find(params[:id])
end
def update
#department = Department.find(params[:id])
end
def delete
#department = Department.find(params[:id])
end
def destroy
Department.find(params[:id]).destroy
redirect_to(:action => 'index')
end
private
def department_params
params.require(:department).permit(:name, :department_ids => [])
end
end
My edit html:
<% provide(:title, "Edit user") %>
<h1>Update your profile</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#user) do |f| %>
<%= f.label :name, class: 'form-spacing' %>
<div class="input-group">
<%= f.text_field :name, class: 'form-control' %>
<span class="input-group-addon" id="basic-addon2">
<span class="glyphicon glyphicon-user"></span>
</span>
</div>
<%= f.label :email, class: 'form-spacing' %>
<div class="input-group">
<%= f.email_field :email, class: 'form-control' %>
<span class="input-group-addon" id="basic-addon2">
<span class="glyphicon glyphicon-envelope"></span>
</span>
</div>
<%= f.label :work_phone, class: 'form-spacing' %>
<div class="input-group">
<%= f.text_field :work_phone, class: 'form-control' %>
<span class="input-group-addon" id="basic-addon2">
<span class="glyphicon glyphicon-phone"></span>
</span>
</div>
<%= f.label :cell_phone, class: 'form-spacing' %>
<div class="input-group">
<%= f.text_field :cell_phone, class: 'form-control' %>
<span class="input-group-addon" id="basic-addon2">
<span class="glyphicon glyphicon-phone"></span>
</span>
</div>
<%= f.label :department, class: 'form-spacing' %>
<div class="input-group">
<div class="input-group-btn">
<%= f.collection_select :department, Department.order(:name), :id, :name, {}, {class: 'form-control'} %>
</div>
</div>
<%= f.label :password, class: 'form-spacing' %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.label :password_confirmation, "Confirmation", class: 'form-spacing' %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
<%= f.submit "Save changes", class: "btn btn-primary center-block btn-margin" %>
<% end %>
</div>
</div>
List HTML:
<div class="row well well-sm">
<div class="col-lg-6">
<div id="filterrific_results">
<div>
<%= page_entries_info users %><%= render_filterrific_spinner %>
</div>
</div>
</div>
<div class="pull-right">
<%= link_to 'Reset', reset_filterrific_url, class: "btn btn-default" %>
</div>
</div>
<table class="table table-condensed">
<tr>
<th>Profile</th>
<th>Name</th>
<th>Email</th>
<th>Work #</th>
<th>Cell #</th>
<th>Department</th>
</tr>
<% users.each do |user| %>
<tr>
<td><%= link_to user_path(user.id), class: "btn btn-xs" do %>
<i class="glyphicon glyphicon-user"></i>
<% end %>
</td>
<td><%= link_to(user.name, edit_user_path(user)) %></td>
<td><%= user.email %></td>
<td><%= user.work_phone %></td>
<td><%= user.cell_phone %></td>
<td><%= user.department %></td>
</tr>
<% end %>
</table>
<%= will_paginate users %>
Here is the trace I receive when trying to use user.department.name:
NoMethodError in Users#index
Showing C:/Users/ngkuligoski/Desktop/workspace/tgna_app/app/views/users/_list.html.erb where line #33 raised:
undefined method `name' for "30":String
Trace of template inclusion: app/views/users/index.html.erb
Rails.root: C:/Users/ngkuligoski/Desktop/workspace/tgna_app
Application Trace | Framework Trace | Full Trace
app/views/users/_list.html.erb:33:in `block in _app_views_users__list_html_erb___81315648_98180820'
app/views/users/_list.html.erb:23:in `_app_views_users__list_html_erb___81315648_98180820'
app/views/users/index.html.erb:39:in `_app_views_users_index_html_erb___1258199830_74038920'
app/controllers/users_controller.rb:33:in `index'
When switching belongs_to :department instead of belongs_to :departments, I get back the following error:
ActiveRecord::AssociationTypeMismatch in UsersController#update
Department(#70215520847100) expected, got String(#70215501520980)
Extracted source (around line #49):
47: def update
48: #user = User.find(params[:id])
49: if #user.update_attributes(user_params)
50: flash[:success] = "Profile successfully updated."
51: redirect_to edit_user_path
52: else
Rails.root: /Users/nkuligoski/Desktop/tgna_app
Application Trace | Framework Trace | Full Trace
app/controllers/users_controller.rb:49:in `update'
After removing :department from the user.params, I now do not receive an error when submitting the form. However, I am now recieving the following error at the list view and it I am getting a "Unpermitted parameter: department" error feedback from SQL.
NoMethodError in Users#index
Showing /Users/nkuligoski/Desktop/tgna_app/app/views/users/_list.html.erb where line #33 raised:
undefined method `name' for nil:NilClass
Extracted source (around line #33):
31 <td><%= user.work_phone %></td>
32 <td><%= user.cell_phone %></td>
33 <td><%= user.department.name %></td>
34 </tr>
35 <% end %>
36 </table>
Trace of template inclusion: app/views/users/index.html.erb
Rails.root: /Users/nkuligoski/Desktop/tgna_app
Application Trace | Framework Trace | Full Trace
app/views/users/_list.html.erb:33:in `block in _app_views_users__list_html_erb__2838324632886829267_70215593187400'
app/views/users/_list.html.erb:23:in `_app_views_users__list_html_erb__2838324632886829267_70215593187400'
app/views/users/index.html.erb:39:in `_app_views_users_index_html_erb___3592670951755992954_70215580220040'
app/controllers/users_controller.rb:33:in `index'
Try belongs_to :department instead of belongs_to :departments inside the User class.
I'm learning RoR and I'm having trouble getting a value from a related table to display. I've tried the suggestions mentioned here and here but I still haven't gotten it to work.
I have a customer record that has a one-to-many relationship with contacts.
Here are snips of my models:
class Contact < ActiveRecord::Base
belongs_to :customer
class Customer < ActiveRecord::Base
has_many :contacts, dependent: :destroy
and this is my Contacts index.html.erb that is producing the error
<% #contacts.each do |contact| %>
<tr class="<%= cycle("even pointer", "odd pointer") %>">
<td><%= contact.first_name %> <%= contact.last_name %></td>
<td><%= contact.customer.name %></td> <!-- this is the error line -->
<td><%= contact.office_phone %></td>
<td><%= contact.cell_phone %></td>
<td><%= contact.email %></td>
<td>
<% if current_user.admin? %>
<%= link_to "edit", contact, method: :edit %>
<% end %>
</td>
</tr>
<% end %>
The error I get is: undefined method `name' for nil:NilClass
What am I doing wrong? It seems to me like the way I'm referencing the field I'm not actually getting to the data in the Customers table but I'm not really sure. Did I build the relationship correctly in my models?
UPDATE to add controller code
class ContactsController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update, :new, :create]
def index
#contacts = Contact.paginate(page: params[:page])
end
def show
#contact = Contact.find(params[:id])
end
def new
#contact = Contact.new
end
def create
#contact = Contact.new(contact_params)
if #contact.save
flash[:success] = "Contact created!"
redirect_to #contact
else
render 'new'
end
end
def edit
#contact = Contact.find(params[:id])
end
def update
#contact = Contact.find(params[:id])
if #contact.update_attributes(contact_params)
flash[:success] = "Contact updated"
redirect_to #contact
else
render 'edit'
end
end
private
def contact_params
params.require(:contact).permit(:first_name, :last_name, :email, :address1,
:address2, :office_phone, :cell_phone, :website, :city, :zip, :facebook, :twitter)
end
end
class CustomersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update, :new, :create]
def index
#customers = Customer.paginate(page: params[:page])
end
def show
#customer = Customer.find(params[:id])
end
def new
#customer = Customer.new
end
def create
end
def edit
#customer = Customer.find(params[:id])
end
def update
#customer = Customer.find(params[:id])
if #customer.update_attributes(customer_params)
flash[:success] = "Customer updated"
redirect_to #customer
else
render 'edit'
end
end
private
def customer_params
params.require(:customer).permit(:name, :email, :address1,
:address2, :phone, :fax, :website, :city, :zip, :facebook, :duns_number)
end
end
EDIT:
This is my contact.html.erb form.
<%= form_for #contact, html: { class: "form-horizontal form-label-left" } do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="form-group">
<%= f.label :first_name, nil, class: 'control-label col-md-3 col-sm-3 col-xs-12' %>
<div class="col-md-6 col-sm-6 col-xs-12">
<%= f.text_field :first_name, class: 'form-control col-md-7 col-xs-12' %>
</div>
</div>
<div class="form-group">
<%= f.label :last_name, nil, class: 'control-label col-md-3 col-sm-3 col-xs-12' %>
<div class="col-md-6 col-sm-6 col-xs-12">
<%= f.text_field :last_name, class: 'form-control col-md-7 col-xs-12' %>
</div>
</div>
<div class="form-group">
<%= f.label :customer_id, nil, class: 'control-label col-md-3 col-sm-3 col-xs-12' %>
<div class="col-md-6 col-sm-6 col-xs-12">
<%= select_tag :customer_id, options_for_select(Customer.all.collect {|c| [ c.name, c.id ] }), class: 'form-control' %>
</div>
</div>
<div class="form-group">
<%= f.label :office_phone, nil, class: 'control-label col-md-3 col-sm-3 col-xs-12' %>
<div class="col-md-6 col-sm-6 col-xs-12">
<%= f.text_field :office_phone, class: 'form-control col-md-7 col-xs-12' %>
</div>
</div>
<div class="ln_solid"></div>
<div class="form-group">
<div class="col-md-6 col-sm-6 col-xs-12 col-md-offset-3">
<%= f.submit "Save changes", class: "btn btn-primary" %>
</div>
</div>
<% end %>
You are referencing it correctly.
It looks like your contact has not yet been saved to the database. This would cause the relation to not yet exist.
You would might need to be creating the relationship differently.
I usually do something like:
customer = Customer.create
customer.contacts << Contact.create({first_name: 'John', last_name: 'Smith'})
which creates the associations and commits to the DB right away. Then, in the same request, your contact's customer will be set and accessible.
You could also do this, but it's a little redundant:
customer = Customer.create
customer.contacts << Contact.create({first_name: 'John', last_name: 'Smith', customer: customer})
EDIT
It seems that perhaps you need to be assigning a customer to the contact when it is created/updated. In your Contact form, you'll likely need something like this (seeing your existing forms would help here):
<%= select_tag :customer_id, options_for_select(Customer.all.collect {|c| [ c.name, c.id ] }) %>
or (using simple_form):
f.input :customer_id, collection: Customer.all, selected: #contact.customer_id
# or more simply
f.association :customer
Or maybe a hidden form field if you know the Customer when building the form:
f.input :customer_id, as: :hidden, value: #customer.id
Then in your controller, add customer_id to the contact_params like this:
def contact_params
params.require(:contact).permit(
:first_name, :last_name, :email, :address1,
:address2, :office_phone, :cell_phone,
:website, :city, :zip, :facebook, :twitter,
:customer_id
)
end
Try .try() activesupport method:
<td><%= contact.customer.try(:name) %></td>
If contact.customer is nil (Contact doesn't belongs_to Customer), :name method wouldn't be invoked.
UPDATED Another hints:
a. That's a bad thing that you have a contact without customer. Consider to add this to your model:
class Contact < ActiveRecord::Base
...
validates :customer, presence: true
b. You can replace code like that:
<tr class="<%= cycle("even pointer", "odd pointer") %>">
with
<%= content_tag :tr, class: cycle('event pointer', 'odd pointer') %>
c. Replace this:
<%= contact.email %>
with this:
<%= mail_to contact.email, contact.customer.try(:name) %>
Generally this can help
For example, you have 2 tables City and Post, each post has city_id and you want to display in the views the name of the city associated with the post, you should call in the views the bloc then the name of the table then the name of column like that:
<% #post.each do |post| %>
<%= post.city.name %
<% end %>
I am creating a customer service web app for our clients that allows them to submit new customer service tickets, once logged in. I have a login system that I created using the sorcery gem, and I have modified it to accept an additional field: client code.
We are assigning client codes to help prevent unauthorized users from creating accounts.
Upon login, it asks for the information like so:
Name:
Email:
Client Code: (we assign this)
Password:
My question is this, is there a way to only display customer service tickets to clients with the same client code? For example, The "Coca-Cola" clients would only see other "Coca-Cola" tickets and the "Pepsi" clients would only see other "Pepsi" tickets, etc.
Here is my Tickets Controller:
class TicketsController < ApplicationController
before_filter :require_login
def new
#ticket = Ticket.new
end
def create
#ticket = Ticket.new(ticket_params)
if
#ticket.save
redirect_to #ticket
flash[:notice] = "Your Ticket has been submitted. We will contact you very soon!"
else
flash[:notice] = "Something went wrong :("
render 'new'
end
end
def show
#ticket = Ticket.find(params[:id])
end
def index
#tickets = Ticket.all
end
def edit
#ticket = Ticket.find(params[:id])
end
def update
#ticket = Ticket.find(params[:id])
if #ticket.update(ticket_params)
redirect_to #ticket
else
render 'edit'
end
end
def destroy
#ticket = Ticket.find(params[:id])
#ticket.destroy
redirect_to tickets_path
end
private
def ticket_params
params.require(:ticket).permit(:name, :email, :phone, :help)
end
end
Here is the Ticket Index View:
<div class="panel panel-default">
<div class="panel-heading">Ticket Queue</div>
<div class="panel-body">
<table class="table">
<tr>
<th>Name</th>
<th>Phone</th>
<th></th>
<th></th>
</tr>
<% #tickets.each do |ticket| %>
<tr>
<td><%= ticket.name %></td>
<td><%= ticket.phone %></td>
<td><%= button_to "View or Edit", ticket_path(ticket), :class => "btn btn-primary btn-sm", :method => :get %></td>
<td><%= button_to "Delete", ticket_path(ticket), :class => "btn btn-primary btn- sm", :method => :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
</div>
Here is the New Ticket View:
<div class="panel panel-info">
<div class="panel-heading">
<div id="wrapper">
<h1 class="panel-title">New Ticket
<div id="first"><%= button_to "Back", root_path, :class => "btn btn-primary btn-sm", :method => :get %></div>
</div>
</h1>
</div>
<div class="panel-body">
<%= form_for :ticket, url: tickets_path do |f| %>
<p>
<%= f.label "Name:" %>
<%= f.text_field :name %>
</p>
<p>
<%= f.label "Email:" %>
<%= f.text_field :email %>
</p>
<p>
<%= f.label :"Phone #:" %>
<%= f.text_field :phone %>
</p>
<p>
<%= f.label :"How can we help?" %>
<p><%= f.text_area :help, :cols=> 38, :rows => 8 %></p>
</p>
<p>
<button type="submit" class="btn btn-primary btn-sm"><span class="glyphicon glyphicon-envelope"></span> Submit Ticket</button>
</p>
<% end %>
</div>
</div>
Here is the User Model:
class User < ActiveRecord::Base
authenticates_with_sorcery!
validates :password, length: { minimum: 3 }
validates :password, confirmation: true
validates :password_confirmation, presence: true
validates :code, inclusion: { in: %w(Client1, Client2), message: "Please enter a valid Client Code", :allow_nil => false}
validates :email, uniqueness: true
validates_format_of :email, :with => /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
end
Here is the New User View:
<%= form_for(#user) do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :email %><br>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %>
</div>
<div class="field">
<%= f.label "Client Code" %><br />
<%= f.text_field :code %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Here is the User Controller:
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
skip_before_filter :require_login, only: [:index, :new, :create]
# GET /users
def index
#users = User.all
end
# GET /users/1
def show
end
# GET /users/new
def new
#user = User.new
end
# GET /users/1/edit
def edit
end
# POST /users
def create
#user = User.new(user_params)
if #user.save
redirect_to(:users, notice: 'User was successfully created')
else
render :new
end
end
# PATCH/PUT /users/1
def update
if #user.update(user_params)
redirect_to #user, notice: 'User was successfully updated.'
else
render :edit
end
end
# DELETE /users/1
def destroy
#user.destroy
redirect_to users_url, notice: 'User was successfully destroyed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def user_params
params.require(:user).permit(:email, :password, :password_confirmation, :code)
end
end
Let me know if you need to see anything else, thank you!
From your example, I would think Users would have an additional database layer:
class User < ActiveRecord::Base
belongs_to :company
has_many :tickets, through: :companies
end
class Company < ActiveRecord::Base
has_many :users
has_many :tickets
end
class Ticket < ActiveRecord::Base
belongs_to :company
end
Then you can easily display tickets associated with each company
still going on my first rails program (ruby 2.0, rails 4.0). I've got a drop down that displays static options from a second model, but when I click on a selection from that drop down, nothing happens. Saving it to the record (presence_of validation turned off) just leaves the field empty.
I'm thinking something in controller or view? Any help?
Sorry for the massive code dump, but I'm so noob that I wasn't sure what was relevant
Contact.rb
class Contact < ActiveRecord::Base
attr_accessible :first_name, :last_name, :email, :zip_code, :favorite_color, :color_id, :name, :hex
belongs_to :color
accepts_nested_attributes_for :color
Color.rb
class Color < ActiveRecord::Base
has_many :contacts
accepts_nested_attributes_for :contacts
attr_accessible :name, :hex
end
contacts_controller.rb
class ContactsController < ApplicationController
before_action :set_contact, only: [:show, :edit, :update, :destroy]
before_filter :prepare_colors
# GET /contacts
# GET /contacts.json
def index
#contacts = Contact.all
end
# GET /contacts/1
# GET /contacts/1.json
def show
end
# GET /contacts/new
def new
#contact = Contact.new
end
# GET /contacts/1/edit
def edit
end
# POST /contacts
# POST /contacts.json
def create
#contact = Contact.new(contact_params)
respond_to do |format|
if #contact.save
format.html { redirect_to #contact, notice: 'Contact was successfully created.' }
format.json { render action: 'show', status: :created, location: #contact }
else
format.html { render action: 'new' }
format.json { render json: #contact.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /contacts/1
# PATCH/PUT /contacts/1.json
def update
respond_to do |format|
if #contact.update(contact_params)
format.html { redirect_to #contact, notice: 'Contact was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #contact.errors, status: :unprocessable_entity }
end
end
end
# DELETE /contacts/1
# DELETE /contacts/1.json
def destroy
#contact.destroy
respond_to do |format|
format.html { redirect_to contacts_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_contact
#contact = Contact.find(params[:id])
end
def prepare_colors
#colors = Color.all
end
# Never trust parameters from the scary internet, only allow the white list through.
def contact_params
params.require(:contact).permit(:first_name, :last_name, :email, :zip_code, :favorite_color, :color_id)
end
end
views/contacts/_form.html.erb
%= form_for(#contact) do |f| %>
<% if #contact.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#contact.errors.count, "error") %> prohibited this contact from being saved:</h2>
<ul>
<% #contact.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :first_name %><br>
<%= f.text_field :first_name %>
</div>
<div class="field">
<%= f.label :last_name %><br>
<%= f.text_field :last_name %>
</div>
<div class="field">
<%= f.label :email %><br>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :zip_code %><br>
<%= f.number_field :zip_code %>
</div>
<div class="field">
<%= f.label :favorite_color %><br>
<%= f.collection_select(:color_id, #colors, :id, :name, :include_blank => "Please select") %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
and /views/contacts/index.html
h3>Listing contacts</h1>
<table>
<thead>
<tr>
<th>First name</th>
<th>Last name</th>
<th>Email</th>
<th>Zip code</th>
<th>Favorite color</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<% #contacts.each do |contact| %>
<tr>
<td><%= contact.first_name %></td>
<td><%= contact.last_name %></td>
<td><%= contact.email %></td>
<td><%= contact.zip_code %></td>
<td><%= contact.favorite_color %></td>
<td><%= link_to 'Show', contact %></td>
<td><%= link_to 'Edit', edit_contact_path(contact) %></td>
<td><%= link_to 'Destroy', contact, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Contact', new_contact_path %>
Ok, I am not entirely sure what is relationship here, but it seems to me that you have two columns in your Contact model which are created for the same reason: favorite_color and colour_id. You are not setting favorite_color value, but you are trying to display it. I guess color_id is to be a foreign_key to contact's favurite color. if so, you need to rename assocaition:
belongs_to :favorite_color, class_name: 'Color'
Rename color_id column to favorite_color_id, and then inside your view:
# form
<div class="field">
<%= f.label :favorite_color %><br>
<%= f.collection_select(:favorite_color_id, #colors, :id, :name, :include_blank => "Please select") %>
</div>
# index
<td><%= contact.favorite_color.name %></td>
Strong Params
First of all, if you're using rails 4.0 you don't need this line:
attr_accessible :first_name, :last_name, :email, :zip_code, :favorite_color, :color_id, :name, :hex
This has been replaced with strong_params now, so you should put this into the bottom of your contacts controller:
private
def contact_params
params.require(:contact).permit(:first_name, :last_name, :email, :zip_code, :favorite_color, :color_id, :name, :hex, colors_attributes: [])
end
Fields_For
The next thing is that you need to include the fields_for tag in your form, like this:
<%= f.fields_for :colors do |color| %><br>
<%= f.collection_select(:color_id, #colors, :id, :name, :include_blank => "Please select") %>
<% end %>
I think that will work. Your code was pretty long, so I guess if you have problems implementing it, just leave a comment :)
Update
You need to add this to your new function:
# GET /contacts/new
def new
#contact = Contact.new
#contact.color.build
#colors = Color.all
end
Also, I don't know if this will work again, but you might want to edit your collection_select to have this code:
<%= f.fields_for :colors do |color| %><br>
<%= color.collection_select(:color, #colors, :id, :name, :include_blank => "Please select") %>
<% end %>
Finally, you should include the :id attribute in your nested_attributes:
private
def contact_params
params.require(:contact).permit(:first_name, :last_name, :email, :zip_code, :favorite_color, :color_id, :name, :hex, colors_attributes: [])
end