msdundar
msdundar

Reputation: 383

Nested Routes and Forms in Has Many Through Relations

I am trying to create a simple Rails4 application. I have User model which is generated by Devise GEM, Examination model and Participation models are both generated by scaffold generator.

These are my models:

class Examination < ActiveRecord::Base
  has_many :participations
  has_many :users, :through => :participations
end

class Participation < ActiveRecord::Base
  belongs_to :user
  belongs_to :examination
end

class User < ActiveRecord::Base
  has_many :participations
  has_many :examinations, :through => :participations
end

Now, I would like to create the structure to make Users to be able to register to exams. In the index page of Examinations (app/views/examinations/index.html.erb) I want to add a "Register" button just next to default Show, Edit and Destroy buttons for each exam. When a user clicks to "Register to Exam" button I want them to see a page where they can choose their exam language preference and then submit their registrations.

Also I want a User can only 1 time register for an exam. They should be able to register for many exams but only 1 time for each.

How can I do this kind of structure? When I'm using nested resources, all my forms are throwing errors.

Upvotes: 0

Views: 129

Answers (1)

jay
jay

Reputation: 12495

I don't see why you would need nested resources for your forms. Both the exam id and the language preference should be attributes of a participation.

So you just need to build a page to create a new participation, based off of an exam id.

In the Participations controller

# if your route is /participations/new?examination_id=1
# you could also do nested routing like /exams/1/participations/new
def new
  @participation = Participation.new
  @examination = params[:examination_id]
end

def create
  @participation = Participation.new params[:participation]
  @participation.user = current_user
    if @participation.save
      redirect_to examinations_page
    else
      render 'new'
    end
end

And then it's just a simple form in the new.html.erb page..

<h1> Sign up for: <%= @examination.name %> </h1>
<%= form_for @participation do |f| %>
  <%= f.hidden :examination_id %>
  <%= f.select :language_preference #add the set of language options in here %>
  <%= f.submit :register %>
<% end %>

If you find your form is submitting to the wrong route, then you can set its url.. for example if you have a participation's resources nested under exam's resources, your rough path would be:

 <%= form_for @participation, as: :participation, url: new_examination_participation_path(@examination) } do |f| %>
     ...
 <% end %>

Upvotes: 1

Related Questions