2017-04-06 63 views
1

架構:
我有兩個模型:端口和App導軌 - 的形式belongs_to的關聯的接入foreign_key

  • 的應用程序屬於端口
  • 在APP的關係等定義以下:
    belongs_to :port, class_name: 'Port', foreign_key: :port_id, required: true
  • 甲端口具有多個和明顯的ID(無,ID和數目不相等)

我需要的是:
端口已經存在於數據庫中。在應用程序的創建表單中,我列出了包含所有可用端口的列表:<%= f.association :port, collection: Port.available_ports, include_blank: false %>。 使用這種方法,選擇項的值等於端口號。但我需要的是,價值不是數字,而是港口的身份。

我的嘗試: 我試圖通過添加以下到f.association解決我的問題:value_method: Port.available_ports。但是這不起作用:no implicit conversion of Array into String

我的問題:
我在正確的軌道上或者我應該接近我的問題以不同的方式?如果是這樣,你會推薦我做什麼?

編輯:
AppController的

class JBossAppsController < ApplicationController 

    before_action :load_app, 
       only: %i[ show destroy ] 

    def index 
    @apps = JBossApp.all 
    end 

    def show 
    end 

    def new 
    @app = JBossApp.new 
    end 

    def create 
    @app = JBossApp.new(app_params) 
    if @app.save! 
     redirect_to root_path 
    else 
     render 'j_boss_apps/new' 
    end 
    end 

    def destroy 
    end 

    protected 
    def load_app 
    @app = JBossApp.find_by(params[:id]) 
    end 

    private 
    def app_params 
    params.require(:j_boss_app).permit(
     params.require(:j_boss_app).permit(
      :id, :group_id, :port_id, :environment, :status, :fault_count, :request_count, :response_count 
     ) 
    ) 
    end 

end 

端口

class Port < ApplicationRecord 


# Helper 
    def self.available_ports 
    unavailable_ports = Port.order(number: :asc).pluck(:number) 
    first_port = 8080 
    last_port = 65080 
    step = 100 
    all_ports = (first_port..last_port).step(step).collect { |n| n } 
    all_ports - unavailable_ports 
    end 

# Relations 
    has_many :apps, 
      class_name: 'JBossApp', 
      foreign_key: :port_id, 
      dependent: :destroy 

    has_one :int_app, ->{ 
    where(port_id: id, environment: :int) 
    } 

    has_one :tst_app, ->{ 
    where(port_id: id, environment: :tst) 
    } 

    has_one :prd_app, ->{ 
    where(port_id: id, environment: :prd) 
    } 

    has_one :dmz_tst_app, ->{ 
    where(port_id: id, environment: :dmz_tst) 
    } 

    has_one :dmz_prd_app, ->{ 
    where(port_id: id, environment: :dmz_prd) 
    } 

# Validations 
    validates :number, 
      numericality: { 
       greater_than: 0, 
       only_integer: true 
      }, 
      presence: true 

end 
+1

<%= f.collection_select:port_id,Port.available_ports,:ID,:姓名,{提示: 「選擇一個端口」},{類: 「形式控制」}%> 參見API文檔 http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_select –

+0

@Dnyanarthlonkar它是數字,而不是名稱。如果我改變它出現錯誤出現:'8080的未定義方法編號:Fixnum 您的意思是?分子' –

+0

您可以使用您想要在選擇列表中顯示的屬性而不是名稱,即替換您想顯示的attritube而不是名稱 –

回答

2

按我的理解的問題,你會無論是需要插入用戶輸入端口號爲Ports表,並將其關聯到應用程序,同時將其保存OR種子所有端口Ports表事先然後找到這些端口沒有相應的/關聯的應用程序。對於您可以按如下改變你available_ports方法:

def self.available_ports 
    Port.includes(:apps).where(apps: {id: nil}).order(ports:{number: :asc}) 

    # Or similar results can be achieved by the following in Rails 5 
    # Port.left_outer_joins(:apps).where(apps: {id: nil}).order(ports:{number: :asc}) 
end 

現在你可以使用你的正常形式的輔助方法collection_select爲:

<%= f.collection_select :port_id, Port.available_ports, :id, :number, {prompt: "Select a port"}, {class: "form-control"} %> 

請讓我知道如果你需要更多的幫助與任何提出解決方案

+0

「需要將用戶輸入的端口號插入到端口表中,並將其保存到應用程序中」是正確的。 –

+0

等一下..我剛剛與我的同事進行了一次討論。他讓我試試你的解決方案。有了這個,我得到一個空的列表。我將函數改爲:'Port.includes(:apps).where(j_boss_apps:{port_id:nil})'來簡化它。但正如我所說:名單仍然是空的。你認爲什麼可能是錯的? –

+0

您是否已將所有端口添加到表中?確保表格中的所有端口位於8080和65080之間。 –

1
def self.available_ports 
    unavailable_ports = Port.order(number: :asc).pluck(:number) 
    first_port = 8080 
    last_port = 65080 
    step = 100 
    all_ports = (first_port..last_port).step(step).collect { |n| n } 
    all_ports = all_ports - unavailable_ports 
    all_ports = Port.where(number: all_ports) 
end 

的意見

<%= f.collection_select :port_id, Port.available_ports, :id, :number, {prompt: "Select a port"}, {class: "form-control"} %> 
+0

沒有錯誤,但列表是空的... –

+0

@colin Herzog您需要將可用的端口號插入端口表中,然後您將獲得列表。 –

+0

好點。但是,如果端口號已經在表中,是不是不可用的端口? 'unavailable_ports = Port.order(number :: asc).pluck(:number)':) –

相關問題