Include column from a :belongs_to association? - ruby-on-rails

Product model
Class Product < ActiveRecord::Base
belongs_to :product_group
end
ProductGroup model
Class ProductGroup < ActiveRecord::Base
has_many :products
end
Is the a way to declare a shortcut for product.product_group.name as product.name,
and have product_group.name included in product.to_json as name whenever a Product is converted to json?

To answer your first question: create a name method in Product
def name
product_group.name
end
As for your second question, you can customize as_json, also in your Product model. Something like this should work.
def as_json(options = {})
super.merge({ name: name })
end

Related

Iterate over STI list in rails 4

I have two sub models, called: Service and Product that inherits from ProductBase. And I have another model to consume it. Acquire that have many AcquireBasket. Check out my code:
product_base.rb:
class ProductBase < ActiveRecord::Base
extend ::EnumerateIt
include Searchable
self.table_name = 'products'
end
product.rb:
class Product < ProductBase
default_scope { where(kind: ProductKind::PRODUCT) }
def initialize(attributes = {})
super(attributes)
self.kind = ProductKind::PRODUCT
self.status = ProductStatus::DRAFT
end
end
service.rb:
class Service < ProductBase
default_scope { where(kind: ProductKind::SERVICE) }
def initialize(attributes = {})
super(attributes)
self.kind = ProductKind::SERVICE
self.status = ProductStatus::DRAFT
end
end
acquire_basket.rb:
class AcquireBasket < ActiveRecord::Base
extend ::EnumerateIt
belongs_to :acquire
belongs_to :product
end
In some part of my project, I get a list (acquire baskets) of both models, Service and Product. And I need to check if I have services inside of it.
My code to check was:
def services_in?(acquire)
acquire.baskets.map(&:product).detect(&:service?)
end
The code works, ONLY if I pass services first, and products after!! Or if I have only one of them.
You should be able to utilize the descendents method to iterate over all of the subclasses
I can't find the answer in blog post around the world, so I will share with you:
class AcquireBasket < ActiveRecord::Base
extend ::EnumerateIt
belongs_to :acquire
belongs_to :product, class_name: 'ProductBase'
end
The problem was, when I try to find (lazily) in a ActiveRecord::Relation, Rails lookup (I think) to just Product model. And It can't find other type models inside of it. So using this typo I put it to work.

ActiveRecord default value if attribute is nil

Looking for a cleaner way to set a default value if attribute is not set yet or has been deleted, and returns nil.
class Category < ActiveRecord::Base
has_and_belongs_to_many :restaurants
belongs_to :picture
def set_picture
if self.picture.nil?
Picture.default_pic
else
self.picture
end
end
end
class Picture < ActiveRecord::Base
belongs_to :review
def self.default_pic
Picture.new(url: "/assets/default.jpg")
end
end
# index.html.erb
<%= image_tag category.set_picture.url %>
categories has many restaurants, and restaurants has many reviews. Reviews has one to one picture. category should be allowed to select from one of its associated pictures, or defaults to image in assets folder.
The #set_picture needs to get refactored out. Hopefully to a callback of some type:
class Category < ActiveRecord::Base
belongs_to :picture, defaults_to: Picture.default_pic
end
Is there a callback that does the above? Can I create one? Or is my framework wrong?
I think you could just override the accessor and call super. If this returns nil then you could return your default picture:
class Category < ActiveRecord::Base
belongs_to :picture
def picture
super || Picture.default_pic
end
end

How to show the sum of all Prices that a Student has

Student has_many Lessons
Lesson belongs_to Prices
How can I show the sum of all Prices that Student has in show action of the StudentsController?
As #mgidea already correctly said:
You want to create a has_many :through relationship in your Student model first and then you want to convert the prices of your Student into an Array with #to_a and then create the sum of your price_attribute.
Add the following to your Student model:
class Student < ActiveRecord::Base
has_many :lessons
has_many :prices, through: :lessons # <= Add this here
end
Your show action could than look like:
class StudentsController < ApplicationController
def show
#student = Student.find(params[:id]
#sum = #student.prices.to_a.sum(&:price)
# Equivalent to:
# #sum = #student.prices.to_a.sum { |p| return p.price }
end
end
Than you could use the instance variable #sum in your view.
Hope this helps!
Happy coding :)
Addin a query of sum in controller does it.
Answer: https://github.com/yshmarov/myclass101/commit/9a998da2af07caee76948d2941ad006029a0f47a

Using sunspot to search down model hierarchy

Example:
I have the following:
class Person < ActiveRecord::Base
has_many :educations
end
class Education < ActiveRecord::Base
belongs_to :school
belongs_to :degree
belongs_to :major
end
class School < ActiveRecord::Base
has_many :educations
# has a :name
end
I want to be able to return all people who went to a specific school so in my PeopleController#index I have
#search = Person.search do
keywords params[:query]
end
#people = #search.results
How do I create the searchable method on the Person model to reach down into school? Do I do something like this:
searchable do
text :school_names do
educations.map { |e| e.school.name }
end
end
which I would eventually have to do with each attribute on education (degree etc) or can I make a searchable method on Education and somehow "call" that from Person.searchable?
Thanks
It would be best if you keep the declaration of all the indexed fields for an specific model in the same place.
Also, you were doing a good job indexing :school_names, just do the same thing for the rest of the associations fields' that you want to index.

How do I count records that satisfy a condition in a associated model?

Okay, what I've got is two models...
Jiraissue:
class Jiraissue < ActiveRecord::Base
# JIRA uses a singular table name for this model
set_table_name 'jiraissue'
has_one :severity
end
Severity:
class Severity < ActiveRecord::Base
belongs_to :jiraissue
end
What I'm trying to do is get a count of all Jiraissues for which jiraissue.severity = "S1"
Now it turns out that the jiraissue table has a column for priority so I can pull this trick in the model...
Jiraissue:
class Jiraissue < ActiveRecord::Base
# JIRA uses a singular table name for this model
set_table_name 'jiraissue'
has_one :severity
def self.count_priority(priority)
where("PRIORITY = ?",priority).count()
end
end
And then in the view do something like...
<%= (1..4).map {
|priority| Jiraissue.biit.bugs.recent.count_priority(priority)
}.inspect %>
How do I do something similar for Jiraissue to get a count_severity method?
This just doesn't work (nor would I expect it to)...
def self.count_severity(severity)
where("severity = ?",severity).count()
end
But I'm totally confused.
Jiraissue.joins(:severities).where(:severities => {:severity => "S1"}).count
model
def self.count_priority(priority)
where("PRIORITY = ?",priority).size
end
controller
def index
#jiraissues = Jiraissue.count_priority('S1')
end
Doesn't it work?

Resources