You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Rails 5如何批量获取用户表中多段时间区间属性值

解决方法:动态获取时间段属性并生成哈希

Hey there! As a fellow Rails developer who started with Michael Hartl's tutorial, I totally get wanting to avoid repetitive code—great question! Here are a few clean ways to get those time slot attributes into a hash without calling each one manually:

方法1:手动定义属性列表(简单直接)

First, list out all the time slot attribute names as symbols, then loop through them to build your hash. Using send lets you call a method (in this case, the attribute getter) from a symbol:

# Define all your time slot attributes in an array
time_slot_attrs = [
  :zero_till_one, :one_till_two, :two_till_three, :three_till_four,
  :four_till_five, :five_till_six, :six_till_seven, :seven_till_eight,
  :eight_till_nine, :nine_till_ten, :ten_till_eleven, :eleven_till_twelve,
  :twelve_till_thirteen, :thirteen_till_fourteen, :fourteen_till_fifteen,
  :fifteen_till_sixteen, :sixteen_till_seventeen, :seventeen_till_eightteen,
  :eightteen_till_nineteen, :nineteen_till_twenty, :twenty_till_twentyone,
  :twentyone_till_twentytwo, :twentytwo_till_twentythree, :twentythree_till_zero
]

# Build the hash using each_with_object
time_slot_hash = time_slot_attrs.each_with_object({}) do |attr, hash|
  hash[attr] = @user.send(attr)
end

方法2:动态生成属性名(更优雅,避免重复)

Since your attributes follow a clear pattern (hour X to hour X+1, with 23 wrapping to 0), you can generate the attribute names dynamically instead of typing them all out. This is great if you ever add/remove time slots later:

# First, map numbers 0-23 to their word equivalents (matches your column names)
number_to_word = %w[
  zero one two three four five six seven eight nine ten eleven twelve
  thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty
  twentyone twentytwo twentythree
]

# Loop through 0-23 to build the hash
time_slot_hash = (0..23).each_with_object({}) do |hour, hash|
  # Get the next hour (23 wraps to 0)
  next_hour = hour == 23 ? 0 : hour + 1
  
  # Generate the attribute name as a symbol
  attr_name = "#{number_to_word[hour]}_till_#{number_to_word[next_hour]}".to_sym
  
  # Fetch the value from the user object
  hash[attr_name] = @user.send(attr_name)
end

方法3:筛选用户属性哈希(快速简便)

Rails gives every ActiveRecord object an attributes method that returns a hash of all column names and values. You can filter this hash to only keep your time slot attributes:

# Select attributes that include "_till_" (works if no other columns use this pattern)
time_slot_hash = @user.attributes.select { |key| key.include?('_till_') }

# If you prefer symbol keys instead of strings:
time_slot_hash = @user.attributes.select { |key| key.include?('_till_') }.transform_keys(&:to_sym)

小提示

  • The send method is super useful in Rails for calling methods dynamically—just pass it a symbol or string of the method name.
  • If you plan to use this logic often, consider adding it as a method in your User model to keep your controller/view code clean:
# app/models/user.rb
def time_slots_hash
  number_to_word = %w[zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree]
  (0..23).each_with_object({}) do |hour, hash|
    next_hour = hour == 23 ? 0 : hour + 1
    attr_name = "#{number_to_word[hour]}_till_#{number_to_word[next_hour]}".to_sym
    hash[attr_name] = send(attr_name)
  end
end

Then you can just call @user.time_slots_hash anywhere in your app!

内容的提问来源于stack exchange,提问作者Sebastian Peter

火山引擎 最新活动