Rails 6 具有嵌套对象的复杂表单 collection_select 不工作

Rails 6 Complex Form with nested objects collection_select not working

如果有人对我应该做但我还没有做的事情有任何见解,我将不胜感激。

db/schema.rb

  create_table "users", force: :cascade do |t|
    t.string "first_name"
    t.string "last_name"
    t.string "email"
    t.string "password_digest"
    t.bigint "cell_number"
    t.boolean "sms_daily"
    t.string "initials"
    t.string "remember_token"
    t.boolean "admin", default: false
    t.boolean "vacation_mode", default: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.string "remember_digest"
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["remember_token"], name: "index_users_on_remember_token"
  end

  create_table "schedules", force: :cascade do |t|
    t.text "comments"
    t.integer "author_id", null: false
    t.boolean "draft", default: true
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["author_id"], name: "index_schedules_on_author_id"
  end

  create_table "rooms", force: :cascade do |t|
    t.integer "schedule_id", null: false
    t.integer "order"
    t.string "site"
    t.string "note"
    t.string "name"
    t.integer "start_hour"
    t.integer "start_minute"
    t.string "user_initials"
    t.boolean "block"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["schedule_id"], name: "index_rooms_on_schedule_id"
  end

app/model/schedule.rb

class Schedule < ApplicationRecord
  belongs_to :author, class_name: "User"
  has_many :rooms
  accepts_nested_attributes_for :rooms
  ...
end

app/model/room.rb

class Room < ApplicationRecord
  belongs_to :schedule
  ...
end

app/views/schedule/new.hthl.erb

<% provide(:title, 'Create Schedule') %>
<h1>Create Schedule</h1>
<div class="row">
  <aside class="span4">
    <section>
      <%= form_with(model: @schedule, local: true) do |f| %>

        <div class="field">

          <%= f.fields_for :rooms, html: {class: 'form-inline' } do |r| %>

            <div class="room-title" id="<%="#{r.object[:site]}-#{r.object[:name].delete(' ')}" unless r.object[:name] == nil %>">
              <%= "#{r.object[:site]} #{r.object[:name]}"%>
              <%= r.hidden_field :site, value: r.object[:site] %>
              <%= r.hidden_field :name, value: r.object[:name] %>
              <% unless (r.object[:name] == "CHARGE" || r.object[:name] == "CO-CHARGE" || r.object[:site] == "ON_CALL" || r.object[:site] == "On-Call TODAY (Sunday or Holiday)") %>
                <br/>
                <%= r.label :start_hour %>
                <%= r.number_field :start_hour, in: 0..24, step: 1 %>
                <br/>
                <%= r.label :start_minute %>
                <%= r.number_field :start_minute, in: 0..60, step: 1 %>
              <% end %>
              <%= r.collection_select(:user_initials,User.all.map(&:initials).sort.unshift("-- late start").collect,:initials,:initials, include_blank: true) %>
            </div>
          <% end %>
          <%= f.submit "Save Schedule and Review", class: "btn btn-large btn-primary",  input_html: { :tabindex => autotab  } %>
        </div>  
      <% end %>
     </section>
  </aside>
</div>

我希望表格可以选择要分配给房间 user_initials 的所有用户姓名首字母,还可以选择不使用“-- late start”指定任何人的姓名首字母作为以及空房间的首字母留空。

当我将我的代码部署到 heroku 时,schedule/new 页面生成“我们很抱歉,出了点问题”错误,日志显示:

 ActionView::Template::Error (undefined method `initials' for "-- late start":String):

我使用 simple_form 在 Rails 4 中完成了所有工作,但 heroku 将不再支持我从 2020 年 11 月开始部署该站点的堆栈,并且 heroku 的新堆栈将不会使用原始站点的旧 ruby 版本。我正在重写 Rails 6 中的代码,其中 simple_form 不适用。

提前感谢您的考虑!

collection_select 处理一组对象并将在每个对象上查找 initials 方法。

当你这样做时...

<%= r.collection_select(:user_initials,User.all.map(&:initials).sort.unshift("-- late start").collect,:initials,:initials, include_blank: true) %>

您只是创建了一个字符串数组,并在该数组前添加了另一个字符串,而这些字符串没有 initials 方法。

更好的可能只是使用select

<%= r.select(:user_initials, options_for_select(User.all.pluck(:initials).sort.unshift("-- late start"), r.object.user_initials), include_blank: true) %>

您可以使用 collection_select,它必须是所有用户对象,因此您可以临时创建一个首字母为“--late start”的用户,例如...

<%= r.collection_select(:user_initials, User.order(:initials).to_a.prepend(User.new(initials: "-- late start")), :initials, :initials, include_blank: true) %>