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...
Related
For example, have the models:
class Activity < ActiveRecord::Base
belongs_to :event
end
class Event < ActiveRecord::Base
has_many :activities
attr_accessible :foo
end
I can get the activity's event foo by using activity.event.foo (simple enough).
But I want to make a generic function that finds out first if an object has a belongs_to association and then get that object's foo through the belongs_to association (pretend that all objects have a foo through the belongs_to association)?
So far I have the following with gives me a reflection:
def get_foo(object)
object.class.reflect_on_all_associations(:belongs_to).each do |belongs_to|
return object.??????
end
end
I can either get an array of the reflection's class name via belongs_to.klass (e.g. [Event]) or an array of symbols for the belongs_to association via belongs_to.name (e.g. [:event]).
How do I get the object's belongs_to's foo given what I get from the reflection?
Is there an easier way to do this without using the reflection?
I'm hoping this is something simple and I'm just spacing out on how to solve this. I also hope I am being somewhat clear. This is my first Stack Overflow question.
You can do this but its not exactly pretty:
def get_foo(object)
object.class.reflect_on_all_associations(:belongs_to).map do |reflection|
object.send(reflection.name).try(:foo)
end
end
That will give you an array of all the foos associated with the object. You can change it to not do map and do a first or something.
I have two models
class Department < ActiveRecord::Base
has_many :checklists
attr_accessible :deadline
after_update :update_checklist
class Checklist < ActiveRecord::Base
belongs_to :department
attr_accessible :content, :category
Basically, the 'department' model has a virtual attribute called 'deadline', and it is in type of date. The actual value of 'deadline' is stored in another model 'checklist', in format of string.
Every time when 'deadline' is updated, I would like to check if there is an entry in 'checklist', and create (if not yet) or update (if already has an entry).
I was thinking this way
def deadline=(deadline)
#cl = Checklist.find_or_create_by_department_id_and_category(self.id, 'deadline')
#cl.update_attributes(:content => deadline.to_s)
#cl.save
end
def deadline
#deadline = self.checklists.find_by_category('deadline')
Date.parse(#deadline.to_s)
end
But the above virtual attribute is not working.
When searching for the answer, I found on rails cast that callback will be a better solution for this kind of situation. So I am trying to something like:
class Department < ActiveRecord::Base
after_update :update_checklist
def update_checklist
#cl = Checklist.find_or_create_by_department_id_and_category(self.id, 'deadline')
#cl.update_attributes(:content => ???)
end
I am not sure how to pass the value to the callback.
Please help me with this design. what is the standard way to handle this? Thank you in advance!
update_checklist is a method of Department. So within update_checklist, you can access any Department attributes, just like self.id, self.deadline is what you want.
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.
I have a situation where I want to make 'parametric' models in rails; for example I'd like to define PrototypeRecipe, and then be able to make multiple DerivedRecipe's; maybe one derived recipe uses more sugar and another uses less eggs or something. The critical point is that I want all the 'derived' instances to inherit properties from a single shared PrototypeRecipe, but be able to make local modifications.
Ideally, I'd like to be able to define methods on the prototype (say, putting together a shopping list), and have these methods respond to local changes in derived instances (so if I specified 3 eggs instead of 2, i could call the prototype's make_shopping_list function and it would reflect that).
Is there an existing method for accomplishing something like this? Here's the best I can come up with so far:
class Ingredient << ActiveRecord::Base
belongs_to :recipe, :polymorphic => true
# uuid => UUID String (for grouping ingredients which change between prototype and derived instances)
end
class PrototypeRecipe << ActiveRecord::Base
has_many :ingredients
def make_ingredient_list(derived_recipe = nil)
self.ingredients.map {|i| derived_recipe.nil? ? i : derived_recipe.ingredients.where(:ingredient_uuid => i.uuid).first }
end
end
class DerivedRecipe << ActiveRecord::Base
belongs_to :prototype_recipe
has_many :ingredients
def method_missing(sym, *args)
self.prototype_recipe.send( sym, *args, self)
end
end
I know this code can be made a lot cleaner, I'm more wondering if the general approach can be improved on. The basic idea is that ingredients would each have a unique ID. To modify a prototype recipe, you simply create an instance of DerivedRecipe, link it to the prototype, and then add an ingredient with the same UUID as one of the prototype's ingredients.
I'm not 100% on what behavior you are looking to have, so here's my attempted solution.
Single-Table Inheritance (STI). Your base class will be PrototypeRecipe and your child class will be DerivedRecipe.
In your prototype_recipes table, specify a type column (text). This signals to Rails you want to use STI. If you put your make_ingredients_list method inside the base class, it will be accessible from your child classes.
# app/models/ingredient.rb
class Ingredient < ActiveRecord::Base
belongs_to :recipe, :class_name => "PrototypeRecipe"
...
end
# app/models/prototype_recipe.rb
class PrototypeRecipe < ActiveRecord::Base
has_many :ingredients
has_many :derived_recipes
def make_ingredient_list
...
end
end
# app/models/derived_recipe.rb
class DerivedRecipe < PrototypeRecipe
belongs_to :prototype_recipe
end
Now you can do something like:
#cupcakes = PrototypeRecipe.create
#cupcakes_with_extra_eggs = #cupcakes.derived_recipes.create
print #cupcakes_with_extra_eggs.make_ingredient_list
Is this what you were looking for?
I'd like to be able to describe different types of a model using RoR associations. An example:
Models:
Post
ImagePost
post_id:integer
url:string
MessagePost
post_id:integer
message:string
ImagePost and MessagePost are a type of Post. I'd like #posts = Post.all to retrieve both types of post and allow me access to their attributes via #posts.url or #posts.message.
I'm sure I'm missing something simple, please enlighten me!
Cheers,
Ben.
Look into the concept of Single Table Inheritance -- the basic idea is that you will have a single Post table which will have a Type column, so a given ImagePost will still just be a row in the Post table. The Post table will have columns for all possible properties, so it will have url and message columns.
Then the corresponding model classes will inherit from Post: ImagePost
You could try the mixed model approach, but it's a fair amount of work to set up. It's bit of of a kludge that trades performance for more efficient database storage.
The idea is that you use STI to handle all the common Post fields, and delegate the unique fields for each subclass to an another table and eager load that association.
The base Post class could look like this. Note the class_eval could be abstracted into a module that gets included and exended into a subclass.
#columns: id:integer, timestamps, user_id:integer,
# topic_id:integer, type:string
class Post < ActiveRecord::Base
# common methods/validations/associations
belongs_to :user
belongs_to :topic
def self.relate_to_detail
class_eval <<-"EOF"
has_one :detail, :class_name => "#{self.name}Detail"
accepts_nested_attributes_for :detail
default_scope :include => :detail
def method_missing(method, *args)
build_detail if detail.nil?
if detail && detail.respond_to?(method, true)
detail.send(method, *args)
else
super(method, *args)
end
end
def respond_to?( method, include_private = false)
build_detail if detail.nil?
super(method, include_private) ||
detail.respond_to?(method, include_private)
end
EOF
end
end
Then you'll need to define the sub and detail class for each type.
#uses posts table
class ImagePost < Post
relate_to_detail
end
#columns: id, image_post_id, url:string, height:integer, :width:integer
class ImagePostDetail < ActiveRecord::Base
belongs_to :image_post
end
#uses posts table
class MessagePost < Post
relate_to_detail
end
#columns: id, message_post_id, message:string
class MessagePostDetail < ActiveRecord::Base
belongs_to :image_post
end
Now we can do things like this:
#user.message_posts.create(:message => "This is a message")
#image_post.url
Which will create a new MessagePost, where the user_id, timestamps, post_id, post_type are all stored in the posts table, while the message is stored in the MessagePostDetails table and return the url of an ImagePost respectively.
The new method_missing and respond_to? definitions work the magic to hide the division.
#Post.all will now list Posts of all types. The only downside is that the detail fields will not be displayed when you fetch a post.