Unable to search by name and primary key - ruby-on-rails

The following query doesn't search by id (primary key) at all - it keeps assigning 0 to id and search_str to name. It does so properly if we use equals operator instead of matches for "id". Is there an issue with the following scope.
scope :or_search, lambda {|name| where(arel_table[:name].matches("%{search_str}%").or(arel_table[:id].matches("%#{search_str}%")))

I'm a little confused by what you're trying to do but first
arel_table[:name].matches("%{search_str}%")
You're missing the #, I think this should be
arel_table[:name].matches("%#{search_str}%")
Second you're not using your name argument anywhere, just from looking at this, maybe you want to replace search_str with name?

first of all you have made a typo which i think is you missed one closing curly brace at the end of the scope defination
Coming to an answer i think you are doing something which is either match id or title?(really i can not believe this you should not do this)
Note the "search_str" is coming from nowhere because the parameter to the block is "name" and hence you can compare it with whatever attribute of the table you want to compare :)
And the answer i can think for your problem is
scope :or_search, lambda {|title| where(arel_table[:title].matches("%#{title}%").or(arel_table[:id].matches("#{title}")))}
pare

Not sure if you're just trying to understand why it doesn't work, or if you're looking for a working solution.
Anyway the following isn't in arel, but would work if you add it to the model:
def self.or_search(str)
where("name like :input OR id like :input", input: "%#{str}%")
end

Related

If condition on RABL

I have two attributes in my relation - flyer and flyer_url. I want to put an if condition which assigns either flyer or flyer_url to flyer_image_url depending on which is not null. All the records have either of them set to null. I've tried the following code but it is only assigning flyer_url to flyer_image_url even when it is null:
attribute :flyer => :flyer_image_url
attribute :flyer_url => :flyer_image_url, :if => lambda { |flyer_url| !flyer_url.nil? }
Please help!
Thanks!!
Thanks to Nathan Esquenazi - the creator of RABL, I finally got the answer.
This is a limitation (although somewhat intentional) of RABL, for a given key name “flyer_image_url” there should only ever be a single statement associated with it. Trying to have two statements associated with a single key is what is causing the confusion here.
He suggests using a single node instead with custom logic: https://github.com/nesquena/rabl#custom-nodes
node :flyer_image_url do |object|
object.flyer_url.nil? ? object.flyer : object.flyer_url
# This is just ruby, put whatever you want that ends up as a string
end
That worked like a charm! Hope this answer finds somebody!

MongoID Like query on embedded model

I have User model embeds_one :profile and Profile model has name. I need to run LIKE query on profile name. I tried below as suggested here
User.where("profile.name" => "/.*Senthil.*/")
But above solution not working. I tried lot of stock overflow answers , but no luck. Any help will be highly appreciated.
Screenshot : I am very sure , there is matching record.
This finds all people with the name senthil (first OR last).
User.where("profile.name" => /.*senthil.*/i )
Here i used to make the query case insensitive.
I think you mean to remove the quotes, otherwise the engine will try to match the string exactly, instead of as regex
edit: The correct regexp would be
User.where("profile.name" => /.*Senthil.*/)

Rails manipulate model query

Assume I have params[:foo] = "bar" and some saved object whose attribute = "key.bar"
How can I manipulate Model.where(attribute: params[:foo]) to query for attribute.split(".")[1] ?
I'm not certain if there's a better way, but the first method that popped in my mind is using the LIKE operator. You can write your query thusly:
Model.where("attribute LIKE '%?'", params[:foo])
Note, given the example you posted, I placed the wildcard (%) in that position so that the attribute is match for anything that ends with your parameter. This assumes all your attributes are similar to what you described, but you can of course change it around to your liking.
Also, while I've never used it myself, I understand that the Squeel gem provides this functionality as an operator (described here).
Small change to answer above
Model.where("attribute LIKE '%.?'", params[:foo])
to prevent matching both .bar and .foobar.

