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 where
bu 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 + 1
Kullanıcılarla ilgilendiğim id > 200
ancak 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 + 1
stratejiyi 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::INFINITY
sadece yazabilirsiniz 201..
. Bu blog yazısında daha fazla bilgi .
where
eş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 ActiveRecord
bir arel_table
getter yöntemi vardır Arel::Table
. Tablodaki sütunlara []
benzer yöntemle erişilir User.arel_table[:id]
. Bu Arel::Attributes::Attribute
, arayabileceğiniz gt
ve 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 id
sadece 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, where
koş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.