我发现下面的内容。使用条件构造where子句。红宝石有可能吗?或者我需要将它分成两个where子句?
Post
.where(tag: "A") if condition A
.where(tag: "B") if condition B
.where(user_id: 1)
.order(....)
实际上,我的情况是这样的。有办法处理吗?
def this_function
@questions = Question.joins(:comment_threads)
.tagged_with(tag_variable, wild: true, any: true) if tag_variable.present?
.where(index_where_clause)
.where("questions.created_at < ?", query_from_date_time)
.order(created_at: :desc).limit(5)
end
def index_where_clause
where_clause = {}
where_clause[:user_detail_id] = current_user_detail.id if params[:type] == "my_question"
where_clause[:comments] = {user_detail_id: current_user_detail.id} if params[:type] == "my_answer"
where_clause[:wine_question_score_id] = params[:wine_question_score_id] if params[:wine_question_score_id].present?
where_clause
end
答案 0 :(得分:2)
你正在使用的方法返回关系,所以你可以这样说:
@questions = Question.joins(:comment_threads)
@questions = @questions.where("questions.created_at < ?", query_from_date_time)
@questions = @questions.tagged_with(tag_variable, wild: true, any: true) if tag_variable.present?
@questions = @questions.where(:user_detail_id => current_user_detail.id) if params[:type] == "my_question"
@questions = @questions.where(:comments => { user_detail_id: current_user_detail.id}) if params[:type] == "my_answer"
@questions = @questions.where(:wine_question_score_id => params[:wine_question_score_id]) if params[:wine_question_score_id].present?
@questions = @questions.order(created_at: :desc).limit(5)
并根据params
中的内容逐个构建查询。
我可能会把它分解一点:
def whatever
@questions = Question.joins(:comment_threads)
@questions = @questions.where("questions.created_at < ?", query_from_date_time)
@questions = with_tag(@questions, tag_variable)
#...
@questions = @questions.order(created_at: :desc).limit(5)
end
private
def with_tag(q, tag)
if tag.present?
q.tagged_with(tag, wild: true, any: true)
else
q
end
end
#...
并以小方法掩埋所有噪音,使事物更清洁,更容易阅读。如果您不止一次这样做,那么您可以使用范围来隐藏模型类中的噪声并根据需要重新使用它。
答案 1 :(得分:1)
#tap
可以帮助修改适当的对象以应用条件逻辑,在这种情况下,对象将是您的.where
条件:
Post
.where(
{ user_id: 1 }
.tap do |conditions|
conditions[:tag] = 'A' if condition A
conditions[:tag] = 'B' if condition B
end
)
.order(...)
或者,如果你创建一个辅助方法,它可能会更清洁一些:
def specific_conditions
{ user_id: 1 }.tap do |conditions|
conditions[:tag] = 'A' if condition A
conditions[:tag] = 'B' if condition B
end
end
Post.where(specific_conditions).order(...)
但是作为旁注,如果condition A
和condition B
都可以为真,则第二条conditions[:tag] = ...
行将覆盖第一行。如果不存在两者都可以为真的情况,您可以尝试使用某种集合来查找标记的正确值。
CONDITION_TAGS = {
a: 'A'.freeze,
b: 'B'.freeze,
}.freeze
def specific_conditions
{ user_id: 1 }
.tap do |conditions|
conditions[:tag] = CONDITION_TAGS[condition_value] if condition_value
end
end
Post.where(specific_conditions).order(...)
答案 2 :(得分:1)
#in Question class
scope :with_user_detail, -> (user_detail_id, flag=true) do
where("user_detail_id = ?", user_detail_id) if flag
end
scope :with_user_detail_comments, -> (user_detail_id, flag=true) do
joins(:comment_threads).where("comments.user_detail_id = ?", user_detail_id) if flag
end
scope :with_wine_question_score, -> (wine_question_score_id) do
where("wine_question_score_id = ?", wine_question_score_id) if wine_question_score_id.present?
end
scope :tagged_with_condition, -> (tag_variable, wild, any) do
tagged_with(tag_variable, wild, any) if tag_variable.present?
end
def this_function
my_question_flag = params[:type] == "my_question"
my_answer_flag = params[:type] == "my_answer"
Question.with_user_detail(current_user_detail.id, my_question_flag)
.tagged_with_condition(tag_variable, wild: true, any: true)
.with_user_detail_comments(current_user_detail.id, my_answer_flag)
.with_wine_question_score(params[:wine_question_score_id])
.order(created_at: :desc).limit(5)
end
答案 3 :(得分:0)
您可以执行以下操作:
condition = {:tag => "A"} if condition A
condition = {:tag => "B"} if condition B
Post
.where(condition)
.where(:user_id => 1)
.order(....)
答案 4 :(得分:0)
你必须使用scope
:
scope :my_scope, -> (variable) { where(some: vatiable) if my_condition }