jeudi 24 septembre 2015

Rails table associations has_many through

I'm new in Rails and am working on a problem. I have two tables:

Shoes and Socks

A Shoe can have many Socks, but only one active Sock. Other Socks are inactive. All Socks are also unique with unique patterns. I think I can do this three ways

1) Using an additional column in table socks to represent the active sock

class Shoe < ActiveRecord::Base
  has_many :socks
end

class Socks < ActiveRecord::Base
  belongs_to :shoe
end

class CreateGettingDressed < ActiveRecord::Migration
  def change
    create_table :shoes do |t|
      t.string :size
      t.timestamps null: false
    end

    create_table :socks do |t|
      t.belongs_to :shoe, index:true
      t.string :pattern
      t.boolean :active
      t.timestamps null: false
    end
  end
end

This seems fairly simple, but cumbersome. I would search socks with shoe_id, and pull out the active_sock and return it's pattern. I think I would index [active_sock, shoe_id] in an array to speed it up.

2) Using an additional table to archive inactive socks

class Shoe < ActiveRecord::Base
  has_many :socks
  has_many :inactive_socks
end

class Socks < ActiveRecord::Base
  belongs_to :Shoe
end

class Inactive_socks < ActiveRecord::Base
  belongs_to :Shoe
end

class CreateGettingDressed < ActiveRecord::Migration
  def change
    create_table :shoes do |t|
      t.string :name
      t.timestamps null: false
    end

    create_table :socks do |t|
      t.belongs_to :shoe, index:true
      t.string :pattern
      t.timestamps null: false
    end


    create_table :inactive_socks do |t|
      t.belongs_to :shoe, index:true
      t.string :pattern
      t.timestamps null: false
    end
  end
end

This seems cumbersome as well, but when you are just dealing with active socks easy to use and fast. But when buying a new sock, I have to check the pattern with both tables.

3) Using a has_many :through relationship

class Shoe < ActiveRecord::Base
  has_many :active_socks
  has_many :socks, through: active_socks 
end

class Active_Socks < ActiveRecord::Base
  belongs_to :Shoe
  belongs_to :Sock
end

class Socks < ActiveRecord::Base
  has_many :active_socks
  has_many :shoes, through: active_socks
end

class CreateGettingDressed < ActiveRecord::Migration
  def change
    create_table :shoes do |t|
      t.string :name
      t.timestamps null: false
    end

    create_table :socks do |t|
      t.string :pattern
      t.timestamps null: false
   end

    create_table :active_socks do |t|
      t.belongs_to :shoe, index: true
      t.belongs_to :sock, index: true
      t.string :pattern
      t.boolean :active
      t.timestamps null: false
    end
  end
end

This seems like option 2, but I feel like I'm using Rails tools to make it less cumbersome. When I'm searching for patterns I'm just checking the socks table, when I'm searching for the one active_sock I'm just searching active_socks table.

I've read up on similar posts, and it seems options 1 and 2 are commonly used in closed_accounts, banning users, banning posts, archiving etc. Situations where you need to differentiate data that is only slightly different. The choice there seems to be look at what you need and choose the option 1 or 2 that best fits you.

My understanding for has_many through situations seems to be when you have a relationship and you need extra meta data you can use it. I think that fits this situation.

Did I set up option 1 correctly and am I right that indexing the array of [shoe_id and active] will give me a faster search? Is option 3 an appropriate use of has_many through? Would my explanation of option 3 work?

Aucun commentaire:

Enregistrer un commentaire