Rails: Getting column value from query

Seems like it should be able to look at a simple tutorial or find an aswer with a quick google, but I can't...
codes = PartnerCode.find_by_sql "SELECT * from partner_codes where product = 'SPANMEX' and isused = 'false' limit 1"
I want the column named code, I want just the value. Tried everything what that seems logical. Driving me nuts because everything I find shows an example without referencing the actual values returned
So what is the object returned? Array, hash, ActiveRecord? Thanks in advance.
For Rails 4+ (and a bit earlier I think), use pluck:
Partner.where(conditions).pluck :code
> ["code1", "code2", "code3"]
map is inefficient as it will select all columns first and also won't be able to optimise the query.
You need this one
Partner.where( conditions ).map(&:code)
is shorthand for
Partner.where( conditions ).map{|p| p.code}
PS
if you are often run into such case you will like this gem valium by ernie
it gives you pretty way to get values without instantiating activerecord object like
Partner.where( conditions ).value_of :code
UPDATED:
if you need access some attribute and after that update record
save instance first in some variable:
instance=Partner.where( conditions ).first
then you may access attributes like instance.code and update some attribute
instance.update_attribute || instance.update_attributes
check documentation at api.rubyonrails.org for details

Remove a 'where' clause from an ActiveRecord::Relation

I have a class method on User, that returns applies a complicated select / join / order / limit to User, and returns the relation. It also applies a where(:admin => true) clause. Is it possible to remove this one particular where statement, if I have that relation object with me?
Something like
User.complex_stuff.without_where(:admin => true)
I know this is an old question, but since rails 4 now you can do this
User.complex_stuff.unscope(where: :admin)
This will remove the where admin part of the query, if you want to unscope the whole where part unconditinoally
User.complex_stuff.unscope(:where)
ps: thanks to #Samuel for pointing out my mistake
I haven't found a way to do this. The best solution is probably to restructure your existing complex_stuff method.
First, create a new method complex_stuff_without_admin that does everything complex_stuff does except for adding the where(:admin => true). Then rewrite the complex_stuff method to call User.complex_stuff_without_admin.where(:admin => true).
Basically, just approach it from the opposite side. Add where needed, rather than taking away where not needed.
This is an old question and this doesn't answer the question per say but rewhere is a thing that exists.
From the documentation:
Allows you to change a previously set where condition for a given attribute, instead of appending to that condition.
So something like:
Person.where(name: "John Smith", status: "live").rewhere(name: "DickieBoy")
Will output:
SELECT `people`.* FROM `people` WHERE `people`.`name` = 'DickieBoy' AND `people`.`status` = 'live';
The key point being that the name column has been overwritten, but the status column has stayed.
You could do something like this (where_values holds each where query; you'd have to tweak the SQL to match the exact output of :admin => true on your system). Keep in mind this will only work if you haven't actually executed the query yet (i.e. you haven't called .all on it, or used its results in a view):
#users = User.complex_stuff
#users.where_values.delete_if { |query| query.to_sql == "\"users\".\"admin\" = 't'" }
However, I'd strongly recommend using Emily's answer of restructuring the complex_stuff method instead.
I needed to do this (Remove a 'where' clause from an ActiveRecord::Relation which was being created by a scope) while joining two scopes, and did it like this: self.scope(from,to).values[:joins].
I wanted to join values from the two scopes that made up the 'joined_scope' without the 'where' clauses, so that I could add altered 'where' clauses separately (altered to use 'OR' instead of 'AND').
For me, this went in the joined scope, like so:
scope :joined_scope, -> (from, to) {
joins(self.first_scope(from,to).values[:joins])
.joins(self.other_scope(from,to).values[:joins])
.where(first_scope(from,to).ast.cores.last.wheres.inject{|ws, w| (ws &&= ws.and(w)) || w}
.or(other_scope(from,to).ast.cores.last.wheres.last))
}
Hope that helps someone

Resources