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
sendmethod 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
Usermodel 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




