Rails 4 : unable to show individual orders - ruby-on-rails

Trying to show individual items on my grocery app.
Using item.product.title & item.quantity.
because I want to do a subtotal of the orders. At the moment i get
NoMethodError in Orders#show - undefined method `product' for #<OrderItem:0x007fe53514d6e8>
orders.show.html
<h1>Your Order</h1>
<table class="table table-striped">
<tr>
<th>Customer</th>
<td><%= #order.user_id %></td>
</tr>
<tr>
<th>Status:</th>
<td><%= #order.status %></td>
</tr>
<tr>
<th>Items:</th>
<td><%= #order.order_items.count %></td>
</tr>
<tr>
<th>Items</th>
<th>Title</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Subtotal</th>
</tr>
<% #order.order_items.each do |item| %>
<tr>
<td></td>
<td><%= item.product.title %></td> <-----Error
<td><%= item.quantity %></td>
<td><%= item.product.price %></td>
<td><%= print_price item.subtotal %></td>
<% end %>
</table>
<%= link_to 'Edit', edit_order_path(#order) %> |
<%= link_to 'Back', orders_path %>
product.rb
class Product < ActiveRecord::Base
validates_numericality_of :price
validates :stock ,numericality: { greater_than_or_equal_to: 0 }
has_many :order_items
end
order.item
class OrderItem < ActiveRecord::Base
belongs_to :Order
belongs_to :Product
validates :order_id, :product_id, presence: true
end
full error
NameError in Orders#show
undefined local variable or method `product' for #<#<Class:0x007fe539003568>:0x007fe5391abd48>
app/views/orders/show.html.erb:30:in `block in _app_views_orders_show_html_erb__2160818799905733439_70311241143160'
app/views/orders/show.html.erb:27:in `_app_views_orders_show_html_erb__2160818799905733439_70311241143160'

Order item needs to be
class OrderItem < ActiveRecord::Base
belongs_to :order
belongs_to :product
validates :order_id, :product_id, presence: true
end
Easiest way to think of it, is that belongs_to is defining the method that returns the object associated with the join. So :product - to create order_item.product. Not :Product

Related

How to add many Categories to one Post in Rails

I want to make a feature to show posts with specific categories, A, B, C..., where there can be more than one category. Currently, I can add only one.
How can I add more and show them?
This is the migration:
class CreateCategories < ActiveRecord::Migration[6.0]
def change
create_table :categories do |t|
t.string :name
t.text :description
t.boolean :display_in_navbar, default: true
t.timestamps
end
end
end
class CreatePosts < ActiveRecord::Migration[6.0]
def change
create_table :posts do |t|
t.string :title
t.text :body
t.string :author
t.boolean :featured
t.integer :likes
t.string :source
t.references :category, null: false, foreign_key: true
t.timestamps
end
end
end
My models:
class Category < ApplicationRecord
has_and_belongs_to_many :posts
end
class Post < ApplicationRecord
has_and_belongs_to :categories
end
And the view:
<table>
<thead>
<tr>
<th>Title</th>
<th>Body</th>
<th>Author</th>
<th>Featured</th>
<th>Likes</th>
<th>Source</th>
<th>Category</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.body %></td>
<td><%= post.author %></td>
<td><%= post.featured %></td>
<td><%= post.likes %></td>
<td><%= post.source %></td>
<td><%= post.category.name %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
This is _form.html.erb:
<table>
<thead>
<tr>
<th>Title</th>
<th>Body</th>
<th>Author</th>
<th>Featured</th>
<th>Likes</th>
<th>Source</th>
<th>Category</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.body %></td>
<td><%= post.author %></td>
<td><%= post.featured %></td>
<td><%= post.likes %></td>
<td><%= post.source %></td>
<td><%= post.category.name %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
and _post.json.jbuilder:
json.extract! post, :id, :title, :body, :author, :featured, :likes, :source, :category_id, :created_at, :updated_at
json.url post_url(post, format: :json)
Looking at the has_and_belongs_to_many guide, notice the references don't go into categories nor posts, but to a join table in the middle, in this case categories_posts.
create_table :categories_posts, id: false do |t|
t.belongs_to :category
t.belongs_to :post
end
Or use create_join_table to do the equivalent.
create_join_table :categories, :posts do |t|
t.index :category_id
t.index :post_id
end
And remove the reference to category in the posts table.
Run rails g migration CreatePostCategory post:references category:references and remove reference of category from post rails g migration RemoveCategoryFromPosts category:references, this will look like as below.
class RemoveCategoryFromPost < ActiveRecord::Migration
def change
remove_reference :posts, :category, index: true, foreign_key: true
end
end
then run rails db:migrate. This will work for you.
Model will remain same.
class Category < ApplicationRecord
has_and_belongs_to_many :posts
end
class Post < ApplicationRecord
has_and_belongs_to :categories
end

Rails controller: Calling associated model records to index view

I am having an issue with this controller Active record query. I have a model called Submissions and each Submission has an AgentActivity associated with it. I am trying to simply show all Submission fields on a row as well as associated Agent Activity next to it using a db query but I am getting errors with this, is that too simple?:
#agent_activities = #submissions.find(:agent_activity)
Submission index action
def index
#agent_activities = #submissions.find(:agent_activity)
#submissions =
SubmissionLocation.includes(:submission).where(location_id:
current_agent.Company_Business_Location).map(&:submission)
end
<% #submissions.each do |submission| %>
<tr>
<td><%= submission.First_Name %></td>
<td><%= submission.Last_Name %></td>
<% if user_signed_in? %>
<td><%= submission.Phone %></td>
<td><%= submission.Email %></td>
<%else%>
<% end %>
<td><%= submission.Desired_Location %></td>
<td><%= submission.number_of_beds %></td>
<td><%= submission.number_of_occupants %></td>
<td><%= submission.Rent_price_per_month_gbp %></td>
<% if user_signed_in? %>
<td><%= submission.Max_move_in_date %></td>
<td><%= submission.Tenant_Occupation %></td>
<td><%= submission.Contact_me_on %></td>
<td><%= submission.Furnished %></td>
<td><%= submission.Current_Address %></td>
<td><%= submission.Property_Requirements %></td>
<%else%>
<% end %>
<% Array(#agent_activities).each do |agent_activity|%>
<td><%= agent_activity.Status %></td>
<td><%= agent_activity.Notes %></td>
<% end%>
<td><%= link_to 'See More', submission %></td>
<% end %>
Submissions model
class Submission < ApplicationRecord
belongs_to :user, :optional => true
has_many :agent_activities, inverse_of: :submission
has_many :agents, through: :agent_activities
accepts_nested_attributes_for :agent_activities, :reject_if=> proc
{|attributes| attributes[:entry].blank?}, :allow_destroy => true
has_many :submission_locations
attr_accessor :location_1, :location_2, :location_3
end
Agent Activity model
class AgentActivity < ApplicationRecord
belongs_to :submission, :optional => true, inverse_of:
:agent_activities #has submission_id foreign key in table
belongs_to :agent, :optional => true, inverse_of: :agent_activities
end
You are assigning #submissions AFTER you are trying to call find on it. You need to reverse the order.
EDIT: Also you are using the association wrong. It doesnt look like you have a SubmissionLocation model.
Should be:
def index
#submissions = Submission.where() #fill this query out
end
And then when looping through submissions on the view you can call submission.agent_activities

Rails - Case Monitoring App - Want to display data from 2 tables in the view

Model:
class Case < ActiveRecord::Base
belongs_to :employee, :foreign_key => :input_id
end
Controller
def index
#cases = Case.all
end
View
<% #cases.each do |c| %>
<tr>
<td><%= c.employee.name %></td>
<td><%= c.problem %></td>
<td><%= c.assigned_id %></td>
<td><%= c.solution %></td>
<td><%= c.verified_id %></td>
</tr>
<% end %>
How do I make the view display the employee name who owns the assigned_id?
(I'm already using employee.name to display the name for the input_id column?)
Use two reflections
class Case < ActiveRecord::Base
belongs_to :employee, :foreign_key => :input_id
belongs_to :assigned_employee, :foreign_key => : assigned_id, : class_name => "Employee"
end
In the View
<% #cases.each do |c| %>
<tr>
<td><%= c.employee.name %></td>
<td><%= c.assigned_employee.name %></td>

Rails model relationship doubts

I have these models
class Course < ActiveRecord::Base
attr_accessible :name
has_many :teachers
end
class Teacher < ActiveRecord::Base
attr_accessible :id, :name, :course_id
belongs_to :course
has_many :evaluations
end
class Evaluation < ActiveRecord::Base
attr_accessible :teacher_id, :course_id
belongs_to :teacher
end
this is the views/evaluations/index.html.erb file
<% #evaluations.each do |evaluation| %>
<tr>
<td><%= evaluation.teacher_id %></td>
<td><%= link_to 'Show', evaluation %></td>
<td><%= link_to 'Edit', edit_evaluation_path(evaluation) %></td>
<td><%= link_to 'Destroy', evaluation, :method => :delete, :data => { :confirm => 'Are you sure?' } %></td>
</tr>
<% end %>
I want to display the teacher's name with:
<td><%= evaluation.teacher.name %></td>
but it doesn't work.Rails shows this error:
"undefined method `name' for nil:NilClass"
Can anyone help me?
For all of your evaluation rails will get the teacher and then display it's name. If only one evaluation has no teacher, it will get nul for the teacher and then try to get name on that nil, then you have your error.
Try this :
<td><% if evaluation.teacher %>
<%= evaluation.teacher.name %>
<% end %></td>

Associations access column values rails

I have a Customer and Invoice Model. A customer has many invoices and an invoice belongs_to a customer. An invoice has many invoice items and Invoice items belong to an invoice
class Customer < ActiveRecord::Base
attr_accessible :billing_address, :customer_currency, :email, :first_name, :last_name, :mobile, :name, :payment_terms, :phase_type, :pays_vat
validates_presence_of :first_name, :last_name, :mobile, :billing_address, :payment_terms, :phase_type, :customer_currency
has_many :invoices
validates :email,
:presence => true,
:uniqueness => true,
:email_format => true
validates :name, :mobile, :presence => true, :uniqueness => true
end
Invoice Model
class Invoice < ActiveRecord::Base
belongs_to :customer
attr_accessible :approved_by, :due_date, :invoice_date, :terms, :customer_id, :customer
validates :invoice_date, presence: true
validates :due_date, presence: true
validates :customer, presence: true
has_many :invoice_items
accepts_nested_attributes_for :invoice_items
end
Invoice Items model
class InvoiceItem < ActiveRecord::Base
belongs_to :invoice
attr_accessible :amount, :description, :rate, :tax_amount
end
I have created an index page for Invoices where I want to list all invoices with their corresponding items however, the challenge I am having is how to access the amount in invoice items and display it in the index page
app/views/index.html.erb
<div class="row">
<div class="span12">
<table class="table table-striped">
<thead>
<tr>
<th>Invoice ID </th>
<th>Customer Name </th>
<th>Invoice Date </th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<% #invoices.each do |invoice| %>
<tr>
<td><%= link_to invoice.id, invoice_path(invoice) %></td>
<td><%= invoice.customer.name %></td>
<td><%= invoice.invoice_date %></td>
<td><%= invoice.invoice_items.amount %></td>
</tr>
<% end %>
</tbody>
</table>
<div class="form actions">
<p>
<%= link_to t('.new', :default => t("helpers.links.new")),
new_invoice_path, :class => 'btn btn-primary' %>
</p>
</div>
</div>
</div>
invoice.invoice_items.amount does not return that amount from Invoice_items for that invoice. Any ideas?
Below is my Invoices_controller index method
class InvoicesController < ApplicationController
before_filter :authenticate_user!
def index
#invoices = Invoice.includes(:customer, :invoice_items).all
end
end
You can get amount of any elements using
invoice.invoice_items.count
or
invoice.invoice_items.size
invoice.invoice_items.first.amount
iterate on invoice_items too, inside #invoices iterator
<% #invoices.each do |invoice| %>
<tr>
<td><%= link_to invoice.id, invoice_path(invoice) %></td>
<td><%= invoice.customer.name %></td>
<td><%= invoice.invoice_date %></td>
<% invoice.invoice_items.each do |invoice_item| %>
<td><%= invoice_item.rate %></td>
<td><%= invoice_item.amount %></td>
</tr>
<% end %>
adjust the table

Resources