Recurring database entries - ruby-on-rails

Quick question about recurring DB entries.
Say I have users posting their Trips on a platform. Now, the user can say these Trips are recurring - she/he makes that trip every Tuesday and Thursday.
To make things even more interesting, say that every Trip has Requests attached to it, that other users can make. And they can make these Requests for every recurring trip.
Any ideas on how would I handle a case like this one on the back-end? Using Rails and Postgres.
Thanks in advance!

User
has_many :trips
Trip
belongs_to :user
has_many :requests
Request
belongs_to :user
belongs_to :trip
Add recurring_start and recurring_end attributes on Trip, and perhaps a recur attribute on Request. I don't know that you need to create any additional records for each Trip then, do you?
If so, you want your business logic handling that. Something like Sidekiq with a Query object that fetches Trips that are due for recurrence and creates the new trip with (for example) updated start and end dates…
class Trip < ApplicationModel
scope :recurring, -> { where(recur: true) }
scope :due_for_recurrence, -> { recurring.where(Trip.arel_table[:end_date].lt(Time.now)) }
end
You can use something like DeepCloneable if you want to automatically clone/dup associated records as well.

Since every trip can have different requests, they all need their own individual ID. It would make sense to treat them exactly the same as non-recurring trips, except for one situation: when the creator of the trips wants to edit or delete all the instances of a recurring trip. For that, you may want to make an additional table for recurring trips, with a one-to-many relation from recurring trip IDs to trip IDs, and allow users to own recurring trip IDs as well as trip IDs. That way the user interface can display the two kinds logically and they won't get lost.
Just make sure that whenever a trip is edited or deleted, the recurring trip table is updated. That could either be accomplished by simply disallowing edits or deletion to trips that are part of a recurring trip, or make the trips table store an optional recurring trip ID.

Related

Can I make a modification to a child force a validation on a parent when using Active Record Autosave Association?

