Question

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!

Was it helpful?

Solution

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

OTHER TIPS

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top