Ruby ActiveRecord has_one with conditions - sql

Let's say I have some Items for sale, and I'm keeping track of their Cost historically:
class Cost < ActiveRecord::Base
belongs_to :item
# eg: costs.amount = 123.45; costs.item_id = 1; costs.created_at = 2011-08-11 16:28
end
class Item < ActiveRecord::Base
has_many :costs
# eg: items.id = 1; items.name = Cheese Sandwich
end
This code works, I can pull out all the previous costs for the item I'm selling.
I feel like it should be possible to have a second clause for Item so that I can pull out the current price directly:
class Item < ActiveRecord::Base
has_many :costs
has_one :current_cost, :class_name => :costs, :conditions => 'MAX(created_at)'
end
my_item.current_cost # => <£123.45, 45 minutes ago>
Any ideas how to achieve this?

class Item < ActiveRecord::Base
has_many :costs
def current_cost
self.costs.order("created_at DESC").first
end
end
my_item.current_cost

has_one :current_cost, :class_name => :costs, :order => 'create_at DESC'

You can use the scope:
class Item < ActiveRecord::Base
has_many :costs
scope :current_cost, limit(1).order("created_at DESC")
end
usage:
my_item.current_cost

Related

How to group by attribute but display value of nested attribute?

I've got these models in my Rails 6 application:
class Client < ApplicationRecord
belongs_to :account
has_many :people
end
class Person < ApplicationRecord
belongs_to :client
end
class Payment < ApplicationRecord
belongs_to :client
end
In my SharesController I am trying to generate the total payments for each client and show them as a pie chart:
class SharesController < ApplicationController
def index
#clients = current_account.clients.joins(:payments)
.where(:payments => {:date => #range, :currency => #currency})
.order("sum_payments_#{#part} DESC")
.group("clients.id", "clients.name")
.having("sum_payments_#{#part} > 0")
.sum("payments.#{#part}")
end
end
The problem with this is that it groups by client correctly. However, rather than showing each client's name I want to show the last_name of each client's first nested person.
How can this be done?
Thanks for any help.
You should try to create a join between Client and Person and then use uniq to avoid duplicated clients.
You could try something like this (I'm not sure if this code works but just to make it clearer what I mean)
#clients = current_account.clients.joins(:payments, :people)
.where(:payments => {:date => #range, :currency => #currency})
.order("sum_payments_#{#part} DESC")
.group("clients.id", "people.last_name")
.having("sum_payments_#{#part} > 0")
.sum("payments.#{#part}")

uninitialized constant Order::OrderItem with belongs_to in OrderItem

I have a code that once i create the order, it will automatically fill up information for the order items (because every order has many items) but i have the error uninitialized constant Order::OrderItem. How do i solve this?
Model
class Order < ActiveRecord::Base
# attr_accessible :title, :body
attr_accessible :amount, :currency
has_many :order_items
end
class OrderItems < ActiveRecord::Base
attr_accessible :items, :order_id, :quantity
belongs_to :order
end
Controller
def checkout
#order = Order.new # Create new order
#order.total = #shopping_cart.total
#order.sub_total = #shopping_cart.subtotal
#order.sales_tax = #shopping_cart.taxes
#shopping_cart.shopping_cart_items.each do |cart_item|
#orderitems = #order.order_items.build(items: cart_item.item.name, quantity: cart_item.quantity)
end
end
uninitialized constant Order::OrderItem
The problem is with this line
class OrderItems < ActiveRecord::Base
Model class names supposed to be singular.Change OrderItems to OrderItem.And also don't forget to change the model file name as well.

Rails active record query through multiple tables

I am trying to query for questions based on subject or category. I have a Category model which has many Subjects, and a Subjects model which has many Questions. How do I select 50 questions where the subject_id = x or category_id = y? I'm not sure if I need to change my model associations then query or use a query with the current associations. Here are the models (stripped of some excess code):
category.rb
class Category < ActiveRecord::Base
has_many :subjects, class_name: "Subject",
foreign_key: "category_id"
has_many :questions, through: :subjects
end
subject.rb
class Subject < ActiveRecord::Base
belongs_to :category
has_many :questions, class_name: "Question",
foreign_key: "subject_id"
end
question.rb
class Question < ActiveRecord::Base
belongs_to :subject
end
The most success I've had is with "Question.joins(:subject).group(category_id:1)", which only returns the last question with an associated category. Any suggestions? Thanks!
So you could make a scope
class Question < ActiveRecord::Base
scope :q_or_c ->(q, c){ where('category_id = ? OR question_id = ?', q, c) }
...
end
and then call it with
Question.q_or_c(question_id, category_id)

rails alternative name for association one to many

Simply i have table
[product_categories]
name
and
[products]
category_id
name
if i use in product model
class Product < ActiveRecord::Base
attr_accessible :...
belongs_to :product_category
end
class ProductCategory < ActiveRecord::Base
attr_accessible :...
set_table_name "product_categories"
has_many :products
end
i can fire
product = Product.new
product.product_category
but it is possible to rename that product_category for association for example
product.category
?
If you don't need to refer to the category with product.product_category and want to use only product.category do:
class Product < ActiveRecord::Base
attr_accessible :...
belongs_to :category, class_name: 'ProductCategory'
end

Using after_create

I have a model, Category. And I want to create an new default sub_category when ever the category is created. But I'm not sure how to do it. Here is what I have.
class Category < ActiveRecord::Base
attr_accessible :title, :position
has_many :sub_categories
after_create :make_default_sub
def make_default_sub
#Sub_Categories.new( :title=>' ');
end
end
Why not to use ancestry gem? In the future if you will have more subcategories, it will be easier to manage them.
For example in your case:
class Category < ActiveRecord::Base
attr_accessible :title, :position
has_ancestry
after_create :create_default_subcategory
def make_default_sub
children = self.children.new
children.title = ''
children.position = 1 # or autogenerated
children.save!
end
end
But can you explain, why do you need such a strange default behaviour?
Thanks