Collection_select сохраняет идентификатор вместо имени
Всего у меня 4 модели: марка, год и модель. Это каскадные выпадающие списки, и их данные извлекаются из их баз данных. Я пытаюсь создать представление "Лодка" и позволить пользователю сохранить его в модели "Лодка". Но вместо сохранения имен в модели Лодки, это сохраняет идентификаторы, поэтому я не могу их использовать. Я пробовал несколько разных вещей, но когда я меняю :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 ответ
Итак, на основании ваших правок похоже, что вы хотите сохранить текст года, а также атрибуты бренда и модели в модели Boats. К вашему сведению, этот подход не очень похож на рельсы (обычно вы сохраняете идентификаторы), но, тем не менее, если вы хотите сохранить текст, вы не можете вызывать его напрямую из params (потому что ваш params
используют идентификаторы, а не строки).
Также ваш collection_selects
в настоящее время проходят в id
не name
,
Опция 1
Один из способов добиться этого изменения - найти бренд, год и модель на основе их идентификаторов:
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'}) %>
но оставьте другой код в покое. Таким образом, вы можете сохранить существующие параметры как есть.