0

我有一个 PHP 驱动的网站,我正在转换为 Rails。我目前在 MySQL 例程中有以下逻辑。

DECLARE FirstWeighinDate DATE;
DECLARE FirstWeighinWeight DECIMAL(5,1);
DECLARE MostRecentWeighinDate DATE;
DECLARE MostRecentWeighinWeight DECIMAL(5,1);
DECLARE NumberOfWeighins INT(11);
DECLARE NumberOfDeficitRecords INT(11);
DECLARE AverageDeficit INT(11);
DECLARE UserHeight INT(11);
DECLARE MostRecentBMI DECIMAL(5,1);

SELECT date INTO FirstWeighinDate FROM tblDeficitEntries WHERE weight IS NOT NULL AND user_id = inUserId ORDER BY date ASC LIMIT 1;
SELECT weight INTO FirstWeighinWeight FROM tblDeficitEntries WHERE weight IS NOT NULL AND user_id = inUserId ORDER BY date ASC LIMIT 1;
SELECT date INTO MostRecentWeighinDate FROM tblDeficitEntries WHERE weight IS NOT NULL AND user_id = inUserId ORDER BY date DESC LIMIT 1;
SELECT weight INTO MostRecentWeighinWeight FROM tblDeficitEntries WHERE weight IS NOT NULL AND user_id = inUserId ORDER BY date DESC LIMIT 1;
SELECT Height INTO UserHeight FROM tblLogins WHERE id = inUserId LIMIT 1;
SELECT COUNT(id) INTO NumberOfWeighins FROM tblDeficitEntries WHERE weight IS NOT NULL AND user_id = inUserId;
SELECT COUNT(id) INTO NumberOfDeficitRecords FROM tblDeficitEntries WHERE user_id = inUserId;
SELECT (SUM(deficit) / NumberOfDeficitRecords) INTO AverageDeficit FROM tblDeficitEntries WHERE user_id = inUserId;
SELECT ((MostRecentWeighinWeight * 703) / (UserHeight * UserHeight)) INTO MostRecentBMI;

SELECT FirstWeighinDate, FirstWeighinWeight, MostRecentWeighinDate, MostRecentWeighinWeight, NumberOfWeighins, NumberOfDeficitRecords, AverageDeficit, MostRecentBMI;

我相信在 MVC 情况下,该逻辑属于模型。我不确定如何实现这一目标。我在想应该用一个散列的虚拟访问器来完成。那是对的吗?如果我应该在模型之外的某个地方拥有这个,它应该去哪里?我不希望在答案中转换整个代码,但我非常感谢要转换的几行代码,以便我能理解。谢谢!

4

1 回答 1

1

因此,您有两个模型:有一个 User,并且该 User 具有许多关联的 Entry 对象。

class User < ActiveRecord::Base
  has_many :entries
end

class Entry < ActiveRecord::Base
  belongs_to :user
  #attributes include weight, date
end

那么,这些值呢?

我认为您想要做的最基本的方法是使用关联的模型将所有这些转换为您的用户模型上的方法。

例如,

SELECT date INTO FirstWeighinDate FROM tblDeficitEntries WHERE weight IS NOT NULL AND user_id = inUserId ORDER BY date ASC LIMIT 1;

可以在 User 类中替换为以下内容:

def first_weighin_date
  entries.order('date asc').first.date
end

然后,在任何有 User 对象的地方,您都可以简单地调用该方法:

u = User.find_by_name('Bob')
u.first_weighin_date

现在,如果您要同时向许多用户显示此信息,您将需要利用预加载。例如,这将是非常低效的:

User.all.map(&:first_weigh_in_date)

它将单独调用数据库以加载每个用户对象的关联条目。100 个用户?101 个数据库命中。所以告诉 Rails 继续加载所有对象,因为您将需要它们:

User.includes(:entries).map(&:first_weigh_in_date)

现在对数据库只有两次调用,一次加载用户,一次加载definition_entries。

于 2012-10-18T17:05:48.333 回答