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
Related
I have a rails scaffold for Accounts and another scaffold for Transactions. The Accounts model as an attribute account_name which is created within the form. For each Transaction, the form then prompts a user to select the account the transaction belongs to which is retrieved from the Accounts account_name field. This displays perfectly but when the Transaction is saved, the Account name does not save in the db or display in my index. When I edit the transaction the account name field is set to blank.
Been stuck on this for so damn long - any advice would be greatly appreciated.
My Account model:
class Account < ActiveRecord::Base
has_many :transactions
end
My Account form looks like this (and saves perfectly in the DB )
<%= form_for(#account) do |f| %>
<% if #account.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#account.errors.count, "error") %> prohibited this account from being saved:</h2>
<ul>
<% #account.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="jumbotron">
<div class="container">
<div class="form-group">
<%= f.label :account_name %><br>
<%= f.text_field :account_name, class: "form-control" %>
</div>
</div>
<div class="form-group">
<%= f.label :account_number %><br>
<%= f.number_field :account_number, class: "form-control" %>
</div>
</div>
<div class="actions">
<%= f.submit %>
</form>
<% end %>
</div>
</div>
Transaction Model
class Transaction < ActiveRecord::Base
has_many :accounts
end
The Transaction form looks like (I used the Pluck method to retrieve the Accounts account_name value and it displays all the created accounts):
<div class="form-group">
<%= form_for(#transaction) do |f| %>
<% if #transaction.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#transaction.errors.count, "error") %> prohibited this transaction from being saved:</h2>
<ul>
<% #transaction.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class = "jumbotron">
<form class="needs-validation" novalidate>
<div class="col-md-4 mb-3">
<%= f.label :date %><br>
<%= f.date_select :date, class:"form-control" %>
</div>
<div class="col-md-4 mb-3">
<%= f.label :reference %><br>
<%= f.text_field :reference, class:"form-control" %>
</div>
<div class="col-md-3 mb-3">
<%= f.label :account_name %> <br>
<%= f.select :account_name, Account.pluck(:account_name), {prompt:"Choose Account"}%>
</div>
<div class="form-row">
<div class="col-md-6 mb-3">
<%= f.label :description %><br>
<%= f.text_field :description, class:"form-control" %>
</div>
</div>
<div class="col-md-3 mb-3">
<%= f.label :amount %><br>
<%= f.text_field :amount, class:"form-control" %></br>
</div>
</br></br></br></br></br></br>
<div class="form-check form-check-inline">
</br>
<%= f.label :payment %>
<%= f.check_box :payment %> |
<%= f.label :receipt %>
<%= f.check_box :receipt %>
</div>
<div class="actions">
<%= f.submit %>
<% end %>
My transaction controller is as follows:
class TransactionsController < ApplicationController
before_action :set_transaction, only: [:show, :edit, :update, :destroy]
# GET /transactions
# GET /transactions.json
def index
#transactions = Transaction.all
#balance = 0
#transactions.each do |transaction|
if transaction.payment == true
#balance += transaction.amount
else
#balance -= transaction.amount
end
end
end
# GET /transactions/1
# GET /transactions/1.json
def show
end
# GET /transactions/new
def new
#transaction = Transaction.new
end
# GET /transactions/1/edit
def edit
end
# POST /transactions
# POST /transactions.json
def create
#transaction = Transaction.new(transaction_params)
respond_to do |format|
if #transaction.save
format.html { redirect_to transactions_url, notice: 'Transaction was successfully created.' }
format.json { render :show, status: :created, location: #transaction }
else
format.html { render :new }
format.json { render json: #transaction.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /transactions/1
# PATCH/PUT /transactions/1.json
def update
respond_to do |format|
if #transaction.update(transaction_params)
format.html { redirect_to transactions_url, notice: 'Transaction was successfully updated.' }
format.json { render :show, status: :ok, location: #transaction }
else
format.html { render :edit }
format.json { render json: #transaction.errors, status: :unprocessable_entity }
end
end
end
# DELETE /transactions/1
# DELETE /transactions/1.json
def destroy
#transaction.destroy
respond_to do |format|
format.html { redirect_to transactions_url, notice: 'Transaction was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_transaction
#transaction = Transaction.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def transaction_params
params.require(:transaction).permit(:date, :description, :reference, :account, :amount, :account_id, :payment, :receipt, account_attributes: [:account_name])
end
end
The problem seems to be in the usage of select method for creating a select tag:
<%= f.select :account_name, Account.pluck(:account_name), {prompt:"Choose Account"}%>
The second parameter is expected to be an array of two-elements arrays (one for displayed value in the select tag, and another one for the value that is going to be sent as a request parameter).
Thus, the solution you're looking for is going to look something like:
<%= f.select :account_name, Account.pluck(:account_name).map { |name| [name, name] }, {prompt:"Choose Account"}%>
Or you might want to use options_from_collection_for_select method:
<%= f.select :account_name, options_from_collection_for_select(Account.all, :name, :name) %>
You are facing that issue because you need to store the id of the account as a reference in the transaction.
Currently you are saving account name, so it is not prefetching and saving the data
You can use collection_select and tell that save id into DB and display account_name in select tag.
Syntax:
collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})
The :value_method and :text_method parameters are methods to be called
on each member of collection. The return values are used as the value
attribute and contents of each <option> tag, respectively.
Here is the collection_select in your example:
<%= f.collection_select(:account_name,Account.all, :id, :account_name, :prompt => 'Choose Account') %>
Here is the documentation for the same
I have a question for rails. I'm creating a form for user to register. What I want to do is that after the user press "Submit" button I want to redirect the user to another page which shows all the information from the form filled by the user just now (read-only).
This is my controller
class PermitsController < ApplicationController
before_action :set_permit, only: [:show, :destroy]
def index
#permits = Permit.all
end
def new
#permits = Permit.new
end
def create
#permits = current_user.permits.build(permit_params)
if #permits.save
redirect_to invoice_path
else
render 'new'
end
end
def destroy
Permit.destroy_all(user_id: current_user)
respond_to do |format|
format.html { redirect_to root_path, notice: 'Permit was successfully canceled.' }
format.json { head :no_content }
end
end
def invoice
#permits = current_user.permits(permit_params)
end
def show
#user = User.find(params[:id])
#permits = #user.permits.paginate(permit_params)
end
def update
#permits = Permit.where(user_id: current_user).take
respond_to do |format|
if #permits.update(permit_params)
format.html { redirect_to root_path}
flash[:success] = "Permit successfully updated"
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_permit
#permits = Permit.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def permit_params
params.require(:permit).permit(:vehicle_type, :name, :studentid, :department, :carplate, :duration, :permitstart, :permitend)
end
end
This is the form filled by user
<% provide(:title, 'New Permit') %>
<h1>Permit Application</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#permits) do |f| %>
<%= f.label :"Vehicle" %>
<%= f.text_field :vehicle_type, class: 'form-control' %>
<%= f.label :"License Plate" %>
<%= f.text_field :carplate, class: 'form-control' %>
<%= f.label :"Student ID" %>
<%= f.text_field :studentid, class: 'form-control' %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :"Department of applicant" %>
<%= f.text_field :department, class: 'form-control' %>
<%= f.label :permit_start %>
<%= f.date_select :permitstart, class: 'form-control' %>
<%= f.label :permit_end %>
<%= f.date_select :permitend, class: 'form-control' %>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
</div>
</div>
You could add an additional action between new and create.
# config/routes.rb
resources :permit do
collection do
post :confirm
end
end
The reason that we use POST even if the route does not create a resource is that we don't want to pass any user info in the request URL.
class PermitsController < ApplicationController
# POST /permits/confirm
def confirm
#fields = %i[vehicle_type, carplate, studentid, name, department, permitstart, permitend]
#permit = current_user.permits.build(permit_params)
render :new and return unless #permit.valid?
end
end
render :new and return unless #permit.valid? shortcuts the process and renders the :new form again if the input is not valid in the first place.
Since we are using POST we need a form for both the new.html.erb and confirm.html.erb all duplicating all those inputs would not be great so lets extract them to a partial:
<% # /views/permits/_inputs.html.erb %>
<%
input_options ||= {}
input_options[:class] ||= 'form-control'
%>
<%= f.label :"Vehicle" %>
<%= f.text_field :vehicle_type, input_options%>
<%= f.label :"License Plate" %>
<%= f.text_field :carplate, input_options %>
<%= f.label :"Student ID" %>
<%= f.text_field :studentid, input_options %>
<%= f.label :name %>
<%= f.text_field :name, input_options %>
<%= f.label :"Department of applicant" %>
<%= f.text_field :department, input_options %>
<%= f.label :permit_start %>
<%= f.date_select :permitstart, input_options %>
<%= f.label :permit_end %>
<%= f.date_select :permitend, input_options %>
So lets point the new.html.erb form so that it submits to /permits/confirm:
<% provide(:title, 'New Permit') %>
<h1>Permit Application</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#permits, url: '/permits/confirm_permits_path') do |f| %>
<% render partial: :inputs %>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
</div>
</div>
And create a /views/permits/confirm.html.erb view:
<% provide(:title, 'Confirm Permit application') %>
<h1>Confirm Permit application</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#permits) do |f| %>
<% render partial: :inputs, input_options: { readonly: 'readonly' } %>
<% end %>
</div>
</div>
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 a ROR newbie and I've somehow broken the create and edit functionalities within my app. I have individual pages for each artwork I've uploaded, a _form that enables editing of those artworks (and their original creation), and two different index pages: one index page that's pretty (on the app's home page), and one that's just a big table with all the info for each artwork (for the backend).
routes.rb
Rails.application.routes.draw do
root "pages#home"
get "artworks" => "artworks#index"
# post "artworks" => "artworks#index"
resources :artworks, path: ''
get "about" => "pages#about"
end
artworks_controller.rb
class ArtworksController < ApplicationController
before_action :set_artwork, only: [:show, :edit, :update, :destroy]
# GET /artworks
# GET /artworks.json
def index
#artworks = Artwork.all
end
# GET /artworks/1
# GET /artworks/1.json
def show
#artwork = Artwork.friendly.find(params[:id])
if request.path != artwork_path(#artwork)
redirect_to #artwork, status: :moved_permanently
end
end
# GET /artworks/new
def new
#artwork = Artwork.new
end
# GET /artworks/1/edit
def edit
end
# POST /artworks
# POST /artworks.json
def create
#artwork = Artwork.new( artwork_params )
respond_to do |format|
if #artwork.save
format.html { redirect_to #artwork, notice: 'Artwork was successfully created.' }
format.json { render :show, status: :created, location: #artwork }
else
format.html { render :new }
format.json { render json: #artwork.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /artworks/1
# PATCH/PUT /artworks/1.json
def update
respond_to do |format|
if #artwork.update(artwork_params)
format.html { redirect_to #artworks, notice: 'Artwork was successfully updated.' }
format.json { render :show, status: :ok, location: #artwork }
else
format.html { render :edit }
format.json { render json: #artwork.errors, status: :unprocessable_entity }
end
end
end
# DELETE /artworks/1
# DELETE /artworks/1.json
def destroy
#artwork.destroy
respond_to do |format|
format.html { redirect_to artworks_url, notice: 'Artwork was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_artwork
#artwork = Artwork.friendly.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def artwork_params
params.require(:artwork).permit(:title, :image, :genre, :category, :medium, :slug, :availability, :date, :height, :width)
end
end
pages_controller.rb
class PagesController < ApplicationController
def home
#artworks = Artwork.all
end
def about
end
end
index.html.rb (in views/artworks)
<div class="row">
<div class="col-xs-6 col-sm-8 col-md-4">
<h1>Listing artworks</h1>
</div>
<div class="col-xs-4 col-sm-2 col-md-2 col-md-offset-6">
<%= link_to 'New Artwork', new_artwork_path, class:"btn btn-default" %>
</div>
</div>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Image</th>
<th>Title</th>
<th>Genre</th>
<th>Category</th>
<th>Medium</th>
<th>Date</th>
<th>Dimensions</th>
<th>Availability</th>
<th>Edit</th>
</tr>
</thead>
<tbody>
<% #artworks.each do |artwork| %>
<tr>
<td><%= link_to image_tag(artwork.image.url(:thumb)), artwork %></td>
<td><%= artwork.title %></td>
<td><%= artwork.genre %></td>
<td><%= artwork.category %></td>
<td><%= artwork.medium %></td>
<td><%= artwork.date %></td>
<td><%= artwork.height %> x <%= artwork.width %></td>
<td><%= artwork.availability %> </td>
<td><%= link_to 'Edit', edit_artwork_path(artwork) %></td>
<td></td>
</tr>
<% end %>
</tbody>
</table>
</div>
<br>
_form.html.rb
<%= simple_form_for #artwork, :html => {:multipart => true } do |f| %>
<% if #artwork.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#artwork.errors.count, "error") %> prohibited this artwork from being saved:</h2>
<ul>
<% #artwork.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="row">
<div class="col-md-4">
<%= f.input :image %>
</div>
<div class="col-md-8">
<%= f.input :title %>
</div>
</div>
<div class="row">
<div class="col-md-4">
<%= f.input :genre, :collection => ['Landscape', 'Still life', 'Figure', 'Interior'], :include_blank => false, :as => :radio_buttons %>
</div>
<div class="col-md-4">
<%= f.input :category, :collection => ['Painting', 'Drawing', 'Sculpture', 'Print', 'Mixed media'], :include_blank => false, :as => :radio_buttons %>
</div>
<div class="col-md-4">
<%= f.input :medium, :collection => ['Oil on paper', 'Oil on canvas', 'Oil on canvas mounted on panel', 'Watercolor', 'Ink wash', 'Charcoal', 'Graphite', 'Oil pastel'] %>
</div>
</div>
<div class="row">
<div class="col-md-4">
<%= f.input :date, :include_blank => true, as: :string, start_year: Time.now.year - 100, end_year: Time.now.year, order: [ :year, :month, :day,], hint: 'Order: Year, month, date' %>
</div>
<div class="col-md-4">
<%= f.input :height %>
<%= f.input :width %>
</div>
<div class="col-md-4">
<%= f.input :availability, :collection => ['Available for purchase','Private collection','Not for sale'], :as => :radio_buttons %>
</div>
</div>
<div class="row">
<div class="col-md-8">
<%= f.input :notes %>
</div>
</div>
<div class="row">
<div class="col-md-2 col-md-offset-10">
<%= f.button :submit, class: "btn btn-primary" %>
</div>
</div>
<!--
<div class="form-group">
<%= f.label :image %><br>
<%= f.file_field :image %>
</div>
<div class="form-group">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="form-group">
<%= f.label :genre %><br>
<%= f.select :genre, ['Landscape', 'Still life', 'Figure', 'Interior'] %>
</div>
<div class="form-group">
<%= f.label :category %><br>
<%= f.select :category, ['Painting', 'Drawing', 'Sculpture', 'Print', 'Mixed media'] %>
</div>
<div class="form-group">
<%= f.label :medium %><br>
<%= f.select :medium, ['Oil on paper', 'Oil on canvas', 'Oil on canvas mounted on panel', 'Watercolor', 'Ink wash', 'Charcoal', 'Graphite'] %>
</div>
<div class="actions">
<%= f.submit %>
</div> -->
<% end %>
and home.html.erb (in views/pages)
<div id="artworks" class="transitions-enabled">
<% #artworks.each do |artwork| %>
<div class="box">
<%= link_to image_tag(artwork.image.url(:medium)), artwork %>
</div>
<% end %>
</div>
model: artwork.rb
class Artwork < ActiveRecord::Base
has_attached_file :image, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
extend FriendlyId
friendly_id :slug_candidates, use: [:slugged, :history]
def slug_candidates
[
:title,
[:title, :genre],
[:title, :genre, :category],
[:title, :genre, :category, :medium]
]
end
def previous
Artwork.where(["id < ?", id]).order('id').last
end
def next
Artwork.where(["id > ?", id]).first
end
end
I'm using a few gems that I like (friendly_id), but somehow I've broken the form because I get the error "ActionController::ActionControllerError in ArtworksController#update
Cannot redirect to nil!" related to line 49:
format.html { redirect_to #artworks, notice: 'Artwork was successfully updated.' }
When I create a new artwork, I see this error: "Routing Error
No route matches [POST] "/artworks""
rake routes:
Prefix Verb URI Pattern Controller#Action
artworks GET /artworks(.:format) artworks#index
root GET / pages#home
GET / artworks#index
POST / artworks#create
new_artwork GET /new(.:format) artworks#new
edit_artwork GET /:id/edit(.:format) artworks#edit
artwork GET /:id(.:format) artworks#show
PATCH /:id(.:format) artworks#update
PUT /:id(.:format) artworks#update
DELETE /:id(.:format) artworks#destroy
about GET /about(.:format) pages#about
Can anyone help me see what I've done wrong? Thanks in advance!
Replace
redirect_to #artworks
to
redirect_to artworks_url
also modify routes.rb
Rails.application.routes.draw do
root "pages#home"
resources :artworks
get "about" => "pages#about"
end
I solved this problem by doing a few things:
Created a new 'admin.html.erb' page within my artworks/ folder. I cut and pasted the code from index.html.erb into it.
Cut code out of my home.html.erb file and pasted into the index.html.erb file.
Removed the 'def home' method from the pages_controller.
Rewrote routes as follows:
root "artworks#index"
get "about" => "pages#about"
get "admin" => "artworks#admin"
This other thread I posted helped me sort out this issue. #Ajay's and #Deep's responses helped me think this through.
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