문제

First things first

Using:

  • rails4
  • oracle enhanced adapter rails4 branch

I have a many to many relationship mapped on an existing database. My models look as such:

class EventMap < ActiveRecord::Base
  self.table_name="TAKE_PART"
  self.primary_key="id"
  belongs_to :event, foreign_key: "lottery_event_id"  
  belongs_to :entrant, foreign_key: "address_id"  
end

class Event < ActiveRecord::Base
  self.table_name="THE_EVENT"
  self.primary_key="id"
  has_many :event_maps, :foreign_key => "lottery_event_id"
  has_many :entrants, :through => :event_maps
  accepts_nested_attributes_for :entrants, :reject_if => :all_blank
end

class Entrant < ActiveRecord::Base
  self.table_name="ADDRESSES"
  self.primary_key="id"
  self.set_date_columns :date_of_birth
  has_many :events, :through => :event_maps
  has_many :event_maps, :foreign_key  => "address_id"
end

static page controller for my voting page

...
def vote
  @event=Event.find_by(id: 4227)
  @entrants=@event.entrants
  @entrant=@event.entrants.build
end
...

vote view:

<%= form_for(@event) do |f| %>

  <%= f.fields_for :entrant do |builder| %>
    <%= render "/entrants/fields", :f => builder %>
  <% end %>

<div class="actions">
  <%= f.submit %>
</div>  
<% end %>

entrant/fields partial:

<% if @entrant.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@entrant.errors.count, "error") %> prohibited this entrant from being saved:</h2>    
      <ul>
      <% @entrant.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>
  <%= f.hidden_field :id %>
  <div class="field">
    <%= f.label :lastname %><br>
    <%= f.text_field :lastname %>
  </div>
  <div class="field">
    <%= f.label :firstname %><br>
    <%= f.text_field :firstname %>
  </div>
  <div class="field">
    <%= f.label :street %><br>
    <%= f.text_field :street %>
  </div>
  <div class="field">
    <%= f.label :country_id %><br>
    <%= f.number_field :country_id %>
  </div>
  <div class="field">
    <%= f.label :city %><br>
    <%= f.text_field :city %>
  </div>
  <div class="field">
    <%= f.label :telephone %><br>
    <%= f.text_field :telephone %>
  </div>
  <div class="field">
    <%= f.label :email %><br>
    <%= f.text_field :email %>
  </div>
  <div class="field">
    <%= f.label :date_of_birth %><br>
    <%= f.date_select :date_of_birth %>
  </div>
  <div class="field">
    <%= f.label :lang_id %><br>
    <%= f.text_field :lang_id %>
  </div>
  <div class="field">
    <%= f.label :added %><br>
    <%= f.date_select :added %>
  </div>
  <div class="field">
    <%= f.label :salut %><br>
    <%= f.text_field :salut %>
  </div>
  <div class="field">
    <%= f.label :zip %><br>
    <%= f.text_field :zip %>
  </div>
  <div class="field">
    <%= f.label :newsletter %><br>
    <%= f.check_box :newsletter %>
  </div>
  <div class="field">
    <%= f.label :company %><br>
    <%= f.text_field :company %>
  </div>

The form now submits to event controller PATCH

class EventsController < ApplicationController
  before_action :set_event, only: [:show, :edit, :update, :destroy]
  ...
  # PATCH/PUT /events/1
  # --> HOW DO I SAVE THE SUBMITTED ENTRANT HERE??? <--
  def update
    respond_to do |format|      
      if @event.update(event_params)
        format.html { redirect_to @event, notice: 'Event was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @event.errors, status: :unprocessable_entity }
      end
    end
  end
...
  private
    # Use callbacks to share common setup or constraints between actions.
    def set_event
      @event = Event.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def event_params
      params.require(:event).permit(:id, :lottery_id, :events_dates_id, :event_date, :event_location, :tickets_for_winner, :prize, :tickets_internally,
        :entrants_attributes => [:id, :lastname, :firstname, :street, :country_id, :city, :telephone, :email, :date_of_birth, :lang_id, :added, :salut, :zip, :newsletter, :company])
    end
end

How do I register an Entrant with an Event, adding data only to the intermediate model EventMap since the Event will always exist?

Do I need to include accepts_nested_attributes_for in my models to propagate changes accross tables (I could not quite figure out what this does from the documentation)? Do I need to send additional params via the Entrant form to update the EventMap?

Main GOAL: I want a form where Entrants can register to an existing event!

도움이 되었습니까?

해결책

Hard to judge about Your forms, as we don't see any ;)

But You are right to be able to create nested attributes, from nested attributes from, You need to set accepts_nested_attributes_for :some_model, :some_other_model

If You find docs confusing, consult Railscasts: http://railscasts.com/episodes/196-nested-model-form-part-1 http://railscasts.com/episodes/197-nested-model-form-part-2

다른 팁

You are requiring custom logic and that custom logic must be defined, Rails will not automatically update everything, it must be defined in the update controller as you suggest.

I might do something along the lines of this:

def update

    entrant = Entrant.find(params[:entrant_id])
    event = Event.find(params[:event_id])

    EventMap.create!(event: event, entrant: entrant)
    #.... go on with usual stuff

    # Alternatively you could use build
    event_map = EventMap.new
    event_map.build(event: event, entrant: entrant)

end
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top