我有级联3个下拉列表。用户可以选择型号品牌和年份,并保存到船模型。用户有很多船。船属于用户。
问题在于我猜#create
动作。因为它将ids而不是名称保存到船模型(品牌型号年份(所有字符串))。
这是我的控制器;
def new
@boat = Boat.new
end
def create
@boat = current_user.boats.new(boat_params) if logged_in?
if @boat.save
flash[:success] = "Boat created!"
render 'edit'
else
render 'new'
end
end
def show
end
def edit
@boat = Boat.find(params[:id])
end
def update
end
def update_years
# updates year and model based on brand selected
brand = Brand.find(params[:brand_id])
# map to name and id for use in our options_for_select
@years = brand.years.map{|a| [a.name, a.id]}.insert(0, "Select a Year")
@models = brand.models.map{|s| [s.name, s.id]}.insert(0, "Select a Model")
end
def update_models
# updates model based on year selected
year = Year.find(params[:year_id])
@models = year.models.map{|s| [s.name, s.id]}.insert(0, "Select a Model")
end
end
private
def boat_params
params.require(:boat).permit(:brand, :year, :model)
end
这是我的#new
视图;
<% provide(:title, 'List My Boat') %>
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(@boat) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="col-md-6">
<%= f.label :Brand %>
<%= f.collection_select(:brand, Brand.all, :id, :name, {:prompt => "Select a Brand"}, {:id => 'brands_select'}) %>
</div>
<div class="col-md-6">
<%= f.label :Year %>
<%= f.collection_select(:year, Year.all, :id, :name, {:prompt => "Select a Year"}, {:id => 'years_select'}) %>
</div>
<div class="col-md-6">
<%= f.label :Model %>
<%= f.collection_select(:model, Model.all, :id, :name, {:prompt => "Select a Model"}, {:id => 'models_select'}) %>
</div>
<div class="col-md-6 col-md-offset-3">
<%= f.submit "Next", class: "btn btn-primary"%>
</div>
<% end %>
</div>
</div>
</div>
<script>
$(document).ready(function() {
$('#brands_select').change(function() {
$.ajax({
url: "<%= update_years_path %>",
data: {
brand_id : $('#brands_select').val()
},
dataType: "script"
});
});
$('#years_select').change(function() {
$.ajax({
url: "<%= update_models_path %>",
data: {
year_id : $('#years_select').val()
},
dataType: "script"
});
});
});
</script>
最后,如果我在这里更改身份
<%= f.collection_select(:brand, Brand.all, :id, :name, {:prompt => "Select a Brand"}, {:id => 'brands_select'}) %>
来命名,然后级联属性不起作用。因此表单不会动态更新自身。
我尝试过像#create
动作
year = Year.find_by("id = ?", params[:year])
model = Year.find_by("id = ?", params[:model])
brand = Year.find_by("id = ?", params[:brand])
@boat = current_user.boats.new(:year, year.name, :brand, brand.name, :model, model.name)
但是由于@boat = current_user.boats.new(:year, year.name, :brand, brand.name, :model, model.name)
错误,它会出错。我收到了
undefined method `name' for nil:NilClass
错误。
编辑1:
update_models.js.erb
$('#models_select').html("<%= escape_javascript(options_for_select(@models)) %>");
update_years.js.erb
$('#years_select').html("<%= escape_javascript(options_for_select(@years)) %>");
$('#models_select').html("<%= escape_javascript(options_for_select(@models)) %>");
答案 0 :(得分:1)
如果您查看rails collection_select method
, 它是以params方式传递的值方法,在您的情况下,它是年份和品牌的ID。 强>
将您的收藏选择方法更改为:
<%= f.collection_select(:brand, Brand.all, :name, :name, {:prompt => "Select a Brand"}, {:id => 'brands_select'}) %>
<%= f.collection_select(:year, Year.all, :name, :name, {:prompt => "Select a Year"}, {:id => 'years_select'}) %>
您的脚本应该是:
<script>
$(document).ready(function() {
$('#brands_select').change(function() {
$.ajax({
url: "<%= update_years_path %>",
data: {
brand_name : $('#brands_select').val()
},
dataType: "script"
});
});
$('#years_select').change(function() {
$.ajax({
url: "<%= update_models_path %>",
data: {
year_name : $('#years_select').val()
},
dataType: "script"
});
});
});
</script>
在您的方法中,您需要按名称而不是ID找到品牌和年份
def update_years
# updates year and model based on brand selected
brand = Brand.find_by_name(params[:brand_name])
# map to name and id for use in our options_for_select
@years = brand.years.map{|a| [a.name, a.name]}.insert(0, "Select a Year") #use a.name here instead of a.id
@models = brand.models.map{|s| [s.name, s.name]}.insert(0, "Select a Model")#use s.name here instead of s.id
end
def update_models
# updates model based on year selected
year = Year.find_by_name(params[:year_name])
@models = year.models.map{|s| [s.name, s.name]}.insert(0, "Select a Model") #use s.name here instead of s.id
end