I am looking for how to trigger a validation on a parent when a child is modified or
deleted.
Some background in case I am asking the wrong question:
I am trying to implement some basic double entry accounting in a Rails app. I have found a couple accounting Gems but they seem poorly maintained and overly complex. I also want to have complete control so I am building it myself.
My abstraction currently is a parent class, Txn (avoiding Transaction becuase although it is not a reserved word, it doesn't play well with Active Record). Txn has meta data about the transaction, as well as many LineItems.
LineItems are pretty simple; they have a debit_amount, credit_amount, account_id, and txn_id. I am trying to enforce a constraint on all LineItems belonging to a single Txn such that the sum of debits == the sum of credits. Autosave Association gets me most of the way there, allowing me to put a validator in Txn, but I want to ensure, at the ORM level, that if a LineItem is updated or deleted, that the parent Txn will re-validate and only allow the LineItem to be updated or deleted if all remaining LineItems balance.
I am hesistant to start messing with callbacks on the
LineItem triggering a change to the Txn for fear of creating cirular logic resulting in a race
condition.
I welcome any suggestions or resources as well as specific steps and or callbacks I should use.
class Txn
has_many :lineItems, autosave: true
end
class LineItem
belongs_to :txn
end

Cost of constantly querying an associated nested model (does activerecord cache results?)

Let's say I have User model with a boolean flag called email_notifications. This lets us know whether this user cares to receive email notifications from the app.
Recently I've been moving all these flags and settings into a separate sub-model call Preference to keep it away from the core user model. A User has_one Preference.
class User < ActiveRecord::Base
has_one :preference, dependent: :destroy
accepts_nested_attributes_for :preference
scope :email_recipients, -> { where(preference: { email_notification: true} ) }
def can_receive_email?
preference.email_notification
end
end
As you can see, I have a helper scope and a helper method on the model.
However, now that it lives in another table, I have always query the association :preference first and then get the value I need. It's not directly available from the User model itself any more.
Is this considered bad practice? Or does Rails help out and cache associated models so it doesn't have to re-query every time? I like organizing my various configs in a separate model, which I DO think is good practice, but this potential cost of constantly re-querying is stopping me.
Thanks!
EDIT:
I'm aware that I can do User.includes(:preference).blah_blah, however I want to avoid updating this in EVERY place where I call the user, and it may not always be known ahead of time whether I'm going to query the sub-model and need to include an .includes()
Rails associations are stored in memory after they're accessed so calling user.preference wouldn't hit the database except for the first time it's referenced.
Also, includes wouldn't have much of an effect in this case since this is a has_one. includes is usually useful for eager loading many associations in a single larger query rather than hitting the database each time a child object is called.

Rails: Designing relations between models

My application needs to implement a functionality for performing competitions of photographers. Process looks like this: Administrator creates a competition, then user can apply a request for participating. Admin can approve request or it can deny it. Admin does it by creating a response with response status field assigned to ACCEPTED (0) or BANNED (100).
class Competition
end
class User
end
class CompetitionRequest
belongs_to :user
belongs_to: competition
end
class CompetitionResponse
ACCEPTED = 0
BANNED = 100
belongs_to :competition_request
end
class Photo
belongs_to :competition
end
But later i need to figure out how to filter banned photos from showing them to users and jury.
And Photo has no direct connection to CompetitionResponse. Photo and CompetitionResponse have relations to Competition but i can not figure out how to make filtration possible. I tried doing it via plain sql (find_by_sql) inside Photo model (it returns records only if appropriate request was approved) but it does not seems to be a good design, because i reference value defined in CompetitionResponse class in Photo model.
Later i changed design and make a before_save filter inside CompetitionResponse model, it checks if status == BANNED and if true, marks all the photos posted to competition by user (who's request was banned) as banned (i added a status field to Photo model).
But now i feel it looks not good. CompetitionRequest model takes too much responsibility.
What is the best way to design it ? May be there must some kind of Observer or something like this or another design pattern ?
First step I would take is assign each Photo to the user it "belongs_to". This will allow you to, at any time, check whether the "owning" user was indeed accepted or banned for the competition that photo refers to...
It seems to me that you should have a many-to-many relation between Competition and User. When the admin accepts a user into the competition, you associate the records. This keeps things simple in your data model and also allows for cases where Users get into a Competition without requesting it (perhaps as part of a tournament?).
Also consider getting rid of CompetitionResponse - it seems like this should just be an attribute of CompetitionRequest, as there would only be one response to a request, right?

What is the Rails way of validating ends of a many-to-many relationship that must agree on a property?

Let's say I have many Schools, many Students and many Clubs.
A student can go to one or more schools.
A school can have any number of clubs.
A student can be added to a club as long as they currently are enrolled in the school the club belongs to.
I would be tempted to do something like this in the ClubStudent join class
class ClubStudent < ActiveRecord::Base
belongs_to: student
belongs_to: club
validate: student_school_matches_club_school
def student_school_matches_club_school
unless student.schools.member? club.school
self.errors.add(:student, "must be enrolled in club's school")
end
end
end
The problem, is based on the ordering of how things are created, or persisted, or if a student is added to a club or a club is added to a student, that validation could be run with a nil student or nil club. OR apparently it can fail validation but still be persisted.
What is the best way to deal with this type of validation?
Recently (as of Rails 3.2.13), Rails will save both ends of the the relation if they are not yet persisted before the validation is run.
So they won't be null and they will look persisted.
Rails does this in a transaction, so if the validation fails, you won't end up with persisted objects.
In previous versions of Rails, the values being related could appear as nil in the relation's validation methods.
This makes coding validations much more straightforward as of 3.2.13.
This seems like a major change for a 'TINY' version bump. Make sure related code is well tested.

Rails Model Association Confusion

Hey guys. I have the following models:
Category
Event
Lock
Item
Site
User
Events are basically a "log item". In other words, they will store what action was done on what Item by what User in what Category. Naturally, when I thought about this, I figured it "has one User", "has one Category", "has one Item", and so on. However, this would mean that there would be a foreign key for the Event in any given User row, but this isn't what I want. I want the foreign key in the Event row, since the Event is just giving information as to what User, what Category, etc.
So my understanding is that I should instead say that an Event "belongs to a user", "belongs to a category", etc. and that they each "have many Events" in return, correct? I'm just making sure, because this doesn't read logically as most other associations. I don't need/want to be able to access an event from the other side (i.e. user.event) because it wouldn't make much sense. So if I do this, would I just add the belongs_to call and not the has_one on the other side?
Perhaps I designed this incorrectly.
I eventually want to be able to render a 'log page' filled with rows, reach row described a little something like:
event.user event.action event.item event.category
I don't need/want to be able to access
an event from the other side (i.e.
user.event) because it wouldn't make
much sense. So if I do this, would I
just add the belongs_to call and not
the has_one on the other side?
Add them both(belongs_to and has_many). Sure, user.event doesn't make sense, but user.events does make sense.
Yes, here you want to use a has_many & belongs_to association. In the context of Activerecord, it is the has_many that defines the need for the belongs_to. "If a model (a) has_many of another model (b) then that associated model (b) belongs_to the first model (a)".
Since a user will have many events associated with it, then an event will belong_to a user.
If on the other hand, a user were to only ever have one event associated with it, then these models would have a "has_one" association.

Resources