In my application I have a customers model that has many payments and invoices.
# customer.rb
class Customer < ActiveRecord::Base
has_many :payments
has_many :invoices
end
# payment.rb
class Payment < ActiveRecord::Base
belongs_to :customer
end
# invoice.rb
class Invoice < ActiveRecord::Base
belongs_to :customer
end
In the customers show template I am combining all Invoices and Payments and storing them in the #transactions instance variable.
class CustomersController < ApplicationController
def show
#customer = Customer.find(params[:id])
payments = Payment.where(customer: #customer)
invoices = Invoice.where(customer: #customer)
#transactions = payments + invoices
end
I want to paginate #transactions using will_paginate. Doing this doesn't work:
#transactions.paginate(page: params[:page])
What is the best way to accomplish this?
Best way is to create a third Table of Transactions with polymorphic association as transactionable. And paginate over transactions.
http://guides.rubyonrails.org/association_basics.html#polymorphic-associations
First Learn polymorphic association
class Transaction < ActiveRecord::Base
belongs_to :transactionable, polymorphic: true
end
class Invoice < ActiveRecord::Base
has_many :transactions, as: :transactionable
end
class Payment < ActiveRecord::Base
has_many :transactions, as: :transactionable
end
Other way which is not good to paginate both or use paginate array.
Related
I have the three models:
class Joinedtravel < ApplicationRecord
belongs_to :travel
belongs_to :user
end
class Travel < ApplicationRecord
has_many :joinedtravels
belongs_to :user
end
class User < ApplicationRecord
has_many :joinedtravels
has_many :travels
end
How can I obtain all travels that a user has joined in the past?
I did something like that:
#user = User.find(id)
#past_travels = Travel.where('travels.data < ?', DateTime.now)
#all_joinedtravels = #user.joinedtravels.travels
but i don't kwon how to correctly join the results.
First you need to fix the relationship
class Joinedtravel < ApplicationRecord
belongs_to :travel
belongs_to :user
end
class Travel < ApplicationRecord
has_many :users, through: joinedtravels
has_many :joinedtravels
end
class User < ApplicationRecord
has_many :travels, through: joinedtravels
has_many :joinedtravels
end
Then you can simply search it using
User
.find(id)
.travels
.where('travels.data < ?', DateTime.now)
This should work:
#user = User.find(id)
#past_joinedtravels = #user.joinedtravels.joins(:travels).where('travels.date < ?', DateTime.now)
Try this in the console, and pay attention to the sql produced. That will show you possible errors.
The travelsin the joins clause is the model name. The travelsin the where clause must be the literal database table name, which I just guessed.
Seems to me you'd be better off using a has_and_belongs_to_many relations and a join table to join the User and Travel models as long as you're not including any additional information in the JoinedTravel model?
https://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association
class Travel < ApplicationRecord
has_and_belongs_to_many :user
end
class User < ApplicationRecord
has_and_belongs_to_many :travels
end
#user = User.find(id)
#past_travels = Travel.where('travels.data < ?', DateTime.now)
#user_travels = #user.travels
You could then see if a user has any travels:
#user.travels.present?
I'm struggling with a .where statement in an index action.
In my Deals controller, i'd like to list all the deals where the bank of the current_user is participating.
Below are my models :
class User < ActiveRecord::Base
belongs_to :bank
end
class Deal < ActiveRecord::Base
has_many :pools
end
class Pool < ActiveRecord::Base
belongs_to :deal
has_many :participating_banks, dependent: :destroy
has_many :banks, through: :participating_banks
end
class ParticipatingBank < ActiveRecord::Base
belongs_to :pool
belongs_to :bank
end
Here is my Deals Controller Index action :
def index
#deals = Deal.all
end
I don't find any way to say : 'I only want to see a deal if this deal has, at least, one pool where the current_user.bank has been added'.
Any idea?
Many thanks :)
You should do inner join and query joined table for id. You can easily do it in Rails by:
def index
#deals = Deal.joins(pools: :banks).where(banks: { id: current_user.bank_id })
end
I have three models Company, User and Division
User have many Division for different Companies
I need to determine in what company owns Divisions
So I build has_many :through association between Users and Divisions
Model UsersDivision have this fields id|user_id|division_id|company_id but when I update User model rails delete old records and create new without company_id field How i can update model UsersDivision and merge company_id ?
Callback?
class UsersDivision < ActiveRecord::Base
after_update :set_company
belongs_to :user
belongs_to :division
belongs_to :company
validates :user_id, :division_id, presence: true
private
def set_company(company)
self.company_id = company
end
end
or in the controller?
class UsersController < ApplicationController
def update
#company = Company.find(params[:company_id])
#user = User.find(params[:id])
if #user.update(user_params)
redirect_to :back
end
end
end
How to merge company_id when create UsersDivision record?
So I build has_many :through association between Users and Divisions
I would expect there to be a table for Divisions, and then a table for CompanyDivisions, and then we can associate users to that.
Here's how I would have it set up:
#app/models/user.rb
class User < ActiveRecord::Base
has_many :user_divisions
has_many :divisions, through: :user_divisions
has_many :company_divisions, through: :user_divisions
has_many :companies, through: :company_divisions
end
#app/models/user_division.rb
class UserDivision < ActiveRecord::Base
belongs_to :user
belongs_to :company_division
end
#app/models/company.rb
class Company < ActiveRecord::Base
has_many :company_divisions
has_many :divisions, through: :company_divisions
end
#app/models/company_division.rb
class CompanyDivision < ActiveRecord::Base
belongs_to :company
belongs_to :division
end
#app/models/division.rb
class Division < ActiveRecord::Base
has_many :company_divisions
has_many :companies, through: :company_divisions
end
This is very bloated, but should give you the ability to call:
#user.divisions
#user.divisions.each do |division|
division.companies.first
How to merge company_id when create UsersDivision record
This will depend on several factors:
params hash
How your associations are set up
I don't have your params hash, but I do have your current code:
class UsersController < ApplicationController
def update
#company = Company.find params[:company_id]
#user = User.find params[:id]
redirect_to :back if #user.update user_params
end
private
def user_params
params.require(___).permit(___).merge(company_id: #company.id)
end
end
I have a quite complicated relation between models and are now frustrated by a SQL Query to retrieve some objects.
given a Product model connected to a category model via a has_many :through association and a joint table categorization.
Also a User model connected to this category model via a has_many :through association and a joint table *category_friendship*.
I am now facing the problem to retrieve all products, which are within the categories of the array user.category_ids. However, I can't just not manage to write the WHERE statement properly.
I tried this:
u = User.first
uc = u.category_ids
Product.where("category_id IN (?)", uc)
However this won't work, as it doesn't have a category_id in the product table directly. But how can I change this to use the joint table categorizations?
I'm giving you the model details, maybe you find it helpful for answering my question:
Product.rb
class Product < ActiveRecord::Base
belongs_to :category
def self.from_users_or_categories_followed_by(user)
cf = user.category_ids
uf = user.friend_ids
where("user_id IN (?)", uf) # Products out of friend_ids (uf) works fine, but how to extend to categories (cf) with an OR clause?
end
Category.rb
class Category < ActiveRecord::Base
has_many :categorizations
has_many :products, through: :categorizations
has_many :category_friendships
has_many :users, through: :category_friendships
Categorization.rb
class Categorization < ActiveRecord::Base
belongs_to :category
belongs_to :product
Category_friendship.rb
class CategoryFriendship < ActiveRecord::Base
belongs_to :user
belongs_to :category
User.rb
class User < ActiveRecord::Base
has_many :category_friendships
has_many :categories, through: :category_friendships
def feed
Product.from_users_or_categories_followed_by(self) #this should aggregate the Products
end
If you need more details to answer, please feel free to ask!
Looking at the associations you have defined and simplifying things. Doing a bit refactoring in what we have to achieve.
Product.rb
class Product < ActiveRecord::Base
belongs_to :category
end
User.rb
class User < ActiveRecord::Base
has_many :categories, through: :category_friendships
scope :all_data , includes(:categories => [:products])
def get_categories
categories
end
def feed
all_products = Array.new
get_categories.collect {|category| category.get_products }.uniq
end
end
Category.rb
class Category < ActiveRecord::Base
has_many :users, through: :category_friendships
has_many :products
def get_products
products
end
end
NO NEED OF CREATING CATEGORY_FRIENDSHIP MODEL ONLY A JOIN TABLE IS NEEDED WITH NAME CATEGORIES_FRIENSHIPS WHICH WILL JUST HAVE USER_ID AND CATEGORY_ID
USAGE: UPDATED
Controller
class UserController < ApplicationController
def index
#all_user_data = User.all_data
end
end
view index.html.erb
<% for user in #all_user_data %>
<% for products in user.feed %>
<% for product in products %>
<%= product.name %>
end
end
end
I've upvoted Ankits answer but I realized there is a more elegant way of handeling this:
given:
u = User.first
uc = u.category_ids
then I can retrieve the products out of the categories by using:
products = Product.joins(:categories).where('category_id IN (?)', uc)
im working on this model association class assignment. the basic association works, but im having issue with the "category"-page view.
Category Page Output should be (/categories/1)
Dish-ID
Dish-Title
Restaurant-Title <= HOW DO I GET THIS VALUE?
rules:
- dish belongs to one category
- same dish can be in multiple restaurants
class Category < ActiveRecord::Base
has_many :dishes
end
class Dish < ActiveRecord::Base
belongs_to :category
end
class Restaurant < ActiveRecord::Base
has_and_belongs_to_many :dishes
end
class DishRestaurant < ActiveRecord::Base
has_many :restaurants
has_many :dishes
end
Category Controller
def show
#category = Category.find(params[:id])
#dishes = #category.dishes
// RESTAURANT TITLE ??
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #category }
end
Category View:
<%= debug #dishes %>
any hint would be helpful.
thanks
pete
Define you models properly:
class Dish < ActiveRecord::Base
belongs_to :category
has_and_belongs_to_many :restaurants
end
class Restaurant < ActiveRecord::Base
has_and_belongs_to_many :dishes
end
This would use the implicit join table names "dishes_restaurants". You only need a join model is you store some join specific information, like price of the dish in the restaurant. In which case you models should be like:
class Dish < ActiveRecord::Base
belongs_to :category
has_many :dish_restaurants
has_many :restaurants, through => :dish_restaurants
end
class Restaurant < ActiveRecord::Base
has_many :dish_restaurants
has_many :dishes, through => :dish_restaurants
end
class DishRestaurant < ActiveRecord::Base
belongs_to :restaurant
belongs_to :dish
end
Whatever approach you follow, you can do dish.restaurants to retrieve the list of the restaurants which serve the dish.