Skip to content

Instantly share code, notes, and snippets.

@jocubeit
Created June 26, 2010 01:39
Show Gist options
  • Save jocubeit/453676 to your computer and use it in GitHub Desktop.
Save jocubeit/453676 to your computer and use it in GitHub Desktop.
Dependent_collection_select in nested form
class Category < ActiveRecord::Base
has_many :products
attr_accessible :name, :type
CATEGORY_TYPES = %w[Product Sale]
validates_inclusion_of :type, :in => CATEGORY_TYPES
named_scope :of_products, :conditions => ["type = ?", "Product"]
named_scope :of_sales, :conditions => ["type = ?", "Sale"]
end
<% semantic_form_for @sale do |sale_form| %>
<%= sale_form.error_messages %>
<% sale_form.inputs :name => "Sale Details" do %>
<%= sale_form.input :name %>
<%= sale_form.input :product_category_id, :collection => Category.of_products, :include_blank => false %>
<%= sale_form.input :sale_category_id, :collection => Category.of_sales, :include_blank => false %>
<% sale_form.inputs :name => "Stores &amp; Products" do %>
<% @sale.sale_items.each do |sale_item| %>
<% sale_form.fields_for :sale_items, sale_item do |sale_item_form| %>
<li>
<%= sale_item_form.hidden_field :store_id, :value => sale_item.store_id %>
<%#= sale_item_form.dependent_collection_select :product_id, @products[sale_item.store_id], :id, :name, :product_category_id, :include_blank => false %>
<%= sale_item_form.input :product_id, :collection => @products[sale_item.store_id], :include_blank => false %>
</li>
<% end %>
<% end %>
<% end %>
<% sale_form.buttons do -%>
<%= sale_form.commit_button "Save Sale" %>
<%= link_to "&larr; Cancel", sales_path %>
<% end %>
<% end %>
<% end %>
class Product < ActiveRecord::Base
has_many :sale_items, :dependent => :destroy
has_many :product_prices, :dependent => :destroy
has_many :stores, :through => :product_prices
belongs_to :category
attr_accessible :name, :category_id, :product_prices_attributes
accepts_nested_attributes_for :product_prices, :allow_destroy => true
named_scope :by_category, lambda { |c| { :conditions => ["category_id = ?", c] } }
def self.by_store(store_id)
product_prices = ProductPrice.by_store(store_id)
products = []
product_prices.each do |p|
products << Product.find(p.product_id) unless products.include?(p.product_id)
end
products
end
def self.by_store_and_category(store_id, category_id)
product_prices = ProductPrice.by_store(store_id)
products = []
product_prices.each do |p|
product = Product.find(p.product_id) unless products.include?(p.product_id)
unless product.nil?
products << product if product.category_id == category_id
end
end
products
end
end
class ProductPrice < ActiveRecord::Base
belongs_to :store
belongs_to :product
attr_accessible :product_id, :store_id, :retail_price, :sale_price
named_scope :by_store, lambda { |s| { :conditions => ["store_id = ?", s] } }
end
class Sale < ActiveRecord::Base
has_many :sale_items, :dependent => :destroy
has_many :stores, :through => :sale_items
belongs_to :product_category, :class_name => "Category", :foreign_key => "product_category_id"
belongs_to :sale_category, :class_name => "Category", :foreign_key => "sale_category_id"
attr_accessible :name, :product_category_id, :sale_category_id, :sale_items_attributes
accepts_nested_attributes_for :sale_items, :allow_destroy => true
end
class SaleItem < ActiveRecord::Base
belongs_to :sale
belongs_to :product
belongs_to :store
attr_accessible :sale_id, :product_id, :store_id
end
class SalesController < ApplicationController
#before_filter :fill_selects, :only => [:new, :edit, :update, :create]
# Standard actions removed for brevity
def new
@products = []
for store in Store.all
@sale.sale_items.build(:store_id => store.id)
@products[store.id] = Product.by_store(store.id)
end
end
def edit
@products = []
for store in Store.all
unless sale_items_has_store?(store)
@sale.sale_items.build(:store_id => store.id)
@products[store.id] = Product.by_store(store.id)
end
end
end
#protected
# def fill_selects
# @products = Product.find(:all, :order => 'name ASC')
# end
private
def sale_items_has_store?(store)
@sale.sale_items.each do |sale_item|
return true if sale_item.store_id == store.id
end
return false
end
end
class Store < ActiveRecord::Base
attr_accessible :name
end
@jocubeit
Copy link
Author

Added a named_scope to ProductPrice for fetching by_store.
Added a named_scope to Product for fetching by_category.
Added a convenience method to Product for fetching by_store.
Added a convenience method to Product for fetching by_store_and_category.

@jocubeit
Copy link
Author

Corrected form to include the store_id in the hidden field rather than country_id. This was a copy paste error.

@jocubeit
Copy link
Author

Modified New and Edit actions in SalesController to return a Products array.
The @products array has products grouped by store_id.
Also modified the New form to use the @products array in the nested form.
Commented out the dependent_collection_select as it raises error: wrong number of arguments (6 for 2).

@jocubeit
Copy link
Author

Commented out the before_filter and protected method in SalesController as it's no longer serving it's purpose.

@jocubeit
Copy link
Author

Divided up the gist into separate files to permit syntax highlighting and easier download.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment