2011-06-27 64 views
2

我想這種方法轉換爲範圍,軌道,所以我可以調用類似Batch.all_completed,它會返回在該方法中符合條件的所有批次:轉換方法的範圍中的Rails 3

def all_completed? 
    articles.with_status('Completed').count >= project.articles_per_week 
end 

批次的類定義,這將是運行的是:

class Batch < ActiveRecord::Base 
    has_many :articles 
    belongs_to :project 

有沒有辦法簡單地做到這一點? with_status是一個命名的範圍,而articles_per_week是一種不是字段的方法。這裏是左側的SQL輸出:

SELECT "articles".* FROM "articles" join jobs on jobs.article_id = articles.id join statuses on statuses.id = jobs.status_id WHERE ("articles".batch_id = XXX) AND (statuses.description = 'Completed') 

謝謝!

+0

對不起,我並不清楚 - 你想要什麼從批號爲#返回all_completed? – Yardboy

+0

我希望它返回批處理的所有實例,滿足方法中的條件 –

回答

0

[編輯2]

鑑於articles_per_week不是一個領域,但一個方法,你必須放棄範圍chainability - 歸結範圍只是AREL產生一個SQL語句,沒有辦法彌合實例方法和數據庫之間的差距。在這一點上,其實事情變得更加容易,你可以直接使整個事情一類的方法,並在最後以呼叫#reject砸不符合計數標準的:

class Batch < ActiveRecord::Base 
    belongs_to :project 
    has_many :articles 

    def self.all_completed 
    joins(:articles). 
    includes(:project). 
    where("articles.status = 'Completed'"). 
    group("batches.id"). 
    select("batches.*, count(articles.id) as article_count"). 
    reject {|batch| batch.article_count.to_i < batch.project.articles_per_week} 
    end 
end 

而且,你仍然可以通過這個(2)獲得最小的DB命中。但是,如前所述,調用#reject會將您的輸出轉換爲基本的對象數組,而不是可鏈接的ActiveRecord集合。

不知道爲什麼我不得不將物品數量轉換爲整數,但事實確實如此。

我已經離開了我的以前的版本,因爲我認爲他們提供了其他情況的好的附加信息。

[編輯1]

這裏是你可以把上批一個範圍的版本,所以它的可鏈接到其他領域。

scope :all_completed, 
    joins(:articles, :project). 
    where("articles.status = 'Completed'"). 
    having("count(articles.id) >= projects.articles_per_week"). 
    group("batches.id"). 
    select("batches.*, projects.articles_per_week") 

我在測試這一點,它可以對一些標準的ActiveRecord的方法產生影響注意。例如,#size不起作用,因爲在ActiveRecord上被轉換爲SELECT COUNT(*),並且由於所選字段中缺少projects.articles_per_week,在這裏不起作用。

[原創]

我在這裏的第一個答案。

我不確定這是否符合您的「簡單」請求,但它在一個SQL語句中完成任務。

Article.includes([:batch => :project]).where(:status => 'Completed').group(:batch_id).having("count(articles.id) >= projects.articles_per_week").map(&:batch) 

這是假設的Rails 3和下面的模型設置:

class Batch < ActiveRecord::Base 
    has_many :articles 
    belongs_to :project 
end 

class Project < ActiveRecord::Base 
    has_many :batches 
end 

class Article < ActiveRecord::Base 
    belongs_to :batch 
end 

順便說一句,這是我的測試數據。在結構上正確地拉批次1和2,而忽視一批3.

-- phpMyAdmin SQL Dump 
-- version 3.3.2deb1 
-- http://www.phpmyadmin.net 
-- 
-- Host: localhost 
-- Generation Time: Jun 27, 2011 at 07:13 PM 
-- Server version: 5.1.41 
-- PHP Version: 5.3.2-1ubuntu4.9 

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; 

-- 
-- Database: `stack_development` 
-- 

-- -------------------------------------------------------- 

-- 
-- Table structure for table `articles` 
-- 

