Create an object based on parameters from another - ruby-on-rails

I'm Using Rails 3.2 and i wish to know a " rails way " to create an object based on parameters coming from another. I have the class StoredItem and the class RequestedItem, they are not related, but during the process to attend the requested item i wish to list all itens and qty stored from a requested part number.
I thought something like
#requested_items = RequestedItem.includes(:item_description).where("item_request_id = ?", params[:id])
#stored_items = StoredItem.where("item_description_id = ?",#requested_items.item_description_id)
Obviously this seems don't work because i have a lot of descriptions id to compare, not only one, so, whats the best and correct way to make it work?
Any help will be appreciated, thank you :)

#stored_items = StoredItem.where("item_description_id IN (?)",#requested_items.map(&:item_description_id))
Or
#stored_items = StoredItem.where(:item_description_id => #requested_items.map(&:item_description_id))

Related

How to get an correspondent id through a model on rails console

I've trying to get the simple situation:
I have a Model called Company, inside Company I have companies and I have the following object: "state_id". I want to find the related companies that contain some id.
This is the only path that I can get the state_id. So, I am doing:
Company.all.each do |comp|
comp.address.city.state_id
end
It works! But when I do:
Company.all.each do |comp|
comp.address.city.state_id = 27
#or comp.address.city.state_id(27)
end
it doesn't return the right data
I know that it simple, but unfortunately, I didn't getting the right output.
Thanks a lot!
Try
Company.joins(address: :city).where(cities: {state_id: 27})
You can make it work with select method. Also, don't mix up == and = - the former one checks equality and the latter one assigns a value:
needed_companies = Company.all.select do |comp|
comp.address.city.state_id == 27
end
But it isn't a correct way, because you're loading all companies in memory and filtering it. Much better is to use SQL query (as in answer by Ursus) and return only needed companies from DB

Rails custom model method in where query

