将MySQL例程移到模型中

时间:2012-10-18 16:30:24

标签: ruby-on-rails-3

我有一个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情况,该逻辑属于模型。我不确定如何实现这一目标。我认为它应该使用一个哈希的虚拟访问器来完成。那是对的吗?如果我应该在模型之外的某个地方使用它,它应该去哪里?我不希望在答案中转换整个代码,但我非常感谢要转换的几行,以便我可以理解。谢谢!

1 个答案:

答案 0 :(得分:1)

所以,你有两个模型:有一个用户,用户有很多关联的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)

现在只有两个数据库调用,一个用于加载用户,另一个用于加载deficit_entries。