我最近在做一个项目,在这个项目中,我面临一个两难的选择,在两种方法中选择一种获得相同的结果。以下是班级结构:
class Book < ApplicationRecord
belongs_to :author
end
class Author < ApplicationRecord
has_many :books
end
作者有名字,姓。我想得到一本书的作者全名作为一个实例方法。
在简单的活动记录术语中,由于book与author相关联,我们可以按如下方式获取book的author名称:
例如在书本课上,我们有:
class Book < ApplicationRecord
belongs_to :author
def author_name
"#{author.first_name} #{author.last_name}"
end
end
我们得到了结果!
但是,根据最小化依赖性的目标(poodr book)、未来的易更改性和更好的面向对象设计,这本书不应该知道作者的属性。它应该通过接口与author对象交互。
因此,图书不应该是负责获得作者姓名的人。作者班应该。
class Book < ApplicationRecord
belongs_to :author
def author_name
get_author_name(self.author_id)
end
private
#minimizing class dependecies by providing private methods as external interfaces
def get_author_name(author_id)
Author.get_author_name_from_id(author_id)
end
end
class Author < ApplicationRecord
has_many :books
#class methods which provides a gate-way for other classes to communicate through interfaces, thus reducing coupling.
def self.get_author_name_from_id(id)
author = self.find_by_id(id)
author == nil ? "Author Record Not Found" : "#{author.first_name.titleize} #{author.last_name.titleize}"
end
end
现在,book只是与author提供的公共接口交互,author负责从其属性中获取全名,这无疑是一个更好的设计。
我尝试在控制台中将查询作为两个独立的方法运行:
class Book < ApplicationRecord
def author_name
get_author_name(self.author_id)
end
def author_name2
"#{author.last_name} + #{author.first_name}"
end
end
结果如下:
看起来两个都运行相同的查询。
我的问题是
rails是否将book类中调用的author.last_名称转换为
与author.find_by_id(author_id)相同的SQL查询。在
当数据量较大时,作者类(通过Book类传递消息)?
在数据量较大的情况下,哪一个性能更好?
不调用作者。Book类中的姓氏违反了设计
原则?
最佳答案
实际上,使用委托更为常见和简单。
class Book < ApplicationRecord
belongs_to :author
delegate :name, to: :author, prefix: true, allow_nil: true
end
class Author < ApplicationRecord
has_many :books
def name
"#{first_name.titleize} #(last_name.titleize}"
end
end
至于性能,如果在进行图书查询时
join
作者,则最终只执行一个查询。@books = Book.joins(:author)
现在,当您遍历
@books
并单独调用book.author_name
时,不需要对authors
表进行sql查询。关于ruby-on-rails - Ruby on Rails事件记录查询哪个有效,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47506689/