Reputation: 978
I have a scaffolded 'Customer.rb' model and a 'Invoice.rb' model. I want people to select a existing Customer from the Customer model and put a few attributes of that selected option in the view of the invoice.
This is the code inside my Invoice#new (@customer = Customer.all in the Invoice_controller)
<%= @customer.select(:company_name) do |f| %>
<h4>Customer:</h4>
<div class="well">
<address>
<strong class="text-dark"><%= f.company_name %></strong><br/>
<%= f.first_name + f.last_name if f.first_name.present? && f.last_name.present?%><br/>
<%= f.address_line_1 %><br/>
<%= f.address_line_2 if present? %>
</address>
</div>
<% end %>
</div>
Invoices Controller
class InvoicesController < ApplicationController
before_action :set_invoice, only: [:show, :edit, :update, :destroy]
# GET /invoices
# GET /invoices.json
def index
@invoices = Invoice.all
end
# GET /invoices/1
# GET /invoices/1.json
def show
end
# GET /invoices/new
def new
@invoice = Invoice.new
@customer = Customer.all
end
# GET /invoices/1/edit
def edit
end
# POST /invoices
# POST /invoices.json
def create
@invoice = Invoice.new(invoice_params)
respond_to do |format|
if @invoice.save
format.html { redirect_to @invoice, notice: 'Invoice was successfully created.' }
format.json { render :show, status: :created, location: @invoice }
else
format.html { render :new }
format.json { render json: @invoice.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /invoices/1
# PATCH/PUT /invoices/1.json
def update
respond_to do |format|
if @invoice.update(invoice_params)
format.html { redirect_to @invoice, notice: 'Invoice was successfully updated.' }
format.json { render :show, status: :ok, location: @invoice }
else
format.html { render :edit }
format.json { render json: @invoice.errors, status: :unprocessable_entity }
end
end
end
# DELETE /invoices/1
# DELETE /invoices/1.json
def destroy
@invoice.destroy
respond_to do |format|
format.html { redirect_to invoices_url, notice: 'Invoice was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_invoice
@invoice = Invoice.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def invoice_params
params.require(:invoice).permit(:number, :currency, :date, :duedate, :btwtotal, :subtotal, :total, :footer)
end
end
This shows the correct information but it shows it for ALL columns in the Customers table. I wan't people to pick a specific column only. Like lets say; someone selects 'Coca Cola Ltd.' from a dropdown and then sees only the information of Coca Cola Ltd. (f.company_name: Coca Cola Ltd. etcetera)
The Invoice.rb model contains 'has_one :customer'
The Customer.rb model contains 'belongs_to :invoice'
I tried everything from the ruby on rails guides but i don't seem to get it. Any help would be MUCH appreciated
UPDATE
Invoices#_form
<%= form_for(@invoice) do |f| %>
<% if @invoice.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@invoice.errors.count, "error") %> prohibited this invoice from being saved:</h2>
<ul>
<% @invoice.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="container-fluid container-fullw">
<div class="row">
<div class="col-md-8">
<div class="panel panel-white">
<div class="panel-body">
<div class="invoice">
<div class="row invoice-logo">
<div class="col-sm-6">
<img alt="" src="">
</div>
<div class="col-sm-6">
<p class="text-dark">
<%= @invoice.number %> <small class="text-light"> 23-07-2016 </small>
</p>
</div>
</div>
<hr>
<div class="row">
<div class="col-sm-4">
<%= f.select :customer, :customer_id, options_for_select(@customers.map{ |customer| [customer.company_name, customer.id, {"data-some-field" => customer.company_name}] },
id: "my_select") %>
<h4>Klant:</h4>
<div class="well">
<address>
<strong class="text-dark"></strong><br/>
<%= f.text_field :company_name, id: "my_field" %>
<br>
<abbr title="Phone">P:</abbr> (123) 456-7890
</address>
<address>
<strong class="text-dark">E-mail:</strong>
<a href="mailto:#"> [email protected] </a>
</address>
</div>
</div>
<div class="col-sm-4 pull-right">
<h4>Gegevens:</h4>
<ul class="list-unstyled invoice-details padding-bottom-30 padding-top-10 text-dark">
<li>
<strong>BTW #:</strong> 233243444
</li>
<li>
<strong>Bedrijfsnaam:</strong> Company B.V
</li>
<li>
<strong>IBAN:</strong> 1233F4343ABCDEW
</li>
<li>
<strong>Factuurdatum:</strong> 01/01/2016
</li>
<li>
<strong>Te betalen voor:</strong> 11/02/2016
</li>
</ul>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<table class="table table-striped">
<thead>
<tr>
<th> # </th>
<th> Item </th>
<th class="hidden-480"> Description </th>
<th class="hidden-480"> Quantity </th>
<th class="hidden-480"> Unit Cost </th>
<th> Total </th>
</tr>
</thead>
<tbody>
<tr>
<td> 1 </td>
<td> Lorem </td>
<td class="hidden-480"> Drem psum dolor </td>
<td class="hidden-480"> 12 </td>
<td class="hidden-480"> $35 </td>
<td> $1152 </td>
</tr>
<tr>
<td> 2 </td>
<td> Ipsum </td>
<td class="hidden-480"> Consectetuer adipiscing elit </td>
<td class="hidden-480"> 21 </td>
<td class="hidden-480"> $469 </td>
<td> $6159 </td>
</tr>
<tr>
<td> 3 </td>
<td> Dolor </td>
<td class="hidden-480"> Olor sit amet adipiscing eli </td>
<td class="hidden-480"> 24 </td>
<td class="hidden-480"> $144 </td>
<td> $8270 </td>
</tr>
<tr>
<td> 4 </td>
<td> Sit </td>
<td class="hidden-480"> Laoreet dolore magna </td>
<td class="hidden-480"> 194 </td>
<td class="hidden-480"> $317 </td>
<td> $966 </td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="row">
<div class="col-sm-12 invoice-block">
<ul class="list-unstyled amounts text-small">
<li>
<strong>Subtotaal:</strong>
<div class="field">
<%= f.text_field :subtotal %>
</div>
</li>
<!-- <li>
<strong>Discount:</strong>
</li> -->
<li>
<strong>BTW:</strong>
<div class="field">
<%= f.text_field :btwtotal %>
</div>
</li>
<li class="text-extra-large text-dark margin-top-15">
<strong >Totaal:</strong>
<div class="field">
<%= f.text_field :total %>
</div>
</li>
</ul>
<br>
</div>
</div>
</div>
<div class="panel-footer">
<%= @invoice.footer.present? ? @invoice.footer : "We verzoeken u vriendelijk het bovenstaande bedrag van
€ #{@invoice.total} voor #{@invoice.duedate} te voldoen op onze bankrekening onder vermelding van het
factuurnummer #{@invoice.number}. Voor vragen kunt u contact opnemen per e-mail." %>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="panel panel-white">
<div class="panel-body">
<div class="form-group">
<div class="field">
<%= f.label :Factuurnummer %><br>
<%= f.text_field :number, placeholder: '2016-0001' %>
</div>
<div class="form-group">
<%= f.label :Munteenheid %><br>
<%= f.select(:currency, [[' €', 1, title: 'Euro', value: 'EURO'], [' $', 2, title: 'US Dollar', value: 'USD'],
[' £', 3, title: 'GBP Pound', value: 'GBP']]) %>
</div>
<div class="field">
<%= f.label :factuurdatum %><br>
<%= f.date_select :date %>
</div>
<div class="field">
<%= f.label 'te betalen voor' %><br>
<%= f.date_select :duedate %>
</div>
<div class="field">
<%= f.label :footer %><br>
<%= f.text_area :footer %>
</div>
<div class="actions">
<%= f.submit 'opslaan', class: 'btn btn-primary btn-success' %>
<%= link_to 'annuleren', invoices_path, class: 'btn btn-primary btn-info' %>
<a onclick="javascript:window.print();" class="btn btn-primary float-right"> print <i class="fa fa-print"></i></a>
</div>
<% end %>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- end: INVOICE -->
<script>
$("#my_select").change(function() {
var selection = $(this).find(":selected");
alert(selection.data("data-some-field"));
});
</script>
Upvotes: 0
Views: 113
Reputation: 10696
What you want is more complicated than you might have imagined. Anytime you want dynamic stuff going on, you're going to have to rely on scripting. The view is largely inert -- it's only displaying information supplied to it by the controller, so you're going to need help from JavaScript and potentially AJAX.
Firstly, pluralize your field name in invoice#new
to save potential confusion for people viewing your code.
@customer = Customer.all
should be:
@customers = Customer.all
This way, it's clear that you're referring to a collection and not a single record.
Then replace your select
in the view with the following:
<%= f.select :customer, options_for_select(@customers.map { | cust | [cust.name, cust.id, 'data-some-field' => cust.some_field] }), { id: "my_select" } %>
What you're doing here is passing the select
an options_for_select
that uses an HTML data attribute to pass in additional information. You're going to have to modify invoice#new
to build this information, an exercise I leave to you because I have no idea what you wish to display.
Add a textfield to your view to display the new information:
text_field_tag (:some_field, id: "my_field")
Then, you're going to have to modify your invoice.js
asset with the following JavaScript:
$("#my_select").change(function()
{
var selection = $(this).find(":selected");
getElementById("my_field").value = selection.data("data-some-field");
});
Upvotes: 1
Reputation: 395
I would say you should associate both with a join table.. the join table will keep record of both customer and invoice id eg
class Customer < ApplicationRecord
has_many :join_table
has_many :invoices, :through => :join_table
end
class Invoice < ApplicationRecord
has_many :join_table
has_many :customers, :through => :join_table
end
class JoinTable < ApplicationRecord
belongs_to :invoice
belongs_to :customer
end
and then in both Invoice and Customer create action you put
def create
@invoice = Invoices.new(invoice_params)
if @invoice.save
@invoice.customers << Customer.all
redirect_to @invoice
else
render new
end
end
This will create join table objects that will link every customer with an invoice with their ids
Then tweak the join_table.rb model
class JoinTable < ActiveRecord::Base
after_create :add_customer_values
def add_customer_values
customer = Customer.find self.customer_id
self.value1 = customer.value1
self.value2 = customer.value2
self.save
end
and then you should have a list of all customers in the invoice show page and display the join_table record as a dummy but same values
Upvotes: 1