以下是我的关系:
论坛 has_many:belongs_to 主题
主题 has_many:belongs_to 帖子
主题 has_many:belongs_to 用户
用户 has_many:belongs_to 帖子
现在,让我们说当创建一个新帖子时,我想通过电子邮件发送给所有订阅该主题的人发送新帖子。在电子邮件中,我提供了论坛的名称,主题的名称以及帖子本身的名称和正文。我将这些参数传递给负责发送电子邮件的实例方法#notify_all_users
。
以下是我在PostsController中的表现:
def create
@user = current_user
@post = @user.posts.new(parameters)
if @post.save
@post.notify_all_users(post: @post, topic: @post.topic, forum: @post.topic.forum)
end
end
现在是否违反了德米特定律? forum
选项的方法链中有两个点,但dependent :destroy
和Topic
上已设置Post
,因此如果帖子不存在,则该帖子不存在主题不存在,如果论坛不存在,则主题不存在,因此任何讨厌的零错误类错误的可能性为零。我是否还应采取措施使其遵守得墨忒耳法则?
就像我说的那样,我已经发现为什么得墨忒耳定律很重要(我想,我不确定)。
我们说我浏览到我的主题页面,其中显示了属于该主题的所有帖子。没有违反demeter的法律!
但是,让我们说我想要在帖子旁边显示每个帖子所有者的用户名,如下所示:
<div> <%= link_to post.user.user_name, post.user %> </div>
<div> <%= post.body %> </div>
这违反了德米特定律,对吧?
由于我们的主题#show action set @topic
,我们循环播放@topic.posts
但现在,在该视图中,我们有效地执行了此操作:@topic.post.user.user_name
每个帖子。< / p>
现在,LOD这么重要吗?因为如果在主题中恰好有帖子的单个用户被删除,整个应用程序就会停止运行。 Nil nil类错误,因为帖子不再具有用户类(当然,它没有user_name)。
我认为绕过这个问题的方法是在父模型中设置dependent :destory
,或者在用户中设置soft_delete,但我发现我只是在挖洞中进一步挖掘。
那么,请问我如何遵守得墨忒耳法则?在这些例子中?我应该如何显示用户的姓名?它应该保存在数据库中吗?因此,当用户创建新帖子时,他的名字实际存储在posts表中?然后,如果用户点击了用户名,如果他被删除,我可以在用户#show action中进行救援ActiveRecord::RecordNotFound
?
似乎(对我来说)遵守法律的唯一方法是广泛地在数据库中写下我们需要的所有信息。所以我的创建动作看起来应该是这样的:
# post controller
def create
parameters = post_params.merge(user_name: @user.user_name)
@user = current_user
@post = @user.posts.new(parameters)
if @post.save
# redirect passed validations
else
# redirect failed validations
end
end
现在我们可以在视图中执行此操作:
<div> <%= link_to post.user_name, user_path(post.user_id) %> </div>
<div> <%= post.body %> </div>
其实,就像写作一样:
@topic.post.user_name
@topic.post.user_id
和
@topic.post.body
哪个不违反法律。看起来有点不正常的人,当我们能够轻松地使用AR(并保存整个表格列)时,项目只会变得足够复杂以便看到LoD的重要性,但我确实看到了重要性。
答案 0 :(得分:1)
正如Held所提到的,为你的Post
课程添加一个方法。我称之为author_name
。因为你的系统有用户,当然,如果你只是看一篇文章,那么问题基本上是&#34;谁写了这个?&#34;而不是&#34;我系统中的哪些用户记录与此特定帖子记录相关联?&#34;
这种间接也可以帮助解决用户删除问题:
当用户被删除时,您可以想象通过该用户的帖子,并在每个帖子上设置author_name
(或其他)属性。 E.g。
class User
# ...
before_destroy :save_name_to_posts
private
def save_name_to_posts
posts.update_all(author_name: name)
end
end
现在,在Post
模型中,你可以这样做:
# you can just use alias/alias_method for this
def author
user
end
def author_exists?
author.present?
end
def author_name
author_exists? ? user.name : super
end
因此,在您看来,您总是会有一些名称来绑定帖子。您使用author_exists?
来检查帖子的作者是否还在,所以如果您要链接到某些内容,则只需link_to
(或者您可以使用link_to_if
)< / p>
如果您不允许用户更改其名称,您当然可以立即将其添加到Post
模型中。但是,如果他们可以更改它,只有在他们即将被删除时(而不是每次更改他们的名字时)运行更新查询,效率会更高。