I'm trying to get my head around the best way to add a record to a join table through alternative controllers in rails.
I have various models in my app that will require this, but I'm focusing on these two first before I transcribe the method into others, so shall use this as the example. I have a Venue
and Interest
model which are to be connected through VenuesInterests
model (it has a couple of extra optional attributes so isn't a HABTM relationship). A user can admin a Venue instance and/or an Interest instance and therefore there should be an ability to select Venues to attach to an Interest and likewise Interests to attach to a Venue. This should be done with an Add Venues link on the Interest instance view and an Add Interests link on the Venue instance view. This would then take the user to a list of the relevant instances for them to select ones they would like to select.
Here are my models:
Venue.rb
class Venue < ActiveRecord::Base
has_many :interests, through: :venue_interests
has_many :venues_interests, dependent: :destroy
accepts_nested_attributes_for :venues_interests, :allow_destroy => true
end
Interest.rb
class Interest < ActiveRecord::Base
has_many :venues, through: :venue_interests
has_many :venues_interests, dependent: :destroy
end
VenuesInterests.rb
class VenuesInterest < ActiveRecord::Base
belongs_to :interest
belongs_to :venue
validates :interest_id, presence: true
validates :venue_id, presence: true
end
This all seems fine, however it's the controller and views that I'm struggling with. I've tried adding an extra method add_interest
to the Venues controller to do the job of the create method in the VenuesInterests controller, so that there will be a different view when adding Venues to an Interest than there would be adding Interests to a Venue, otherwise I don't know how I would do this. My current Venues controller is as follows:
VenuesController.rb:
class VenuesController < ApplicationController
before_filter :authenticate_knocker!, only: [:new, :edit, :create, :update, :destroy]
respond_to :html, :json
def index
@venues = Venue.all.paginate(page: params[:page]).order('created_at DESC')
end
def show
@venue = Venue.find(params[:id])
@hash = Gmaps4rails.build_markers(@venue) do |venue, marker|
marker.lat venue.latitude
marker.lng venue.longitude
marker.infowindow venue.name
end
end
def new
@venue = Venue.new
end
def edit
@venue = Venue.find(params[:id])
end
def create
@venue = current_knocker.venues.create(venue_params)
respond_to do |format|
if @venue.save!
format.html { redirect_to @venue, notice: 'Venue was successfully created.' }
format.json { render json: @venue, status: :created, location: @venue }
else
format.html { render action: "new" }
format.json { render json: @venue.errors, status: :unprocessable_entity }
end
end
end
def update
@venue = Venue.find(params[:id])
@venue.update_attributes(venue_params)
respond_to do |format|
if @venue.update_attributes(venue_params)
format.html { redirect_to(@venue, :notice => 'Your Venue was successfully updated.') }
format.json { respond_with_bip(@venue) }
else
format.html { render :action => "edit" }
format.json { respond_with_bip(@venue) }
end
end
end
def destroy
end
def add_interests
@venues_interests = VenuesInterest.new
@interests = Interests.all.paginate(page: params[:page]).order(:name)
end
private
def venue_params
params.require(:venue).permit(:admin... etc)
end
end
This isn't currently working as I'm not sure how to reference other classes within a controller, but the important thing I'd like to know is is there a better way to do this or am I (kind of) on the right track? If anyone has a good method (perhaps a jQuery plugin) for allowing multiple selection of instances for the view, that would be great too!