Предоставление пользователям возможности либо выбрать из выпадающего меню, либо ввести свои собственные и добавить его в таблицу

Я прошу прощения за вопрос новичка. Но я пытался создать особый тип ассоциации, и все мои усилия терпели неудачу. Я хотел бы дать пользователям возможность выбирать свои родные города. Я отложил несколько вариантов, из которых они могут выбирать, но если его в данный момент нет в списке - я бы хотел, чтобы пользователь просто мог добавить его: "Не видеть свой город, добавьте его". Затем другой пользователь, который зарегистрируется позже, сможет увидеть новый город в своем списке. Я перечислил весь свой соответствующий код ниже, который работает до сих пор.

огромное спасибо

HomeCity Migration

class CreateHomecities < ActiveRecord::Migration[5.0]
  def change
    create_table :homecities do |t|
      t.string :Hometown

      t.timestamps
    end
  end
end

HomeCity Ссылка на пользователей

class AddHomecitiesRefToUsers < ActiveRecord::Migration[5.0]
  def change
    add_reference :users, :homecity, foreign_key: true
  end
end

User.rb

class User < ApplicationRecord
  cattr_accessor :current_user
  belongs_to :homecity, optional: true
end

Homecity.rb

class Homecity < ApplicationRecord
  has_many :users
end

edit.html.erb

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
<%= devise_error_messages! %>
<div class="field">
  <%= f.label :homecity %>
  <br>
  <%= f.collection_select :homecity_id, Homecity.all, :id, :Hometown %>
</div>
<div class="form-group">
  <%= f.submit "Update", class: 'btn btn-lg btn-block btn-primary' %>
</div>
<% end %>             

Seeds.rb

Homecity.destroy_all
bigapple = Homecity.create!(Hometown:"New York City")
techhub = Homecity.create!(Hometown:"San Francisco")
longhorns = Homecity.create!(Hometown:"Austin")
angels = Homecity.create!(Hometown:"Los Angeles")
windycity = Homecity.create!(Hometown:"Chicago")

Homecities_controller.rb (Создан новый файл контроллера на основе ответа)

class HomecitiesController < ApplicationController
before_action :authenticate_user!, only: [:new, :create]
def new
 @homecity = Homecity.new
end
def create
 @homecity = Homecity.new(homecity_params)
end
private
def homecity_params
 params.require(:homecity).permit(:user_id)
end
end

Пример похож на то, как Facebook делает это с образованием

2 ответа

Решение

Я понял это после нескольких часов поиска и подключения. Я перечислил то, что я сделал ниже, на случай, если кому-то еще понадобится помощь по аналогичному вопросу.

  1. Лучший способ решить эту проблему - использовать Selectize.js (Rubygems.org).
  2. Добавьте гем в ваш Gemfile - запустите пакетную установку
  3. Обязательно добавьте ( *= require selectize, *= require selectize.default) в ваш application.scss и добавьте (//= require selectize) в ваш application.js
  4. Вам нужно будет создать контроллер для Homecities, файл edit.js (настроить selectize, вашу базу данных и выпадающий список) и модал начальной загрузки в файле Edit.html.erb.

Homecities_controller.rb

class HomecitiesController < ApplicationController
before_action :authenticate_user!, only: [:new, :create]
def create
@homecity = Homecity.new(homecity_params)
if @homecity.save
  render json: @homecity
else
  render json: {errors: @homecity.errors.full_messages}
end
end
private
def homecity_params
params.require(:homecity).permit(:Hometown)
end
end

edit.html.erb

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
                  <%= devise_error_messages! %>       
                            <div class="field">
                            <%= f.label :homecity, "Home Town" %><br>
                            <%= f.select :homecity_id, Homecity.all.pluck(:Hometown, :id), {}, { class: "selectize" } %>

                          </div>
                        <div class="form-group">
                    <%= f.submit "Update", class: 'btn btn-lg btn-block btn-primary' %>
                  </div>
            <% end %>

            <div class="modal fade homecity-modal" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel">
              <div class="modal-dialog modal-sm" >
                <div class="modal-content">
                  <div class="modal-header">      
                    <h4 class="modal-title" id="mySmallModalLabel">Create a New City</h4>
                  </div>
                  <div class="modal-body">
                    <%= form_for Homecity.new do |f| %>
                      <div class="form-group">
                        <%= f.label :Hometown %>
                        <%= f.text_field :Hometown, class: "form-control" %>
                      </div>                
                      <div class="form-group">
                        <%= f.submit class: "btn btn-primary" %>
                      </div>
                      <div class="modal-footer">                      
                      <span class="form-control-static pull-right">     
                        <button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
                      </span>
                      </div>
                    <% end %>
                  </div>
                </div>
              </div>
            </div>

edit.js

$(document).on("turbolinks:load", function() {
var selectizeCallback = null;
$(".homecity-modal").on("hide.bs.modal", function(e) {
if (selectizeCallback != null) {
  selectizeCallback();
  selecitzeCallback = null;
}

$("#new_homecity").trigger("reset");
$.rails.enableFormElements($("#new_homecity"));
});
$("#new_homecity").on("submit", function(e) {
e.preventDefault();
$.ajax({
  method: "POST",
  url: $(this).attr("action"),
  data: $(this).serialize(),
  success: function(response) {
    selectizeCallback({value: response.id, text: response.Hometown});
    selectizeCallback = null;

    $(".homecity-modal").modal('toggle');
  }
});
});
$(".selectize").selectize({
create: function(input, callback) {
  selectizeCallback = callback;

  $(".homecity-modal").modal();
  $("#homecity_Hometown").val(input);
}
});
});

Вы заново изобретаете колесо - это нормально, если вы просто делаете это для целей обучения, я думаю, но если это реальное приложение, вам, скорее всего, лучше использовать сторонний драгоценный камень.

Исходные данные для этого могут быть легко обновлены (см. Readme)

https://github.com/loureirorg/city-state

Если вы не хотите использовать это, добавьте на страницу кнопку "Добавить город", которая затем сделает поле ввода доступным с помощью кнопки отправки, которая затем вставит новый город в вашу базу данных.

Другие вопросы по тегам