I am learning rails from rails tutorial. I got a problem in the Section 11.3.1, the code in the Listing 11.44:
def self.from_users_followed_by(user)
followed_user_ids = user.followed_user_ids.join(', ')
where("user_id IN (?) OR user_id = ?", followed_user_ids, user)
end
will not return user_id in followed_user_ids.
After searching at stackoverflow, I found the solution here, which said that just remove the "join" method and it works for me.
But I am curious about why there is no error when I run RSPEC before remove the "join" method.
In Listing 11.41:
subject { Micropost.from_users_followed_by(user) }
it { should include(own_post) }
it { should include(followed_post) }
If the "join" method will make the SQL statement wrong, why RSPEC passed?
Does anyone have the same problem?
Update 2012.04.03
I used rails console to check the problem.
user = User.first
ids = ids = user.following_users.map(&:id).join(', ')
Which got
User Load (2.6ms) SELECT "users".* FROM "users" INNER JOIN "follows" ON
"follows"."followable_id" = "users"."id" AND "follows"."followable_type" = 'User' WHERE
"follows"."blocked" = 'f' AND "follows"."follower_id" = 1 AND "follows"."follower_type"
= 'User' AND "follows"."followable_type" = 'User'
=> "6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 55, 56, 5"
Then the SQL
Collection.where("user_id IN (?)", ids)
The result is
Collection Load (0.7ms) SELECT "collections".* FROM "collections" WHERE (user_id IN
('6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 55, 56, 5')) ORDER BY collections.created_at DESC
=> []
Which return an empty array.
But I got all my rspec passed. Still no idea.
Assuming the join creates a string '1,2,3', then perhaps you want to join("','") to have ('1','2','3'), but I don't think this will work - I'm sure PostgreSQL doesn't like IDs as strings.
Alternatively:
Squeel is a good SQL syntax gem where you could use:
user = User.first
ids = user.following_users.map(&:id)
Collection.where{(user_id.like_any ids)}
This will allow you to pass in the array of integers and Squeel will setup the query where:
SELECT "collections".* FROM "collections" WHERE (("collections"."user_id" LIKE 1 OR "collections"."user_id" LIKE 2 OR "collections"."user_id" LIKE 3))
EDIT: You can also use the syntax:
ids = User.first.following_users.pluck(:id)
Collection.find_by_user_id(ids)
Related
I'm migrating from MySQL to PostgreSQL, but I'm getting the following error:
PG::TooManyArguments: ERROR: cannot pass more than 100 arguments to a function
when running queries like this:
Project.where(id: ids)
Which is translated to
"SELECT \"projects\".* FROM \"projects\" WHERE \"projects\".\"id\" IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100) ORDER BY FIELD(projects.id, '1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52','53','54','55','56','57','58','59','60','61','62','63','64','65','66','67','68','69','70','71','72','73','74','75','76','77','78','79','80','81','82','83','84','85','86','87','88','89','90','91','92','93','94','95','96','97','98','99','100')"
For me it's a common use case to query by specific IDs and it worked pretty well with MySQL. Is there any way to make this work with PostgreSQL?
I'm using PostgreSQL 13.2 on a docker container.
According to the error you have, cause is the function not the query itself. you can pass 32K arguments to the query and it will work (2byte int limit). As for functions, postgres by default has 100 arg limit (set during compilation). you can try to compile from source and set that number to higher value (I dont recommend doing that, unless you really understand the consequences).
Best approach would be probably to look into how to replace FIELD() function that is executed and modify so that you don't run into the problem. Can you change your system so that you can use column in DB to sort by? That way you dont need to pass those IDs for sorting. Or, if you have to use IDs, what about using CASE for sorting, like in this SO question: Simulating MySQL's ORDER BY FIELD() in Postgresql
The only "fix" I could find was downgrading PostgreSQL docker image to 11.11 where this error does not happen.
I have this simple code that doesn't compile.
const s = [_][_]int {
[_]int{08, 02, 22, 97, 38, 15, 00},
[_]int{49, 49, 99, 40, 17, 81, 18},
[_]int{81, 49, 31, 73, 55, 79, 14},
[_]int{52, 70, 95, 23, 04, 60, 11},
[_]int{22, 31, 16, 71, 51, 67, 63},
[_]int{24, 47, 32, 60, 99, 03, 45},
[_]int{32, 98, 81, 28, 64, 23, 67},
[_]int{67, 26, 20, 68, 02, 62, 12},
[_]int{24, 55, 58, 05, 66, 73, 99},
[_]int{21, 36, 23, 09, 75, 00, 76}
};
pub fn main() void
{
const w = s[0].len;
const h = s.len;
}
The compiler says:
./a.zig:1:14: error: inferred array size invalid here
const s = [_][_]int {
^
./a.zig:16:15: note: referenced here
const w = s[0].len;
What is the problem?
I'd be interested to know there's a deeper reason, but my simple understanding is that the current syntax [N]T allows for the array size to be elided using _, but not for more than one dimension.
So you can fix your problem using the following (N.B. I've used u8 because I'm unsure what your int is):
const s = [_][7]u8{
// Your items
}
I suspect this is because of the way the parsing rules are applied, so [7]u8 would be the type your nested array would hold, and will be used by the compiler to check contents are all of type [7]u8; you can confirm this by modifying one of your rows to have 6 elements and examining the resulting error.
If you want a variable number of items, you could start to look into an array of slices: [_][]u8, but I don't think that's what you're currently after.
This question already has answers here:
Create array of n items based on integer value
(6 answers)
Closed 4 years ago.
Need to create an array of 1 to n numbers with a single line of code in ruby.
I have tried it using while loop. But I'm sure there are other simpler way of doing this in ruby.
a = []
b = 1
while b < 100 do
a << b
b += 1
end
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
Convert a range into an array.
(1..n).to_a
another way
You can just splat a range:
[*1..n]
example
[*1..10]
=>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Or
a= Array(0..10)
puts a # => =>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
I have a specific order in which I want to show a number of my blog posts, but I'd also like to display regular blog posts after those selected ones.
So let's say I have posts [1, 7, 35, 36, 48] which I want to go first:
#selected_posts = Post.find([1, 7, 35, 36, 48])
But now I need to query for every other post, excluding those above:
#other_posts = Post.where.not(id: [1, 7, 35, 36, 48])
And now I need to combine those to maintain that order:
Post.find([1, 7, 35, 36, 48]) + Post.where.not(id: [1, 7, 35, 36, 48])
I'm using Postgres. Is it possible to do this in one query?
You can do order by case...
priority_ids = [1, 7, 35, 36, 48]
#all_posts = Post.all.order("CASE WHEN id IN (#{priority_ids.join(',')}) THEN 1 ELSE 2 END")
(thanks to #DeepakMahakale for correction)
I can't find a simple way to get the ids of pointfields from this relationship
pointtype has_and_belongs_to_many pointfields
pointfield has_and_belongs_to_many pointtypes
I do the following :
#pointtypes = current_project.points.map{|p| p.pointtype}.uniq
#pointtypes = #pointtypes - [nil] # tricky... Is this Railsy ?
#pointfield_ids = #pointtypes.map(&:pointfield_ids)
returns
[[16, 17, 18, 23, 24, 25, 26, 27, 28, 29], [16, 17, 32, 33, 34, 35, 36]]
and thus
#pointfield_ids.uniq!
is not working because there is two sub-arrays...
What I need is to get one single array with the unique ids of the pointfields (or the objects itself)