Show results depending on association - ruby-on-rails

I am building a landlord mgt application. But I am having an issue - I only want to index requests where the house.id (association value) matches the current user.
Currently, I have got it to work depending if the user has created it. But I would like the landlord to see all requests that are related to their properties.
requests_controller.rb:
def index
unless current_user.estate_agent?
#requests = Request.where(user_id: current_user).search(params[:search])
else
#requests = Request.search(params[:search])
end
end
request.rb
class Request < ActiveRecord::Base
belongs_to :user
belongs_to :house
def self.search(search)
key = "%#{search}%"
if search
where('description LIKE ? OR title LIKE ?', key, key)
else
all
end
end
end
house.rb
class House < ActiveRecord::Base
belongs_to :user
belongs_to :tenant
has_many :requests
belongs_to :contract
mount_uploader :energy, EnergyUploader
validates_presence_of :house_title, :description, :doorno, :postcode, :price, :bedroom, :house_type
def full_house_name
"#{doorno} #{house_title}"
end
def self.search(search)
key = "%#{search}%"
if search
where('doorno LIKE ? OR house_title LIKE ? OR price LIKE ? OR postcode LIKE ? OR house_type LIKE ? OR bedroom LIKE ?', key, key, key, key, key, key)
else
all
end
end
end

If I understood you correctly, you want to show all requests that were made by the user or made for his real-state.
The code below will create your initial filter, then you can call your search method over it.
Request.where(user_id: current_user.id).or(Request.where(house: { user_id: current_user.id}))

Related

Get Orders not Liked by logged in User Model in Rails 4

I have 3 Models: User, LikeOrder and Like. User has many LikeOrders. A User can like a LikeOrder only once. So I created Models as below:
class User < ActiveRecord::Base
has_many :like_orders
accepts_nested_attributes_for :like_orders
has_many :likes, dependent: :destroy
end
class LikeOrder < ActiveRecord::Base
belongs_to :user
has_many :likes, dependent: :destroy
end
class Like < ActiveRecord::Base
belongs_to :user
belongs_to :like_order
end
And Migration for Like Model is:
class CreateLikes < ActiveRecord::Migration
def change
create_table :likes do |t|
t.references :user, index: true, foreign_key: true
t.references :like_order, index: true, foreign_key: true
t.timestamps null: false
end
end
end
So when User likes a LikeOrder I do it this way (using likes method directly) without any problem:
class User < ActiveRecord::Base
...
def like(order)
likes.create(like_order: order) if likes.where(like_order: order).count == 0
end
end
class UserController < ApplicationController
def like
#user = User.find(params[:user_id])
#order = LikeOrder.find(params[:order_id])
#user.like #order
end
end
There was no problem.
My Problem is I want to get Orders that:
their status are pending and the id is greater that from_id param and are not liked by logged in User.
class LikeOrder < ActiveRecord::Base
...
def self.not_likeds(user, from_id)
joins(:likes).where("like_orders.id > ? and like_orders.status = ?", from_id, 'pending')
end
end
I'm getting the greater than from_id and pending ones.
I made a Join(:likes) But don't know how to Get Not Liked ones from likes table? I've been trying for 6 hours with no luck.
UPDATED: (1 Oct 2015)
Finally I think this is working:
class LikeOrder < ActiveRecord::Base
...
def self.not_likeds(user, from_id)
not_liked = []
pending_form_id(from_id).each do |order|
not_liked << order if order.likes.where('user_id = ?', user.id).count == 0
end
not_liked
end
end
But there might be another way without any block, using where method. can anyone help?
UPDATED: (15 Dec 2015)
I found a better solution:
where("id > ? AND status = ?",from_id, 'pending').where("id not in (SELECT like_order_id from likes WHERE user_id = ?)",user.id).where("user_id != ?",user.id).limit(limit)
I want to get Orders that: their status are pending and the id is
greater that from_id param and are not liked by logged in User.
#app/models/order.rb
class Order < ActiveRecord::Base
def not_liked user, from_id
joins(:likes).where(status: "pending", id > from_id).not(likes: {user_id: user.id})
end
end
This would allow you to call:
#order = Order.not_liked current_user, "5"
Not tested.
Your structure really confused me; why don't you just have a Like model instead of LikeOrder...
#app/models/like.rb
class Like < ActiveRecord::Base
#you could include an "order" attribute here
belongs_to :user
belongs_to :order
validates :user, uniqueness: { scope: :order, message: "Only one Order like per user!" }
end
#app/models/user.rb
class User < ActiveRecord::Base
has_many :likes
has_many :favourites, through: :likes, class: "Order", foreign_key: "order_id"
end
#app/models/order.rb
class Order < ActiveRecord::Base
has_many :likes
has_many :fans, through: :likes, class: "User", foreign_key: "user_id"
end
This would allow you to call...
#user = User.find params[:id]
#user.favourites => all the orders they liked
Hey you can try in this way
def self.not_likeds(user, from_id)
joins(:likes).where("like_orders.id > ? and like_orders.status = ? and likes.user_id not in (?)", from_id, 'pending',current_user.id)
end
UPDATE
In this case, I'm guessing that user is current_user so try to do this:
def self.not_likeds(user, from_id)
joins(:user, :likes).where("like_orders.id > ? and like_orders.status = ? and likes.id NOT IN (?)", from_id, 'pending', user.like_ids)
end
the solution for me was:
class LikeOrder < ActiveRecord::Base
...
def self.not_liked(user, from_id=0, limit=20)
where("id > ? AND status = ?",from_id, 'pending').where("id not in (SELECT like_order_id from likes WHERE user_id = ?)",user.id).where("user_id != ?",user.id).limit(limit)
end
end