DROP TABLE IF EXISTS `articles`; 
CREATE TABLE IF NOT EXISTS `articles` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `batch_id` int(11) DEFAULT NULL, 
    `name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `status` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `created_at` datetime DEFAULT NULL, 
    `updated_at` datetime DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=16 ; 

-- 
-- Dumping data for table `articles` 
-- 

INSERT INTO `articles` (`id`, `batch_id`, `name`, `status`, `created_at`, `updated_at`) VALUES 
(1, 1, 'Test 1 Article', 'Completed', '2011-06-27 22:38:55', '2011-06-27 22:38:55'), 
(2, 1, 'Test 2 Article', 'Completed', '2011-06-27 22:40:36', '2011-06-27 22:40:36'), 
(3, 1, 'Test 3 Article', 'Completed', '2011-06-27 22:40:42', '2011-06-27 22:40:42'), 
(4, 1, 'Test Article 4', 'Completed', '2011-06-27 22:38:55', '2011-06-27 22:38:55'), 
(5, 1, 'Test Article 5', 'Pending', '2011-06-27 22:38:55', '2011-06-27 22:38:55'), 
(6, 2, 'Test 1 Article', 'Completed', '2011-06-27 22:38:55', '2011-06-27 22:38:55'), 
(7, 2, 'Test 2 Article', 'Completed', '2011-06-27 22:40:36', '2011-06-27 22:40:36'), 
(8, 2, 'Test 3 Article', 'Completed', '2011-06-27 22:40:42', '2011-06-27 22:40:42'), 
(9, 2, 'Test Article 4', 'Pending', '2011-06-27 22:38:55', '2011-06-27 22:38:55'), 
(10, 2, 'Test Article 5', 'Pending', '2011-06-27 22:38:55', '2011-06-27 22:38:55'), 
(11, 3, 'Test 1 Article', 'Completed', '2011-06-27 22:38:55', '2011-06-27 22:38:55'), 
(12, 3, 'Test 2 Article', 'Completed', '2011-06-27 22:40:36', '2011-06-27 22:40:36'), 
(13, 3, 'Test 3 Article', 'Pending', '2011-06-27 22:40:42', '2011-06-27 22:40:42'), 
(14, 3, 'Test Article 4', 'Pending', '2011-06-27 22:38:55', '2011-06-27 22:38:55'), 
(15, 3, 'Test Article 5', 'Pending', '2011-06-27 22:38:55', '2011-06-27 22:38:55'); 

-- -------------------------------------------------------- 

-- 
-- Table structure for table `batches` 
-- 

DROP TABLE IF EXISTS `batches`; 
CREATE TABLE IF NOT EXISTS `batches` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `project_id` int(11) DEFAULT NULL, 
    `name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `created_at` datetime DEFAULT NULL, 
    `updated_at` datetime DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=4 ; 

-- 
-- Dumping data for table `batches` 
-- 

INSERT INTO `batches` (`id`, `project_id`, `name`, `created_at`, `updated_at`) VALUES 
(1, 1, 'Test 1 Batch', '2011-06-27 22:38:11', '2011-06-27 22:38:11'), 
(2, 2, 'Test 2 Batch', '2011-06-27 22:38:11', '2011-06-27 22:38:11'), 
(3, 3, 'Test 3 Batch', '2011-06-27 22:38:11', '2011-06-27 22:38:11'); 

-- -------------------------------------------------------- 

-- 
-- Table structure for table `projects` 
-- 

DROP TABLE IF EXISTS `projects`; 
CREATE TABLE IF NOT EXISTS `projects` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `articles_per_week` int(11) DEFAULT NULL, 
    `created_at` datetime DEFAULT NULL, 
    `updated_at` datetime DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=4 ; 

-- 
-- Dumping data for table `projects` 
-- 

INSERT INTO `projects` (`id`, `name`, `articles_per_week`, `created_at`, `updated_at`) VALUES 
(1, 'Test 1 project', 3, '2011-06-27 22:37:11', '2011-06-27 22:37:11'), 
(2, 'Test 2 Project', 3, '2011-06-27 22:37:21', '2011-06-27 22:37:21'), 
(3, 'Test 3 Project', 3, '2011-06-27 22:37:21', '2011-06-27 22:37:21'); 
+0

這看起來像一個非常好的開始。但是,有一點小問題:articles_per_week是一種方法。它看起來像這樣:'def articles_per_week (!articles_per_period.blank?&&!frequency_period.blank?)? articles_per_period *(1.week.to_i/frequency_period).to_i:nil end' –

+0

Urgh,我發現那裏 - 在一讀時(第二,第三等)錯過了更新以符合此要求。 – Yardboy

+0

圍場 - 這真棒。謝謝你的幫助!! –