0

I am using Rails 5 with postgresql 9.6. I have the following model and relationships

Tables

  1. people
  2. segments
  3. people_segments (join table)

Relationships

person:

has_and_belongs_to_many :segments, through: :people_segments 

segment:

has_and_belongs_to_many :people, through: :people_segments 

Here I want to get the people who not associated with particular segment. I tried using join but could not get result. Now I am using "not in" query and it took more time. Is there any other way without using "not in"?

  • 1
    "Here I want to get the people who not associated with particular segment. I tried using join but could not get result." -> what was the Activerecord query you wrote, what did you expect, what did you get? – kiddorails Nov 02 '17 at 08:38

1 Answers1

2

your objects are wrong

the model is person and the table is people

Model Person.rb

has_and_belongs_to_many :segments

Model Segment.rb

has_and_belongs_to_many :people

The migration looks like this

class CreatePeopleAndSegments < ActiveRecord::Migration[5.0]
  def change
    create_table :people do |t|
      t.string :name
      t.timestamps
    end

    create_table :segments do |t|
      t.string :part_number
      t.timestamps
    end

    create_table :people_segments, id: false do |t|
      t.belongs_to :person, index: true
      t.belongs_to :segment, index: true
    end
  end
end

So when you do @person.segments you get an array including all the segments viceversa @segment.people

Here I want to get the people who not associated with particular segment. I tried using join but could not get result. Now I am using "not in" query and it took more time. Is there any other way without using "not in"?

Between the two tables there is already a Join, maybe your best choice is making sure you can use that join as Model in the application side.

There is a specific chapter in the association_basics guide from rails discussing about this, it is called choosing-between-has-many-through-and-has-and-belongs-to-many

I quote them

The simplest rule of thumb is that you should set up a has_many :through relationship if you need to work with the relationship model as an independent entity. If you don't need to do anything with the relationship model, it may be simpler to set up a has_and_belongs_to_many relationship (though you'll need to remember to create the joining table in the database).

I believe that if you read that chapter you will understand the best choice for you is using has_many :through and having an object in your Application that represents the table people_segments.

Think with creativity what is this relationship, is this relationship between people and segments a role or a position...

To implement has_many :through you can follow the guide

Once you have done that, you can use the Position object to do the query.

Position.where.not(segment_id: 1)

If this is not what you need, the rails query documentation includes many more info and StackOverflow does not substitute the official documentation

Fabrizio Bertoglio
  • 5,890
  • 4
  • 16
  • 57