【问题标题】:Drop down List saves id instead of name in Rails下拉列表在 Rails 中保存 id 而不是 name
【发布时间】: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


【解决方案1】:

如果您查看 rails collection_select method这是作为参数传递的值方法,在您的情况下,它是年份和品牌的 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

【讨论】:

  • 但在这种情况下,模型不会动态更新自身。 (最后一个下拉菜单)
  • @Shalafister 这是一个不同的问题。当用户选择一个选项时,您需要查看如何更新选择。
  • 这里我得到错误:NoMethodError in BoatsController#update_models undefined method models' for nil:NilClass`。我添加了js文件。谢谢
  • 这里来自网络选项卡,它使用 19 作为 id 而不是年份名称,这就是模型(第三个下拉菜单没有更新自身)的原因。但是为什么会发生呢,https://........................../boats/update_models?year_name=19&amp;_=1429438923235
  • 很奇怪,我添加了js文件。我不是 js 专家,但对我来说似乎没什么问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-29
  • 1970-01-01
  • 1970-01-01
  • 2021-08-31
  • 1970-01-01
相关资源
最近更新 更多