Get specific result by checking a simple variable inside a double array - ruby-on-rails

I have a #customers variable in which each customer has multiple contracts. Each of those contract has multiple users.
What I would like to do is to get all the customers that have a specific user
I tried using the find method but I don't understand how to do that inside a what seems to be double array.
Currently I have this:
cust.each do |c|
if c.contracts.where(users.find(session[:login]))
#customers << c
end
end
What am I missing here?

I think you have to mention user field in where clause, Can you try below code
cust.each do |c|
if c.contracts.where(user: users.find(session[:login]))
#customers << c
end
end

Related

ActiveRecord how to use Where only if the parameter you're querying has been passed?

I'm running a query like the below:
Item.where("created_at >=?", Time.parse(params[:created_at])).where(status_id: params[:status_id])
...where the user can decide to NOT provide a parameter, in which case it should be excluded from the query entirely. For example, if the user decides to not pass a created_at and not submit it, I want to run the following:
Item.where(status_id: params[:status_id])
I was thinking even if you had a try statement like Time.try(:parse, params[:created_at]), if params[created_at] were empty, then the query would be .where(created_at >= ?", nil) which would NOT be the intent at all. Same thing with params[:status_id], if the user just didn't pass it, you'd have a query that's .where(status_id:nil) which is again not appropriate, because that's a valid query in itself!
I suppose you can write code like this:
if params[:created_at].present?
#items = Item.where("created_at >= ?", Time.parse(params[:created_at])
end
if params[:status_id].present?
#items = #items.where(status_id: params[:status_id])
end
However, this is less efficient with multiple db calls, and I'm trying to be more efficient. Just wondering if possible.
def index
#products = Product.where(nil) # creates an anonymous scope
#products = #products.status(params[:status]) if params[:status].present?
#products = #products.location(params[:location]) if params[:location].present?
#products = #products.starts_with(params[:starts_with]) if params[:starts_with].present?
end
You can do something like this. Rails is smart in order to identify when it need to build query ;)
You might be interested in checking this blog It was very useful for me and can also be for you.
If you read #where documentation, you can see option to pass nil to where clause.
blank condition :
If the condition is any blank-ish object, then #where is a no-op and returns the current relation.
This gives us option to pass conditions if valid or just return nil will produce previous relation itself.
#items = Item.where(status_condition).where(created_at_condition)
private
def status_condition
['status = ?', params[:status]] unless params[:status].blank?
end
def created_at_condition
['created_at >= ?', Time.parse(params[:created_at])] unless params[:created_at].blank?
end
This would be another option to achieve the desired result. Hope this helps !

Displaying from my database

I'm new to rails and I'm working on a project where I'm having an issue. I'm trying to display all the gyms that have the same zipcode. When I tried the code below, it only displays 1 and not the other ones. How can display all the gym that have the same zip code?
controller
def gym
#fitness = Fitness.find_by(zip_code: params[:zip_code])
end
gym.html.erb
<%= #fitness.name %>
You're doing this to yourself. By definition, #find_by only returns a single record, or nil. You probably want #where instead:
Fitness.where(zip_code: params[:zip_code])
If that still doesn't work, check both your table data and the content of your params hash to make sure you're creating a valid query.
def gyms
#fitness = Fitness.where("zip_code = ?", params[:zip_code])
end

Case statement for STI type column

