Answer the question
In order to leave comments, you need to log in
ActiveRecord interesting case?
class A < ActiveRecord::Base
has_many :ab_relationships
has_many :bs, through: :ab_relationships, source: :b
end
class B < ActiveRecord::Base
has_many :ab_relationships
has_many :as, through: :ab_relationships, source: :a
end
class AbRelationship < ActiveRecord::Base
belongs_to :a
belongs_to :b
validate :ololo_validator
private
def ololo_validator
if AbRelationship.where(a: self.a).first.present?
errors.add(:ab_relationships, "error")
end
end
end
2.2.2 :005 > B.create
(0.1ms) begin transaction
SQL (0.3ms) INSERT INTO "bs" ("created_at", "updated_at") VALUES (?, ?)
(1.7ms) commit transaction
=> #<B id: 2, created_at: "2015-10-10 08:46:40", updated_at: "2015-10-10 08:46:40">
2.2.2 :006 > a = A.create(b_ids: [B.first.id])
B Load (0.2ms) SELECT "bs".* FROM "bs" ORDER BY "bs"."id" ASC LIMIT 1
B Load (0.1ms) SELECT "bs".* FROM "bs" WHERE "bs"."id" = ? LIMIT 1
(0.1ms) begin transaction
AbRelationship Load (0.1ms) SELECT "ab_relationships".* FROM "ab_relationships" WHERE "ab_relationships"."a_id" IS NULL ORDER BY "ab_relationships"."id" ASC LIMIT 1
SQL (0.3ms) INSERT INTO "as" ("created_at", "updated_at") VALUES (?, ?)
AbRelationship Load (0.1ms) SELECT "ab_relationships".* FROM "ab_relationships" WHERE "ab_relationships"."a_id" = 1 ORDER BY "ab_relationships"."id" ASC LIMIT 1
SQL (0.1ms) INSERT INTO "ab_relationships" ("b_id", "a_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)
AbRelationship Load (0.1ms) SELECT "ab_relationships".* FROM "ab_relationships" WHERE "ab_relationships"."a_id" = 1 ORDER BY "ab_relationships"."id" ASC LIMIT 1
(0.8ms) rollback transaction
=> #<A id: nil, created_at: "2015-10-10 08:46:58", updated_at: "2015-10-10 08:46:58">
2.2.2 :007 > a.valid?
AbRelationship Load (0.2ms) SELECT "ab_relationships".* FROM "ab_relationships" WHERE "ab_relationships"."a_id" IS NULL ORDER BY "ab_relationships"."id" ASC LIMIT 1
=> true
2.2.2 :008 > a.persisted?
=> false
2.2.2 :009 >
Answer the question
In order to leave comments, you need to log in
Everything is logical. First, the first connecting model is created (id 12), then when trying to create the second one, we see that another model from b already has a connection with this record a. So, yes, it must break. In fact, your validator checks that you have a one-to-one-through relationship (however, it is not clear why this is).
UPD: relationships are not fully declared in models, it should be like this:
class A < ActiveRecord::Base
has_many :ab_relationships, class_name: ABRelationship
has_many :bs, through: :ab_relationships, source: :b
end
class B < ActiveRecord::Base
has_many :ab_relationships, class_name: ABRelationship
has_many :as, through: :ab_relationships, source: :a
end
a = A.create!(b_ids: [1])
B Load (0.2ms) SELECT `bs`.* FROM `bs` WHERE `bs`.`id` = 1 LIMIT 1
(0.1ms) BEGIN
ABRelationship Load (0.4ms) SELECT `ab_relationships`.* FROM `ab_relationships` WHERE `ab_relationships`.`a_id` IS NULL ORDER BY `ab_relationships`.`id` ASC LIMIT 1
SQL (21.7ms) INSERT INTO `as` (`created_at`, `updated_at`) VALUES ('2015-10-10 08:43:24', '2015-10-10 08:43:24')
ABRelationship Load (0.6ms) SELECT `ab_relationships`.* FROM `ab_relationships` WHERE `ab_relationships`.`a_id` = 4 ORDER BY `ab_relationships`.`id` ASC LIMIT 1
SQL (0.5ms) INSERT INTO `ab_relationships` (`b_id`, `a_id`, `created_at`, `updated_at`) VALUES (1, 4, '2015-10-10 08:43:24', '2015-10-10 08:43:24')
ABRelationship Load (0.6ms) SELECT `ab_relationships`.* FROM `ab_relationships` WHERE `ab_relationships`.`a_id` = 4 ORDER BY `ab_relationships`.`id` ASC LIMIT 1
(85.8ms) ROLLBACK
ActiveRecord::RecordInvalid: Validation failed: Ab relationships error
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question