如何使这个ActiveRecord调用更有效与Rails 6.0.3.3和Ruby 2.7.1 &g



我的应用程序在这个例子中使用了以下模型

  • <
  • 祈祷请求/gh>
  • 杂志
  • <
  • 期刊条目/gh>

我想做的是显示在日志条目当天完成的prayer_requests和prayers的数量。我曾尝试将代码添加到模型,控制器或直接在视图中,每次它总是需要为每个条目做额外的调用时,在视图中显示它们。所以,我已经让它工作了,但是在日志的显示页面上,它做了三个db调用,只是为了到达页面(成员、配置文件和日志条目),然后为每个条目(prayer_requests和prayers)做了两个额外的调用。请求、祈祷和日志都连接到成员模型,日志条目通过日志连接到成员。必须有一种更有效的方法来实现这一点。任何关于如何改变我的模型或ActiveRecord调用的帮助将不胜感激。

<成员模型/strong>

class Member < ApplicationRecord
has_one :profile, dependent: :destroy

has_one  :prayer_journal
has_many :journal_entries, through: :prayer_journal
has_many :prayer_requests    
has_many :prayer_request_shares, foreign_key: "shared_with_id"
has_many :shared_prayer_requests, through: :prayer_request_shares, source: :prayer_request
has_many :prayers

accepts_nested_attributes_for :profile
def daily_prayer_count(date)
self.prayers.where("date(created_at) = ?", date).count
end
def daily_request_count(date)
self.prayer_requests.where("date(created_at) = ?", date).count
end
end

祷告日志模型

class PrayerJournal < ApplicationRecord
belongs_to :member
has_many :journal_entries
end

日记账模型

class JournalEntry < ApplicationRecord
belongs_to :prayer_journal
encrypts :content
validates :content, presence: true  
has_many :prayer_requests, :through => :member
has_many :prayer_request_updates, :through => :prayer_requests
has_many :prayers, :through => :member
def request_count(requests)
requests.where("date(created_at) = ?", self.created_at).count
end
def prayer_count(prayers)
prayers.where("date(created_at) = ?", self.created_at).count
end
end

<杂志控制器/strong>

class PrayerJournalsController < ApplicationController
before_action :authenticate_member
def show
@prayer_journal = current_member.prayer_journal
@journal_entries = @prayer_journal.journal_entries.group_by_day(format: "%a, %B %d, %Y", reverse: true) { |u| u.created_at }
end
end

Journal Show View

<% if @journal_entries.any? %>
<div class="row justify-content-center">
<div class="col-lg-10">
<% @journal_entries.each do |date, entries| %>
<h2 class="post-archive-item mb-3"><%= date %></h2>
<%= pluralize(daily_prayer_count(date), "prayer") given %>
<%= pluralize(daily_request_count(date), "requests") made %>
<% entries.each do |journal_entry| %>
<span class="post-archive-meta">
<span class="post-archive-meta-details">
<p class="post-archive-meta-details-date font-weight-bold mb-1">
<span class="convert-utc-to-time-zone align-middle" style="text-decoration: underline;"><%= journal_entry.created_at %></span>
<%= link_to "Edit", edit_journal_entry_path(journal_entry), class: 'badge badge-pill badge-primary' %>
</p>
</span>
</span>
<%= simple_format(journal_entry.content) %>          
<% end %>
<hr class="my-5" />
<% end %>
</div>
</div>
<% else %>
<div class="text-center">
<p class="lead">Create your first Journal Entry</p>
<%= link_to 'New Journal Entry', new_journal_entry_path, class: "btn btn-primary", style:"color:white;" %>
</div>
<% end %>

我想你在这里只是选择聚合而不是急于加载。

class JournalEntry < ApplicationRecord
has_one :member, though: :prayer_journal
def self.with_prayer_count(date)
prayers = Prayer.arel_table
subquery = Prayer.arel_table.then do |prayers|
prayers.project(prayers[Arel.star].count)
.where(
prayers['member_id'].eq('members.id').and(
prayers['date'].eq(date)
)
)
.as('prayer_count')
end
joins(:member)
.select(
arel_table[Arel.star],
subquery 
)
end
end

这个例子使用了一个子查询:

(SELECT COUNT(prayers.*) FROM prayers WHERE prayers.member_id = members.id AND prayers.date = ?) AS prayer_count

根据您使用的RDBMS,可能有其他方法,如窗口函数或横向连接来实现相同的目标。

相关内容

  • 没有找到相关文章

最新更新