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.
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'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 %>
When I clicked on "display your data" link it is showing me the following error.
Error:
NoMethodError in Users#show
Showing C:/Site/new/app/views/users/show.html.erb where line #10 raised:
undefined method `email' for #<User::ActiveRecord_Relation:0x2bd81e8>
My code snippets are given below.
views/users/index.html.erb
<h1>Choose your option</h1>
<%= link_to "Enter your data",users_new_path %>
<%= link_to "Display your data",users_show_path %>
views/users/new.html.erb
<h1>Enter your data here</h1>
<%= form_for #user,:url => {:action => 'create'} do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.text_field:name,placeholder:"Enter your name" %><br>
<%= f.email_field:email,placeholder:"Enter your email" %><br>
<%= f.text_field:message,placeholder:"Enter your message"%><br>
<%= f.submit "Submit" %>
<% end %>
views/users/show.html.erb
<h1>Display your data</h1>
<ul>
<li>
<p>
<strong>Name:</strong>
<%= #user.name %>
</p>
<p>
<strong>Email:</strong>
<%= #user.email %>
</p>
<p>
<strong>Message:</strong>
<%= #user.message %>
</p>
</li>
</ul>
<%= link_to "Edit",users_edit_path(:id => t.id) %><%= link_to "Delete",users_delete_path(:id => t.id),data: { confirm: 'Are you sure to delete it ?' } %>
<%= link_to "Back",users_index_path %>
controller/users_controller.rb
class UsersController < ApplicationController
def index
end
def new
#user=User.new
end
def create
#user=User.new(users_params)
if #user.save
flash[:notice]="Your data is saved succesfully"
flash[:color]="valid"
redirect_to :action => 'index'
else
flash[:alert]="You are entering wrong data"
flash[:color]="invalid"
render :new
end
end
def show
#user=User.all
end
def delete
#user=User.find(params[:id])
#user.delete
end
def edit
#edit=User.find(params[:id])
#user=User.new
end
def update
#user=User.find(params[:id])
if #user.update_attributes(update_params)
flash[:notice]="Your data has updated successfully"
flash[:color]="valid"
redirect_to :action => 'index'
else
flash[:alert]="Your data could not update..check it.."
flash[:color]="invalid"
render :edit
end
end
private
def users_params
params.require(:user).permit(:name, :email, :message,pets_attributes: [:name, :email,:message])
end
def update_params
params.require (:user).permit(:name,:email,:message,pets_attributes: [:name,:email,:message])
end
end
model/user.rb
class User < ActiveRecord::Base
has_many :pets
accepts_nested_attributes_for :pets
EMAIL_REGEX = /\A[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}\z/i
validates :name, :presence => true,:length => { :minimum => 5 }
validates :email, :presence => true, :uniqueness => true, :format => EMAIL_REGEX
validates :message, :presence => true
end
You should fix your show action from:
def show
#user = User.all
end
to:
def show
#user = User.find(params[:id])
end
In show action, you have
#user = User.all
which assigns relation with all users to #user variable. That's why you have this error, because you can't query whole relation for email. You should have:
#user = User.find(params[:id])
User.find(params[:id]) returns single User instance.
def show
#user=User.all
end
This will return array of users instead of user, so in order to call email on it you have to iterate loop over it.
<% user in #users %> <!-- I have change #user to #users in show method -->
<h1>Display your data</h1>
<ul>
<li>
<p>
<strong>Name:</strong>
<%= user.name %>
</p>
<p>
<strong>Email:</strong>
<%= user.email %>
</p>
<p>
<strong>Message:</strong>
<%= user.message %>
</p>
</li>
</ul>
<%= link_to "Edit",users_edit_path(:id => t.id) %><%= link_to "Delete",users_delete_path(:id => t.id),data: { confirm: 'Are you sure to delete it ?' } %>
<%= link_to "Back",users_index_path %>
<% end %>
Or just change show method
#user = User.find(params[:id])
fix your show action.
replace
#user = User.all
with
#user = User.find(params[:id])
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>
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