2012-09-13 67 views
0

我想在Rails模型的作用域(或self.func_name)中使用數組函數(特別是「keep_if」和「include?」),但不知道如何使其工作。我認爲這是可能的,因爲它看起來像一個「在哪裏」意味着「set.where」,所以「set.keep_if」將是有意義的。在Rails模型作用域定義中使用數組函數

我有一張文檔(或者說,文檔的元數據),其中每個文檔在表中有不同的版本,鏈接; doc.next_version和doc.prior_version。我有一個人的表格鏈接到文檔(通過另一個表,「作者」),所以person.documents是該人員工作的每個文檔的所有版本的列表。我想獲取每個人工作的文檔的第一個或最後一個版本,而不是/每個版本。

這是我的猜測,代碼:

class Document < ActiveRecorrd::Base 

    has_many :authors 

    belongs_to :next_version, :class_name => 'Document' 
    has_one :prior_version, :class_name => 'Document' 
    #document.document_id is the ID of the prior version of this document 

    scope :last!, lambda{ keep_if{|d| (d.next_version.nil?)||(! include?(d.next_version))}} 
    # Keep a doc if it either has no next_version (and is thus the last version in 
    # the database), or it's next version isn't in this list. 
end 

class Person < ActiveRecord::Base 
    has_many :authors 
    has_many :documents, :through => :authors 
end 

class Author > ActiveRecord::Base 
    belongs_to :person 
    belongs_to :document 
end 

#Usage Example 
documents = Person.find(id).documents.last! 
published = documents.keep_if{|d| d.published} 
success_rate = published.size/documents.size 
# etc 

我試圖轉換爲self.first!,但這並沒有幫助。 (我意識到,如果一個人跳過賬單的一個版本,這種方法不會跳過,並且會返回該文檔的兩個版本)

我期待着瞭解更多「範圍內發生了什麼「,以及如何做我想做的事情,即使它使用了完全不同的方法。

雖然我從純文本自己生成元數據,但我可以添加新的元數據字段,但我必須完成所有需要的工作。

+0

看來我的猜測是關於範圍工作是如何完全關閉的 - 他們被命名爲查詢片段,所以我需要制定一些查詢來做我想做的事情。 – Narfanator

回答

1

所以 - 這是怎麼回事:如查詢的命名片段

scopes功能;您可以使用它們來構建查詢,並且ActiveRecord會延遲評估生成的組合查詢。所以,從範圍和類方法的角度來看,Person.first.documents不是一個數組,即使它像一個從其他代碼的角度 - Person.first.documents.keep_if{...}

周圍的工作很簡單 - 只是提示AREL評估查詢並變成一個數組:

def self.last! 
    all.keep_if{...} 
#^^^ It's the "all" that does it 
end 

注意,我在這種情況下,實際的邏輯,(d.next_version.nil?)||(! all.include?(d.next_version))不工作,而我還沒有知道爲什麼。

編輯:這與'belongs_to:next_version ...'有關,而def next_version解決方法可以使事情順利進行,如果不是真正解決問題的話。

編輯2:我現在要接受這個答案,因爲它以我想要的方式得到我想要的使用代碼,但IMO/AFAIK它不是一個非常Rails的解決方案 - 所以如果你我有一個更好的,我會完全跳到那一個。

0

ActiveRecord已經有一個last!方法,這是你的重寫。我不認爲這是一個好主意。相反,我認爲會更好地以不同的方式表達您的邏輯:

class Document < ActiveRecord::Base 

    def self.published_documents 
     keep_if do |d| 
      (d.next_version.nil? || !include?(d.next_version)) && d.published 
     end 
    end 
end 

這實現了IMO之後的基本邏輯。

爲了進一步走一步,我想我還會提出這個方法Person類,因爲你是在一個人的公開文件很感興趣:

class Person < ActiveRecord::Base 

    def published_documents 
     documents.keep_if do |d| 
      (d.next_version.nil? || !documents.include?(d.next_version)) && d.published 
     end 
    end 
end 

您的使用就變成了:

Person.find(id).published_documents 
+0

第一個代碼不起作用,而第二個代碼不工作,重點在於使文檔變得更加智能,以便任何數量的其他關係都可以使用智能。你還沒有解決「這裏發生了什麼?」問題的一部分,只是概述的具體情況。 (謝謝你,順便說一下,這只是沒有幫助) – Narfanator

相關問題