如何重构一个简单的长案例语句
How to refactor a simple long case statement
所以我为我的 Sinatra 项目创建了一个下拉表单,我希望它能预填充选项。我能够做到这一点,但它变成了一个大案例陈述!任何想法如何重构这个?谢谢!
get '/animes/:id/edit' do
if is_logged_in?
@anime = Anime.find_by_id(params[:id])
case @anime.rating
when 1
@oneselect = "selected"
when 2
@twoselect = "selected"
when 3
@threeselect = "selected"
when 4
@fourselect = "selected"
when 5
@fiveselect = "selected"
when 6
@sixselect = "selected"
when 7
@sevenselect = "selected"
when 8
@eightselect = "selected"
when 9
@nineselect = "selected"
when 10
@tenselect = "selected"
end
erb :'animes/edit'
else
redirect to '/'
end
end
这是我的 .erb 查看文件表格!
<label for="rating">Rating:</label>
<select name="rating" id="rating" value="<%=@anime.rating%>">
<option value="10"<%=@tenselect%>>10 (Masterpiece)</option>
<option value="9"<%=@nineselect%>>9 (Great)</option>
<option value="8"<%=@eightselect%>>8 (Very Good)</option>
<option value="7"<%=@sevenselect%>>7 (Good)</option>
<option value="6"<%=@sixselect%>>6 (Fine)</option>
<option value="5"<%=@fiveselect%>>5 (Average)</option>
<option value="4"<%=@fourselect%>>4 (Bad)</option>
<option value="3"<%=@threeselect%>>3 (Very Bad)</option>
<option value="2"<%=@twoselect%>>2 (Horrible)</option>
<option value="1"<%=@oneselect%>>1 (Appalling)</option>
</select><br>
抱歉,我对 Sinatra 一无所知,所以这个答案可能有误。
如果我自己查看这段代码,我会按照类似的思路进行思考(未测试,我的 erb 有点生疏):
<label for="rating">Rating:</label>
<%
options = [
[10, '10 (Masterpiece)'],
[9, '9 (Great)'],
[8, '8 (Very Good)'],
[7, '7 (Good)'],
[6, '6 (Fine)'],
[5, '5 (Average)'],
[4, '4 (Bad)'],
[3, '3 (Very Bad)'],
[2, '2 (Horrible)'],
[1, '1 (Appalling)']
]
%>
<select name="rating" id="rating">
<% options.each do |option| %>
<option value="<%= option[0].to_s %>"<%= @anime.rating == option[0] ? ' selected' : '' %>><%= option[1] %></option>
<% end %>
</select><br>
然后删除 case 语句。
有用的对象可能是从数字评分到其字符串表示的映射:
@ratings_map = {
1 => "1 (Appalling)",
2 => "2 (Horrible)",
3 => "3 (Very Bad)",
etc...
}
无需为每个评分(@oneselect、@twoselect 等)传递一个单独的变量,您只需使用@anime 本身作为所选值即可。然后,您可以使用 options_for_select 辅助函数:
<label for="rating">Rating:</label>
<%= options_for_select(@ratings_map.map{|key, value| [value, key]}, @anime.rating) %>
一些关于 options_for_select 助手的有用文档:
https://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/options_for_select
编辑:
抱歉,我的头在 Rails 土地上。如果您使用的是 Sinatra,则必须在 Sinatra 应用程序的顶部显式 require 'active_support'
才能使此解决方案起作用。您还需要确保 active_support 包含在您的 Gemfile 中,并且 bundle install
所以我为我的 Sinatra 项目创建了一个下拉表单,我希望它能预填充选项。我能够做到这一点,但它变成了一个大案例陈述!任何想法如何重构这个?谢谢!
get '/animes/:id/edit' do
if is_logged_in?
@anime = Anime.find_by_id(params[:id])
case @anime.rating
when 1
@oneselect = "selected"
when 2
@twoselect = "selected"
when 3
@threeselect = "selected"
when 4
@fourselect = "selected"
when 5
@fiveselect = "selected"
when 6
@sixselect = "selected"
when 7
@sevenselect = "selected"
when 8
@eightselect = "selected"
when 9
@nineselect = "selected"
when 10
@tenselect = "selected"
end
erb :'animes/edit'
else
redirect to '/'
end
end
这是我的 .erb 查看文件表格!
<label for="rating">Rating:</label>
<select name="rating" id="rating" value="<%=@anime.rating%>">
<option value="10"<%=@tenselect%>>10 (Masterpiece)</option>
<option value="9"<%=@nineselect%>>9 (Great)</option>
<option value="8"<%=@eightselect%>>8 (Very Good)</option>
<option value="7"<%=@sevenselect%>>7 (Good)</option>
<option value="6"<%=@sixselect%>>6 (Fine)</option>
<option value="5"<%=@fiveselect%>>5 (Average)</option>
<option value="4"<%=@fourselect%>>4 (Bad)</option>
<option value="3"<%=@threeselect%>>3 (Very Bad)</option>
<option value="2"<%=@twoselect%>>2 (Horrible)</option>
<option value="1"<%=@oneselect%>>1 (Appalling)</option>
</select><br>
抱歉,我对 Sinatra 一无所知,所以这个答案可能有误。
如果我自己查看这段代码,我会按照类似的思路进行思考(未测试,我的 erb 有点生疏):
<label for="rating">Rating:</label>
<%
options = [
[10, '10 (Masterpiece)'],
[9, '9 (Great)'],
[8, '8 (Very Good)'],
[7, '7 (Good)'],
[6, '6 (Fine)'],
[5, '5 (Average)'],
[4, '4 (Bad)'],
[3, '3 (Very Bad)'],
[2, '2 (Horrible)'],
[1, '1 (Appalling)']
]
%>
<select name="rating" id="rating">
<% options.each do |option| %>
<option value="<%= option[0].to_s %>"<%= @anime.rating == option[0] ? ' selected' : '' %>><%= option[1] %></option>
<% end %>
</select><br>
然后删除 case 语句。
有用的对象可能是从数字评分到其字符串表示的映射:
@ratings_map = {
1 => "1 (Appalling)",
2 => "2 (Horrible)",
3 => "3 (Very Bad)",
etc...
}
无需为每个评分(@oneselect、@twoselect 等)传递一个单独的变量,您只需使用@anime 本身作为所选值即可。然后,您可以使用 options_for_select 辅助函数:
<label for="rating">Rating:</label>
<%= options_for_select(@ratings_map.map{|key, value| [value, key]}, @anime.rating) %>
一些关于 options_for_select 助手的有用文档: https://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/options_for_select
编辑:
抱歉,我的头在 Rails 土地上。如果您使用的是 Sinatra,则必须在 Sinatra 应用程序的顶部显式 require 'active_support'
才能使此解决方案起作用。您还需要确保 active_support 包含在您的 Gemfile 中,并且 bundle install