After checkout we have a form to fill with data from the user, if not fill we are presented with errors, after fill the data if we click Place Order it is suppose that will be an update of database, but all data disappears from the form and display errors like the first time with no data.
Here is my code:
/app/views/carts/_cart.html.erb:
<h2>Your Cart</h2>
<table>
<%= render(cart.line_items) %>
<tr class="total_line">
<td colspan="2">Total</td>
<td class="total_cell"><%= number_to_currency(cart.total_price) %></td>
</tr>
</table>
<!-- START_HIGHLIGHT -->
<%= button_to "Checkout", new_order_path, method: :get %>
<!-- END_HIGHLIGHT -->
<%= button_to 'Empty cart', cart, method: :delete,
data: { confirm: 'Are you sure?' } %>
/app/controllers/orders_controller.rb:
class OrdersController < ApplicationController
include CurrentCart
before_action :set_cart, only: [:new, :create]
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
if #cart.line_items.empty?
redirect_to store_url, notice: "Your cart is empty"
return
end
#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
Cart.destroy(session[:cart_id])
session[:cart_id] = nil
format.html { redirect_to store_url, notice:
'Thank you for your order.' }
format.json { render action: 'show', status: :created,
location: #order }
else
format.html { render action: '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 { head :no_content }
else
format.html { render action: '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 }
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(:name, :address, :email, :pay_type)
end
#...
end
/app/views/orders/new.html.erb:
<div class="depot_form">
<fieldset>
<legend>Please Enter Your Details</legend>
<%= render 'form' %>
</fieldset>
</div>
/app/views/orders/_form.html.erb:
<%= 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 |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<!-- START_HIGHLIGHT -->
<%= f.text_field :name, size: 40 %>
<!-- END_HIGHLIGHT -->
</div>
<div class="field">
<%= f.label :address %><br>
<!-- START_HIGHLIGHT -->
<%= f.text_area :address, rows: 3, cols: 40 %>
<!-- END_HIGHLIGHT -->
</div>
<div class="field">
<%= f.label :email %><br>
<!-- START_HIGHLIGHT -->
<%= f.email_field :email, size: 40 %>
<!-- END_HIGHLIGHT -->
</div>
<div class="field">
<%= f.label :pay_type %><br>
<!-- START_HIGHLIGHT -->
<%= f.select :pay_type, Order::PAYMENT_TYPES,
prompt: 'Select a payment method' %>
<!-- END_HIGHLIGHT -->
</div>
<div class="actions">
<!-- START_HIGHLIGHT -->
<%= f.submit 'Place Order' %>
<!-- END_HIGHLIGHT -->
</div>
<% end %>
/app/models/order.rb:
class Order < ActiveRecord::Base
PAYMENT_TYPES = [ "Check", "Credit card", "Purchase order" ]
has_many :line_items, dependent: :destroy
# ...
validates :name, :address, :email, presence: true
validates :pay_type, inclusion: PAYMENT_TYPES
end
/app/models/line_item.rb:
class LineItem < ActiveRecord::Base
belongs_to :order
belongs_to :product
belongs_to :cart
def total_price
product.price * quantity
end
end
Ok , it is solved, the problem is in app/models/order.rb
What I have when the update orders do not work
class Order < ActiveRecord::Base
has_many :line_items, dependent: :destroy
PAYMENT_TYPES = [ "Check", "Credit card", "Purchase order" ]
validates :name, :address, :email, presence: true
validates :pay_type, inclusion: PAYMENT_TYPES
def add_line_items_from_cart(cart)
cart.line_items.each do |item|
item.cart_id = nil
line_items << item
end
end
end
After change with attr_accessible :cart_id, :product_id, :product, :name, :address, :email, :pay_type
class Order < ActiveRecord::Base
attr_accessible :cart_id, :product_id, :product, :name, :address, :email, :pay_type
has_many :line_items, dependent: :destroy
PAYMENT_TYPES = [ "Check", "Credit card", "Purchase order" ]
validates :name, :address, :email, presence: true
validates :pay_type, inclusion: PAYMENT_TYPES
def add_line_items_from_cart(cart)
cart.line_items.each do |item|
item.cart_id = nil
line_items << item
end
end
end
Now, everything is working has expected.
Thanks
Regards
Related
I'm trying to set up a nested form in rails and both the parent and child objects in the form need to have an "Account ID" so that they are both scoped to the current user's account, but I can't figure out how to pass the current user's Account ID for the child object through the nested form. I keep getting a validation error of "Account id must be present" for the nested object.
The parent form is "Product" and I'm trying to nest "Options" into the Product.new form.
I'm trying to do something like this:
#product.options.account_id = current_user.account.id
But it's not working.
Here is the Product model:
class Product < ApplicationRecord
belongs_to :account
has_many :options, dependent: :destroy
accepts_nested_attributes_for :options, allow_destroy: true
validates :account_id, presence: true
validates :name, presence: true, length: { maximum: 120 }
end
And options model:
class Option < ApplicationRecord
belongs_to :account
belongs_to :product
has_many :option_values, dependent: :destroy
validates :account_id, presence: true
validates :name, presence: true,
length: { maximum: 60 }
end
Here's how I'm nesting "Options" into the Product form:
<%= form.fields_for :options do |builder| %>
<fieldset class='form-group'>
<%= builder.label :name, 'Add option(s)' %>
<%= builder.text_field :name %>
<small id="optionHelp" class="form-text text-muted">
(e.g. "Sizes" or "Color")
</small>
</fieldset>
<% end %>
And here is my ProductsController:
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
before_action :restrict_access
def index
#products = Product.where(:account_id => current_user.account.id).all
end
def show
end
def new
#product = Product.new
#product.options.build
end
def edit
end
def create
#account = current_user.account
#product = #account.products.build(product_params)
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
else
format.html { render :new }
end
end
end
def update
respond_to do |format|
if #product.update(product_params)
format.html { redirect_to #product, notice: 'Product was successfully updated.' }
else
format.html { render :edit }
end
end
end
def destroy
#product.destroy
respond_to do |format|
format.html { redirect_to products_url, notice: 'Product was successfully destroyed.' }
end
end
private
def set_product
if Product.find(params[:id]).account_id == current_user.account.id
#product = Product.find(params[:id])
else
redirect_to dashboard_path
end
end
def restrict_access
if index
authorize #products
else
authorize #product
end
end
def product_params
params.require(:product).permit(:account_id, :name,
options_attributes: [:id, :account_id, :name ])
end
end
What is the correct way to do this?
Alternatively, you can pass a hidden_field with form and nested_form as given below: -
<%= form_for #product do |form|%>
<%= form.fields_for :options do |builder| %>
<fieldset class='form-group'>
<%= builder.label :name, 'Add option(s)' %>
<%= builder.text_field :name %>
<small id="optionHelp" class="form-text text-muted">
(e.g. "Sizes" or "Color")
</small>
<%=builder.hidden_field :account_id, value: current_user.account.id%>
</fieldset>
<% end %>
<%= form.hidden_field :account_id, value: current_user.account.id%>
<%end%>
Other than this you can set account_id at the controller
def new
##product = Product.new
#product = current_user.account.products.new
#product.options.build(account_id: current_user.account.id)
end
The easiest option would be to add a hidden field into both forms:
https://apidock.com/rails/ActionView/Helpers/FormHelper/hidden_field
So in your case, for the options form, something like:
<%= form.fields_for :options do |builder| %>
<fieldset class='form-group'>
<%= builder.label :name, 'Add option(s)' %>
<%= builder.hidden_field :account_id, value: current_account.id %>
<%= builder.text_field :name %>
<small id="optionHelp" class="form-text text-muted">
(e.g. "Sizes" or "Color")
</small>
</fieldset>
<% end %>
This will give you access to the [:option][:account_id] param, which will match the current user's.
I'm trying to create a nested form in Ruby on Rails. The form appears as expected. But when it is saved the nested attribute, Booking, is not saved.
cleaner.rb
class Cleaner < ActiveRecord::Base
validates_presence_of :first_name
validates_presence_of :last_name
validates_presence_of :quality_score
validates :quality_score, inclusion: 0.0...5.0
has_many :assignments
has_many :bookings
has_many :cities, through: :assignments
has_many :customers, through: :bookings
end
customer.rb
class Customer < ActiveRecord::Base
validates_presence_of :first_name
validates_presence_of :last_name
validates_uniqueness_of :phone_number
belongs_to :city
has_many :bookings
has_many :cleaners, through: :bookings
accepts_nested_attributes_for :bookings
end
booking.rb
class Booking < ActiveRecord::Base
belongs_to :customer
belongs_to :cleaner
validates_presence_of :customer
validates_presence_of :cleaner
validates_presence_of :date
end
customers_controller.rb
class CustomersController < ApplicationController
before_action :set_customer, only: %i[show edit update destroy]
def index
#customers = Customer.all
end
def show; end
def new
#customer = Customer.new
end
def edit; end
def create
#customer = Customer.find_or_initialize_by(phone_number: params[:phone_number])
#customer.assign_attributes(customer_params)
respond_to do |format|
if #customer.save
format.html { redirect_to #customer, notice: 'Customer was successfully created.' }
format.json { render :show, status: :created, location: #customer }
else
format.html { render :new }
format.json { render json: #customer.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #customer.update(customer_params)
format.html { redirect_to #customer, notice: 'Customer was successfully updated.' }
format.json { render :show, status: :ok, location: #customer }
else
format.html { render :edit }
format.json { render json: #customer.errors, status: :unprocessable_entity }
end
end
end
def destroy
#customer.destroy
respond_to do |format|
format.html { redirect_to customers_url, notice: 'Customer was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_customer
#customer = Customer.find(params[:id])
end
def customer_params
params.require(:customer).permit(:first_name, :last_name, :phone_number, :city, :city_id, bookings_attributes: %i[cleaner_id date])
end
end
HomeController.rb
class HomeController < ApplicationController
def index
#customer = Customer.new
#customer.bookings.build
end
end
Parameters
{"utf8"=>"✓", "authenticity_token"=>"c4xo2M4r57+/xBsmcc+7yajpQU13u1kiwmOthx/nP7HiJXJIfS9/OqC0MrWCcaDrSW/xN8UGk2+LVfnUnbTb3A==", "customer"=>{"first_name"=>"adfad", "last_name"=>"fad", "phone_number"=>"9392323", "city_id"=>"1", "bookings_attributes"=>{"0"=>{"cleaner_id"=>"1"}}}, "#<ActionView::Helpers::FormBuilder:0x007f86bec96480>"=>{"date(1i)"=>"2017", "date(2i)"=>"8", "date(3i)"=>"2"}, "commit"=>"Create Customer"}
updated form
<h1>Sign Up Now</h1>
<%= form_for #customer do |f| %>
<% if #customer.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#customer.errors.count, "error") %> prohibited this customer from being saved:</h2>
<ul>
<% #customer.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :first_name %><br>
<%= f.text_field :first_name %>
</div>
<div class="field">
<%= f.label :last_name %><br>
<%= f.text_field :last_name %>
</div>
<div class="field">
<%= f.label :phone_number %><br>
<%= f.text_field :phone_number %>
</div>
<div class="field">
<%= f.label :city %><br>
<%= f.select :city_id, options_for_select(City.pluck(:name, :id)) %>
</div>
<%= f.fields_for :bookings do |b| %>
<%= b.date_select :date %>
<br>
<%= b.select :cleaner_id, Cleaner.all.pluck(:first_name, :id) %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
It's now failing with 2 errors
Bookings customer can't be blank
Bookings date can't be blank
use the iteration of the first #customer so rails can read properly
i saw this example https://www.sitepoint.com/complex-rails-forms-with-nested-attributes/
<%= f.fields_for :booking do |ff| %>
<%= ff.select :city_id,options_for_select(City.pluck(:name, :id)) %>
i hope it works cross finger :)
I'm very new to Rails development and having a problem saving multiple images/attachments to a model. My problem is that the code below is not actually saving to the item_images table when I submit the form. I am following This Article as a guide, though it seems to be a bit out of date. I feel I'm in a little over my head at this point so I hope someone can point out what I'm missing. Thanks!
I have the following models:
item.rb
class Item < ActiveRecord::Base
has_many :item_images, :dependent => :destroy
accepts_nested_attributes_for :item_images, :reject_if => lambda { |t| t['item_image'].nil? }
end
item_image.rb
class ItemImage < ActiveRecord::Base
belongs_to :item
has_attached_file :image,
:styles => { thumb: "100x100#", small: "400x400#", large: "700x700" }
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
end
My controller looks like this:
items_controller.rb
class ItemsController < ApplicationController
before_action :set_item, only: [:show, :edit, :update, :destroy]
# GET /items
# GET /items.json
def index
#items = Item.all
end
# GET /items/1
# GET /items/1.json
def show
end
# GET /items/new
def new
#item = Item.new
4.times {#item.item_images.build}
end
# GET /items/1/edit
def edit
4.times {#item.item_images.build}
end
# POST /items
# POST /items.json
def create
#item = Item.new(item_params)
respond_to do |format|
if #item.save
format.html { redirect_to #item, notice: 'Item was successfully created.' }
format.json { render :show, status: :created, location: #item }
else
format.html { render :new }
format.json { render json: #item.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /items/1
# PATCH/PUT /items/1.json
def update
respond_to do |format|
if #item.update(item_params)
format.html { redirect_to #item, notice: 'Item was successfully updated.' }
format.json { render :show, status: :ok, location: #item }
else
format.html { render :edit }
format.json { render json: #item.errors, status: :unprocessable_entity }
end
end
end
# DELETE /items/1
# DELETE /items/1.json
def destroy
#item.destroy
respond_to do |format|
format.html { redirect_to items_url, notice: 'Item was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_item
#item = Item.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def item_params
params.require(:item).permit(:title, :description, :price, :available, :sort_shop, :sort_gallery, :item_type, :size)
end
end
form.html.erb
<%= form_for #item, html: { multipart: true } do |f| %>
<% if #item.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#item.errors.count, "error") %> prohibited this item from being saved:</h2>
<ul>
<% #item.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :price %><br>
<%= f.text_field :price %>
</div>
<div class="field">
<%= f.label :available %><br>
<%= f.check_box :available %>
</div>
<div class="field">
<%= f.label :sort_shop %><br>
<%= f.number_field :sort_shop %>
</div>
<div class="field">
<%= f.label :sort_gallery %><br>
<%= f.number_field :sort_gallery %>
</div>
<div class="field">
<%= f.label :item_type %><br>
<%= f.text_field :item_type %>
</div>
<div class="field">
<%= f.label :size %><br>
<%= f.text_field :size %>
</div>
<%= f.fields_for :item_images do |builder| %>
<% if builder.object.new_record? %>
<div class="field">
<%= builder.label :image, "Image File" %>
<%= builder.file_field :image %>
</div>
<% end %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Try this in strong parameters in Items controller
params.require(:item).permit(:title, :description, :price, :available, :sort_shop, :sort_gallery, :item_type, :size,item_images_attributes: [:image ])
than in ItemImage.rb add this line
belongs_to :item, optional: true,
and remove this line from Item.rb
:reject_if => lambda { |t| t['item_image'].nil? }
`
If you get any error please reply
i made a nested form for my invoice application with the cocoon gem but the form isn't showing on my application but it isn't giving out any errors either.
_form.html.erb - scaffold form partial
<address>
<%= f.fields_for :customer do |customer| %>
<%= render 'customer_fields', f: customer %>
<%= link_to_add_association 'Add customer',f, :customer %>
<% end %>
</address>
_customer_fields.html.erb - cocoon partial
<div class="nested-fields">
<div class="form-group">
<%= f.label 'Company Name' %><br/>
<%= f.text_field :company_name, placeholder: 'company name' %>
</div>
<div class="form-group">
<%= f.label 'Address' %><br>
<%= f.text_field :address_line_1, placeholder: 'address' %>
</div>
<div class="form-group">
<%= f.label 'Zip Code' %><br>
<%= f.text_field :zip_code %>
</div>
<%= link_to_remove_association "remove customer", f, class: 'btn btn-primary' %>
</div>
Invoice.rb model
class Invoice < ActiveRecord::Base
has_one :company
has_one :customer
has_many :products
accepts_nested_attributes_for :customer, reject_if: :all_blank, allow_destroy: true
validates :number, :currency, :date, :duedate, :btwtotal, :subtotal, :total, presence: true
end
customer.rb model
class Customer < ActiveRecord::Base
belongs_to :invoice
end
Invoices_controller.rb
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
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, customers_attributes: [:id, :company_name, :address_line_1, :zip_code, :_destroy],
companies_attributes: [:id, :btw_number, :iban_number, :kvk_number, :company_name, :_destroy])
end
end
Does anybody know how to fix this? Any help would be much much appreciated!
try it
<address>
<%= f.object.build_customer if f.object.customer.nil? %>
<%= f.fields_for :customer do |customer| %>
<%= render 'customer_fields', f: customer %>
<%= link_to_add_association 'Add customer',f, :customer %>
<% end %>
</address>
edit
in the Luissimo solution was missing to insert invoice_id in customer schema
rails generate migration AddInvoiceIdToCustomer invoice_id:integer
rake db:migrate
Invoice.first.build_customer
Looking at your original code, in your controller you should have added:
def new
#invoice = Invoice.new
#invoice.customer.build
end
still going on my first rails program (ruby 2.0, rails 4.0). I've got a drop down that displays static options from a second model, but when I click on a selection from that drop down, nothing happens. Saving it to the record (presence_of validation turned off) just leaves the field empty.
I'm thinking something in controller or view? Any help?
Sorry for the massive code dump, but I'm so noob that I wasn't sure what was relevant
Contact.rb
class Contact < ActiveRecord::Base
attr_accessible :first_name, :last_name, :email, :zip_code, :favorite_color, :color_id, :name, :hex
belongs_to :color
accepts_nested_attributes_for :color
Color.rb
class Color < ActiveRecord::Base
has_many :contacts
accepts_nested_attributes_for :contacts
attr_accessible :name, :hex
end
contacts_controller.rb
class ContactsController < ApplicationController
before_action :set_contact, only: [:show, :edit, :update, :destroy]
before_filter :prepare_colors
# GET /contacts
# GET /contacts.json
def index
#contacts = Contact.all
end
# GET /contacts/1
# GET /contacts/1.json
def show
end
# GET /contacts/new
def new
#contact = Contact.new
end
# GET /contacts/1/edit
def edit
end
# POST /contacts
# POST /contacts.json
def create
#contact = Contact.new(contact_params)
respond_to do |format|
if #contact.save
format.html { redirect_to #contact, notice: 'Contact was successfully created.' }
format.json { render action: 'show', status: :created, location: #contact }
else
format.html { render action: 'new' }
format.json { render json: #contact.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /contacts/1
# PATCH/PUT /contacts/1.json
def update
respond_to do |format|
if #contact.update(contact_params)
format.html { redirect_to #contact, notice: 'Contact was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #contact.errors, status: :unprocessable_entity }
end
end
end
# DELETE /contacts/1
# DELETE /contacts/1.json
def destroy
#contact.destroy
respond_to do |format|
format.html { redirect_to contacts_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_contact
#contact = Contact.find(params[:id])
end
def prepare_colors
#colors = Color.all
end
# Never trust parameters from the scary internet, only allow the white list through.
def contact_params
params.require(:contact).permit(:first_name, :last_name, :email, :zip_code, :favorite_color, :color_id)
end
end
views/contacts/_form.html.erb
%= form_for(#contact) do |f| %>
<% if #contact.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#contact.errors.count, "error") %> prohibited this contact from being saved:</h2>
<ul>
<% #contact.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :first_name %><br>
<%= f.text_field :first_name %>
</div>
<div class="field">
<%= f.label :last_name %><br>
<%= f.text_field :last_name %>
</div>
<div class="field">
<%= f.label :email %><br>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :zip_code %><br>
<%= f.number_field :zip_code %>
</div>
<div class="field">
<%= f.label :favorite_color %><br>
<%= f.collection_select(:color_id, #colors, :id, :name, :include_blank => "Please select") %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
and /views/contacts/index.html
h3>Listing contacts</h1>
<table>
<thead>
<tr>
<th>First name</th>
<th>Last name</th>
<th>Email</th>
<th>Zip code</th>
<th>Favorite color</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<% #contacts.each do |contact| %>
<tr>
<td><%= contact.first_name %></td>
<td><%= contact.last_name %></td>
<td><%= contact.email %></td>
<td><%= contact.zip_code %></td>
<td><%= contact.favorite_color %></td>
<td><%= link_to 'Show', contact %></td>
<td><%= link_to 'Edit', edit_contact_path(contact) %></td>
<td><%= link_to 'Destroy', contact, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Contact', new_contact_path %>
Ok, I am not entirely sure what is relationship here, but it seems to me that you have two columns in your Contact model which are created for the same reason: favorite_color and colour_id. You are not setting favorite_color value, but you are trying to display it. I guess color_id is to be a foreign_key to contact's favurite color. if so, you need to rename assocaition:
belongs_to :favorite_color, class_name: 'Color'
Rename color_id column to favorite_color_id, and then inside your view:
# form
<div class="field">
<%= f.label :favorite_color %><br>
<%= f.collection_select(:favorite_color_id, #colors, :id, :name, :include_blank => "Please select") %>
</div>
# index
<td><%= contact.favorite_color.name %></td>
Strong Params
First of all, if you're using rails 4.0 you don't need this line:
attr_accessible :first_name, :last_name, :email, :zip_code, :favorite_color, :color_id, :name, :hex
This has been replaced with strong_params now, so you should put this into the bottom of your contacts controller:
private
def contact_params
params.require(:contact).permit(:first_name, :last_name, :email, :zip_code, :favorite_color, :color_id, :name, :hex, colors_attributes: [])
end
Fields_For
The next thing is that you need to include the fields_for tag in your form, like this:
<%= f.fields_for :colors do |color| %><br>
<%= f.collection_select(:color_id, #colors, :id, :name, :include_blank => "Please select") %>
<% end %>
I think that will work. Your code was pretty long, so I guess if you have problems implementing it, just leave a comment :)
Update
You need to add this to your new function:
# GET /contacts/new
def new
#contact = Contact.new
#contact.color.build
#colors = Color.all
end
Also, I don't know if this will work again, but you might want to edit your collection_select to have this code:
<%= f.fields_for :colors do |color| %><br>
<%= color.collection_select(:color, #colors, :id, :name, :include_blank => "Please select") %>
<% end %>
Finally, you should include the :id attribute in your nested_attributes:
private
def contact_params
params.require(:contact).permit(:first_name, :last_name, :email, :zip_code, :favorite_color, :color_id, :name, :hex, colors_attributes: [])
end