200'den büyük bir kimliğe sahip tüm Kullanıcıları bulmaya çalışıyorum, ancak belirli sözdiziminde bazı sorunlar yaşıyorum.
User.where(:id > 200)
ve
User.where("? > 200", :id)
her ikisi de başarısız oldu.
Baska öneri?
200'den büyük bir kimliğe sahip tüm Kullanıcıları bulmaya çalışıyorum, ancak belirli sözdiziminde bazı sorunlar yaşıyorum.
User.where(:id > 200)
ve
User.where("? > 200", :id)
her ikisi de başarısız oldu.
Baska öneri?
Yanıtlar:
Bunu dene
User.where("id > ?", 200)
?Satır içi kullanmak yerine, kullanmayı tercih etmek için herhangi bir neden var mı 200?
Bunu sadece Rails 4'te test ettim, ancak wherebu davranışı elde etmek için karma içeren bir aralık kullanmanın ilginç bir yolu var .
User.where(id: 201..Float::INFINITY)
SQL üretecek
SELECT `users`.* FROM `users` WHERE (`users`.`id` >= 201)
Aynı şey, daha az ile yapılabilir -Float::INFINITY.
Ben sadece SO burada tarihlerle bunu yapmak isteyen soran benzer bir soru yayınladı .
>= vs >İnsanları incelemek ve yorum konuşmalarını takip etmek zorunda kalmamak için burada öne çıkan özellikler vardır.
Yalnızca yukarıda yöntem oluşturur >=sorgu ve değildir bir >. Bu alternatifi ele almanın birçok yolu vardır.
Ayrık sayılar için
number_you_want + 1Kullanıcılarla ilgilendiğim id > 200ancak aslında aradığım yukarıdaki gibi bir strateji kullanabilirsiniz id >= 201. Bu, tek bir ilgi birimiyle arttırabileceğiniz tamsayılar ve sayılar için iyidir.
Sayıyı iyi adlandırılmış bir sabit haline getirdiyseniz, bu bir bakışta okunması ve anlaşılması en kolay olabilir.
Ters mantık
Biz gerçeği x > y == !(x <= y)kullanabilir ve zincir değil nerede kullanabilirsiniz.
User.where.not(id: -Float::INFINITY..200)
hangi SQL üretir
SELECT `users`.* FROM `users` WHERE (NOT (`users`.`id` <= 200))
Bu, okunması ve gerekçelendirilmesi için fazladan bir saniye sürer, ancak + 1stratejiyi kullanamayacağınız ayrık olmayan değerler veya sütunlar için işe yarayacaktır .
Arel masası
Eğer fantezi almak istiyorsanız kullanabilirsiniz Arel::Table.
User.where(User.arel_table[:id].gt(200))
SQL üretecek
"SELECT `users`.* FROM `users` WHERE (`users`.`id` > 200)"
Ayrıntılar aşağıdaki gibidir:
User.arel_table #=> an Arel::Table instance for the User model / users table
User.arel_table[:id] #=> an Arel::Attributes::Attribute for the id column
User.arel_table[:id].gt(200) #=> an Arel::Nodes::GreaterThan which can be passed to `where`
Bu yaklaşım size tam olarak ilgilendiğiniz SQL'i sağlayacaktır, ancak pek çok kişi Arel tablosunu doğrudan kullanmaz ve dağınık ve / veya kafa karıştırıcı bulabilir. Siz ve ekibiniz sizin için en iyisini bilirsiniz.
Rails 5'ten başlayarak bunu tarihlerle de yapabilirsiniz!
User.where(created_at: 3.days.ago..DateTime::Infinity.new)
SQL üretecek
SELECT `users`.* FROM `users` WHERE (`users`.`created_at` >= '2018-07-07 17:00:51')
Ruby 2.6 yayınlandıktan sonra (25 Aralık 2018) yeni sonsuz aralık sözdizimini kullanabilirsiniz! Bunun yerine 201..Float::INFINITYsadece yazabilirsiniz 201... Bu blog yazısında daha fazla bilgi .
whereeşleştiricileri kullanarak yapabileceğinize inanmıyorum . Çünkü basitlik için >bir kullanmanızı öneririz >= (number_you_want + 1). Gerçekten sadece bir >sorgu olduğundan emin olmak istiyorsanız ARel tablosuna erişebilirsiniz. Devralınan her sınıfın o sınıf için döndüren ActiveRecordbir arel_tablegetter yöntemi vardır Arel::Table. Tablodaki sütunlara []benzer yöntemle erişilir User.arel_table[:id]. Bu Arel::Attributes::Attribute, arayabileceğiniz gtve iletebileceğiniz bir döner 200. Bu daha sonra 'ya aktarılabilir where. örn User.where(User.arel_table[:id].gt(200)).
User.where(created_at: 3.days.ago..DateTime::Infinity.new).
WHERE (users.created_at >= '2016-04-09 14:31:15' AND users.created_at < #<Date::Infinity:0x00>)(SO yorum biçimlendirmesi için atlanan tablo ve sütun adlarını geri alır).
Daha sezgisel bir yazı istiyorsanız, squeel adlı bir mücevher var, bu da talimatınızı şöyle yazmanıza izin verecek:
User.where{id > 200}
'Brace' karakterlerine {} ve idsadece bir metin olduğuna dikkat edin .
Tek yapmanız gereken Gemfile'ınıza squeel eklemek:
gem "squeel"
Bu, Ruby'de karmaşık SQL ifadeleri yazarken hayatınızı çok kolaylaştırabilir.
Başka bir fantezi olasılığı ...
User.where("id > :id", id: 100)
Bu özellik, örneğin birden çok yerde değiştirmek istiyorsanız daha anlaşılır sorgular oluşturmanıza olanak tanır, örneğin ...
User.where("id > :id OR number > :number AND employee_id = :employee", id: 100, number: 102, employee: 1205)
Bu ?sorgu üzerinde bir sürü sahip daha fazla anlamı vardır ...
User.where("id > ? OR number > ? AND employee_id = ?", 100, 102, 1205)
Sık sık tarih alanlarıyla (karşılaştırma işleçlerinin çok yaygın olduğu) bu sorunu yaşıyorum.
Mihai'nin cevabı üzerinde daha ayrıntılı olarak durmak istiyorum, ki bu sağlam bir yaklaşım.
Modellere şu kapsamları ekleyebilirsiniz:
scope :updated_at_less_than, -> (date_param) {
where(arel_table[:updated_at].lt(date_param)) }
... ve daha sonra kumandanızda veya modelinizi kullandığınız her yerde:
result = MyModel.updated_at_less_than('01/01/2017')
... birleştirmelerle daha karmaşık bir örnek şöyle:
result = MyParentModel.joins(:my_model).
merge(MyModel.updated_at_less_than('01/01/2017'))
Bu yaklaşımın büyük bir avantajı (a) sorgularınızı farklı kapsamlardan oluşturmanıza olanak tanır ve (b) arel_table sorgu oluşturma işleminin bu bölümünü ele alacağından aynı tabloya iki kez katıldığınızda takma ad çarpışmalarını önler.
Rails 6.1, wherekoşullardaki karşılaştırma operatörleri için yeni bir 'sözdizimi' ekledi , örneğin:
Post.where('id >': 9)
Post.where('id >=': 9)
Post.where('id <': 3)
Post.where('id <=': 3)
Böylece sorgunuz aşağıdaki gibi yeniden yazılabilir:
User.where('id >': 200)
İşte halkla bir bağlantı Daha fazla örnek bulabilirsiniz.
Daha kısa:
User.where("id > 200")
where("id > ?", 200)sözdizimi) kullanarak SQL enjeksiyonundan kaçınmak istediğini varsayıyorum . Bu bunu başaramaz.