I have a User model that can have many Websites. For example, I will be able to call User.websites and it will pull up an ActiveRecord array of all of the websites that the User owns. But each website uses Single Table Inheritance (STI) and a type column that will determine the type of the website, like commercial, advertising, or forum. My problem is, that I was to make a case/when statement that runs a function if the the User has a website that is of a certain type. for example:
#user = User.first
case #user.websites
when includes?(Commercial)
'This user has a commercial website'
when includes?(Forum)
'This user has a forum website'
when include?(Ad)
'This user has a advertisement website'
end
Does anyone have a clue on the best way to do such a thing?
Shortest way to do this is using a the map method. Just one line!
#user.websites.select(:type).uniq.map{
|x| puts "This user has a #{x.type.downcase} website"
}
Or if you want to have these strings in an array.
#user.websites.select(:type).uniq.map{|x| x.type.downcase}
If you want to run functions. I would advice naming the functions in a friendly way such as commercial_cost, forum_cost, etc.. so that you can use the send method which makes your code compact.
#user.websites.select(:type).uniq.map{ |x| #user.send(x.type.downcase + "_cost") }
def types
'This user has following websites: ' +
websites.pluck(:type).map(&:downcase).join(', ')
end
#user.rb
def return_data(*types)
types.each do |t|
if Website.where(:user_id => self.id, :type=> t).length>0
send "method_for_owners_of_#{t}_site"
end
end
end
def method_for_owners_of_Commercial_site
end
#...
#user.return_data(["Commercial"])
#user.return_data(["Commercial", "Ad"])
...
According to Rails API
When you do Firm.create(name: "37signals"), this record will be saved
in the companies table with type = “Firm”.

Indexing and ordering by dynamic field with sunspot

So I have many items that can be part of many different pages. So here is the simplified models:
class Page
#we just need the id for this question
end
class Item
embeds_many :page_usages
end
class PageUsage
field :position, :default => 0
embedded_in :item
belongs_to :page
end
So the page_usage is holding the position of the items on every page. I want to put that into solr so it can pull up the right items and in the right order for me.
I've looked into dynamic fields and ended up with something like this but not really sure. I want the field to basically be the page id pointing to the position of the item:
searchable do
dynamic_integer :page_usages do
page_usages.inject({}) do |hash, page_usage|
hash.merge(page_usage.page_id => page_usage.position)
end
end
end
And in my controller I have something like this:
Item.search do
dynamic :page_usages do
#i have #page.id but not sure how to get all items with the #page.id
end
end
I need something that will check if the item exist on the page and find out how to use order_by with the position. Is this possible this way or do I have to find another solution?
Solved it after lots of trial and error.
searchable do
dynamic_integer :page_usages do
page_usages.inject({}) do |hash, page_usage|
hash.merge( ("page" + page_usage.page_id.to_s).to_sym => page_usage.position)
end
end
end
So I first had to store the key as a symbol which is important. But the problem I ran into was that the symbol couldn't have quotes in it. So if you call to_sym on the id, it would look something like :"123456789" which will give you a "wrong constant name" error later on. So I threw on a string before the id to create the new symbol which looks like :page123456789.
Next step was to create the search block:
Item.search do
dynamic :page_usages do
with ("page" + page.id.to_s).to_sym ).greater_than(-1)
order_by(("page" + page.id.to_s).to_sym, :asc)
end
end
By using that page id, I was able to pull up all the right items in the right order. I used greater than -1 because by default my positions start at 0 and goes up from there.

How can this be re-written as an ActiveRecord query? (Rails)

I have the following method in a controller:
# GET /units/1
def show
#unit = Unit.find(params[:id]
#product_instances = Array.new
current_user.product_instances.each do |product_instance|
if product_instance.product.unit == #unit
#product_instances.push(product_instance)
end
end
... #rest of method
end
As can be seen, I have four tables/models: User, Product, ProductInstance, and Unit. A User has many ProductInstances. Each ProductInstance maps to a Product. A Unit has many Products.
I would like to fetch only the User's ProductInstances that are linked to a Product in the current Unit. The current code does it, but how can I re-write it better? I'd like to get rid of the for-each loop and if statement and replace it with chained ActiveRecord queries, if possible.
I tried something like below but it didn't work:
#product_instances = current_user.product_instances.where(:product.unit => #unit)
Seems you cannot do :product.unit.
I think you can try this
current_user.product_instances.joins(:product).where("products.unit_id = ?",#unit.id)
or with hashes
current_user.product_instances.joins(:product).where(:products => {:unit_id => #unit.id})

Resources