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
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
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.
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.
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
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