简体   繁体   English

哈希/数组到活动记录

[英]Hash/Array to Active Record

I have been searching everywhere but I can't seem to find this problem anywhere. 我到处都在搜索,但似乎在任何地方都找不到此问题。 In Rails 5.0.0.beta3 I need to sort a my @record = user.records with an association and it's record. 在Rails 5.0.0.beta3中,我需要使用关联及其记录对@record = user.records进行排序。 The sort goes something like this. 排序是这样的。

@record = @record.sort_by { |rec| 
If user.fav_record.find(rec.id)
  User.fav_record(rec.id).created_at
Else 
  rec.created_at
End

This is just an example of what I do. 这只是我所做的一个例子。 But everything sorts fine. 但是一切都很好。

The problem: This returns an array and not an Active Record Class. 问题:这将返回一个数组,而不是一个Active Record类。

I've tried everything to get this to return an Active Record Class. 我已经尽一切努力使它返回Active Record类。 I've pushed the sorted elements into an ID array and tried to extract it them in that order, I've tried mapping. 我已将排序后的元素推入ID数组,并尝试按该顺序将它们提取出来,我尝试了映射。 Every result that I get turns my previous active record into an array or hash. 我得到的每个结果都将以前的活动记录转换为数组或哈希。 Now I need it to go back into an active record. 现在,我需要它返回活动记录。 Does anyone know how to convert an array or hash of that active record back into an Active Record class? 有谁知道如何将活动记录的数组或哈希转换回活动记录类?

There isn't a similarly easy way to convert ActiveRecord to array. 没有类似的简单方法可以将ActiveRecord转换为数组。

If you want to optimize the performance of your app, you should try to avoid converting arrays to ActiveRecord queries. 如果要优化应用程序的性能,则应尽量避免将数组转换为ActiveRecord查询。 Try and keep the object as a query as long as possible. 尝试使对象尽可能长地作为查询。

That being said, working with arrays is generally easier than queries, and it can feel like a hassle to convert a lot of array operations to ActiveRecord query (SQL) code. 话虽这么说,使用数组通常比查询更容易,并且将许多数组操作转换为ActiveRecord查询(SQL)代码似乎很麻烦。

It'd be better to write the sort code using ActiveRecord::Query methods or even writing it in plain SQL using find_by_sql . 最好使用ActiveRecord :: Query方法编写sort代码,甚至最好使用find_by_sql在普通SQL中编写sort代码。

I don't know what code you should specifically use here, but I do see that your code could be refactored to be clearer. 我不知道您应该在此处专门使用什么代码,但是我确实看到可以将您的代码重构为更加清晰。 First of all, If and Else should not be capitalized, but I'm assuming that this is just pseudocode and you already realize this. 首先, IfElse不应大写,但是我假设这只是伪代码,您已经意识到这一点。 Second, your variable names should be pluralized if they are queries or arrays (ie @record.sort_by should be @records.sort_by instead). 其次,如果变量名是查询或数组,则变量名应为复数形式(即@record.sort_by应该改为@records.sort_by )。

It's worth mentioning that ActiveRecord queries are difficult to master and a lot of people just use array operations instead since they're easier to write. 值得一提的是,ActiveRecord查询很难掌握,并且很多人只使用数组操作,因为它们更易于编写。 If "premature optimization is the root of all evil", it's really not the end of the world if you sacrifice a bit of performance and just keep your array implementation if you're just trying to make an initial prototype. 如果“过早的优化是万恶之源”,那么如果您牺牲了一些性能,而只是想制作一个初始原型,那么就保留数组实现,那实际上不是世界末日。 Just make sure that you're not making "n+1" SQL calls, ie do not make a database call every iteration of your loop. 只要确保您没有进行“ n + 1”次SQL调用,即不要在循环的每次迭代中都进行数据库调用。

Here's an example of an array implementation which avoids the N+1 SQL issue: 这是避免N + 1 SQL问题的数组实现示例:

# first load all the user's favorites into memory
user_fav_records = user.fav_records.select(:id, :created_at)
@records = @records.sort_by do |record|
  matching_rec = user.fav_records.find { |x| x.id.eql?(rec.id) }
  # This is using Array#find, not the ActiveRecord method
  if matching_rec
    matching_rec.created_at
  else 
    rec.created_at
  end
end

The main difference between this implementation and the code in your question is that I'm avoiding calling ActiveRecord's find each iteration of the loop. 此实现与您所询问的代码之间的主要区别在于,我避免了调用ActiveRecord来find循环的每次迭代。 SQL read/writes are computationally expensive, and you want your code to make as little of them as possible. SQL读/写在计算上是昂贵的,并且您希望您的代码使它们尽可能少。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM