【发布时间】:2015-06-23 20:05:10
【问题描述】:
我有级联 3 个下拉列表。用户可以选择模型品牌和年份并保存到船模型。用户有很多船。船属于用户。
我猜问题出在#create 操作上。因为它将ID而不是名称保存到Boat Model(Brand Model Year(所有字符串))。
这是我的控制器;
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>
最后,如果我在这里更改 id
<%= 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)) %>");
【问题讨论】:
-
为什么要名称而不是 id?
-
因为 3 个下拉菜单是级联的并且它们是关联的。因此,当用户选择模型品牌和年份时,它将获取名称并将其保存到与用户模型关联的另一个模型中。也许有不同的方法可以做到这一点,但这就是我想到的。我对其他想法持开放态度。
标签: ruby-on-rails controller cascading