Итак, у меня похожая ситуация, когда один из пользователей разместил здесь 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