I have Devise installed and have set up a UsersController. My UsersController looks like the following:
class UsersController < ApplicationController
def index
#users = User.all
end
end
My routes currently look like this:
Rails.application.routes.draw do
root 'users#home'
devise_for :admins
devise_for :users, controller: :users
scope "/admin" do
resources :users, only: [:index, :show, :new]
end
I created an index page under my users folder with the following code:
<div class = 'container' style = 'width:750px'>
<table>
<thead>
<th>User ID </th>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
<th>Phone Number</th>
</thead>
<tbody>
<%= #users.each do |user| %>
<tr>
<td><%= user.id %></td>
<td><%= user.first_name %></td>
<td><%= user.last_name %></td>
<td><%= user.email %></td>
<td><%= user.country_code %><%= user.phone_number %></td>
</tr>
<%end%>
</tbody>
</table>
</div>
Everything displays perfectly, but I keep receiving this above my table:
This is a screenshot of what I am viewing with the text I want removed highlighted.
Please show me how I can fix this. Big thanks to all that submit!
You should modify your #users.each line to not use the <%=, like so:
<% #users.each do |user| %>
...
<% end %>
In ERB, <%= %> evaluates and prints the result of the code contained within, whereas <% %> only evaluates the expression within.
Hope it helps!
Related
I'm struggling to display only the RELEVANT data in a table that is using has_many and through relationships. My models are the following:
Models
class TrainingResource
has_many :user_training_resources, dependent: :destroy
end
class UserTrainingResource
belongs_to :user
belongs_to :training_resource
end
class Users
has_many :user_training_resources, dependent: :destroy
has_many :training_resources, through: :user_training_resources
end
Ultimately I'm trying to build out a table on the Training Resource Show page of those users that have THAT Training Resource and their current status along with the ability for the user to delete said resource (User Training Resource).
So example while looking at Alpha Training Resource the user sees of the Training Resource: Name, Description, URL, and Total Subscriptions. Then below a list of the users that have Alpha Training along with their current status AND the option to delete it.
Controller
class Admin::TrainingResourcesController < Admin::ApplicationController
belongs_to_app :training_resources
add_breadcrumb 'Training Resources', :admin_training_resources_path
before_action :load_training_resource, only: [:show, :edit, :update, :destroy]
respond_to :html, :json
def show
#user_training_resources = UserTrainingResource.all
#users = User.all
respond_with(#training_resource)
end
private
def load_training_resource
#training_resource = TrainingResource.find_by!(id: params[:id])
end
end
My Training Resource Show template looks like:
<dl class="dl-horizontal">
<dt>Name:</dt>
<dd><%= #training_resource.name %></dd>
<dt>Description:</dt>
<dd><%= #training_resource.description %></dd>
<dt>Subscriptions Available:</dt>
<dd><%= #training_resource.subscriptions_available %></dd>
<dt>Total Subscriptions:</dt>
<dd><%= #training_resource.total_subscriptions %></dd>
<dt>Url:</dt>
<dd><%= #training_resource.url %></dd>
</dl>
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Name</th>
<th>Training Resource Names</th>
<th>Status</th>
<th> </th>
</tr>
</thead>
<tbody>
<% #users.all.each do |user| %>
<tr>
<td><%= user.full_name %></td>
<td><%= user.training_resources.map(&:name).join(', ') %></td>
<td><% user.user_training_resources.each do |user_training_resource| %></td>
<td><%= user_training_resource.status %></td>
<% end %>
<td class="table-actions">
<%# <%= link_to 'Delete', admin_user_training_resource_path(#user_training_resource), :method => :delete, :data => {:confirm => 'Are you sure you want to delete this Training resource?'}, :class => 'btn btn-danger btn-sm' %> %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
So if I go to Training Resource and click on the show for Alpha I see it's name, description, total subscriptions, and url. However the table below will show me all users, all their training resources, and then their status. Not exactly what I want.
I've tried doing something like below in hopes of just going through Training Resource:
<% #training_resource.each do |training_res| %>
<%= training_res.name %>
<% end %>
This results in undefined method 'each'. So how do I display ONLY the data associated with the TrainingResource?
Add a new association for users in model TrainingResource, so that you can directly fetch all the users for a training_resource record.
class TrainingResource
has_many :user_training_resources, dependent: :destroy
has_many :users, through: :user_training_resources
end
Change your controller action show to look like below:
def show
respond_with #training_resource
end
And display the users inside <tbody> tag on training_resource show page in the following way:
<% #training_resource.users.each do |user| %>
<tr>
<td><%= user.full_name %></td>
<!-- If you want to display all the training_resources of the user and their statuses -->
<td><%= user.training_resources.map(&:name).join(', ') %></td>
<td><%= user.user_training_resources.map(&:status).join(', ')</td>
<td class="table-actions">
<!-- Assuming your path is something like '/admin/training_resources/:id/users/:user_id' -->
<%= link_to 'Delete', admin_user_training_resource_path(#training_resource, user), method: :delete, data: { confirm: 'Are you sure you want to delete this Training resource?' }, class: 'btn btn-danger btn-sm' %>
</td>
</tr>
<% end %>
This code is not tested. So, please let me know, if you face any errors.
Update
If you want to show the status of only the current training_resource for all the users, do:
<%- utr = user.user_training_resources.where(training_resource: #training_resource).first %>
<td><%= utr.status %></td>
I'm building a marketplace app where I'm trying to use the Best in Place gem to allow sellers to add a tracking number for each of their orders.
I get a NoMethodError which I'm not able to resolve.
NoMethodError in Orders#sales
undefined method `tracking' for nil:NilClass
The error points to the best in place line below in the view page. This view page is based on the method Sales (in the controller below) where I filter for orders for that particular seller.
Here is my routes.rb with order routing. Since orders need not be edited or destroyed, I didn't create an edit or delete route.
resources :listings do
resources :orders, only: [:new, :create, :update]
collection { post :import }
end
Here is a snippet from my orders controller
class OrdersController < ApplicationController
before_action :set_order, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
before_action :check_user, only: [:edit, :update]
def sales
#orders = Order.all.where(seller: current_user).order("created_at DESC")
end
def update
#order.update_attributes(params[:order])
end
def check_user
if current_user.id != #seller && current_user.name != "admin admin"
redirect_to root_url, alert: "Sorry, you are not the seller of this listing"
end
end
Here is my view page:
<table class="table table-striped table-bordered">
<tr>
<th class="col-md-2">Image</th>
<th class="col-md-2">Item</th>
<th class="col-md-1">Price</th>
<th class="col-md-2">Customer</th>
<th class="col-md-2">Date Sold</th>
<th class="col-md-2">Shipment Tracking #</th>
<th class="col-md-1">Carrier (UPS, USPS, etc.)</th>
</tr>
<% #orders.each do |order| %>
<tr>
<td><%= image_tag order.listing.image.url(:thumb) %></td>
<td><%= order.listing.name %></td>
<td><%= number_to_currency(order.listing.price) %></td>
<td><%= order.buyer.name %></td>
<td><%= order.created_at.strftime("%B %-d, %Y") %></td>
<td><%= best_in_place #order, :tracking, :type => :input %> </td>
<td><%= best_in_place #order, :carrier, :type => :input %></td>
</tr>
<% end %>
</table>
Been stuck on this for a while. Appreciate any help on this.
I think the problem is that you are calling #order inside your .each method.
Try:
<%= best in place order, :tracking, :type => :input %>
You will need to change the next line in your view as well.
I figured it out. The problem was that since I was using best_in_place in a non-Activerecord environment (as part of a table with a list of orders), I needed to pass the order id explicitly. I found this in the best_in_place documentation https://github.com/bernat/best_in_place#non-active-record-environments
I created a custom route for the update action
put 'orderupdate' => "orders#update"
Then in my do loop in the view, I used the custom path for the route above and passed the order id to that route.
<% #orders.each do |order| %>
<tr>
<td><%= order.id %></td>
<td><%= image_tag order.listing.image.url(:thumb) %></td>
<td><%= order.listing.name %></td>
<td><%= number_to_currency(order.listing.price) %></td>
<td><%= order.buyer.name %></td>
<td><%= order.created_at.strftime("%B %-d, %Y") %></td>
<td><%= best_in_place order, :tracking, :type => :input, :url => orderupdate_path(id: order.id) %> </td>
<td><%= best_in_place order, :carrier, :type => :input, :url => orderupdate_path(id: order.id) %> </td>
</tr>
<% end %>
Here is the update method in my controller:
def update
#order = Order.find(params[:id])
respond_to do |format|
if #order.update(order_params)
format.html { redirect_to sales_url, notice: 'Order updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
Hope this helps someone!
I have a model called Task Order that has_many Invoices. When I click "Show" for a Task Order, it is supposed to show all of the Invoices that belong to that Task Order. However, when I click "Show" it shows ALL of the invoices, even ones that do not belong to that task order. Note that I have the same relationship and views for my Contract/Task Order, but it is working correctly so I am not sure where I went wrong.
Here is my Task Order model:
class TaskOrder < ActiveRecord::Base
belongs_to :contract
has_many :invoices, :dependent => :destroy
validates_presence_of :id
validates_uniqueness_of :id
self.primary_key = :id
end
Here is my Invoice model
class Invoice < ActiveRecord::Base
belongs_to :task_order
validates_presence_of :task_order_id
end
Here is my views/task_orders/show code
Invoices:
<table>
<thead>
<tr>
<th>Invoice Date</th>
<th>Invoice #</th>
<th>PoP</th>
<th>Amount</th>
<th>Description</th>
<th>Invoice TO</th>
<th></th>
<th></th>
</tr>
</thead>
</tr>
<tbody>
<% #invoices.each do |invoice| %>
<tr>
<td><%= invoice.invoiceDate%></td>
<td><%= invoice.invoiceNumber %></td>
<td><%= invoice.PoP %></td>
<td><%= number_to_currency(invoice.amount) %></td>
<td><%= invoice.description %></td>
<td><%= invoice.task_order_id %></td>
<td><%= link_to 'Show', invoice %></td>
<td><%= link_to 'Edit', edit_invoice_path(invoice) %></td>
<td><%= link_to 'Destroy', invoice, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
And here is my Task Order controller:
def show
#invoices = Invoice.all
end
def index
#task_orders = TaskOrder.all
end
In your show method, you just want to get only the task order's invoices, rather than all invoices, which you are currently getting.
def show
#task_order = TaskOrder.find(params[:id])
#invoices = #task_order.invoices
end
This way, you don't need to change your show.html.erb file. In addition, you should take a look at the Rails Guides, which should aid you in your quest to learn Rails.
I have records in my Submitter model being shown in Application Index view being displayed in a table like below. Only I want to be able to click on the number that's listed for the .count() and be taken to my Tickets Index view with all of the corresponding records (Tickets) listed.
I'm having trouble understanding how I can link instance variables to a controller's action, in order to use the layout of my views.
Any ideas?
<table>
<tr>
<th>Name</th>
<th>Number of Tickets</th>
</th>
<tr>
<% Submitter.where(:school_id => current_user.school_id, :disabled => false).each do |sub| %>
<td><%= link_to sub.full_name, edit_submitter_path(sub) %></td>
<td><%= Ticket.where(:submitter_id => sub).count %></td>
</tr>
<% end %>
</table>
routes.rb
resources :feedbacks
resources :products
get "password_resets/new"
get 'signup', to: 'users#new', as: 'signup'
get 'login', to: 'sessions#new', as: 'login'
get 'logout', to: 'sessions#destroy', as: 'logout'
resources :users
resources :sessions
resources :password_resets
resources :mailing_lists
resources :submitters
resources :emails
resources :notes
resources :reminders
resources :descriptions
resources :issues
resources :locations
resources :schools
resources :tickets
root :to => "application#index"
It sounds like you have a submitter that has many tickets. If so, you'd show a list of submitters (in the submitters_controller#index method) and count the number of tickets. Then link that number to the tickets_controller#index method. Like this...
routes.rb
resources :submitters do
resources :tickets
end
submitters_controller.rb
class SubmittersController < ApplicationController
def index
#submitters = Submitter.where(:school_id => current_user.school_id, :disabled => false)
end
end
tickets_controller.rb
class TicketsController < ApplicationController
def index
#submitter = Submitter.find(params[:submitter_id])
#tickets = #submitter.tickets
end
end
views/submitters/index.html.erb
<table>
<tr>
<th>Name</th>
<th>Number of Tickets</th>
</th>
<% #submitters.each do |sub| %>
<tr>
<td><%= link_to sub.full_name, edit_submitter_path(sub) %></td>
<td><%= link_to pluralize(sub.tickets.count, 'ticket'), submitter_tickets_path(sub) %></td>
</tr>
<% end %>
</table>
views/tickets/index.html.erb
# This would show a list of tickets and their attributes - possibly linking to a ticket.
Something like this maybe? Not 100% understanding your question.
<table>
<tr>
<th>Name</th>
<th>Number of Tickets</th>
</th>
<tr>
<% Submitter.where(:school_id => current_user.school_id, :disabled => false).each do |sub| %>
<td><%= link_to sub.full_name, edit_submitter_path(sub) %></td>
<td><%= link_to pluralize(sub.tickets.count, 'ticket'), tickets_path %></td>
<% end %>
</tr>
</table>
I, of course, can't give you perfectly working code unless I know what your config/routes.rb looks like, since I don't know what is the method for your Tickets Index view.
I am developing a very basic shopping cart and the issue I am having is that if I add more than one of the same product to my shopping cart I am not seeing the quantity increase and am instead just seeing multiple versions of the item.
For example I see:
1 x green light = £15
1 x green light = £15
rather than seeing:
2 x green light = £30
How can I make it so that my shopping cart will check for multiple versions in the cart and then add them together?
Currently I have:
Application Controller
def current_cart
if session[:cart_id]
#current_cart ||= Cart.find(session[:cart_id])
end
if session[:cart_id].nil?
#current_cart = Cart.create!
session[:cart_id] = #current_cart.id
end
#current_cart
end
Cart Controller
def show
#cart = current_cart
end
Cart Model
has_many :items
def total_price
items.to_a.sum(&:full_price)
end
Cart View
<table id="line_items">
<tr>
<th>Product</th>
<th>Qty</th>
<th class="price">Unit Price</th>
<th class="price">Full Price</th>
</tr>
<% for item in #cart.items %>
<tr class="<%= cycle :odd, :even %>">
<td><%=h item.product.name %></td>
<td class="qty"><%= item.quantity %></td>
<td class="price"><%= gbp(item.unit_price) %></td>
<td class="price"><%= gbp(item.full_price) %></td>
</tr>
<% end %>
<tr>
<td class="total price" colspan="4">
Total: <%= gbp(#cart.total_price) %>
</td>
</tr>
</table>
FURTHER INFORMATION
Products#Index
<%= link_to "Add to Cart", line_items_path(:product_id => product), :method => :post %>
Any advice people can offer would be much appreciated. Thanks!
New Setup - Causing Error Uninitialised Constant CartController
Routes.rb
Checkout::Application.routes.draw do
ActiveAdmin.routes(self)
devise_for :admin_users, ActiveAdmin::Devise.config
post '/add_to_cart/:product_id' => 'cart#add_to_cart', :as => 'add_to_cart'
resources :carts
resources :products
resources :items
root :to => 'products#index'
end
Carts Controller
class CartsController < ApplicationController
def show
#cart = current_cart
end
def add_to_cart
current_cart.add_item(params[:product_id])
redirect_to carts_path(current_cart.id)
end
end
Carts Model
class Cart < ActiveRecord::Base
has_many :items
def add_item(product_id)
item = items.where('product_id = ?', product_id).first
if item
# increase the quantity of product in cart
item.quantity + 1
save
else
# product does not exist in cart
product = Product.find(product_id)
items << product
end
save
end
def total_price
items.to_a.sum(&:full_price)
end
end
Product#Index
<table class="jobs">
<thead>
<tr>
<th scope="col" id="name">Product Code</th>
<th scope="col" id="company">Name</th>
<th scope="col" id="company">Price</th>
<th scope="col" id="company">Action</th>
</tr>
</thead>
<tbody>
<% #product.each do |product| %>
<tr>
<td><%= product.product_code %></td>
<td><%= product.name %></td>
<td><%= gbp(product.price) %></td>
<td><%= button_to "Add to Cart", add_to_cart_path(:product_id => product), :method => :post %></td>
</tr>
<% end %>
</tbody>
</table>
In your Cart model, create a method called
def add_item(product_id)
item = items.where('product_id = ?', product_id).first
if item
# increase the quantity of product in cart
item.quantity + 1
save
else
# product does not exist in cart
cart.items << Item.new(product_id: product_id, quantity: 1)
end
save
end
In routes.rb,
post '/add_to_cart/:product_id' => 'cart#add_to_cart', :as => 'add_to_cart'
Change your Add to Cart route to a call add_to_cart method in the Cart controller.
def add_to_cart
current_cart.add_item(params[:product_id])
# redirect to shopping cart or whereever
end
This should give you the idea of what you are wanting to accomplish.