In my rails app I have defined in the Kid model a calculation based on the fields from the Kids DB. the method is as follows:
def flip_date
self.dob.advance(months: 10)
end
I want to use this in my controller as I have a method where I am defining something as follows:
new_kids = Kid.where(discharge_date: nil).where('flip_date > ?', Date.current.advance(year: 1).beginning_of_year)
However I keep getting the following error:
SQLite3::SQLException: no such column: flip_date: SELECT "kids".* FROM "kids" WHERE "kids"."discharge_date" IS NULL AND (flip_date < '2017-01-01')
Any ideas on how can I make this work? All help is appreciated!
If you really want to use model methods take a look at http://apidock.com/rails/v4.0.2/ActiveRecord/QueryMethods/select
For your case:
new_kids = Kid.where(discharge_date: nil).select{|k| k.flip_date > Date.current.advance(year: 1).beginning_of_year}
But select method takes every object in memory before returning final result. Hence I will advise to use normal where clause and instead of flip_date take dob (which is a column in database) in consideration.
Like this
new_kids = Kid.where(discharge_date: nil).where('dob > ?', <date criteria>)
The select method (http://apidock.com/rails/v4.0.2/ActiveRecord/QueryMethods/select) works great if you are okay with the return being an Array.
I am still looking for a way to do this with an ActiveRecord_Relation return.
If others know how to do this, it would be much appreciated if you can share.
This example doesn't respond to your specific code, but to the extent it helps someone else with a similar question, here's a very simple example of how .select can be really handy:
#expired_memberships = User.select{|u| u.membership_expired_yesterday?}
In that example you've looped through all your Users and filtered them based on a custom method you defined on the User model (membership_expired_yesterday?). Now you can easily do stuff with that collection like this example in a mailer:
#expirations.each do |user|
MembershipExpirationMailer.with(user: user).first_reminder.deliver_now
end

Rails find by first attribute or second attribute

I currently have the following in my controller to find the device:
Device.find_by_token(params[:token])
Replacing token with unique_id.
So the new query would be:
Device.find_by_unique_id(params[:unique_id])
For some of older requests, unique_id is not being passed in params and device won't be found.
How can I do something like:
Device.find_by_token_or_unique_id(params[:token], params[:unique_id])
or course this doesn't exist.
Also, I don't want to do:
if params[:token]
Device.find_by_unique_id(params[:unique_id])
else
Device.find_by_token(params[:token])
end
Thanks in advance.
I think this is what you are looking for:
Devise.where("token = ? OR unique_id = ?", params[:token], params[:unique_id]).first
Keeping in mind the previous answer could potentially return you 2 items, you could do this alternative:
user = Device.where(unique_id: params[:unique_id]).first
user ||= Device.where(token: params[:token]).first
Or you could implement Arel Helpers and be able to actual build it as a or query.
https://github.com/camertron/arel-helpers
I prefer to using Arel as it makes your code no longer contain ANY SQL.

How can I get all the records in a table where any value of an associated table is in a given array?

I think if I had a better idea how to word this question, I would have been able to find an answer already... Anyways, I have a table called Vendors that has a many-to-many relationship with a table called Basins. I would like to be able to retrieve all the vendors that have at least one basin in an array of basins that is passed in as input.
So if I had three vendors like:
vendor1.basins = [Basin.first, Basin.second]
vendor2.basins = [Basin.second, Basin.third]
vendor3.basins = [Basin.third, Basin.fourth]
And I wanted to get all the vendors containing anything from [Basin.first, Basin.fourth], I would get both vendor1 and vendor3. If the array was [Basin.first, Basin.second], I would get both vendor1 and vendor2. I thought select might be the way to go here, but everything I've tried has been flagrantly wrong.
Thanks in advance.
I am assuming you are using Rails >= v4.0.0.
You can get vendors like:
Vendor.joins(:basins).where(basins: { id: [Basin.first.id, Basin.fourth.id] })
I hope this will help you.
You can add scope to Vendor model:
scope :foo, ->(basins_arr){ joins(:basins).
where(basins: { id: basins_arr.collect(&:id)})

Ruby set dictionary for search with activerecord

In my rails app i'm fetching data from mysql database, part of code:
#search = ArtLookup.find(:all, :conditions => ['MATCH (ARL_SEARCH_NUMBER) AGAINST(? IN BOOLEAN MODE) and ARL_KIND = 1', search_condition.gsub(/[^0-9A-Za-z]/, '')])
But main trouble that i have different suppliers price list's, and there i have different coding's for same variable in db, for example:
LEMFÖRDER
But how can i set dictionary for my search_condition so that if my search_condition is for example:
LEM?FORDER or
LEMFOERDER or
LEMFÖRDER
It will find my LEMFÖRDER in db?
I know that it could sound very strange, sorry for my english, but i explain all on my example...
I think that, in this case, you should start using a library to deal with full-text-search and additional search capabilities, like Solr or Sphinx.
Take a look at http://pat.github.com/ts/en/searching.html.
This kind of complexity is common and it is already implemented in many algorithms.
Hope it helps!
You could do this by using ActiveRecord's AREL engine like the following:
def lookup(*alternatives)
match_condition = 'MATCH (ARL_SEARCH_NUMBER) AGAINST(? IN BOOLEAN MODE)'
or_conditions = alternatives.map do |alternative|
ArtLookup.where(match_condition, alternative).
where_values.reduce(:and)
end
and_condition = ArtLookup.where('ARL_KIND = 1').where_values.reduce(:and)
# Build a disjunction
conditions = or_conditions.shift
or_conditions.each do |condition|
conditions = conditions.or(condition)
end
# Build the final conjunction
conditions = conditions.and(and_condition)
ArtLookup.where(conditions)
end
Then you can find the objects like the following:
#search = lookup('LEM?FORDER', 'LEMFOERDER', 'LEMFÖRDER')
Or directly provide an array:
alternatives = [
'LEM?FORDER',
'LEMFOERDER',
'LEMFÖRDER'
]
#search = lookup(*alternatives)
I'm aware of the fact that this is far too much code for the simple thing it's doing. But it should do it and I'm not aware of a much better way. I didn't test that code, so it could contain some minor mistakes.
If I've understood your question correctly, you want to have Mysql treat those three values as the same thing. Now, assuming that they are considered the same thing in a specific language (for example, ß = ss in German), Mysql will handle this automatically based on your collation settings, so selecting the correct collation should fix it for you.

Resources