我正在尝试以下方法 - 我有模特:故事,书籍,关键词
class Tale < ActiveRecord::Base
has_many :tale_culture_joins
has_many :cultures, through: :tale_culture_joins
has_many :tale_purpose_joins
has_many :purposes, through: :tale_purpose_joins
has_many :tale_book_joins
has_many :books, through: :tale_book_joins
has_many :tale_keyword_joins
has_many :keywords, through: :tale_keyword_joins
class Book < ActiveRecord::Base
has_many :tale_book_joins
has_many :tales, through: :tale_book_joins
end
class TaleBookJoin < ActiveRecord::Base
belongs_to :tale
belongs_to :book
end
class Keyword < ActiveRecord::Base
has_many :tale_keyword_joins
has_many :tales, through: :tale_keyword_joins
end
class TaleKeywordJoin < ActiveRecord::Base
belongs_to :tale
belongs_to :keyword
end
这些是迁移
class CreateTales < ActiveRecord::Migration
def change
create_table :tales do |t|
t.text :name, null: false, unique: true
t.boolean :exists, default: nil
t.timestamps null: false
end
end
end
class CreateBooks < ActiveRecord::Migration
def change
create_table :books do |t|
t.text :name, null: false, unique: true
t.boolean :exists, default: nil
t.timestamps null: false
end
end
end
class CreateKeywords < ActiveRecord::Migration
def change
create_table :keywords do |t|
t.text :name, null: false, unique: true
t.boolean :exists, default: nil
t.timestamps null: false
end
end
end
我想要发生的是每次我通过以下方法删除(Tale,Book)或(Tale,Keyword)之间的连接 tale_instance_object.book_ids = []
它应该检查关系被破坏的书籍是否有任何其他故事关系。如果没有,则设置:Book对象实例中存在为false。
我可以通过控制器代码完成此操作。 想知道如何使用CallBacks或ActiveModel
答案 0 :(得分:1)
只有当关系本身就是一个对象时,才应该真正使用连接类。 考虑以下情况:
doctors -> appointments <- patients
years -> days <- hours
在这些情况下,关系对象具有自己的数据(appointments.time
,days.weekday
)和逻辑。否则你只是浪费内存,因为对象必须为每个关系实例化。请改用has_and_belongs_to
。
class Tale < ActiveRecord::Base
# has_and_belongs_to_many :cultures
# has_and_belongs_to_many :purposes
has_and_belongs_to_many :books
has_and_belongs_to_many :keywords
after_destroy :update_books!
end
class Book
has_and_belongs_to_many :tales
def check_status!
self.update_attribute(status: :inactive) unless books.any
end
end
class Keyword
has_and_belongs_to_many :tales
end
同样exists
对于模型字段来说是一个非常糟糕的命名选择,因为它与exists?
方法中构建的Rails发生冲突。这将产生意想不到的后果。
更好的选择是使用整数with an enum
。
class Book
# ...
enum :status [:inactive, :active] # defaults to inactive
end
class CreateBooks < ActiveRecord::Migration
def change
create_table :books do |t|
t.text :name, null: false, unique: true
t.integer :status, default: 0
t.timestamps null: false
end
end
这也会添加方法book.inactive?
和book.active?
。
你可以向Tale添加一个回调,告诉Book更新故事时更新但是这段代码真的很臭,因为Tale现在负责维护Book的状态。
class Tale < ActiveRecord::Base
# ...
after_destroy :update_books!
def update_books!
self.books.each { |b| b.check_status! }
end
end
class Book
has_and_belongs_to_many :tales
def check_status!
self.update_attribute(status: :inactive) unless tales.any?
end
end
更好的替代方法是在书籍上添加回调或在销毁故事时在控制器中执行回调:
class Book
has_and_belongs_to_many :tales
before_save :check_for_tales!, if: -> { self.tales_changed? }
def check_for_tales!
self.status = :inactive unless self.tales.any?
end
end