Associations access column values rails - ruby-on-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

Related

How to initialise a nested input field with ruby on rails?

I am creating a hierarchical list of values (id, code, name, parent_id) for which the code is the business key. This means that when a user wants to attach a value to a parent, he fills in a parent_code field, and before save the model associates the parent value id. The value.rb model has a virtual attribute: parent_code, and the following before_save action:
class Value < ActiveRecord::Base
extend CsvHelper
# This virtual attribute allows user to ignore parent value id
attr_accessor :parent_code
### scope
# Value is linked to a list which belongs to the correct scope
### before filter
before_save :set_parent_id # user only inputs parent code
### validation
validates :code, presence: true
validates :name, presence: true
belongs_to :values_list
has_many :subs, :class_name => "Value", :foreign_key => :parent_id
belongs_to :superior, :class_name => "Value", :foreign_key => :parent_id
### private functions definitions
private
### before filters
def set_parent_id
self.level = 1
if not self.parent_code.blank?
#parent = Value.where("code = ? and values_list_id = ?", self.parent_code, self.values_list_id).first
self.parent_id = #parent.id
self.level = #parent.level.next
end
end
end
This model is used as nested object of a values_list model. This works fine at creation, and produces the expected result.
But when editing a record, the parent_code attribute is by no way initialized, and thus now shown in the input field. Here is the nested form:
<table class="table table-striped table-condensed">
<tr align="left">
<th></th>
<% if #values_list.is_hierarchical %>
<th> <%= t('ParentCode') %> </th>
<th> <%= t('Level') %> </th>
<% end %>
<th> <%= t('Code') %> </th>
<th> <%= t('Value') %> </th>
<th> <%= t('Description') %> </th>
</tr>
<%= f.nested_fields_for :values, #values_list.values.order(:code), wrapper_tag: 'tr' do |value| %>
<td><%= value.remove_nested_fields_link {image_tag("remove.png")} %></td>
<% if #values_list.is_hierarchical %>
<td><%= value.text_field :parent_code, ***# code to initialise #*** %> </td>
<td><%= value.text_field :level, disabled: true %> </td>
<% end %>
<td><%= value.text_field :code %> </td>
<td><%= value.text_field :name %> </td>
<td><%= value.text_field :description %> </td>
<% end %>
</table>
How can I initialise the input field with myvalue.superior.code ?
Thanks a lot!
You could access the form object that you're using in your f.nested_fields_for and set the value that way probably.
<%= f.nested_fields_for :values, #values_list.values.order(:code), wrapper_tag: 'tr' do |value| %>
...
<td><%= value.text_field :parent_code, value: value.object.superior.code %> </td>
<td><%= value.text_field :level, disabled: true %> </td>
...

Rails 4 How to display belongs_to record in a list

so please bear with me :)
group.rb
class Group < ActiveRecord::Base
has_many :categories, dependent: :destroy
validates :name, :presence => true, :uniqueness => { :case_sensitive => false }
validates :content, :presence => true
end
category.rb
class Category < ActiveRecord::Base
belongs_to :group
validates :name, :presence => true, :uniqueness => { :case_sensitive => false }
validates :content, :presence => true
validates :group_id, :presence => true
end
app/views/categories/index.html.erb
<% #categories.each do |category| %>
<tr>
<td><%= category.id %></td>
<td>
<%= link_to category.name, admin_category_path(category) %>
</td>
<td><%= ***[GROUP WHERE CURRENT CATEGORY BELONGS TO]*** %></td>
<td>
<%= link_to admin_category_path(category), class: "btn btn-info btn-xs" do %>
<i class="fa fa-search"></i>
<% end %>
<%= link_to edit_admin_category_path(category), class: "btn btn-primary btn-xs" do %>
<i class="fa fa-pencil"></i>
<% end %>
<%= link_to admin_category_path(category), method: :delete, data: { confirm: 'Are you sure?' }, class: "btn btn-danger btn-xs" do %>
<i class="fa fa-trash-o"></i>
<% end %>
</td>
</tr>
<% end %>
My question is: how to display a group belongs_to this categories?
It's simple, just write:
<td><%= category.group %></td>
Or
<td><%= category.group.name %></td>
One good idea is to define the function "to_s" for your classes.
For example
group.rb
class Group < ActiveRecord::Base
def to_s
name
end
That way Rails will automatically output the name for the group when printing the group meaning that
<td><%= category.group %></td>
and
<td><%= category.group.name %></td>
Will output the same information.
Use <%= category.group.name %> to display a group belongs_to this categories.

Rails 4 : unable to show individual orders

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

