Rails 5 API - 使用来自 belongs_to 关联模型的值在 has_one 的一侧设置默认值
Rails 5 API - setting default values on the one side of a has_one using values from the belongs_to associated model
This question 似乎是 Stack Overflow 上关于设置模型默认值的最多 voted/relevant 问题。尽管探索了多种方法,但其中 none 涵盖了这个问题。
请注意,这是一个 API - 因此提醒的默认文本必须由 api 提供,因此我将其存储在数据库中。有些用户希望使用该默认值,有些用户会更新它。
这是我的代码,但感觉不对,因为我必须在 'parent'(User
模型中设置默认值之一(:body
) ).
class User < ActiveRecord::Base
# Relationships
belongs_to :account
has_one :reminder
before_create :build_default_reminder
private
def build_default_reminder
build_reminder(body: get_default_body)
end
def get_default_body
<<~HEREDOC
This is a quick reminder about the outstanding items still on your checklist.
Thank you,
#{self.name}
HEREDOC
end
end
class Reminder < ApplicationRecord
# Relationships
belongs_to :user
# Default attributes
attribute :is_follow_up, :boolean, default: true
attribute :subject, :string, default: "your checklist reminder!"
attribute :greeting, :string, default: "Hi"
end
我更愿意做的是这样,以便所有默认值都在同一模型中(child):
class User < ActiveRecord::Base
# Relationships
belongs_to :account
has_one :reminder
end
class Reminder < ApplicationRecord
# Relationships
belongs_to :user
# Default attributes
attribute :is_follow_up, :boolean, default: true
attribute :subject, :string, default: "your checklist reminder!"
attribute :greeting, :string, default: "Hi"
attribute :body, :string, default:
<<~HEREDOC
This is a quick reminder about the outstanding items still on your checklist.
Thank you,
#{self.user.name}
HEREDOC
end
但这当然会引发错误:
undefined method `user' for #<Class:0x007fa59d4d0f90>
问题的出现是因为默认的:body
字符串必须包含用户名。有没有办法实现这一点 - 即。在 reminder
模型中拥有所有默认值,但不知何故引用了创建它的用户?
我认为这很棘手这一事实可能表明您可能想要稍微重新设计一下。特别是,您似乎将模型逻辑与视图逻辑混合在一起。
您可以通过将实际创建字符串的逻辑移动到更靠近它要呈现的位置(ERB 文件、电子邮件模板等)来解决此问题。然后,当您传入要为其生成字符串的 Reminder
实例时,调用 @reminder.user.name
的代码将起作用,因为 @reminder
的 .user
关联不起作用空白。
I think the fact that this is tricky may be an indication that you
might want to redesign this a little bit. In particular, it looks like
you're mixing model logic with view logic.
这是@Adam Berman 的中肯观察。所以它已经重新设计 - 在@MrYoshiji 的评论的帮助下,谢谢大家!
我认为以下是更好且更易于维护的解决方案,尤其是当应用程序确实需要能够提供这些默认英文文本的实际翻译时 - 因此我还将创建 custom_greeting
和 custom_subject
这两个属性。
class User < ActiveRecord::Base
# Relationships
belongs_to :account
has_one :reminder
end
class Reminder < ApplicationRecord
# Relationships
belongs_to :user
# Default attributes
attribute :subject, :string, default: "your checklist reminder!"
attribute :greeting, :string, default: "Hi"
def body=(value)
self.custom_body = value
end
def body
custom_body.presence || I18n.t('reminder.default_body', name: self.user.name)
end
end
en.yml 文件:
reminder:
default_body: "\nThis is a quick reminder about the outstanding items still on your checklist.\
\nPlease click the button below to review the items we're still waiting on.\
\nThank you,\
\n%{name}"
(this question 对 yml 中的 multi-line 文本帮助很大)
(this question 有助于理解 getter/setter - 请参阅@pascal betz 中有关存储价格的答案)
This question 似乎是 Stack Overflow 上关于设置模型默认值的最多 voted/relevant 问题。尽管探索了多种方法,但其中 none 涵盖了这个问题。
请注意,这是一个 API - 因此提醒的默认文本必须由 api 提供,因此我将其存储在数据库中。有些用户希望使用该默认值,有些用户会更新它。
这是我的代码,但感觉不对,因为我必须在 'parent'(User
模型中设置默认值之一(:body
) ).
class User < ActiveRecord::Base
# Relationships
belongs_to :account
has_one :reminder
before_create :build_default_reminder
private
def build_default_reminder
build_reminder(body: get_default_body)
end
def get_default_body
<<~HEREDOC
This is a quick reminder about the outstanding items still on your checklist.
Thank you,
#{self.name}
HEREDOC
end
end
class Reminder < ApplicationRecord
# Relationships
belongs_to :user
# Default attributes
attribute :is_follow_up, :boolean, default: true
attribute :subject, :string, default: "your checklist reminder!"
attribute :greeting, :string, default: "Hi"
end
我更愿意做的是这样,以便所有默认值都在同一模型中(child):
class User < ActiveRecord::Base
# Relationships
belongs_to :account
has_one :reminder
end
class Reminder < ApplicationRecord
# Relationships
belongs_to :user
# Default attributes
attribute :is_follow_up, :boolean, default: true
attribute :subject, :string, default: "your checklist reminder!"
attribute :greeting, :string, default: "Hi"
attribute :body, :string, default:
<<~HEREDOC
This is a quick reminder about the outstanding items still on your checklist.
Thank you,
#{self.user.name}
HEREDOC
end
但这当然会引发错误:
undefined method `user' for #<Class:0x007fa59d4d0f90>
问题的出现是因为默认的:body
字符串必须包含用户名。有没有办法实现这一点 - 即。在 reminder
模型中拥有所有默认值,但不知何故引用了创建它的用户?
我认为这很棘手这一事实可能表明您可能想要稍微重新设计一下。特别是,您似乎将模型逻辑与视图逻辑混合在一起。
您可以通过将实际创建字符串的逻辑移动到更靠近它要呈现的位置(ERB 文件、电子邮件模板等)来解决此问题。然后,当您传入要为其生成字符串的 Reminder
实例时,调用 @reminder.user.name
的代码将起作用,因为 @reminder
的 .user
关联不起作用空白。
I think the fact that this is tricky may be an indication that you might want to redesign this a little bit. In particular, it looks like you're mixing model logic with view logic.
这是@Adam Berman 的中肯观察。所以它已经重新设计 - 在@MrYoshiji 的评论的帮助下,谢谢大家!
我认为以下是更好且更易于维护的解决方案,尤其是当应用程序确实需要能够提供这些默认英文文本的实际翻译时 - 因此我还将创建 custom_greeting
和 custom_subject
这两个属性。
class User < ActiveRecord::Base
# Relationships
belongs_to :account
has_one :reminder
end
class Reminder < ApplicationRecord
# Relationships
belongs_to :user
# Default attributes
attribute :subject, :string, default: "your checklist reminder!"
attribute :greeting, :string, default: "Hi"
def body=(value)
self.custom_body = value
end
def body
custom_body.presence || I18n.t('reminder.default_body', name: self.user.name)
end
end
en.yml 文件:
reminder:
default_body: "\nThis is a quick reminder about the outstanding items still on your checklist.\
\nPlease click the button below to review the items we're still waiting on.\
\nThank you,\
\n%{name}"
(this question 对 yml 中的 multi-line 文本帮助很大)
(this question 有助于理解 getter/setter - 请参阅@pascal betz 中有关存储价格的答案)