I have the following models:
class Company
# ...
has_many :invoices
end
class Invoice
# ...
belongs_to :company
has_many :items
field :type, String
scope :expense, where(type: 'expense')
scope :income, where(type: 'income')
end
class Item
# ...
belongs_to :invoice
end
The question is how to fetch all income Items for the given company?
Something similar to company.items.expense
Using embedded relations won't make any difference. Calling company.items.expense would still return an error, since company.items returns an Array.
Try something like this:
class Company
#...
def expenses
self.invoices.where(type: 'expense')
end
def incomes
self.invoices.where(type: 'income')
end
end
Then you can call company.expenses and company.incomes.
Depending on your usage, you may find it better to embed Item inside Invoice or leave it as a separate collection. Also, since you're dealing with invoices, remember to be careful with your callbacks and make them cascade where necessary, so Invoice modified time changes if an Item gets changed.
Related
I have a basic data model with parent-child relationship between Import and ProductLicenseData defined as:
class Import < ActiveRecord::Base
has_many :product_license_data, class: ProductLicenseData, dependent: :destroy
att_reader :extract_at
end
class ProductLicenseData < ActiveRecord::Base
belongs_to :import
end
I want to write a method on ProductLicenseData that will return all "active" records, where "active" is defined as a record where "expirationDate" (a field in the database table the model represents) is greater than import's "extracted_at" value (a field on the database table that model represents). As such, I have something like
def self.active
where("\"expirationDate\" > #{import.extracted_at}")
end
But this doesn't work. I have also tried:
def self.active
ProductLicenseData.joins(:import).where("expirationDate > ?", import.extracted_at)
end
And just about every variation I can think of. Most end up with it telling me it doesn't know what "import" is, or "extracted_at". This seems like something that should be simple, but I am at a loss. How do I write this?
It turns out it's .joins(:import).where('"expirationDate" > imports.extracted_at'), with the extra quotes due to an insect in PostgreSQL...
I have a number of associated tables in an application
class Listing < ActiveRecord::Base
belongs_to :house
belongs_to :multiple_listing_service
end
class House < ActiveRecord::Base
has_one :zip_code
has_one :primary_mls, through: :zip_code
end
I wanted to create a scope that produces all the Listings that are related to the Primary MLS for the associated House. Put another way, the scope should produce all the Listings where the multiple_listing_service_id = primary_mls.id for the associated house.
I've tried dozens of nested joins scopes, and none seem to work. At best they just return all the Listings, and normally they fail out.
Any ideas?
If I understand correctly, I'm not sure a pure scope would be the way to go. Assuming you have:
class MultipleListingService < ActiveRecord::Base
has_many :listings
has_many :zip_codes
end
I would go for something like:
class House < ActiveRecord::Base
...
def associated_listings
primary_mls.listings
end
end
Update 1
If your goal is to just get the primary listing then I would add an is_primary field to the Listing. This would be the most efficient. The alternative is a 3 table join which can work but is hard to optimize well:
class Listing < ActiveRecord::Base
...
scope :primary, -> { joins(:houses => [:zip_codes])
.where('zip_codes.multiple_listing_service_id = listings.multiple_listing_service_id') }
product.rb
has_many :votes
vote.rb
belongs_to :product
Every time, i use sorting in my index controller:
index_controller.rb
def index
#products = Product.all.sort { |m| m.votes.count }
end
So, i think it would be good to cache votes count for each product (create additional column votesCount in products table)?
If yes, can i preform that using before_save and before_delete callbacks in vote.rb model?
Or what is the best practice method?
Give me some examples please.
I guess you are looking for counter_cache
The :counter_cache option can be used to make finding the number of belonging objects more efficient
Consider these models:
class Order < ActiveRecord::Base
belongs_to :customer, counter_cache: true
end
class Customer < ActiveRecord::Base
has_many :orders
end
With this declaration, Rails will keep the cache value up to date, and then return that value in response to the size method.
Although the :counter_cache option is specified on the model that includes the belongs_to declaration, the actual column must be added to the associated model. In the case above, you would need to add a column named orders_count to the Customer model
I have an Order which has many line_items. Only this is not a LineItem module, but a list of "things that act Orderable". E.g. Addon or Site.
class Order
attr_accessor :line_items
before_save :persist_line_items
private
def persist_line_items
#line_items.each {|li| li.save }
end
end
class Addon
belongs_to: order
end
class Site
belongs_to: order
end
Which can be used as:
order = Order.new
order.line_items << Addon.new(order: order)
order.line_items << Site.new(order: order)
But, now I want to load an Order and join the "associated" line_items. I
could load them in an after_initialize hook, and do an
Addon.find_by(order_id: self.id) but that quickly leads to a lot of
queries; where a JOIN would be more appropriate. In addition, I
currently miss the validations trickling up: when a normal has_many
related item is invalid the containing model will not be valid either:
order = Order.new(line_items: [an_invalid_line_item])
order.valid? #=> false
I am wondering if there is a way
to leverage ActiveRecords' has_many-relation to be used with a list of
different models.
I think that a polymorphic association should do the trick.
Would look like this:
class Order < ActiveRecord::Base
has_many :line_items
end
class LineItem < ActiveRecord::Base
belongs_to :orderable, polymorphic: true
end
class Site < ActiveRecord::Base
has_many :line_items, as: :orderable
end
class Addon < ActiveRecord::Base
has_many :line_items, as: :orderable
end
It would use a join table, but i think this is actually a good thing. Otherwise you could use STI for your Addon and Site models, but that would not make a lot of sense in my regard.
Assuming a typical has_many association
class Customer < ActiveRecord::Base
has_many :orders
end
class Order < ActiveRecord::Base
belongs_to :customer
end
How can I add a method to the collection of orders? For the sake of code organization, I'm trying to reactor this method (this is a made-up example) inside of my Customer class:
def update_orders
ThirdPartyAPI.look_up(self.orders) do |order|
# Do stuff to the orders
# May need to access 'self', the Customer...
end
end
I don't like this because it puts a lot of knowledge about the Order class inside my Customer class. I can't use an instance method off of an order, since the ThirdPartyAPI can do a batch lookup on multiple orders. I could make a static method off of Order and pass in the array of orders, and their parent customer, but this feels clunky.
I found this in the rails docs, but I couldn't find any good examples of how to use this in practice. Are there any other ways?
I think this should do it
has_many :entities do
def custom_function here
end
def custom_function here
end
end