I have the following query
model = (1,2,3,4)
#posts = Post.where(category_id: id, product_model_id: model)
My above query is justing taking the 1 from model how can i use where in condition over here
Edit-1
This piece of code works but I don't feel this as a good code right?
#posts = Post.where("category_id = ? and product_model_id in (#{model})", id)
Edit-2
If I use
#posts = Post.where("category_id = ? and product_model_id in (?)", id, model)
Throwing error as
invalid input syntax for integer: "15,16" because my input is like this
select * from posts where category_id=5 and product_model_id in ('15,16')
How to correct it then..
model_ids = model.split(",").map(&:to_i)
#posts = Post.where(category_id: id, product_model_id: model_ids)
or
model_ids = model.split(",").map(&:to_i)
#posts = Post.where("category_id = ? AND product_model_id IN (?)", id, model_ids)
According to the rails guide, you can pass in an array to where and it should understand that you want to use IN. See the guide here: http://guides.rubyonrails.org/active_record_querying.html#subset-conditions
I'm a little confused by your syntax, since model = (1, 2, 3, 4) doesn't look like valid array syntax.
Relevant part of the guide:
Client.where(orders_count: [1,3,5])
You could use arel, but I'd just do something like:
#posts = Post.where("category_id = ? AND product_model_id IN (?)", id, model)
Related
I have items in a table that have :parent_id that are empty to signify it being a main category. I was wondering how to iterate over these using .where (if that's even the right method to call).
Here's my controller:
def new
#title = 'New Post';
#post = Post.new
#categories = BlogCategory.all
#cat_zero = BlogCategory.where(:parent_id NULL)
#cat_one = BlogCategory.where(parent_id: 1)
#cat_two = BlogCategory.where(parent_id: 2)
#cat_three = BlogCategory.where(parent_id: 3)
#cat_four = BlogCategory.where(parent_id: 4)
end
The rest works fine, it's just that NULL isn't working. (The relationship between BlogCategory and Post have been made.)
I have tried doing these, but with no fortune (and a few other versions of these):
#cat_zero = BlogCategory.where(:parent_id == NULL)
#cat_zero = BlogCategory.where(:parent_id.nil?)
Thanks for the help!
The spelling you're looking for is:
#cat_zero = BlogCategory.where(parent_id: nil)
It's just the same as the spelling for other values, only using nil.
I have two queries, I need an or between them, i.e. I want results that are returned by either the first or the second query.
First query is a simple where() which gets all available items.
#items = #items.where(available: true)
Second includes a join() and gives the current user's items.
#items =
#items
.joins(:orders)
.where(orders: { user_id: current_user.id})
I tried to combine these with Rails' or() method in various forms, including:
#items =
#items
.joins(:orders)
.where(orders: { user_id: current_user.id})
.or(
#items
.joins(:orders)
.where(available: true)
)
But I keep running into this error and I'm not sure how to fix it.
Relation passed to #or must be structurally compatible. Incompatible values: [:references]
There is a known issue about it on Github.
According to this comment you might want to override the structurally_incompatible_values_for_or to overcome the issue:
def structurally_incompatible_values_for_or(other)
Relation::SINGLE_VALUE_METHODS.reject { |m| send("#{m}_value") == other.send("#{m}_value") } +
(Relation::MULTI_VALUE_METHODS - [:eager_load, :references, :extending]).reject { |m| send("#{m}_values") == other.send("#{m}_values") } +
(Relation::CLAUSE_METHODS - [:having, :where]).reject { |m| send("#{m}_clause") == other.send("#{m}_clause") }
end
Also there is always an option to use SQL:
#items
.joins(:orders)
.where("orders.user_id = ? OR items.available = true", current_user.id)
You can write the query in this good old way to avoid error
#items = #items.joins(:orders).where("items.available = ? OR orders.user_id = ?", true, current_user.id)
Hope that helps!
Hacky workaround: do all your .joins after the .or. This hides the offending .joins from the checker. That is, convert the code in the original question to...
#items =
#items
.where(orders: { user_id: current_user.id})
.or(
#items
.where(available: true)
)
.joins(:orders) # sneaky, but works! 😈
More generally, the following two lines will both fail
A.joins(:b).where(bs: b_query).or(A.where(query)) # error! 😞
A.where(query).or(A.joins(:b).where(bs: b_query)) # error! 😞
but rearrange as follows, and you can evade the checker:
A.where(query).or(A.where(bs: b_query)).joins(:b) # works 😈
This works because all the checking happens inside the .or() method. It's blissfully unaware of shennanigans on its downstream results.
One downside of course is it doesn't read as nicely.
I ran into the same issue, however the code was defined in a different place and was very difficult to change directly.
# I can't change "p"
p = Post.where('1 = 1').distinct # this could also be a join
And I needed to add an or statement to it
p.or(Post.where('2 = 2'))
The following code won't raise an error, because it has distinct like the initial relationship.
p.or(Post.where('2 = 2').distinct)
The problem with it it that it only works as long as you know the relationship. It may or not have a join, or distinct.
This works regardless of what the relationship is:
p.or(p.unscope(:where).where('2 = 2'))
=> SELECT DISTINCT `posts`.* FROM `posts` WHERE ((1 = 1) OR (2 = 2))
It occurs when you try to combine two multi-active records of the same type, but one of them has a joins value or an includes value, or in your case a reference value, that the other does not.
Therefore we need to match the values between them, and I found a general way to do this without knowing the actual values in advance.
items_1 = #items.joins(:orders)
.where(orders: { user_id: current_user.id})
items_2 = #items.where(available: true)
.joins(items_1.joins_values)
.includes(items_1.includes_values)
.references(items_1.references_values)
#items = items_1.or(items_2)
just solve it!
def exec_or_statement(q1, q2)
klass = q1.klass
key = klass.primary_key
query_wrapper_1 = {}
query_wrapper_1[key] = q1
query_wrapper_2 = {}
query_wrapper_2[key] = q2
klass.where(query_wrapper_1).or(klass.where(query_wrapper_2))
end
query_1 = #items.where(available: true)
query_2 =
#items
.joins(:orders)
.where(orders: { user_id: current_user.id})
exec_or_statement(query_1, query_2)
So, Ive been trying to query my PostgreSQL model in Rails, but get the following error:
undefined method `id' for TransactionTemplate::ActiveRecord_Relation
My code:
#transaction_templates = TransactionTemplate.where("transaction_category_id = 1")
#transaction = Transaction.where("transaction_template_id in (?)", #transaction_templates.id)
I know that the transaction templates is an array and that there is therefor not just one ID it needs to look up, but multiple of IDs, just as I want it.
Any suggestions?
Try this:
#transaction_templates = TransactionTemplate.where("transaction_category_id = 1")
#transaction = Transaction.where("transaction_template_id in (?)", #transaction_templates.map(&:id))
If you need just ids then try:
#transaction_template_ids = TransactionTemplate.where("transaction_category_id = 1").pluck(:id)
#transaction = Transaction.where("transaction_template_id in (?)", #transaction_template_ids)
Or you have proper associations then
#transaction = Transaction.joins(:transaction_template).where("transaction_category_id = 1")
I'm trying to find all associated records where two conditions are met.
I'm trying this, but it doesn't work, examples:
#students = #group.students
.includes(:attendances)
.where.not(attendances: {student_id: #ids, event_time_id: #event_id})
#students = #group.students
.includes(:attendances)
.where.not(attendances: {event_time_id: #event_id})
.where.not(attendances: {student_id: #ids})
#students = #group.students
.includes(:attendances)
.where("attendances.student_id IN (?) AND NOT attendances.event_time_id = ?", #ids, #event_id)
I want to get all the student records that exist in group and not have attendance with #event_id or have not attendance at all.
I think this might do what you want (untested), not the most elegant looking code...
exists_fragment = "SELECT 1 FROM attendances WHERE student_id = students.id"
#group.students
.joins(:attendance)
.where("attendances.event_id <> ? OR NOT EXISTS(?)", #event_id, exists_fragment)
Working solution:
#students = #group.students.includes(:attendances)
.where("attendances.event_time_id != ?", #event_id)
.references(:attendances)
#students_on = #group.students.includes(:attendances)
.where(attendances: { event_time_id: #event_id })
#students = #students - #students_on
Not sure if this is the best solution but it solves the mentioned problems
UPDATE
Less code version:
#students = #group.students
#students_exist = #group.students.includes(:attendances)
.where(attendances: { event_time_id: #event_id })
#students = #students - #students_exist
Here is my code. It work fine if I have something in the :search field or if I have something in the :supplier field but if I have something in both i get "Ambiguous column name 'NUMBER'". Is there a way to select AS or something?
#date_from = params[:date_from] || Date.today.beginning_of_month.strftime('%m/%d/%Y')
#date_to = params[:date_to] || Date.today.strftime('%m/%d/%Y')
q = "%#{params[:search]}%"
#products = Product.where("DISCONT = ? AND NONPRODUCT = ?" ,0,0)
#products = #products.where('NUMBER like ?' ,q) if params[:search].present?
#products = #products.joins(:supplier_items).where('SUPPLIER = ?' ,params[:supplier]) if params[:supplier].present?
#products = #products.paginate(page: params[:page], per_page: 25)
Just prefix the number with the table name
For example:
#products = Product.where(:discount => 0, :nonproduct => 0)
#products = #products.where('products.number like ?', query)
I'm guessing your suppliers table and products table both have a column named "number". Honestly, you'd be best off running a migration to change the column names now (maybe supplier_num / product_num) because keeping it something as generic as "number" will likely keep causing you headaches.