undefined method `attr_accessible' while using paperclips for updating photo field in update form

My update form is giving me this error when I choose a new value for the :photo field and update it. It doesnt give an error when non-image fields like username, cellphone, or email are updated and saved. I'm using paperclip as the file attachment management gem.
end
attr_accessible :photo # this is where the error points to
has_attached_file :photo,
:styles => {
:thumb=> "100x100#",
here is the full trace: http://pastie.org/private/etie0qfqujkvrzpetpuqw
Here is the edit.html.erb:
<h1>Add A teacher</h1>
<%= form_for #teacher, :url => { :action => 'update', :id => #teacher.id}, :html => { :multipart => true } do |f| %>
<table summary="teacher form fields">
<tr>
<th>First Name*</th>
<td><%= f.text_field :firstname %></td>
</tr>
<tr>
<th>Last Name*</th>
<td><%= f.text_field :lastname %></td>
</tr>
<tr>
<th>Email*</th>
<td><%= f.email_field :email %></td>
</tr>
<tr>
<th>Cellphone</th>
<td><%= f.telephone_field :cellphone %></td>
</tr>
<tr>
<th>Username*</th>
<td><%= f.text_field :username %></td>
</tr>
<tr>
<tr>
<th>Password*</th>
<td><%= f.password_field :password %></td>
</tr>
<tr>
<th>Confirm Password*</th>
<td><%= f.password_field :password_confirmation %></td>
</tr>
<tr>
<th>Address Street#</th>
<td><%= f.text_field :addr_streetno %></td>
<th>Apt #</th>
<td><%= f.number_field :addr_aptno %></td>
</tr>
<tr>
<th>City</th>
<td><%= f.text_field :addr_city %></td>
<th>State</th>
<td><%= f.text_field :addr_state %></td>
<th>Zip</th>
<td><%= f.number_field :addr_zip %></td>
</tr>
<tr>
<th>Photo</th>
<td><%= f.file_field :photo %></td>
</tr>
</table>
<%= f.submit 'Update teacher' %>
<% end %>
<% if #teacher.errors.any? %>
<ul class="Signup_Errors">
<% for message_error in #teacher.errors.full_messages %>
<li>* <%= message_error %></li>
<% end %>
</ul>
<% end %>
</div>
Here is the controller:
class TeacherController < ApplicationController
def index
#teachers= Teacher.all
end
def new
#teacher = Teacher.new
end
def create
#teacher = Teacher.new(teacher_params)
if #teacher.save
flash[:notice] = "Teacher created."
redirect_to :action => 'index'
else
render :action => 'new'
end
end
def edit
#teacher = Teacher.find(params[:id])
end
def update
#teacher = Teacher.find(params[:id])
# Update the object
if #teacher.update_attributes(teacher_params)
# If update succeeds, redirect to the list action
flash[:notice] = "Teacher updated."
redirect_to :action => 'show', :id => #teacher.id
else
# If update fails, redisplay the form so user can fix problems
render :action => 'edit'
end
end
def show
#teacher = Teacher.find(params[:id])
end
private
def teacher_params
params.require(:teacher).permit(:firstname,
:lastname,
:email,
:cellphone,
:username,
:password,
:password_confirmation,
:addr_streetno,
:addr_aptno,
:addr_city,
:addr_state,
:addr_zip,
:photo)
end
end
Here is the model:
class Teacher < ActiveRecord::Base
has_many :students
has_secure_password
EMAIL_REGEX = /\A[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}\z/i
CELLPHONE_REGEX = /\A([0-9]( |-)?)?(\(?[0-9]{3}\)?|[0-9]{3})( |-)?([0-9]{3}( |-)?[0-9]{4}|[a-zA-Z0-9]{7})\z/i
validates :firstname, :presence => true
validates :lastname, :presence => true
validates :username, :presence => true, :uniqueness => true, :length => { :in => 3..20 }
validates :email, :presence => true, :uniqueness => true, :format => EMAIL_REGEX
validates :cellphone, :presence => true, :format => CELLPHONE_REGEX
[:addr_aptno, :addr_zip].each do |n|
validates n, numericality: { only_integer: true,
:greater_than => 0,
:allow_blank => true
}
end
attr_accessible :photo
has_attached_file :photo,
:styles => {
:thumb=> "100x100#",
:small => "150x150>",
:medium => "300x300>",
:large => "400x400>" }
end
Answer the Original Question
updating an image field gives NoMethodError undefined method name'
for nil:NilClass inupdate'
OP wasn't using amy gem to facilitate uploading files in the Rails application which was causing this issue. Suggested OP to use one of the well known gems Paperclip or CarrierWave.
Answer the Modified Question
undefined method `attr_accessible' while using paperclips for updating
photo field in update form
As you are using Rails 4, attr_accessible :photo will not work as it has been removed. Instead you would need to use Strong Parameters for attribute whitelisting which you are already doing by permitting :photo attribute in teacher_params method.
So, all you need to do is remove attr_accessible :photo from Teacher model.
Adding restarting the rails server (since the paperclips gem was added) & adding add_attachment :, : to the migration file and running it, the following fields in the table (add_attachment :teachers :photo used run here)
t.string "photo_file_name"
t.string "photo_content_type"
t.integer "photo_file_size"
t.datetime "photo_updated_at"
In addition, I had to add :photo in the strong parameter assignment call in the controller file and also had to add add_attachment :teachers :photo in the migration file & run it. There were several pieces to it.

