最近作ってるサービスで、
利用可能日を月〜金,日みたいな風に表示する必要があったので、やり方をまとめてみる。
お店のオープン日や、貸し出し系のサービスなどで使えるかなーと思います。
こんな感じに表示します。
やり方としてはDBには文字列として
"0,2,3,4,6"
こんな感じで保存して表示の際に表記を日本語にする感じです。
DBとView(入力)
id | name | open_days |
---|---|---|
1 | "ショップA" | "0,2,3,4,6" |
2 | "ショップB" | "0,1,2,3,4,6" |
テーブルはこんな感じで、Shopテーブルに曜日を文字列で持てるようにしておきます。
<% 7.times do |i| %>
<%= check_box_tag "shop[open_days][]", i, false, {id: "open_days_#{i}"} %>
<label for="open_days_<%=i%>"><%= I18n.t('date.abbr_day_names')[i] %></label>
<% end %>
で、viewでこんな感じでやってやればいいと思います。
<% 7.times do |i| %>
<% if @shop.open_days.match(/#{i}/) %>
<% match = true %>
<% else %>
<% match = false %>
<% end %>
<%= check_box_tag "shop[open_days][]", i, match, {id: "open_days_#{i}"} %>
<label for="open_days_<%=i%>" class=""><%= I18n.t('date.abbr_day_names')[i] %></label>
<% end %>
editの時は@shop.open_daysに正規表現で都度対応する曜日の数字をmatchさせて結果を変数に突っ込んで、check_box_tagのcheckedプロパティを設定してやるといいと思います。
Controller
@shop.available_date = shop_params[:open_days].join(",")
private
def shop_params
params.require(:shop).permit(
:name,open_days: []
)
end
strong_parametersに追加して、
コントローラで受け取った値を,つなぎの文字列に整形して保存します。
View(表示)
あとはshop.open_daysの値を整形して表示するのみです。
def nums_to_num_range(str)
nums = str.split(',').map { |i| i.to_i }.uniq.sort
nums.inject([[nums.shift]]) { |r, s|
if r.last.last.succ == s
r.last << s
else
r << [s]
end
r
}.map { |i|
if i.size == 1
i.first
elsif i.size == 2
[i.first, i.last].join(',')
elsif i.size > 1
[i.first, i.last].join('~')
end
}.join(',')
end
def replace_num_in_str_to_day_names(str)
str.gsub(/\d/) {|num| I18n.t('date.abbr_day_names')[num.to_i] }
end
"0,2,3,4,5"のようなカンマ区切りの文字列を"0,2~4,6"のような範囲形式っぽいものに整形するメソッドと
nums_to_num_rangeで整形した文字列の数字部分を曜日に変換するメソッドをhelperに定義してやって、viewで呼び出せば完了です。