Rails:用块重构代码
Rails: refactor code with blocks
我使用 Rails 4.2,我想重构我的辅助方法以去除重复代码:
在app/helpers/admin/tasks_helper.rb
def chosen_select(name, method, chzes, selected = nil, options = {}, html_options = {})
options[:value_method] ||= :id
options[:text_method] ||= :name
if options.key?(:placeholder)
html_options['data-placeholder'.intern] = options[:placeholder]
options.delete(:placeholder)
end
if html_options.key?(:class)
html_options[:class] = 'chosen-select ' + html_options[:class]
else
html_options[:class] = 'chosen-select'
end
chzes = options_from_collection_for_select(chzes, options[:value_method], options[:text_method], selected)
options.delete(:value_method)
options.delete(:text_method)
select(name, method, chzes, options.merge!(include_hidden: false), html_options)
end
def chosen_select_array(name, method, chzes, selected = nil, options = {}, html_options = {})
options[:value_method] ||= :id
options[:text_method] ||= :name
if options.key?(:placeholder)
html_options['data-placeholder'.intern] = options[:placeholder]
options.delete(:placeholder)
end
if html_options.key?(:class)
html_options[:class] = 'chosen-select ' + html_options[:class]
else
html_options[:class] = 'chosen-select'
end
chzes = options_for_select(chzes, selected)
options.delete(:value_method)
options.delete(:text_method)
select(name, method, chzes, options.merge!(include_hidden: false), html_options)
end
我认为我有很多方法调用,例如 app/views/admin/tasks/index。html.erb
<%= chosen_select(:select, :project_id, [TaskFilterOptgroups.active_projects, TaskFilterOptgroups.inactive_projects] , @task_filter_configuration.project_id, {:include_blank => true, :placeholder => 'Project'}, {'data-last-project_id' => @task_filter_configuration.project_id, :style => 'width: 150px;'}) %>
这样我就不想更改视图中的方法调用。
我的尝试是制作一个通用方法 "chosen_select_generic" ,它将从特定方法调用,例如 "chosen_select":
def chosen_select_generic(name, method, chzes, selected = nil, options = {}, html_options = {})
options[:value_method] ||= :id
options[:text_method] ||= :name
if options.key?(:placeholder)
html_options['data-placeholder'.intern] = options[:placeholder]
options.delete(:placeholder)
end
if html_options.key?(:class)
html_options[:class] = 'chosen-select ' + html_options[:class]
else
html_options[:class] = 'chosen-select'
end
# 2 different chzes in 2 methods:
# 1) chosen_select(...)
# chzes = options_from_collection_for_select(chzes, options[:value_method], options[:text_method], selected)
# 2) chosen_select_array(...)
# chzes = options_for_select(chzes, selected)
yield chzes
options.delete(:value_method)
options.delete(:text_method)
select(name, method, chzes, options.merge!(include_hidden: false), html_options)
end
然后 chosen_select 可能看起来像:
def chosen_select(name, method, chzes, selected = nil, options = {}, html_options = {})
chosen_select_generic(name, method, chzes, selected = nil, options = {}, html_options = {}) do |contents|
chzes = option_groups_from_collection_for_select(chzes, :entries, :status, options[:value_method], options[:text_method], selected)
end
end
但这不起作用。如何在不更改视图中的方法调用的情况下提取块中的重复代码?
你块中的这个作业不会按照你的想法去做:
chzes = option_groups_from_collection_for_select(...)
它创建一个新的局部变量而不是改变外部变量。如果它是这里唯一可以改变的部分,那么你可以 return 它来自块:
chosen_select_generic(name, method, chzes, selected = nil, options = {}, html_options = {}) do |chzes|
option_groups_from_collection_for_select(chzes, :entries, :status, options[:value_method], options[:text_method], selected)
end
然后像这样在您的通用方法中接收值:
chzes = yield(chzes)
我使用 Rails 4.2,我想重构我的辅助方法以去除重复代码:
在app/helpers/admin/tasks_helper.rb
def chosen_select(name, method, chzes, selected = nil, options = {}, html_options = {})
options[:value_method] ||= :id
options[:text_method] ||= :name
if options.key?(:placeholder)
html_options['data-placeholder'.intern] = options[:placeholder]
options.delete(:placeholder)
end
if html_options.key?(:class)
html_options[:class] = 'chosen-select ' + html_options[:class]
else
html_options[:class] = 'chosen-select'
end
chzes = options_from_collection_for_select(chzes, options[:value_method], options[:text_method], selected)
options.delete(:value_method)
options.delete(:text_method)
select(name, method, chzes, options.merge!(include_hidden: false), html_options)
end
def chosen_select_array(name, method, chzes, selected = nil, options = {}, html_options = {})
options[:value_method] ||= :id
options[:text_method] ||= :name
if options.key?(:placeholder)
html_options['data-placeholder'.intern] = options[:placeholder]
options.delete(:placeholder)
end
if html_options.key?(:class)
html_options[:class] = 'chosen-select ' + html_options[:class]
else
html_options[:class] = 'chosen-select'
end
chzes = options_for_select(chzes, selected)
options.delete(:value_method)
options.delete(:text_method)
select(name, method, chzes, options.merge!(include_hidden: false), html_options)
end
我认为我有很多方法调用,例如 app/views/admin/tasks/index。html.erb
<%= chosen_select(:select, :project_id, [TaskFilterOptgroups.active_projects, TaskFilterOptgroups.inactive_projects] , @task_filter_configuration.project_id, {:include_blank => true, :placeholder => 'Project'}, {'data-last-project_id' => @task_filter_configuration.project_id, :style => 'width: 150px;'}) %>
这样我就不想更改视图中的方法调用。 我的尝试是制作一个通用方法 "chosen_select_generic" ,它将从特定方法调用,例如 "chosen_select":
def chosen_select_generic(name, method, chzes, selected = nil, options = {}, html_options = {})
options[:value_method] ||= :id
options[:text_method] ||= :name
if options.key?(:placeholder)
html_options['data-placeholder'.intern] = options[:placeholder]
options.delete(:placeholder)
end
if html_options.key?(:class)
html_options[:class] = 'chosen-select ' + html_options[:class]
else
html_options[:class] = 'chosen-select'
end
# 2 different chzes in 2 methods:
# 1) chosen_select(...)
# chzes = options_from_collection_for_select(chzes, options[:value_method], options[:text_method], selected)
# 2) chosen_select_array(...)
# chzes = options_for_select(chzes, selected)
yield chzes
options.delete(:value_method)
options.delete(:text_method)
select(name, method, chzes, options.merge!(include_hidden: false), html_options)
end
然后 chosen_select 可能看起来像:
def chosen_select(name, method, chzes, selected = nil, options = {}, html_options = {})
chosen_select_generic(name, method, chzes, selected = nil, options = {}, html_options = {}) do |contents|
chzes = option_groups_from_collection_for_select(chzes, :entries, :status, options[:value_method], options[:text_method], selected)
end
end
但这不起作用。如何在不更改视图中的方法调用的情况下提取块中的重复代码?
你块中的这个作业不会按照你的想法去做:
chzes = option_groups_from_collection_for_select(...)
它创建一个新的局部变量而不是改变外部变量。如果它是这里唯一可以改变的部分,那么你可以 return 它来自块:
chosen_select_generic(name, method, chzes, selected = nil, options = {}, html_options = {}) do |chzes|
option_groups_from_collection_for_select(chzes, :entries, :status, options[:value_method], options[:text_method], selected)
end
然后像这样在您的通用方法中接收值:
chzes = yield(chzes)