简体   繁体   English

Ruby on Rails:如果表值在指定范围之间,则返回名称

[英]Ruby on Rails: Return name if table value is between a specified range

I have three tables (that are relevant to this problem). 我有三个表(与此问题相关)。 One table is called organizations. 一个表称为组织。

I also have a table called organization_details, which contains organization_id and multi-row information about the organization. 我还有一个名为organization_details的表,其中包含有关组织的organization_id和多行信息。

I work in the event industry, so the organization_details table contains a column called total_attendance, where a person can input an integer of the org's attendance for a certain year. 我在事件行业工作,因此organization_details表包含一个名为total_attendance的列,其中一个人可以输入组织某一年的出勤率的整数。

The third table is called divisions. 第三个表称为分区。 This has five rows total, with columns division_smallest and division_largest (referring to the attendance range). 这总共有五行,其中列division_smallest和division_largest(指出勤范围)。 Each row has a range to separate which division an organization should belong to according to their most recent attendance record. 每行都有一个范围,用于根据组织最近的出勤记录将组织应属于哪个部门。

For example, one row in the division table shows a division_smallest equal to 1 and a division_largest equal to 100000 (again, referring to attendance). 例如,除法表中的一行表示division_smallest等于1,division_largest等于100000(再次表示出勤)。 Finally, the division table also has a name column (eg "Division 1"). 最后,除法表还有一个名称列(例如“Division 1”)。

I want the app to automatically figure out which division an organization belongs to according to their most recent total_attendance. 我希望应用程序根据最近的total_attendance自动确定组织所属的部门。 Ideally, the division's name would display in the organization index and show pages. 理想情况下,分部的名称将显示在组织索引和显示页面中。

I'd like to make a custom method for this, but am unsure how best to tackle it. 我想为此制作一个自定义方法,但我不确定如何最好地解决它。 I've read a little bit about .between? 我读了一下。之间的内容? as in (possibly) .between?(division.division_smallest, division.division_largest) return "#{division.name}" 如(可能).between?(division.division_smallest,division.division_largest)返回“#{division.name}”

...But I am not sure how the entire method would work or if I need to steer away from that entirely. ......但我不确定整个方法是如何工作的,或者我是否需要完全避开它。 I would greatly appreciate any insight into this! 我非常感谢对此的任何见解!

My suggestion is to add the following method to organization.rb 我的建议是将以下方法添加到organization.rb

def division_name
  last_details = organization_details.order('created_at DESC').first
  if last_details.present?
    Division.where(':attendance >= division_smallest AND :attendance <= division_largest', attendance: last_details.attendance).first.name
  else
    "None"
  end
end

The code first grabs the organization details that have been created most recently. 代码首先获取最近创建的组织详细信息。 If the organization has organization details it uses the attendance value to select the appropriate division and it returns that division's name. 如果组织有组织详细信息,则使用出勤值选择适当的部门,并返回该部门的名称。 If the organization doesn't have any organization_details it returns the string "None". 如果组织没有任何organization_details,则返回字符串“None”。 You may also want to handle the case where the attendance isn't inside of the range on any of the divisions you have defined. 您可能还希望处理出勤率不在您定义的任何部门范围内的情况。

I hope this points you in the right direction. 我希望这能指出你正确的方向。

A naive implementation might look something like this: 一个天真的实现可能看起来像这样:

class Division
  def self.for_attendance(total)
    first('? BETWEEN divisions.division_smallest AND divisions.division_largest', total)
  end
end

class Organization
  def latest_division
    Division.for_attendance(organization_details.last.try(:total_attendance))
  end
end

Now calling some_organization.latest_division will pull the latest division for that organization . 现在调用some_organization.latest_division将拉出该组织的最新部门。 This is great for a 'show' page, but will run you into trouble when you have an 'index' with many Organizations - these 2 queries will need to run for each Organization (an N+1 problem). 这对于“显示”页面非常有用,但是如果您拥有包含许多组织的“索引”,则会遇到麻烦 - 这两个查询需要针对每个组织运行(N + 1问题)。 Instead use this: 而是使用这个:

class Division
  def self.merge_latest!(organizations)
    left_join = "LEFT JOIN organization_details od2 ON organization_details.organization_id = od2.organization_id AND organization_details.created_at < od2.created_at"
    subquery = OrganizationDetails.where(organization_id: organizations.map(&:id)).
       joins(left_join).
       where(od2: {id: nil}).to_sql
    divisions = joins("#{subquery} as t ON t.total_attendance  divisions.division_smallest AND divisions.division_largest").
                select('divisions.*, t.organization_id')
    organizations.each {|org| org.latest_division = divisions.detect{|d| d.organization_id == org.id}
  end
end

def Organization
  attr_accessor :latest_division
end

Now you can call Division.merge_latest!(organizations) to collect the latest division for all the organizations in a single query, addressable via an organization's :latest_division attribute. 现在,您可以调用Division.merge_latest!(organizations)在单个查询中收集所有组织的最新部门,可通过组织的:latest_division属性进行寻址。

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

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