Nested attributes are not updating in rails

I have 3 models:
class DropShipOrderLineItem < ActiveRecord::Base
belongs_to :drop_ship_order
belongs_to :line_item
validates_associated :drop_ship_order
validates_associated :line_item
validates :drop_ship_order_id, :presence => true
validates :line_item_id, :presence => true
attr_accessible :missing
end
class DropShipOrder < ActiveRecord::Base
attr_accessible :line_items, :line_items_attributes, :orders, :order_attributes
belongs_to :retailer
belongs_to :order
belongs_to :shipping_method
has_many :drop_ship_order_line_items
has_many :line_items, :through => :drop_ship_order_line_items
has_many :shipments, :dependent => :destroy
accepts_nested_attributes_for :line_items
accepts_nested_attributes_for :order
accepts_nested_attributes_for :drop_ship_order_line_items
before_create :generate_order_number
scope :by_number, lambda {|number| where("drop_ship_orders.number = ?", number)}
scope :between, lambda {|*dates| where("drop_ship_orders.created_at between ? and ?", dates.first.to_date, dates.last.to_date)}
scope :by_customer, lambda {|customer| joins(:order).joins(:user).where("users.email =?", customer)}
scope :by_state, lambda {|state| where("state = ?", state)}
scope :complete, where("drop_ship_orders.completed_at IS NOT NULL")
scope :incomplete, where("drop+ship_orders.orders.completed_at IS NULL")
make_permalink :field => :number
validates_associated :order
validates_associated :retailer
end
LineItem.class_eval do
has_one :drop_ship_order_line_item, :dependent => :destroy
has_one :drop_ship_order, :through => :drop_ship_order_line_items
accepts_nested_attributes_for :drop_ship_order_line_item
attr_accessible :drop_ship_order_line_item
# def missing
# self.drop_ship_order_line_item.missing
# end
end
View #1:
<div data-hook="admin_order_edit_form">
<div id="order-form-wrapper">
<%= render :partial => 'form', :locals => {:drop_ship_order => #drop_ship_order} %>
</div>
</div>
View form:
<%= form_for(#drop_ship_order, :url => admin_drop_ship_order_path(#drop_ship_order), :html => { :method => :put}) do |f| %>
<%= f.hidden_field :number %>
<table class="index">
<tbody id='line-items'>
<tr data-hook="admin_order_form_line_items_headers">
<th><%= t('item_description') %></th>
<th class="price"><%= t('price') %></th>
<th class="qty"><%= t('qty') %></th>
<th class="total"><span><%= t('total') %></span></th>
<th class="orders-actions" data-hook="admin_order_form_line_items_header_actions"></th>
</tr>
<%= f.fields_for :line_items do |li_form| %>
<%= render :partial => "admin/drop_ship_orders/line_item", :locals => { :f => li_form } %>
<% end %>
</tbody>
<tbody id='subtotal' data-hook="admin_order_form_subtotal">
<tr id="subtotal-row">
<td colspan="3"><b><%= t('subtotal') %>:</b></td>
<td class="total"><span><%= number_to_currency #drop_ship_order.item_total %></span></td>
<td></td>
</tr>
</tbody>
view line_item:
<tr id="<%= dom_id(f.object) %>" data-hook="admin_order_form_line_item_row">
<td width="300"><%=f.object.variant.product.name%> <%= "(" + variant_options(f.object.variant) + ")" unless f.object.variant.option_values.empty? %></td>
<td valign="top" class="price"><%= number_to_currency f.object.price %></td>
<td valign="top" class="qty"><strong><%= f.object.quantity %></strong></td>
<td valign="top" class="total"><%= number_to_currency (f.object.price * f.object.quantity)%></td>
<td data-hook="admin_order_form_line_item_actions">
<!--<input type="checkbox" name="apple" id="apples"/>-->
<%#= f.object.drop_ship_order_line_item.missing %>
<%= f.fields_for :drop_ship_order_line_item do |build|%>
<%= build.check_box :missing, :type => "checkbox" %>
<% end %>
</td>
</tr>
The :missing attribute is not being updated, and I just can't figure out why! Although the checkboxe is correctly being ticked if I manually change the values in my SQL table.
p.s: I just posted the relevant parts of my code.
In your LineItem model change attr_accessible :drop_ship_order_line_item to attr_accessible :drop_ship_order_line_item_attributes.
What is the :type => "checkbox" for in the following code:
<%= build.check_box :missing, :type => "checkbox" %>
The second parameter for the check_box form helper should be the method. I think if you change to the following code, it should work:
<%= build.check_box :missing %>

Resources