2012-05-25 3 views
1

Мне нужно сделать запрос из массива, где каждый член массива является «как», который является ANDed. Пример:Создание запроса where в рельсах из массива

SELECT ... WHERE property like '%something%' AND property like '%somethingelse%' AND ... 

Это достаточно легко сделать, используя функцию ActiveRecord where, но я не уверен, как дезинфицировать его первым. Я, очевидно, не могу просто создать строку и использовать ее в функции where, но, похоже, нет возможности использовать ?.

Благодаря

ответ

6

Самый простой способ построить ваши LIKE шаблоны струнный интерполяции:

where('property like ?', "%#{str}%") 

и если у вас есть все ваши строки в массиве, то вы можете использовать цепочки запросов и inject ActiveRecord, чтобы построить свой окончательный запрос:

a = %w[your strings go here] 
q = a.inject(YourModel) { |q, str| q.where('property like ?', "%#{str}%") } 

Тогда вы можете q.all или q.limit(11) или что вам нужно сделать, чтобы получить окончательный результат.


Вот краткое руководство по тому, как это работает; вы должны просмотреть Active Record Query Interface Guide и Enumerable documentation.

Если у вас две вещи (a и b), чтобы соответствовать, вы можете сделать это:

q = Model.where('p like ?', "%#{a}%").where('p like ?', "%#{b}%") 

Метод where возвращает объект, который поддерживает все обычные методы запроса так что вы можете вызовы цепи, как M.where(...).where(...)..., как необходимости; другие методы запроса (например, order, limit ...) возвращает тот же вид объекта, так что вы можете цепи эти, а также:

M.where(...).limit(11).where(...).order(...) 

У вас есть ряд вещей, чтобы, как против и вы хотите применить where к классу модели, затем примените where к тому, что возвращается, затем снова, пока вы не исчерпали свой массив. Вещь, которая выглядит как петля обратной связи, как правило, требует inject (AKA reduce от "Map-Reduce" славы):

нагнетающих (начальное) {| memo, obj | Блок} → OBJ

сочетает в себе все элементы перечисления путем применения бинарную операцию, указанную в блоке или символ, что имена метода или оператора.

Если указать блок, то для каждого элемента в перечисления блок передается значение аккумулятора (памятки) и элемент [...] результат становится новым значением для памятки. В конце итерации конечное значение memo - это возвращаемое значение для метода.

Так inject принимает выход блока (который является возвращаемым значением where в нашем случае) и каналы, что в качестве входных данных для следующего выполнения блока. Если у вас есть массив, и вы inject на нем:

a = [1, 2, 3] 
r = a.inject(init) { |memo, n| memo.m(n) } 

то, что это так же, как это:

r = init.m(1).m(2).m(3) 

Или, в псевдокоде:

r = init 
for n in a 
    r = r.m(n) 
+0

Woah! Это работает! Я новичок в рельсах (и рубине), не возражаете ли вы дать мне короткое объяснение того, что здесь происходит? – MGA

+0

@Mattieu: Это помогает? Трудно объяснить функциональные вещи, которые вы используете все время, обычно есть «ага!». момент, когда вы его получите, и до этого все волшебство. –

+1

@Mattieu, Если вы не боитесь добавлять драгоценные камни, взгляните на squeel https://github.com/ernie/squeel. У этого есть удивительная функция 'like_all' /' like_any': 'queries =% w [ruby rails] .map {| s |"% # {s}% "}; Product.where {title.like_all query} '. – jdoe

0

Если вы используете AR, сделать что-то вроде Model.where(property: your_array) или Model.where("property in (?)", your_array) Таким образом, все продезинфицировать

+0

Поправьте меня, если я ошибаюсь , но разве это не будет "="? Мне нужно сделать «как» – MGA

+0

, вы правы, я думаю, что пропустил подобную часть, когда прочитал вопрос –

0

Допустим, ваш массив model_array, попробуйте массив выбрать:

model_array.select{|a|a.property=~/something/ and a.property=~/somethingelse/} 

Конечно, вы можете использовать любое регулярное выражение по своему усмотрению.

Смежные вопросы