রেলস: যেখানে স্টেটমেন্টের চেয়ে তার চেয়ে বেশি / কম ব্যবহার করা হচ্ছে


142

আমি 200 এর বেশি আইডি সহ সমস্ত ব্যবহারকারীকে সন্ধান করার চেষ্টা করছি, তবে নির্দিষ্ট সিনট্যাক্স নিয়ে আমার কিছুটা সমস্যা হচ্ছে।

User.where(:id > 200) 

এবং

User.where("? > 200", :id) 

উভয়ই ব্যর্থ হয়েছে।

কোনও পরামর্শ?

উত্তর:


276

এটা চেষ্টা কর

User.where("id > ?", 200) 

1
এছাড়াও আর্নি মিলার থেকে স্কুয়েল রত্নটি দেখুন
cpuguy83

7
?ইনলাইনিংয়ের পরিবর্তে ব্যবহারকে পছন্দ করার কোনও কারণ আছে কি 200?
ডেভেটপ্লে

20
এটি স্বয়ংক্রিয়ভাবে ২০০ পালিয়ে যায় (যদি ব্যবহারকারীটির জন্য মান প্রবেশ করা সম্ভব হত তবে এটি এসকিউএল ইনজেকশন হামলার সম্ভাবনা
এড়ায়

124

আমি কেবল এটি 4 রেলগুলিতে পরীক্ষা করেছি তবে whereএই আচরণটি পেতে হ্যাশ সহ একটি পরিসর ব্যবহার করার একটি আকর্ষণীয় উপায় রয়েছে ।

User.where(id: 201..Float::INFINITY)

এসকিউএল উত্পন্ন করবে

SELECT `users`.* FROM `users`  WHERE (`users`.`id` >= 201)

একই চেয়ে কম জন্য করা যেতে পারে -Float::INFINITY

আমি এখানে এসও-তে তারিখগুলি সহ এটি করার বিষয়ে জিজ্ঞাসা করে একটি অনুরূপ প্রশ্ন পোস্ট করেছি ।

>= বনাম >

লোকেদের এড়াতে এবং মন্তব্যগুলির কথোপকথনটি অনুসরণ করতে এখানে হাইলাইট are

উপরের পদ্ধতিটি কেবল একটি >=কোয়েরি উত্পন্ন করে না a >। এই বিকল্পটি পরিচালনা করার অনেক উপায় রয়েছে are

পৃথক সংখ্যার জন্য

আপনি number_you_want + 1উপরের মতো কৌশল ব্যবহার করতে পারেন যেখানে আমি ব্যবহারকারীদের সাথে আগ্রহী id > 200কিন্তু বাস্তবে সন্ধান করব id >= 201। এটি পূর্ণসংখ্যার এবং সংখ্যার জন্য সূক্ষ্ম যেখানে আপনি একক একক আগ্রহের দ্বারা বৃদ্ধি করতে পারবেন।

যদি আপনার নামটি একটি নামযুক্ত ধ্রুবক থেকে বের করা থাকে তবে এটি এক নজরে পড়তে ও বুঝতে সহজ হতে পারে।

উল্টানো যুক্তি

আমরা এটি ব্যবহার করতে পারি x > y == !(x <= y)এবং চেইন নয় যেখানে ব্যবহার করতে পারি।

User.where.not(id: -Float::INFINITY..200)

যা এসকিউএল উত্পন্ন করে

SELECT `users`.* FROM `users` WHERE (NOT (`users`.`id` <= 200))

এটি পড়ার জন্য এবং যুক্তিতে অতিরিক্ত সেকেন্ড লাগে তবে নন বিযুক্ত মূল্য বা কলামগুলির জন্য কাজ করবে যেখানে আপনি + 1কৌশলটি ব্যবহার করতে পারবেন না ।

আরেল টেবিল

আপনি অভিনব পেতে চাই আপনি ব্যবহার করতে পারেন Arel::Table

User.where(User.arel_table[:id].gt(200))

এসকিউএল উত্পন্ন করবে

"SELECT `users`.* FROM `users` WHERE (`users`.`id` > 200)"

সুনির্দিষ্টভাবে নিম্নরূপ:

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`

এই পদ্ধতির সাহায্যে আপনার সঠিক আগ্রহী এসকিউএল পাবেন তবে অনেকেই সরাসরি আরেল টেবিলটি ব্যবহার করেন না এবং এটি অগোছালো এবং / বা বিভ্রান্তিকর খুঁজে পেতে পারেন। আপনার এবং আপনার দলটি জানবে যে আপনার পক্ষে সেরা।

বোনাস

5 কারাগারে শুরু করে আপনি খেজুর দিয়েও এটি করতে পারেন!

User.where(created_at: 3.days.ago..DateTime::Infinity.new)

এসকিউএল উত্পন্ন করবে

SELECT `users`.* FROM `users` WHERE (`users`.`created_at` >= '2018-07-07 17:00:51')

ডাবল বোনাস

একবার রুবি ২. Once প্রকাশিত হলে (ডিসেম্বর 25, 2018) আপনি নতুন অসীম পরিসরের সিনট্যাক্সটি ব্যবহার করতে সক্ষম হবেন! পরিবর্তে 201..Float::INFINITYআপনি কেবল লিখতে সক্ষম হবেন 201..এই ব্লগ পোস্টে আরও তথ্য ।


3
কেন এটি কৌতূহলের বাইরে গ্রহণযোগ্য উত্তরের চেয়ে শ্রেষ্ঠ?
মেক্যাম্পবেলসপ 21

5
সুপরিয়র বিভ্রান্তিকর হয়। আপনি যদি স্ট্রিংগুলিতে হ্যাশ সিনট্যাক্স ব্যবহার করতে সক্ষম হন তবে সাধারণভাবে আপনি আপনার আরেল প্রশ্নের সাথে আরও নমনীয়তা অর্জন করতে পারেন যার কারণে অনেকে এই সমাধানটিকে পছন্দ করে। আপনার প্রকল্প / দল / সংস্থার উপর নির্ভর করে আপনি এমন কিছু চাইতে পারেন যা কোডের দিকে ঝলক দেওয়া কারও পক্ষে সহজেই নির্ণয় করা যায় যা গ্রহণযোগ্য উত্তর।
হারুন

2
আমি বিশ্বাস করি না যে আপনি এটি করতে পারেন বেসিক whereম্যাথার্স ব্যবহার করে । জন্য >আমি একটি ব্যবহার করার পরামর্শ দিই >= (number_you_want + 1)সরলীকরণের জন্য। আপনি যদি সত্যই এটি নিশ্চিত করতে চান তবে এটি কেবল একটি >ক্যোয়ারী আপনি আর্য়েল টেবিলটি অ্যাক্সেস করতে পারেন। প্রতিটি শ্রেণীর যে উত্তরাধিকার সূত্রে প্রাপ্ত ActiveRecordরয়েছে তার একটি arel_tableগেটর পদ্ধতি রয়েছে যা Arel::Tableসেই শ্রেণির জন্য ফিরে আসে । টেবিলের কলামগুলি এমন []পদ্ধতিতে অ্যাক্সেস করা হয় User.arel_table[:id]। এটি Arel::Attributes::Attributeআপনাকে কল gtকরে এবং পাস করতে পারে এমন একটি ফেরত দেয় 200। এটি তখন পাস করা যেতে পারে where। যেমন User.where(User.arel_table[:id].gt(200))
অ্যারন

2
@ ব্লুহেল্লু আপনি একটি উদাহরণ প্রদান করতে পারেন? নিম্নলিখিতটি আমার পক্ষে কাজ করছে না User.where(created_at: 3.days.ago..DateTime::Infinity.new)
অ্যারন

1
আহ! এটি সম্ভবত উপকারী আচরণ দেয় যা রেল 5 এ সম্ভবত একটি নতুন পরিবর্তন। R.২.৫ (রুবি ২.২.২) এ আপনি একটি প্রশ্ন পেয়ে যাবেন WHERE (users.created_at >= '2016-04-09 14:31:15' AND users.created_at < #<Date::Infinity:0x00>)(টেবিলের চারপাশে পিছনে টিক্স এবং কলামের নামগুলি এসও মন্তব্য বিন্যাসকরণের জন্য বাদ দেওয়া হয়েছে)।
অ্যারন

22

আরও ভাল ব্যবহার হ'ল ব্যবহারকারীর মডেলটিতে একটি সুযোগ তৈরি করা where(arel_table[:id].gt(id))


6

আপনি যদি আরও স্বজ্ঞাত লেখা চান তবে এটিতে স্ক্যয়েল নামে একটি রত্ন রয়েছে যা আপনাকে আপনার নির্দেশটি এভাবে লিখতে দেয়:

User.where{id > 200}

'ব্রেস' অক্ষর Notice Notice এবং idকেবল একটি পাঠ্য হিসাবে লক্ষ্য করুন।

আপনাকে যা করতে হবে তা হ'ল আপনার জেমফাইলে স্কেল যুক্ত করুন:

gem "squeel"

রুবিতে জটিল এসকিউএল স্টেটমেন্ট লেখার সময় এটি আপনার জীবনকে অনেক সহজ করতে পারে।


11
আমি squeel ব্যবহার এড়ানোর পরামর্শ দিই। দীর্ঘমেয়াদী বজায় রাখা কঠিন এবং কখনও কখনও অদ্ভুত আচরণ রয়েছে। এছাড়াও এটি নির্দিষ্ট অ্যাক্টিভ রেকর্ড সংস্করণগুলির সাথে বগী
জন ওভেন চিলি

আমি কয়েক বছর ধরে স্কেল ব্যবহার করছি এবং এটিতে এখনও খুশি। তবে উদাহরণস্বরূপ সিক্যুয়াল (<> স্কুয়েল) এর মতো অন্য একটি ওআরএম চেষ্টা করার পক্ষে এটি অ্যাক্টিভেকর্ড প্রতিস্থাপনের জন্য দুর্দান্ত বৈশিষ্ট্যগুলির প্রতিশ্রুতিবদ্ধ বলে মনে হচ্ছে।
ডগলাস


4

আর অভিনব সম্ভাবনা হ'ল ...

User.where("id > :id", id: 100)

আপনি যদি একাধিক জায়গায় প্রতিস্থাপন করতে চান তবে এই বৈশিষ্ট্যটি আপনাকে আরও বোধগম্য ক্যোয়ারী তৈরি করতে দেয়, উদাহরণস্বরূপ ...

User.where("id > :id OR number > :number AND employee_id = :employee", id: 100, number: 102, employee: 1205)

?ক্যোয়ারিতে অনেক কিছু থাকার চেয়ে এটির আরও অর্থ রয়েছে ...

User.where("id > ? OR number > ? AND employee_id = ?", 100, 102, 1205)

3

আমার প্রায়শই তারিখের ক্ষেত্রগুলির সাথে সমস্যা হয় (যেখানে তুলনা অপারেটরগুলি খুব সাধারণ)।

মিহাইয়ের উত্তর সম্পর্কে আরও বিস্তারিতভাবে জানানো, যা আমি বিশ্বাস করি এটি একটি দৃ approach় পদ্ধতির।

মডেলগুলিতে আপনি এর মতো স্কোপগুলি যুক্ত করতে পারেন:

scope :updated_at_less_than, -> (date_param) { 
  where(arel_table[:updated_at].lt(date_param)) }

... এবং তারপরে আপনার নিয়ামক বা আপনি যেখানেই আপনার মডেলটি ব্যবহার করছেন:

result = MyModel.updated_at_less_than('01/01/2017')

... যোগদানের সাথে আরও জটিল উদাহরণ এটির মতো দেখাচ্ছে:

result = MyParentModel.joins(:my_model).
  merge(MyModel.updated_at_less_than('01/01/2017'))

এই পদ্ধতির একটি বিশাল সুবিধা হ'ল (ক) এটি আপনাকে বিভিন্ন স্কোপগুলি থেকে আপনার প্রশ্নগুলি রচনা করতে দেয় এবং (খ) আপনি যখন একই টেবিলে দু'বার যোগদান করেন তখন এলএল সংঘাতগুলি এড়ানো যায় কারণ arel_table ক্যোয়ারী জেনারেশনের সেই অংশটি পরিচালনা করবে।


1

রেলগুলি 6.1+

রেল .1.১ whereশর্তাদি তুলনামূলক অপারেটরদের জন্য একটি নতুন 'সিনট্যাক্স' যুক্ত করেছে , উদাহরণস্বরূপ:

Post.where('id >': 9)
Post.where('id >=': 9)
Post.where('id <': 3)
Post.where('id <=': 3)

সুতরাং আপনার ক্যোয়ারী নিম্নরূপে আবার লেখা যেতে পারে:

User.where('id >': 200) 

এখানে PR এর একটি লিঙ্ক যেখানে আপনি আরও উদাহরণগুলি পেতে পারেন find


-3

অপেক্ষাকৃত ছোট:

User.where("id > 200")

8
আমি ধরে নিলাম এটি গতিশীল হতে হবে এবং পোস্টারটি প্যারামিটারাইজড কোয়েরি ( where("id > ?", 200)সিনট্যাক্স) ব্যবহার করে এসকিউএল ইঞ্জেকশনটি এড়াতে চায় । এটি অর্জন করে না।
ম্যাথু হিনা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.