2017-07-23 52 views
0

我的应用程序创建一个QuoteRequest目标对象时保存该对象的分贝我想它来创建一个Quote.new对象(QuoteRequesthas_oneQuote)。在一个新的Quote比如我要设置一些实例变量,这关系到的Watir履带各种方法来用,那么的Watir爬&刮将#save从而持续的报价对象到数据库的结果。我应该如何在ApplicationRecord对象上设置初始化实例变量?

我想尽快设置Quote实例变量在initialize方法的对象被创建,但这是它从ApplicationRecord继承此有一个初始化冲突的事实产生的问题。

什么是实例变量与一个ApplicationRecord对象,不与Rails库初始化代码矛盾的正确方法是什么?

+0

这两个真正有用的答案,谢谢你们。希望我能接受两个答案,但是因为我不能,所以我不得不接受M.西蒙博格斯的解释提供了很长的时间,尽管维杰是一个非常好的答案。再次感谢维杰,下次再见。 – jbk

回答

1

如果你只是想设置一个实例变量没有在初始化任何额外的逻辑则维杰的回答是一个很好的一个。但是,您可以拥有更多的灵活性,而不仅限于attr方法。

与所有的红宝石,你总是可以利用super如果你保持正确的接口超级方法。 ActiveRecord::Base#initialize只需要一个可选参数,即属性和值的hash。如果给出一个块,它也会自动产生一个块。 https://github.com/rails/rails/blob/master/activerecord/lib/active_record/core.rb#L313

所以,如果你想设置在初始化实例变量还没有定义任何公共接入方式,您可以:

class Quote < ApplicationRecord 
    def initialize(attributes = nil, &block) 
    @my_var = attributes.delete(:my_var) if attributes 
    super 
    end 
end 

quote = Quote.new(my_var: 'value') 
quote.instance_variable_get(:@my_var) # => "value" 

您还可以执行更复杂的操作。假设你有User has_many :postsPost belongs_to :userUser:namePost:title

class User < ApplicationRecord 
    def initialize(attributes = nil, &block) 
    title = attributes.delete(:first_post_title) if attributes 
    super 
    posts.build(title: "#{name}'s first post: #{title}") if title 
    end 
end 

user = User.new(first_post_title: 'Hello, world!', name: 'Matz') 
user.posts.first # => #<Post:xxxxxxxxxxx title: "Matz's first post: Hello, world!"> 

希望这演示如何灵活的是,即使ActiveRecord对象,有时可能回调是有点实施过于复杂和限制性在使用时如果使用得当super可以工作得很好,甚至更好。

+0

@ m-simon-borg,我仍然在努力用'expected 0'来实例化。 .1'参数错误,我完全按照您在初始化方法中的建议,但使用以下变量; '@username = attributes.delete(:username)if attributes'和'@password = attributes.delete(:password)if attributes'和'@url = attributes.delete(:url)if attributes'然后在调用'super'之后变量声明。 – jbk

+0

@jbk你的代码是什么样的? “ArgumentError”还说了些什么? '预计0..1,收到???'如果你的方法声明是'def initialize(attributes = nil,&block)',那么你应该不带任何参数地调用'super'。还要确保你的'Quote.new'调用使用哈希语法,就像你会另外'Quote.new(用户名:“...”,密码:“...”,网址:“...”)'。如果你想把它放在Gist并链接到它,我会很高兴看到。另外Vijay的答案可能就是你所需要的所有答案 –

+0

对不起,m-simon-borg,在我的最后一个愚蠢的语法错误,现在这个超级初始化方法工作得很好谢谢。 – jbk

1

对于Quote的属性,您不想保存在数据库中,请创建attr_reader(或attr_accessor)。假设你的Watir方法需要var1var2对象,那么你的Quote应该是这样的:

class Quote < ApplicationRecord 
    attr_reader :var1, :var2 
end 

然后在after_create回调QuoteRequest你应该简单地通过这些变量作为键值对像任何其他财产。现在

obj1 = Var1.new 
obj2 = Var2.new 
quote = Quote.new(var1: obj1, var2: obj2, ....)` 

您可以通过调用quote.var1quote.var2访问这些。呼吁quotesave将坚持所有这些都有相应的列分贝除了var1var2属性。

+0

在上面的上下文中,如果我为他们创建了列,'Quote.save'上的'var1'和'var2'是否会被持久化到db? – jbk

+0

如果你有var1和var2的列,那么你不需要添加这一行: 'attr_reader:var1,:var2' –

+0

aha,所以id在模型模式中定义了一列,然后rails自动添加'attr_accessor'? – jbk