Last active
August 29, 2015 14:15
-
-
Save rossmari/8bea8b06d9e224e0b580 to your computer and use it in GitHub Desktop.
Refactoring example [02]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# === BEFORE REFACTORING | |
# problems : include russian text, include translation, include unused code | |
#encoding: utf-8 | |
class SearchOption < ActiveRecord::Base | |
has_no_table | |
column :include, :string | |
column :field_name, :string | |
column :text, :string | |
column :state, :string | |
column :mood_id, :integer | |
OPERATIONS = {eql: '=', neql: '!=', include: 'LIKE'} | |
HUMAN_OPERATIONS = {eql: 'равно', neql: 'не равно', include: 'похоже на'} | |
COLUMN_CONTROLS = {text: :value, state: :relation, mood_id: :relation} | |
RELATED_MODELS = {mood_id: Mood} | |
def self.get_related_models(column) | |
if column == :state | |
states = Publishing::Publication::Base.state_machine.states.map(&:name) | |
return states.map{|state| {name: I18n.t("PublicationStates.#{state.to_s}"), id: state} } | |
end | |
model = RELATED_MODELS[column] | |
model.all.map{|i| {id: i.id, name: i.name}} | |
end | |
# параметры объявления по которым разрешен параметризованный поиск | |
SEARCH_COLUMNS = {state: 'Статус', text: 'Текст', mood_id: 'Настроение'} | |
def self.search_columns | |
SEARCH_COLUMNS.map{|c| [c[1], c[0]]} | |
end | |
def self.operations_with_human_labels | |
operations = [] | |
OPERATIONS.keys.each do |key| | |
operations << [HUMAN_OPERATIONS[key], key] | |
end | |
operations | |
end | |
end | |
# === AFTER REFACTORING | |
# remove all translation and russian code , move them into presenter class | |
# add procs to define different queries (solve problem with LIKE query) | |
# include generation of query logic in this class | |
class ParametrizeSearcher < ActiveRecord::Base | |
# no table model to store and process custom search | |
has_no_table | |
column :include, :string | |
column :field_name, :string | |
# параметры объявления по которым разрешен параметризованный поиск | |
SEARCH_COLUMNS = [ :state, :text, :mood_id ] | |
# поддерживаемые операции сравнения | |
OPERATIONS = [:equal, :not_equal, :include] | |
SEARCH_PROCS = { equal: ->(param, value){"#{param} = '#{value}'"}, | |
not_equal: ->(param, value){"#{param} != #{value}"}, | |
include: ->(param, value){"#{param} ILIKE '%#{value}%'"} | |
} | |
# construct search query from array of sub queries containing operation_type (proc), column and value | |
def self.construct_query(options) | |
query = Publishing::Publication::Base | |
options.each do |option| | |
proc = SEARCH_PROCS[option['include'].to_sym] | |
param = option['field_name'] | |
value = option['value_field'] | |
query = query.where(proc.call(param, value)) | |
end | |
return query | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# === AFTER REFACTORING | |
# this class was added to store logic of translation and data presentation | |
class ParametrizeSearchPresenter | |
# to set relation between column and form control type | |
COLUMN_CONTROLS = {text: :value, state: :relation, mood_id: :relation} | |
class << self | |
def search_columns | |
ParametrizeSearcher::SEARCH_COLUMNS.map{|c| [I18n.t("parametrize_searcher.columns.#{c}"), c]} | |
end | |
def operations_with_human_labels | |
ParametrizeSearcher::OPERATIONS.map{|o| [I18n.t("parametrize_searcher.operations.#{o}"), o.to_s]} | |
end | |
def available_values(column) | |
case column | |
when :state | |
states = Publishing::Publication::Base.state_machine.states.map(&:name) | |
states.map{|state| {name: I18n.t("PublicationStates.#{state.to_s}"), id: state} } | |
when :mood_id | |
Mood.all.map{|i| {id: i.id, name: i.name}} | |
else | |
nil | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# === AFTER REFACTORING | |
# yml translation file now include all translations | |
ru: | |
parametrize_searcher: | |
columns: | |
state: Статус объявления | |
text: Текст объявления | |
mood_id: Настроение объявления | |
operations: | |
equal: Равно | |
not_equal: Не равно | |
include: Похоже на |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# === BEFORE REFACTORING | |
# problems: to fat, include logic for query generation | |
# problems: cant create query "column LIKE '%value%'" (row 9) | |
def find | |
options = params[:search_query][:search_options_attributes].map{|s| s[1]}.select{|s| s['_destroy'] == 'false'} | |
query = Publishing::Publication::Base | |
options.each do |option| | |
operator = SearchOption::OPERATIONS[option['include'].to_sym] | |
query = query.where("#{option['field_name']} #{operator} '#{option['value_field']}'") | |
end | |
@users = query.map{|p| p.user}.uniq.compact | |
@users_count = @users.count | |
@notification = ArchiveEmail.new() | |
end | |
# === AFTER REFACTORING | |
# use ParametrizeSearcher.construct_query() to create query | |
def find | |
# remove deleted rows from nested attributes | |
options = params[:search_query][:parametrize_searchers_attributes].map{|s| s[1]}.select{|s| s['_destroy'] == 'false'} | |
query = ParametrizeSearcher.construct_query(options) | |
@users = query.map{|p| p.user}.uniq.compact | |
@users_count = @users.count | |
@notification = ArchiveEmail.new() | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment