Rails has_and_belongs_to_many и формы - PullRequest
       1

Rails has_and_belongs_to_many и формы

0 голосов
/ 06 сентября 2018

Итак, у меня похожая ситуация, когда один из пользователей разместил здесь Rails 4 - флажки для ассоциации has_and_belongs_to_many , где это было бы отличным примером:

#app/models/campaign.rb
class Campaign < ActiveRecord::Base
  has_and_belongs_to_many :options
end

, а затем

#app/models/option.rb
class Option < ActiveRecord::Base
  has_and_belongs_to_many :campaigns
end

Вот как выглядит миграция моей таблицы соединений:

class CreateJoinTableCampaignsOptions < ActiveRecord::Migration[5.1]
  def change
    create_join_table :campaigns, :options do |t|
      t.index [:campaign_id, :option_id], :unique => true, name: "CampaignO"
      t.index [:option_id, :campaign_id], :unique => true, name: "OptionC"
    end
  end
end

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

Учитывая все вышесказанное, я хочу, чтобы в моей форме Campaign была показана опция, связанная с ней. Если это изменилось, я хочу, чтобы контроллер изменил свою ассоциацию в таблице соединений. Это возможно?

Вот мой взгляд на Кампанию.

#app/views/campaigns/index.html.erb
<%= form_with(model: @campaign, local: true) do |form| %>
<%= form.collection_select :option_ids, Option.order("name ASC").all, "id", :name, prompt: "Select an option", class: "form-control" %>
<% end %>

Теперь, когда я отправляю эту форму, она выглядит следующим образом:

=> <ActionController::Parameters {"utf8"=>"✓", "authenticity_token"=>"3Dxl5mvuS82BzjM20CYgNgIMay4mNtOv3FY3E79onO/w7yN5wOfwsf20SzEh3VoRN+sLgAo22dhfxuI2zR6O+Q==", "campaign"=><ActionController::Parameters {"name"=>"HEllo World", "option_ids"=>"3"} permitted: false>, "controller"=>"campaign", "action"=>"create"} permitted: false>

Проблема в том, что между Option и Campaign не создается никакой связи.

Пытаюсь выяснить, чего мне здесь не хватает. Я знаю, что это очевидно, но я не могу понять это. Единственное, о чем я могу думать, - это создать другое действие в контроллере и использовать его для создания ассоциации.

** Редактировать **

Вот контроллер, который, опять же, просто по умолчанию:

  def create
    @campaign = Campaign.new(campaign_params)

    respond_to do |format|
      if @campaign.save
        format.html { redirect_back fallback_location: campaigns_path, notice: 'Campaign was successfully created.' }
        format.json { render :show, status: :created, location: @campaign }
      else
        format.html { render :new }
        format.json { render json: @campaign.errors, status: :unprocessable_entity }
      end
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_campaign
      @campaign = Campaign.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def campaign_params
      params.require(:campaign).permit(:name, option_ids: [])
    end

1 Ответ

0 голосов
/ 06 сентября 2018

Как я уже сказал, белый список option_ids в виде массива здесь не необходим, если вы фактически не передаете ему несколько значений. Вы должны изменить campaign_params ниже

def campaign_params
  params.require(:campaign).permit(:name, :option_ids)
end

Кроме того, я рекомендую изменить option_ids на option_id, так как вы выбираете только одну опцию за раз. Так что campaign_params будет

def campaign_params
  params.require(:campaign).permit(:name, :option_id)
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...