Sunspot, solr indexing belongs_to associations

I am trying to set search on a model that has a lot of different associations. I am starting with the belongs_to associations. I am able to search on the name field of the Product model successfully but the when I perform a search on what would be in the associated models I just get the default results.
What am I doing wrong?
Any help would be much appreciated.
#Product Model
Class Product < ActiveRecord::Base
searchable do
text :name
integer :store_id, :references => Store.name
text :store do
Store.all.map { |store| store.name }
end
end
end
#product controler
def search
#search = Sunspot.search(Product) do
fulltext params[:search] do
fields(:name, :store)
end
end
#products = #search.results
end
#Store Model
searchable do
text :name
end
Class Product < ActiveRecord::Base
belongs_to :store
searchable do
text :name
index :store do
index :name
end
integer :store_id # do you really need this? I think not.
end
end
Don't forget to reindex after each change in your models.
EDIT: You don't need to index the Store class by itself, unless you plan to search on it.

Ruby on Rails: Undefined Method Error with has_one associations

For some reason I'm getting an NoMethodError for some query, which actually works in the rails console.
Code in index.html.erb
#requests.first.acceptance
This is my Error
undefined method `acceptance' for #<ActiveRecord::Relation::ActiveRecord_Relation_Arrangement:0x000000042ceeb8>
These are my Modules.
class Arrangement < ActiveRecord::Base
belongs_to :acceptance
belongs_to :request
belongs_to :offer, inverse_of: :arrangements
end
class Acceptance < ActiveRecord::Base
belongs_to :user, inverse_of: :acceptances
has_one :arrangement
end
class Request < ActiveRecord::Base
belongs_to :user, inverse_of: :requests
has_one :arrangement
end
This is my Controller
def index
#requests = Array.new
for request in current_user.requests do
#requests << Arrangement.where("request_id = ?", request.id)
end
#acceptances = Array.new
for acceptance in current_user.acceptances do
#acceptances << Arrangement.where("acceptance_id = ?", acceptance.id)
end
end
I can't figure out what I've done wrong here. Everything works in the console, though not in the browser.
Arrangement.where("request_id = ?", request.id)
Returns an array-like relation object which may contain multiple records, not just a single record.
However, on this line in your controller
#requests << Arrangement.where("request_id = ?", request.id)
You're adding the relation to your array, so that
#requests.first.acceptance
Returns the relation, instead of the first record.
One way to fix this is to do this in your controller:
#requests = Array.new
for request in current_user.requests do
#requests << Arrangement.where("request_id = ?", request.id).first
end
Solved
I was passing an array in the #requests array in my controller.

Rails and Postgres: Finding items that are a "good deal"

I have two models in my Rails application which keeps track of the prices of products at different shops. Here they are, but simplified:
class Product < ActiveRecord::Base
attr_accessor :name
def latest_prices
prices.where('created_at >= ?', 30.days.ago)
end
def average_price
latest_prices.prices.map(&:value).sum / latest_prices.count
end
end
class Price < ActiveRecord::Base
attr_accessor :value, :shop_name, :created_at
belongs_to :product
end
I now want to find all Price objects which fall below the current average for that product. That basically means all Prices created in the last 30 days, that have a price below the recent average price for that Product.
Is this possible? I'm using Postgres.
Edit: I should have mentioned - I want to implement this method from the Price model - that is, just be able to display all prices that are a good deal, rather than all prices for a Product that are good deals.
Thanks in advance for any help!
Using named scopes in ActiveRecord, you can use composition to get what you want:
class Product < ActiveRecord::Base
attr_accessor :name
has_many :prices
end
class Price < ActiveRecord::Base
attr_accessor :value, :shop_name, :created_at
belongs_to :product
scope :latest, where('created_at >= ?', 30.days.ago)
scope :less_than, lambda { |value| where("value < ?", value) }
def good_deals
latest.less_than(average('value'))
end
end
try this:
class Product < ActiveRecord::Base
attr_accessor :name
def your_query
prices.where('created_at >= ?', 30.days.ago).where('value < ?', average_price)
end
def latest_prices
prices.where('created_at >= ?', 30.days.ago)
end
def average_price
latest_prices.prices.map(&:value).sum / latest_prices.count
end
end

Access rails includes with has_many

I have a model called "Match" and a model called "Bet"
class Match < ActiveRecord::Base
...
has_many :bets
end
And my Model Bet:
class Bet < ActiveRecord::Base
attr_accessible :match_id, :user_id, :bet
...
belongs_to :match
belongs_to :user
end
I'm using the following code to select some matches and user's bets together:
#matches = Match.includes(:bets).where("bets.user_id = ? or bets.user_id is NULL", #user.id)
How can I access user bets with this query?
Using this does not work:
#matches.each do |match|
match.bet.bet
...
How to access bet attribute inside match?
Thanks!!
Trying #sevenseacat answer with this code:
#user ||= User.find_by_id(params[:user_id]) if params[:user_id]
if #user
#matches = Match.includes(:home_team, :away_team, :bets).where("bets.user_id = ? or bets.user_id is NULL", #user.id) #.group_by{ |match| match.date.strftime("%d/%m/%y")}
#matches.each do |match|
match.bets.each do |bet|
bet.bet
end
end
end
I've changed it to match.bets.first (I only have 1 bet for each match_id and user_id so it works).
You would access each match's bets by doing simply match.bets inside your block.
If you wanted to iterate over those bets, use another each.
#sevenseacat is right
#match.bet.each { |bet| bet.attr } maybe good for you

Resources