5

I have this models and association many-to-many : through:

class RailwayStation < ActiveRecord::Base
  has_many :railway_stations_routes
  has_many :routes, through: :railway_stations_routes
end

class Route < ActiveRecord::Base
  has_many :railway_stations_routes
  has_many :railway_stations, through: :railway_stations_routes
end

class RailwayStationsRoute < ActiveRecord::Base
  belongs_to :railway_station
  belongs_to :route
end

I added the column st_index:

add_column :railway_stations_routes, :st_index, :integer

for index station in route, but I don't understand how change it from route view form:

ul
  - @route.railway_stations.each do |railway_station|
   li = railway_station.title
      = ????
max
  • 96,212
  • 14
  • 104
  • 165
Vadim Sergeevich
  • 143
  • 1
  • 10
  • 1
    For the `has_many :routes, through: :railway_stations_routes` to work properly the join table needs to be named `railway_station_routes` not `railway_stations_routes`.The join model should be `RailwayStationRoute`. See this question for an explaination why http://stackoverflow.com/questions/33045170/join-table-for-has-many-through-in-rails/33046300?noredirect=1#comment53915024_33046300 – max Oct 09 '15 at 21:09

1 Answers1

2

First you need to correct the naming scheme for your models and tables so that they follow the rails conventions.

Run this from the command line:

$ rails g migration RenameRailwayStationsRoute

And edit the migration in 'db/migrations' to read:

class RenameRailwayStationsRoute < ActiveRecord:Migration
  def change
    rename_table :railway_stations_route, :railway_station_routes
  end 
end 

Run the migration

$ rake db:migrate

Rename the model file:

$ cd app/models
$ mv railway_stations_route.rb railway_station_route.rb

Or if you are using GIT

$ git mv railway_stations_route.rb railway_station_route.rb

Edit your models to use the correct naming:

class RailwayStation < ActiveRecord::Base
  has_many :railway_station_routes
  has_many :routes, through: :railway_station_routes
end

class RailwayStationRoute < ActiveRecord::Base
  belongs_to :railway_station
  belongs_to :route
end

class Route < ActiveRecord::Base
  has_many :railway_station_routes
  has_many :railway_stations, through: :railway_station_routes
end

Add associated records to a form

The simplest way is to use the simple_form gem. After following the instructions instructions (and remember to restart your rails server) add the form:

<%= simple_form_for(@route) do |f| %>
  <%= f.association :stations, collection: Station.all, name_method: :title %>
<% end %>

Without simple form you could do it something like this:

<%= form_for(@route) do |f| %>
  <%= f.collection_check_boxes(:stations_ids, Station.all, :id, :title) do |b| 
    b.label { b.checkbox checked: @route.stations_ids.include?(object.id) } 
  end %>
<% end %>

Added - accessing the join model

There is no unfortunatly no straight forward way to to access the properties of the join model from one end of a many to many relationship.

This is due to the fact that Rails does not keep track of where the model was loaded from well at least not in the way you want. (it does - but it's pretty complicated).

One way to solve this would be to do:

class RoutesController < ApplicationController
  def show
    @route = Route.eager_load(railway_station_routes: :railway_station).find(params[:id])
  end
end

We join in both models with eager_load so that rails runs one database query and loads both the railway_station_routes and railway_station.

You would then loop through the join model instead of the stations:

ul
  - @route.railway_station_routes.each do |rs|
    li
      # note that you cannot both use = and have a body in HAML/Slim
      p = "index: #{ rs.st_index }"
      p = rs.railway_station.title
max
  • 96,212
  • 14
  • 104
  • 165
  • Thank you for your answer, but how I'm understand the name of the join table is not important, for example, there it's name not in any way connected with the names of the other tables. http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association Add station to route works well. My question was: how I can reach attribute(st_index) in the jion table from route views? – Vadim Sergeevich Oct 10 '15 at 11:57
  • When you are using `has_many through` the join table name is very important. Rails will not be able instantiate the correct class for the related object. – max Oct 10 '15 at 14:38
  • Added one possible way to access the join model - there are various other hacks and tricks to do this. See http://bradleypriest.com/2012/03/18/accessing-attributes-from-has-many-through-join-models/ http://stackoverflow.com/questions/25235025/rails-4-accessing-join-table-attributes – max Oct 10 '15 at 18:43
  • Also the guide example does not use compound words. Pluralization does matter when the join table has an underscore in middle. `user_cats` will load `UserCat` and `users_cats` will load `Users::Cat` – max Oct 10 '15 at 19:57