【问题标题】:Obtain the average of the ages of a model - Ruby on Rails获取模型的平均年龄 - Ruby on Rails
【发布时间】:2021-08-27 22:13:45
【问题描述】:

下午好。我是 ruby​​ 新手,正在尝试构建我的第一个应用程序。 我正在使用 sqlite 数据库和 rails 5.0。 我有一个名为 Person 的模型,它具有名字、姓氏和出生日期作为属性。 在我列出人员的页面上,我要添加人员的年龄并获取人员的平均年龄

我的控制器如下所示:

  before_action :set_persona, only: %i[ show edit update destroy ]

  # GET /personas or /personas.json
  def index
    @persona = Persona.order("cast(strftime('%m', fecha_nacimiento) as integer)")
  end 

我的看法是这样的


<table>
  <thead>
    <tr>
      <th>Nombre</th>
      <th>Apellido</th>
      <th>Fecha nacimiento</th>
      <th>Dni</th>
      <th>Edad</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @persona.each do |persona| %>
      <tr>
        <td><%= persona.nombre %></td>
        <td><%= persona.apellido %></td>
        <td><%= persona.fecha_nacimiento %></td>
        <td><%= persona.dni %></td>
        <td><%= Time.now.year - persona.fecha_nacimiento.year %></td>
        <td><%= link_to 'Detail', persona %></td>
        <td><%= link_to 'Edit', edit_persona_path(persona) %></td>
      </tr>
    <% end %>
  </tbody>
</table>
  <p>El promedio de edad de las personas es: </p>

由于我在数据库中没有名为“年龄”的字段,我无法理解如何获得结果。 目标是遍历每个人并将其除以长度,还是有更简单的方法?

请原谅我的无知,非常感谢您。

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

    你要做的是选择你的计算列并给它一个别名:

      def index
        @persona = Persona.select(
             Persona.arel_table[Arel.star], # personas.*
             "cast(strftime('%m', fecha_nacimiento) as integer) as age"
           )
           .order(age: :desc)
      end 
    

    您选择的任何列都将在生成的模型实例中作为属性使用:

    <table>
      <thead>
        <tr>
          <th>Nombre</th>
          <th>Apellido</th>
          <th>Fecha nacimiento</th>
          <th>Dni</th>
          <th>Edad</th>
          <th colspan="3"></th>
        </tr>
      </thead>
    
      <tbody>
        <% @persona.each do |persona| %>
          <tr>
            <td><%= persona.nombre %></td>
            <td><%= persona.apellido %></td>
            <td><%= persona.fecha_nacimiento %></td>
            <td><%= persona.dni %></td>
            <td><%= persona.age %></td>
            <td><%= link_to 'Detail', persona %></td>
            <td><%= link_to 'Edit', edit_persona_path(persona) %></td>
          </tr>
        <% end %>
      </tbody>
    </table>
    

    【讨论】:

    • 不要在模型中做所有那些骇人听闻的事情,只需使用"cast(strftime('%m', fecha_nacimiento) as integer) as age",直到您切换到像 Postgres 这样的真实数据库,它实际上具有日期和时间列以及用于处理日期差异的函数。在 PG 上,您只需使用 AGE(NOW(), 'birth_date') 之类的东西。
    【解决方案2】:

    实现您所要求的最简单方法是在视图中执行操作。这种破坏MVC但它是最快的。

    <% edades = 0 %>
    <% @persona.each do |persona| %>
    <% edades += Time.now.year - persona.fecha_nacimiento.year %>
    <!-- ... the rest of the view code -->
    <% end %>
    <% average = edades.to_d / @persona.length # need to typecast to decimal so you can have fractionals %>
    

    要以 MVC 方式执行此操作,您必须在控制器中进行计算。

      def index
        @persona = Persona.order("cast(strftime('%m', fecha_nacimiento) as integer)")
        @average = @persona.collect { |p| Time.now.year - p.fecha_nacimiento.year }.sum / @persona.length.to_d
      end 
    

    Person 模型中实现age 方法会更容易,因此您只需调用该方法即可。

    class Person
      def edad
        Time.now.year - fecha_nacimiento.year
      end
    end
    

    最后,年龄的计算比当前年份减去生日年份更复杂。我们使用这个函数(取自https://stackoverflow.com/a/2357790/365218)来计算年龄。

    def age(dob)
      now = Time.now.utc.to_date
      now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
    end
    

    【讨论】:

    • 如果投反对票的人解释了他们投反对票的原因,那就太好了,这样我就可以改进这个答案。
    猜你喜欢
    • 1970-01-01
    • 2021-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-04
    • 1970-01-01
    • 1970-01-01
    • 2020-04-23
    相关资源
    最近更新 更多