Running ruby 1.8.7.
(1.005 * 100).round
result: 100
(1.006 * 100).round
result: 101
100.5.round
result: 101
(1.005 * 100)
result: 100.5
What is going on here? Can someone try this in the latest version of ruby please?
Thanks!
Floating Point Math is what's going on.
For the last one, I do not get 100.5, and you aren't either, even if for some reason it's displaying as that:
Loading development environment (Rails 3.2.8)
1.9.3p194 :001 > (1.005 * 100).round
=> 100
1.9.3p194 :002 > (1.006 * 100).round
=> 101
1.9.3p194 :003 > 100.5.round
=> 101
1.9.3p194 :004 > (1.005 * 100)
=> 100.49999999999999
Related
I have a Post that has_many :comments. Let's say Comment has the following field: another_model_id. I would like to select Posts, that have from 2 to 5 comments with another_model_id = 10 (for example). I tried several constructions but with no success :(
Example of what I tried:
# Invalid SQL syntax error
Post
.joins(:comments)
.select("count(comment.another_model_id = 10) as comments_count)
.where("comments_count BETWEEN 2 AND 5")
I have literally no idea where to dig. Is it possible to achieve that in a single query? Thanks!
Post
.joins(:comments)
.where(comments: { another_model_id: 10 })
.group('posts.id')
.having('count(comments.id) > 2 AND count(comments.id) < 5')
Using counter_cache is the best practice for your scenario:
In your Comment model, you need to set the counter_cache:
belongs_to :post, counter_cache: true
Then simply you can use this query:
Post.joins(:comments)
.where(comments: { another_model_id: 10 })
.where('comments_count > ? AND comments_count < ?', 2, 5)
I want to perform a query on first 10 records.
So, from Rails console I type:
Log.all.limit(10).where({"username"=>"peeyush"}).explain
This gives:
Log Load (0.8ms) SELECT "logs".* FROM "logs" WHERE "logs"."username" = 'peeyush' LIMIT 10
Clearly, LIMIT 10 happens later.
I try running:
Log.all.first(10).where({"username"=>"peeyush"}).explain
But this gives an error:
NoMethodError: undefined method `where' for #<Array:0x0000000539acd8>
How should the query be performed?
If I understand you correctly, you want to retrieve the 1st 10 rows and then filter those 10 records by username?
Filter in ruby
all.first(10).find_all {|i| i.username == "peeyush" }
Filter on the database
all.where(:id => all.first(10).map {|x| x.id}, :username => "peeyush")
im trying to find records that are NOT created in a certain date range using a thinking sphinx query in my rails 4 project with postgresql as database
THIS WORKS
Housing.search "some text",
star: true,
ranker: :bm25,
with: {created_at (3.weeks.ago..Time.zone.now)}
BUT THIS DOESN´T
Housing.search "some text",
star: true,
ranker: :bm25,
without: {created_at:(3.weeks.ago..Time.zone.now)}
I´m thinking its a bug in the query since it finds all record within the given date range, but fails to find the opposite?
This is my gemfile
gem 'mysql2', '0.3.12b4'
gem 'thinking-sphinx', github: 'pat/thinking-sphinx'
gem 'flying-sphinx', github: 'flying-sphinx/flying-sphinx'
gem 'delayed_job_active_record', '>= 4.0.0.beta2'
gem 'delayed_job_web'
gem 'ts-delayed-delta', github: 'pat/ts-delayed-delta'
This is my housing_indices
ThinkingSphinx::Index.define :housing, :with => :active_record, :delta => ThinkingSphinx::Deltas::DelayedDelta do
has created_at
< + OTHER FIELDS THAT ARE INDEXED >
set_property :enable_star => true
set_property :min_infix_len => 1
set_property :html_strip => true
set_property :charset_type => "utf-8"
end
this is the query from the log when using without: {created_at:(3.weeks.ago..Time.zone.now)}
Sphinx Query (1.0ms) SELECT * FROM `housing_core`, `housing_delta` WHERE MATCH('#location_name *Krimml*') AND max_capacity BETWEEN 1 AND 1000 AND number_of_bathrooms BETWEEN 1 AND 3 AND number_of_bed_places BETWEEN 2 AND 10 AND sphinx_deleted = 0 AND created_at < 1376554070 OR created_at > 1378368470 AND activated_at <> 0 LIMIT 0, 20 OPTION ranker=bm25
And this Is the error I am getting
sphinxql: syntax error, unexpected OR, expecting $end near 'OR created_at > 1378368470 AND activated_at <> 0 LIMIT 0, 20 OPTION ranker=bm25; SHOW META'
this is the query from the log when using with: {created_at:(3.weeks.ago..Time.zone.now)}
Sphinx Query (3.9ms) SELECT * FROM `housing_core`, `housing_delta` WHERE MATCH('#location_name *Krimml*') AND created_at BETWEEN 1376555152 AND 1378369552 AND max_capacity BETWEEN 1 AND 1000 AND number_of_bathrooms BETWEEN 1 AND 3 AND number_of_bed_places BETWEEN 2 AND 10 AND sphinx_deleted = 0 AND activated_at <> 0 LIMIT 0, 20
so i think what I´m looking for is this query to be executed
AND created_at NOT BETWEEN 1376555152 AND 1378369552
I think that the without method doesn't have ranges, i imagine is because you want to index portions of data and not the all data without some portion, so you can use the inverse expression.
A without like this
without: {created_at (3.weeks.ago..Time.zone.now)}
will be something like this(with a safe year for your data)
with: {created_at (Time.now.change(:year => 2012)..3.weeks.ago)}
Of course your case is a good case for this because you wouldn't have created things in the "future" if the data is consistence.
Trying to search where movies coming out have a release date greater than today's date
Movie.where('release > ?', Date.today)
ActiveRecord::StatementInvalid: Mysql::ParseError: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'release > '2011-09-25')' at line 1: SELECT `movies`.* FROM `movies` WHERE (release > '2011-09-25')
Rails 3+ :
Movie.where('release > ?', DateTime.now)
Pre Rails 3
Movie.where(['release > ?', DateTime.now])
In recent versions of rails, you can do this:
User.where(created_at: 3.days.ago..Time.now)
See some other examples here: https://stackoverflow.com/a/24150094
Update
Rails core team decided to revert this change for a while, in order to discuss it in more detail. See this comment and this PR for more info.
I am leaving my answer only for educational purposes.
new 'syntax' for comparison in Rails 6.1 (Reverted)
Movie.where('release >': DateTime.now)
Here is a link to PR where you can find more examples.
In Ruby 2.7, you can try this:
License.where(expiration: Time.zone.today..)
SELECT "licenses".* FROM "licenses" WHERE "licenses"."expiration" >= '2021-07-06 15:12:05'
Ruby beginless/endless ranges can also be used as an out-of-the-box solution:
Post.where(id: 1..)
=> Post Load (0.4ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" >= $1 [["id", 1]]
Post.where(id: ..9)
=> Post Load (0.3ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" <= $1 [["id", 9]]
Post.where(id: ...9)
=> Post Load (0.3ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" < $1 [["id", 9]]
Note:
Replace id with your date column release
Replace value with Date.today
I currently have the following query
User.sum(:experience, :group => "clan", :conditions => ["created_at >= ? and created_at <= ?", "2010-02-15", "2010-02-16"])
I want to return the top 50 clans in terms of experience listed from most experience to least experience with only the top 50 in experience returning. How would I modify the query to achieve that result. I know I'll need :limit => 50 to limit the query but if I add :order => "clan DESC" I get the error column "users.experience" must appear in the GROUP BY clause or be used in an aggregate function
You need to repeat the calculation in the order clause
User.sum(:experience, :group => "clan", :order=> "sum(experience) DESC", :limit => 50, :conditions => ["created_at >= ? and created_at <= ?", "2010-02-15", "2010-02-16"])