Ruby on rails Setter方法可以';初始化回调后看不到子内置父级
一封电子邮件有许多变体(用于ab测试),并且始终有一个设置为主版本 我想确保电子邮件总是有一个基于初始化的主变量 我还想将attr访问器“subject”和“body”委托给主变量 我最初尝试使用Ruby on rails Setter方法可以';初始化回调后看不到子内置父级,ruby-on-rails,associations,Ruby On Rails,Associations,一封电子邮件有许多变体(用于ab测试),并且始终有一个设置为主版本 我想确保电子邮件总是有一个基于初始化的主变量 我还想将attr访问器“subject”和“body”委托给主变量 我最初尝试使用 delegate :subject, :body, to: :master 但rails抱怨master为零 因此,我尝试手动滚动我自己的subject=setter方法,通过pry我发现,虽然在after_initialize回调中设置了我的master,但对subject=complaints
delegate :subject, :body, to: :master
但rails抱怨master为零
因此,我尝试手动滚动我自己的subject=setter方法,通过pry我发现,虽然在after_initialize回调中设置了我的master,但对subject=complaints master的后续调用是nil。我不明白为什么
class Email < ActiveRecord::Base
has_one :master,
-> { where is_master: true },
class_name: 'Tinycourse::Variant',
dependent: :destroy,
inverse_of: :email
def subject=(str)
master.subject = str # Rails says master is nil here
end
#
# Callbacks
#-----------------------------------------
after_initialize :ensure_master
def ensure_master
return unless new_record?
self.master ||= build_master
end
end
Email.new(:subject => 'yah') # undefined method `subject=' for nil:NilClass
class电子邮件{师父:真的在哪里},
类名:“Tinycourse::Variant”,
依赖::破坏,
电子邮件的反作用
def subject=(str)
master.subject=str#Rails说这里的master为零
结束
#
#回调
#-----------------------------------------
初始化后:确保\u主控
def确保_主机
除非有新的记录,否则返回?
self.master | |=构建主控
结束
结束
Email.new(:subject=>'yah')#nil:NilClass的未定义方法'subject='
当您的电子邮件实例被初始化时,您的主机
为零,您需要在设置任何内容之前触发构建主机
那么:
# app/models/email.rb
class Email < ActiveRecord::Base
def subject=(str)
master.subject = str # Rails says master is nil here
end
def master
super || build_master
end
end
…这是另一个用于持久化记录的变体
更新
甚至更好
# app/models/email.rb
class Email < ActiveRecord::Base
has_one :master,
-> { where is_master: true },
class_name: 'Tinycourse::Variant',
dependent: :destroy,
inverse_of: :email
end
# app/lib/email_builder.rb
class EmailBuilder
attr_reader :args, :subject
def self.build(args={})
new(args).build
end
def initialize(args)
@subject = args.fetch(:subject)
@args = args
end
def build
email = Email.new args
email.build_master
email.master.subject = subject
email
end
end
email = EmailBuilder.build subject: 'yah'
email.class # => Email
#app/models/email.rb
类电子邮件{师父:真的在哪里},
类名:“Tinycourse::Variant”,
依赖::破坏,
电子邮件的反作用
结束
#app/lib/email_builder.rb
类电子邮件生成器
属性读取器:args,:subject
def self.build(args={})
新建(args)。生成
结束
def初始化(args)
@subject=args.fetch(:subject)
@args=args
结束
def构建
email=email.new args
email.build\u master
email.master.subject=主题
电子邮件
结束
结束
email=EmailBuilder.build主题:“耶”
email.class#=>电子邮件
Email.new正在初始化实例,您在初始化后有一个,
所以我认为这就是它不起作用的原因。如果你做了e=Email.new
那么e.subject='yah'
,它能工作吗?如果我在new之后设置,它能工作。但是,如果我在after_initialize和setter方法中放置pry,那么首先pry在after_initialize处停止,然后它在setter处停止。所以,如果这是命令,大师是建立的,为什么二传看不到它?我不认为这是命令虽然。我认为它试图在初始化时设置它,这将是在构建主程序之前……这样,您将在模型之外提取业务逻辑,使您的模型更轻,测试更快更容易。
# app/models/email.rb
class Email < ActiveRecord::Base
has_one :master,
-> { where is_master: true },
class_name: 'Tinycourse::Variant',
dependent: :destroy,
inverse_of: :email
end
# app/lib/email_builder.rb
class EmailBuilder
attr_reader :args, :subject
def self.build(args={})
new(args).build
end
def initialize(args)
@subject = args.fetch(:subject)
@args = args
end
def build
email = Email.new args
email.build_master
email.master.subject = subject
email
end
end
email = EmailBuilder.build subject: 'yah'
email.class # => Email