activerecord records not in the :through condition - activerecord

I need to get the records not in the :through condition.
I have 3 tables:
class A < ActiveRecord::Base
has_many :B_A
has_many :B, through: :B_A
end
class B < ActiveRecord::Base
has_many :B_A
has_many :A, through: :B_A
end
class BA < ActiveRecord::Base
belongs_to :A
belongs_to :B
end
I get all A linked to a specific B by listOfA = B.A but I need also to get all A not in any B. How can I do ?

Ok, I had two conditions to put in my join query.
My MySql was :
select a.`id`, a.`label`
from `A` a
left join `BA` ba
on a.`id` = ba.`a`
where a.`uid`='userId'
and ba.`a` is null
My activeRecord now is :
A.select(['A.id', :label])
.joins('left outer join B_A on B_A.a_id = A.id')
.where({ user_id: current_user.id, "B_A.a_id" => nil })
And I have all my A not in BA

Related

Retrieve records count from has_many relation

I have the following models
Bookrack.rb
has_many :faculties
Faculty.rb
belongs_to :bookrack
has_many :books
Book.rb
belongs_to :faculty
has_many :barcodes
Barcode.rb
belongs_to :book
I have a controller name bookrack controller. I can extract record of barcode in Bookrack using loop and empty array. Is there any simpler method to extract barcode record from Bookrack.
Did you try this (for example for counting barcodes of the first book in the first faculty in the first bookrack):
b = Bookrack.first.faculties.first.books.first.barcodes.count
This should probably help..
Bookrack.rb
has_many :faculties
has_many :books, through: :faculties
has_many :barcodes, through: :books
Then you can do,
Bookrack.find(1).barcodes.count
Also to note that, has_many relations has to be plural, your model seems inappropriate..or correct it if it's a typo..
With model relationships like:
# app/models/bookrack.rb
has_many :faculties
# app/models/faculty.rb
belongs_to :bookrack
has_many :books
# app/models/book.rb
belongs_to :faculty
has_many :barcodes
# app/models/barcode.rb
belongs_to :book
You could use joins in a "nested" way:
Bookrack.joins(faculties: [books: :barcodes]).count
# => SELECT COUNT(*) FROM "bookracks"
# INNER JOIN "faculties" ON "faculties"."bookrack_id" = "bookracks"."id"
# INNER JOIN "books" ON "books"."faculty_id" = "faculties"."id"
# INNER JOIN "barcodes" ON "barcodes"."book_id" = "books"."id"
# => 1

merge ActiveRecord::Relation with ActiveRecord::Associations

I have 2 models
class User < ActiveRecord::Base
has_many :games
def created_games
Game.where(created_by: self.id)
end
end
class Game < ActiveRecord::Base
belongs_to :user
end
u = User.take
joined_games = u.games
created_games = u.created_games
the variable joined_games is a instance of ActiveRecord::Associations, and created_games is an instance of ActiveRecord::Relation.
Is there any way I can join joined_games and created_games together?
Try adding a scope in User model
scope :joined_games, where(user_id: self.id, created_by: self.id)

ActiveRecord - Finding all objects with shared attributes in a join model

I have three models
class Boat < ActiveRecord::Base
belongs_to :captain
has_many :boat_classifications
has_many :classifications, through: :boat_classifications
end
class Classification < ActiveRecord::Base
has_many :boat_classifications
has_many :boats, through: :boat_classifications
end
class BoatClassification < ActiveRecord::Base
belongs_to :boat
belongs_to :classification
end
I'm trying to write a simple ActiveRecord query to find all the boats of type sailboat. Something like Boat.where(classifications: "Sailboat")
I think this could work:
Boat.joins(:classifications).where(classifications: { name: 'Sailboat' }) # name or whatever field contains Sailboat
Generates this query:
SELECT `boats`.* FROM `boats` INNER JOIN `boat_classifications` ON `boat_classifications`.`boat_id` = `boats`.`id` INNER JOIN `classifications` ON `classifications`.`id` = `boat_classifications`.`classification_id` WHERE `classification`.`name` = 'Sailboat'
I think you want something like this:
Boat.includes(:classifications).where(classifications: {id: Classification.sailboats})
For this to work, you also need a scope on Classification like this:
def self.sailboats
where(name: "Sailboat")
end

find_or_create_by on intermediate table in rails 2.3

I have 2 tables , related to a third table as follows.
class A < ActiveRecord::Base
has_many :B, :through => :AB
has_many :AB
end
class B < ActiveRecord::Base
has_many :A, :through => :AB
has_many :AB
end
class AB < ActiveRecord::Base
belongs_to :B,
belongs_to :A
end
I want to be able to insert into the intermediate table(AB), using find_or_create.But find_or_create doesnot work on AB. How can I do it, other than finding and creating seperately ??
PS: I dont want to use has_and_belongs_to_many because that doesnot create the intermediate model and i want to insert into the intermediate table without creating any extra rows in the end tables, A and B.
Some suggestions please??
find_or_create_by has been added in rails 4. You can write it by yourself (should go to initializers):
class ActiveRecord::Base
def self.find_by(params)
scoped.where(params).limit(1).first
end
def self.find_or_create_by(params)
find_by(params) || create(params)
end
end

ActiveRecord::HasManyThroughAssociationPolymorphicSourceError

I need a player to have many structures and the structure to belong to the player. Structure is a polymorphic relationship.
class Player < ActiveRecord::Base
has_many :player_structures
has_many :structures, :through => player_structures
end
class PlayerStructures < ActiveRecord::Base
belongs_to :structure, polymorphic: true
belongs_to :player
end
class StructureA < ActiveRecord::Base
has_one :player_structure, :as => :structure
has_one :player, :through => :player_structure
end
class StructureB < ActiveRecord::Base
has_one :player_structure, :as => :structure
has_one :player, :through => :player_structure
end
But if I pull out Player.first and ask for its structures, it gives:
ActiveRecord::HasManyThroughAssociationPolymorphicSourceError: Cannot have a has_many :through association 'Player#structures' on the polymorphic object 'Structure#structure'.
But it should be able to generate a SQL query where it finds all player_structures with its id, then fetches the structure based on the structure_id and structure_type. Why does this fail and how can I validly construct a polymorphic join table?
UPDATE
If I do what I want it to do manually, it works:
player_structures.collect(&:structure)
Rails, y u no do that?
I think you need to be more specific in defining your relationships in your Player model. For example:
class Player < ActiveRecord::Base
has_many :player_structures
has_many :structureas, :through => player_structures, :source => :structure, :source_type => 'StructureA'
has_many :structurebs, :through => player_structures, :source => :structure, :source_type => 'StructureB'
end
Then you can make a method that'll return all the structures defined in the relationships instead of having to access each one individually.

Resources