Collection_select保存id而不是名称

时间:2015-04-15 21:31:26

标签: ruby-on-rails view model cascading

我总共有4个型号,品牌,年份和型号。这些是级联下拉列表,它们的数据从其数据库中检索。我想要做的是创建一个Boat视图,让用户将其保存到Boat模型。但不是将名称保存到Boat模型,而是节省了ID,因此我无法使用它们。我尝试过几种不同的东西,但是当我在这里将:id更改为:name时,

<%= f.collection_select(:brand, @brands, :id, :name, {:prompt => "Select a Brand"}, {:id => 'brands_select'}) %>

我说错了;

ActiveRecord::RecordNotFound in BoatsController#update_years

Couldn't find Brand with 'id'=A & L Fiberglass

我认为问题发生在#create方法中但无法解决

这是代码;

#boats controller
class BoatsController < ApplicationController
  def new
    @boats = Boat.new
    @brands  = Brand.all
    @years = Year.all
    @models   = Model.all
  end

  def create
  @boats = Boat.new(boat_params)
    if @boats.save

      flash[:info] = "New boat has added"
      redirect_to root_url
    else
      render 'new'
    end
  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.html
<%= form_for(@boats) do |f| %>

<%= f.collection_select(:brand,  @brands,  :id, :name, {:prompt   => "Select a Brand"}, {:id => 'brands_select'}) %>

<%= f.collection_select(:year, @years, :id, :name, {:prompt   => "Select a Year"}, {:id => 'years_select'}) %>

<%= f.collection_select(:model, @models, :id, :name, {:prompt   => "Select a Model"}, {:id => 'models_select'}) %>

<%= f.submit "Create my account"%>

    <% end %>

<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>

控制台输出如下;

Started GET "/boats/update_years?brand_id=1&_=1429136250545" for 88.240.3.128 at 2015-04-15 22:01:09 +0000
Processing by BoatsController#update_years as JS
  Parameters: {"brand_id"=>"1", "_"=>"1429136250545"}
  Brand Load (0.3ms)  SELECT  "brands".* FROM "brands" WHERE "brands"."id" = ? LIMIT 1  [["id", 1]]
  Year Load (0.3ms)  SELECT "years".* FROM "years" WHERE "years"."brand_id" = ?  [["brand_id", 1]]
  Model Load (0.6ms)  SELECT "models".* FROM "models" INNER JOIN "years" ON "models"."year_id" = "years"."id" WHERE "years"."brand_id" = ?  [["brand_id", 1]]
  Rendered boats/update_years.js.erb (2.7ms)
Completed 200 OK in 38ms (Views: 24.6ms | ActiveRecord: 1.1ms)


Started GET "/boats/update_models?year_id=5&_=1429136250546" for 88.240.3.128 at 2015-04-15 22:01:27 +0000
Processing by BoatsController#update_models as JS
  Parameters: {"year_id"=>"5", "_"=>"1429136250546"}
  Year Load (0.3ms)  SELECT  "years".* FROM "years" WHERE "years"."id" = ? LIMIT 1  [["id", 5]]
  Model Load (0.3ms)  SELECT "models".* FROM "models" WHERE "models"."year_id" = ?  [["year_id", 5]]
  Rendered boats/update_models.js.erb (0.3ms)
Completed 200 OK in 23ms (Views: 14.8ms | ActiveRecord: 0.7ms)


Started POST "/boats" for 88.240.3.128 at 2015-04-15 22:01:32 +0000
Processing by BoatsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"fJc21Wf0eC+4Qq9Lag5+r7/qSow3W4Zt1Fvr2GzyWbmkoTf9miFcpfo3R9r39Q/zoTtfQ4JwzUMEP0JJEm1ELw==", "boat"=>{"brand"=>"1", "year"=>"5", "model"=>"16"}, "commit"=>"Create my account"}
PARAMS: {"utf8"=>"✓", "authenticity_token"=>"fJc21Wf0eC+4Qq9Lag5+r7/qSow3W4Zt1Fvr2GzyWbmkoTf9miFcpfo3R9r39Q/zoTtfQ4JwzUMEP0JJEm1ELw==", "boat"=>{"brand"=>"1", "year"=>"5", "model"=>"16"}, "commit"=>"Create my account", "controller"=>"boats", "action"=>"create"}
   (0.2ms)  begin transaction
  SQL (0.5ms)  INSERT INTO "boats" ("brand", "year", "model", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?)  [["brand", "1"], ["year", "5"], ["model", "16"], ["created_at", "2015-04-15 22:01:32.178987"], ["updated_at", "2015-04-15 22:01:32.178987"]]
   (11.5ms)  commit transaction
Redirected to https://rails-tutorial-shalafister.c9.io/
Completed 302 Found in 19ms (ActiveRecord: 12.1ms)


Started GET "/" for 88.240.3.128 at 2015-04-15 22:01:32 +0000
Processing by BoatsController#new as HTML
  Brand Load (0.4ms)  SELECT "brands".* FROM "brands"
  Year Load (0.3ms)  SELECT "years".* FROM "years"
  Model Load (1.6ms)  SELECT "models".* FROM "models"
  Rendered boats/new.html.erb within layouts/application (24.8ms)
Completed 200 OK in 188ms (Views: 183.6ms | ActiveRecord: 2.3ms)

这是架构;

create_table "boats", force: :cascade do |t|
    t.string   "brand"
    t.string   "year"
    t.string   "model"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "brands", force: :cascade do |t|
    t.string   "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "models", force: :cascade do |t|
    t.string   "name"
    t.integer  "year_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "years", force: :cascade do |t|
    t.string   "name"
    t.integer  "brand_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

1 个答案:

答案 0 :(得分:0)

好的,基于您的编辑,它看​​起来像是要将年份和品牌和模型属性的文本保存到Boats模型。仅供参考,这不是一种非常类似的方法(通常你会保存ID),但是,如果你想保存文本,你不能直接从params调用它(因为你的params正在使用ID,而不是字符串)。

此外,您的collection_selects目前正在传递id,而不是name

选项1

完成此更改的一种方法是根据其ID找到品牌,年份和模型实例:

def create
  @boats = Boat.new
  brand = Brand.find(params[:brand_id])
  year = Year.find(params[:year_id])
  model = Model.find(params[:model])
  @boats.brand = brand.name
  @boats.year = year.name
  @boats.model = model.name


  if @boats.save

   flash[:info] = "New boat has added"
   redirect_to root_url
  else
   render 'new'
  end
end

选项2

另一种选择是将collection_select更改为:

<%= f.collection_select(:brand,  @brands, :name, :name, {:prompt   => "Select a Brand"}, {:id => 'brands_select'}) %>

<%= f.collection_select(:year, @years, :name, :name, {:prompt   => "Select a Year"}, {:id => 'years_select'}) %>

<%= f.collection_select(:model, @models, :name, :name, {:prompt   => "Select a Model"}, {:id => 'models_select'}) %>

但保留其他代码。通过这种方式,您可以按原样保留现有的参数。