maxedison
maxedison

Reputation: 17553

How to manage this has_many :through relationship in Rails?

I have a type of data called a chain. Each chain is made up of a specific sequence of another type of data called a step. So a chain is ultimately made up of multiple steps in a specific order. I ultimately settled on the following tables:

TABLE chains
id   date_created

TABLE steps
id   description

TABLE chain_step_positions
chain_id   step_id   step_position

I'm unclear on how to manage the saving and retrieval of each chain's steps. I'm currently imagining the following:

Saving

  1. The chain_step_controller would have an instance variable that is an array of the steps.
  2. In the create method of the chain_step_controller, it would iterate over this array, instantiating and saving a new ChainStepPosition model.

Retrieving

Assuming I start with a Chain, I could do chain.steps to get an array of its steps. If this is right, would they be in the correct order (as specified by the step_position column in the table chain_step_positions)?

Upvotes: 0

Views: 240

Answers (3)

Richard Peck
Richard Peck

Reputation: 76774

As per Rohit Siddha's answer, I'd recommend using a has_many :through association if you have two sets of data (chain and step):


Models

#app/models/chain.rb
Class Chain < ActiveRecord::Base
    has_many :step_positions
    has_many :steps, through: :step_positions
end

#app/models/step_position.rb
Class StepPosition < ActiveRecord::Base
    belongs_to :chain
    belongs_to :step
end

#app/models/step.rb
Class Step < ActiveRecord::Base
   has_many :step_positions
   has_many :steps, through: :step_positions
end

Schemas

chains
id | your | attributes | here | created_at | updated_at

step_positions
id | chain_id | step_id | your | attributes | created_at | updated_at

steps
id | your | attributes | here | created_at | updated_at

Retrieval

This will allow you to perform these queries in ActiveRecord:

@chain = Chain.find(params[:id])
@chain.steps == "step1 step2 step3 etc"

If you wanted to order the steps, I think you could use a where condition in the has_many :through association, like this:

#app/models/chain.rb
has_many :step_positions, -> { order(position: :asc) }
has_many :steps, through: :step_positions

Upvotes: 1

Rohit Siddha
Rohit Siddha

Reputation: 459

You can achieve this as given below :

class Chain < ActiveRecord::Base
  has_many :chain_step_positions
  has_many :steps, :through => :chain_step_positions
end

class Step < ActiveRecord::Base
  has_many :chain_step_positions
  has_many :chains, :through => :chain_step_positions
end

class ChainStepPosition < ActiveRecord::Base
  belongs_to :chain
  belongs_to :step
end

there is no need of chain_step_controller. You can use association methods to save record in chain_step_positions table

Upvotes: 0

msanteler
msanteler

Reputation: 2183

I believe chain.steps will be ordered by their primary key in the join (ie chain_step_positions.id).

You should be able to specify the sort order when you set up the relationship in your model, but I couldn't tell you how specifically without doing a bit of research first...

Upvotes: 0

Related Questions