user1854802
user1854802

Reputation: 388

ruby-on-rails collection_select exclude some selections

Summary I wish to exclude some selection options when using a collection_select. For example when adding a new company_code (table = Company_Listings) for a given company (table = Companies) that for the exchange drop down list (table = Exchanges) only exchanges that his given company is NOT listed on are displayed. Option information can also be entered for the company (again on table = Company_Listings).

More Detail.

General I have a screen where company information can be entered. I allow for a company to be listed on multiple exchanges. I also allow for Option information to be entered. For example Broken Hill Pty is listed on he Australian Stock Exchange (ASX) as BHP as well as on the London Stock Exchange (LSE) as BIL. As well multiple options could be added for each exchange.
This information is stored in Companies and Company_listings tables (see below).

Example - what I am trying to do
1- List of exchanges = ASX, LSE, AMEX, NYSE
2- Companies table Company = Broken Hill Pty Ltd
3- Company_Listings table - Broken Hill Pty Ltd listed on both ASX (Australian Stock Exchange) and the LSE (London Stock Exchange)
e.g. on ASX = BHP and on LSE = BIL
4- When going to the Company Listings page for BHP I want the Listed Exchange drop down list to only display AMEX and NYSE (that is for ASX and LSE to be excluded).

Tables

table "companies" do |t|
    t.string   "name"
    t.string   "full_name"
    t.integer  "exchange_id"

create_table "company_listings" do |t|
    t.integer  "company_id"
    t.integer  "share_number"         
    t.integer  "share_price"
 t.string   "option_name"
 t.integer  "option_strike_price"
 t.date     "option_expiration_date"
 t.integer  "exchange_id"
 t.string   "company_code" 

 table "exchanges" do |t|
  t.string   "name"
  t.string   "full_name"

From the code for that screen - what I need to change

  <%= f.hidden_field :company_id %>
  <%= content_tag :tr do %>
    <%= content_tag :td, content_tag(:span, "Listed Exchange"), 
      class: 'very_large_column' %>
    <%= content_tag :td, f.collection_select(:exchange_id, Exchange.order(:id), 
          :id, :name, {}, {class: "input-fullwidth"}), class: 'data small_column' %>   
  <% end %>
  <%= content_tag :tr do %>
    <%= content_tag :td, content_tag(:span, "Stock Code"), 
      class: 'very_large_column' %>
    <%= content_tag :td, f.text_field(:company_code, 
        class: 'small_column'), class: 'data' %>  

Models

class CompanyListing < ActiveRecord::Base
   ...
   belongs_to :company
   belongs_to :exchange
   ...
end


class Exchange < ActiveRecord::Base
   ...
   has_many :company_listings, dependent: :destroy
end

Upvotes: 0

Views: 932

Answers (2)

user1854802
user1854802

Reputation: 388

A colleague, Tristian, provided this answer. In the view

<%= content_tag :td, f.collection_select(:exchange_id, Exchange.order(:id), 
          :id, :name, {}, {class: "smallish_column"}), class: 'data' %>

becomes

<%= content_tag :td, f.collection_select(:exchange_id, 
          Exchange.where.not(id: @company.company_listings.where.not(company_code: nil).pluck(:exchange_id)).order(:id), 
          :id, :name, {}, {class: "input-fullwidth"}), class: 'data column' %> 

thanks Pierre

Upvotes: 0

steakchaser
steakchaser

Reputation: 5249

The third param for collection_select is the collection. Instead of having this use Exchange.order(:id), you could have it apply some logic based on the company id. As an example:

class Exchange < ActiveRecord::Base
  def self.not_listed_for_company_id(company)
    # AR scope that retrieves all exchanges that the company is NOT listed on
    # NOTE: This can be made more efficient since company.exchanges will result in additional database queries 
    Exchange.where("id not in (?)", company.exchanges.collect{|e| e.id})
  end 
end

Then, in the view:

<%= content_tag :td, f.collection_select(:exchange_id, Exchange.not_listed_for_company_id(company), 
      :id, :name, {}, {class: "input-fullwidth"}), class: 'data small_column' %>   

Upvotes: 1

Related Questions