Rails - 在表单中访问 belongs_to 关联的 foreign_key
Rails - access foreign_key of belongs_to association in a form
架构:
我有两个模型:Port 和 App
- 一个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 %>
。
使用这种方法,select Item 的值等于端口号。但我需要的是,该值不是数字而是端口的 ID。
我试过的:
我试图通过向 f.association 添加以下内容来解决我的问题:value_method: Port.available_ports
。但这没有用:no implicit conversion of Array into String
.
我的问题:
我走在正确的轨道上还是应该以不同的方式解决我的问题?如果是这样,您会推荐我做什么?
编辑:
应用程序控制器
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
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"} %>
根据我对问题的理解,您 EITHER 需要将用户输入的端口号插入 Ports
table 并将其关联到应用程序,同时保存它 或 预先将所有端口播种到 Ports
table,然后找到没有其 corresponding/associated 应用程序的端口。为此,您可以按如下方式更改 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"} %>
如果您需要任何建议的解决方案的进一步帮助,请告诉我。
架构:
我有两个模型:Port 和 App
- 一个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 %>
。
使用这种方法,select Item 的值等于端口号。但我需要的是,该值不是数字而是端口的 ID。
我试过的:
我试图通过向 f.association 添加以下内容来解决我的问题:value_method: Port.available_ports
。但这没有用:no implicit conversion of Array into String
.
我的问题:
我走在正确的轨道上还是应该以不同的方式解决我的问题?如果是这样,您会推荐我做什么?
编辑:
应用程序控制器
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
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"} %>
根据我对问题的理解,您 EITHER 需要将用户输入的端口号插入 Ports
table 并将其关联到应用程序,同时保存它 或 预先将所有端口播种到 Ports
table,然后找到没有其 corresponding/associated 应用程序的端口。为此,您可以按如下方式更改 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"} %>
如果您需要任何建议的解决方案的进一步帮助,请告诉我。