2017-07-23 57 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