How to Manage Time/Date Schedules? - ruby-on-rails

I'm putting together a tool that allows a user to generate reports for a class of students. I'd like to incorporate report "periods" or "schedules" but I'm unsure of how to do so.
Essentially, I want the user to assign an evaluation "schedule" to each class, i.e. from the 5th of one month to the 4th of the next. Thus, reports will (and must) be run for sequential periods. However, I do want the user to be able to adjust the end period of the schedule for a student on an ad hoc basis.
I thought of creating a "schedules" table, but I'm not sure of how to store the start and end dates so the cycle can be repeated. Anyone have any suggestions?

I've used ice_cube (GitHub project) with some success. The module handles recurrences well, it's got its own serializer/deserializer, and it's well-documented.

You could create a report model/table with a start day and end day (such as 4 and 5) and use that to set the date with. This would persist to the database normally, but for a one off report that doesn't need to be stored, you could just create a new report with a different end date.
I.E., you have a reports table for persistent reports (A report for an entire class of students), but don't save your individual reports.

Related

Track count of the new and updated records seperatly

Currently working on a project where any admin can import a xlsx product sheet into active record. I've developed it so that the xlsx parser hands each unique product row to a job which either updates an existing product or creates a new based on the attributes given.
I would like to keep track of the count of products either updated and created per sheet imported, assets added etc, to display in the admin panel.
The method i use now is simply creating events with an associated product id's that respond to a save record conditional, which i then count up and display after the import is done.
if product.save
product.events.new(payload: 'save')
end
The problem with this technique is that i can't differentiate between if the product is new or has been updated.
Are there better techniques that are more suitable to achieve counting products saved while differentiating between if its updated or new?
TDLR;
Importing products to active record (1 job per product) from an excel sheet. What are the better practise's/techniques for keeping count of new and updated records seperatly per import.
You have several choices here:
A simple option, as per my comment, is simply to check the created_at and updated_at columns after the record is saved. If they're equal, it's a new record, if not, it means the record already existed and was updated. You would have something along these lines:
if product.created_at == product.updated_at
new_product_count += 1
else
updated_product_count += 1
end
However, there might be better ways to do this. Just as an example: If I understand correctly you keep track of the number of saved products by creating a new 'save' event. You could instead have two types of events: created and updated. (This would have the added benefit of allowing you to count how many times a product has been updated since it was created)
I don't know if this can help you but in these cases I use persisted? method.
person = Person.new(id: 1, name: 'bob')
person.persisted? # => false

Generic flags for a model in RoR

I am making a Ruby on Rails app and am realizing that my User class could potentially end up with a lot of generic boolean / integer attributes. For example, suppose I have a promotion each quarter, and I only want a person to be able to use the promotion once. Then I'd have to make a new column each quarter has_used_promotion_N to track that promotion.
Alternatively, I'm thinking of creating a new column called "Generic Flags" which is just a comma separated value of flags set on the account. For example:
"has_used_promotion_1, has_used_promotion_2, limit_on_feature_a=20" etc. could be set for some particular user
(or maybe I'll store it as JSON)
In any case, I'm thinking of giving myself some sort of NoSQL-like functionality in my DB.
Is this really bad design for some reason? Has anyone else done this before? Anything I'm completely missing about RoR?
In my opinion Promotion should be a separate model with a many to many relationship with User. When you have a promotion you would create a Promotion instance and when a person uses that promotion you add that person to promotion.users relationship.
This is much better than your idea because you can now query those relationship. Want a list of all users that used the first quarter promotion? No problem. You can do that with your solution, but you have to resort to some hackiness (is that a word?) to do it, and you'd have to parse the generic flag string for EVERY user on EVERY query. Not ideal to say the least.
If there's an arbitrarily-sized collection of associations then it should be a real relation, modeled using the existing DB and facilities. Promotions sounds like that, and it seems like it would be something you'd be modeling in your DB already; no real reason to keep a duplicate value hierarchy.
For actually-generic flags, you could have a named-flag table and again use a real association.
You could also just serialize a flag object to a text column. Doing so impedes your ability to do trivial searches on a flag/flag value, however. This may not matter for a wad of flags associated with a single user that you don't care about unless they're logged in, but tread lightly--it depends on your usecase.

Where in Rails to fill in gaps in time series?

My basic set of models looks roughly like this (simplified):
[ PayPeriod ]
id
start_date
end_date
notes
[ Transaction ]
id
amount
fkPayPeriod
When a user logs in, I want to present them with a list of the last 4 pay periods. The user can select a pay period to enter notes and transactions.
I'm inclined to just do something like this in the controller:
def index
#pay_periods = PayPeriod.get_or_create_last(4)
end
The PayPeriod model itself would implement the behavior, and records would be created "on demand" as users used the app.
An alternative approach might be to have some other (background) process that combs through accounts on a daily basis to proactively create new PayPeriods. Although neither solution strikes me as particularly challenging, I'd like to get some feedback on where others feel this functionality belongs conceptually.
I'd say it depends on what a PayPeriod is, conceptually. Is it a universal description of time periods on a common calendar (i.e., the year 2011 has 26 pay periods of two weeks each)? If so, then the creation of all the PayPeriods belongs in your db/seeds.rb file.
If a PayPeriod belongs to an account, I'd say that the creation of the last four PayPeriods belongs in an after_create hook on the account in question. Going forward from there, I think the best practice would be to create new PayPeriods as your user needs them; that is, the first time I go to add notes or a transaction to a PayPeriod is probably when it should get created.
If for any reason you have a system policy in place that allows users to edit a specific window of PayPeriods (e.g., you can edit this and the next calendar year), then you might set up a Rake task and hook it up to a Cron job that runs it however often it needs to be run (e.g., if you're limiting your window by calendar year, then you could set up a Cron job to run every January 1 at 12:01am that creates the year's PayPeriods).

Creating a Calendar/Planner Application - Ruby on Rails

I am considering developing an application using Ruby on Rails that is a planner of sorts. I would like to give a user the ability to see a list of days, click a particular day, and then add things like: Meals, Expenses, Events, Todos, and Exercises. Really I am doing this for me and my growing family.
I am curious with how best to implement this. I can certainly see that Meals, Expenses, etc. need to belong_to :user but I am curious how to implement the belongs_to :day or something like that. Using the created_at or updated_at wouldn't necessarily allow me to provide views for future dates.
I can see how if I created a Days table and then added days through a time and date field that this would work but seems a little strange to ask people to create the actual days.
Or perhaps instead of that I could just create links to variables that search for #today, #tomorrow, but that would get messy.
I have browsed for gems/plugins but can't find one that works. Ideally a person would be able.
Anyone have any thoughts on how to implement something like this?
There are a number of existing Rails calendars, such as http://github.com/elevation/event_calendar or http://github.com/topfunky/calendar%5Fhelper.
However, to answer your specific question about dates: I don't think there's any need to have Day as a model; simply give each event a start date and time, and an end date and time. Remember that Ruby makes it easy to search based on ranges, so "give me all of the events next week" is a cinch if each event has dates and times associated with it.
I'll give it a shot...
Two tables; users and events. A user has many events and an event belongs to a user. Meal, Expenses, etc. are various types of Event. Within events, you can have fields for start and end time of the events. If needed (lets say an events last over multiple days), you could remove the day/time when events occurs into it's own table.
This way, when displaying the calendar for a user, you can find all the events for that date. If none are found, then display nothing.
What do you think?
I would add a model called "Events" and have a properties of the model to represent start date/time, end date/time. I do not think you need a Days model, you can generate your calendar view from the Date class built into ruby.
I have done same kind of project for the Event management in training institute. At there I used event_calender plug in with rails. (enter link description here)
In there we just need to create Event model only. Then we can easily work with that.

Generating sequential numbers in multi-user saas application

How do people generate auto_incrementing integers for a particular user in a typical saas application?
For example, the invoice numbers for all the invoices for a particular user should be auto_incrementing and start from 1. The rails id field can't be used in this case, as it's shared amongst all the users.
Off the top of my head, I could count all the invoices a user has, and then add 1, but does anyone know of any better solution?
Typical solution for any relation database could be a table like
user_invoice_numbers (user_id int primary key clustered, last_id int)
and a stored procedure or a SQL query like
update user_invoice_numbers set last_id = last_id + 1 where user_id = #user_id
select last_id from user_invoice_numbers where user_id = #user_id
It will work for users (if each user has a few simultaneously running transactions) but will not work for companies (for example when you need companies_invoice_numbers) because transactions from different users inside the same company may block each other and there will be a performance bottleneck in this table.
The most important functional requirement you should check is whether your system is allowed to have gaps in invoice numbering or not. When you use standard auto_increment, you allow gaps, because in most database I know, when you rollback transaction, the incremented number will not be rolled back. Having this in mind, you can improve performance using one of the following guidelines
1) Exclude the procedure that you use for getting new numbers from the long running transactions. Let's suppose that insert into invoice procedure is a long running transaction with complex server-side logic. In this case you first acquire a new id , and then, in separate transaction insert new invoice. If last transaction will be rolled back, auto-number will not decrease. But user_invoice_numbers will not be locked for long time, so a lot of simultaneous users could insert invoices at the same time
2) Do not use a traditional transactional database to store the data with last id for each user. When you need to maintain simple list of keys and values there are lot of small but fast database engines that can do that work for you. List of Key/Value databases. Probably memcached is the most popular. In the past, I saw the projects where simple key/value storages where implemented using Windows Registry or even a file system. There was a directory where each file name was the key and inside each file was the last id. And this rough solution was still better then using SQL table, because locks were issued and released very quickly and were not involved into transaction scope.
Well, if my proposal for the optimization seems to be overcomplicated for your project, forget about this now, until you will actually run into performance issues. In most projects simple method with an additional table will work pretty fast.
You could introduce another table associated with your "users" table that tracks the most recent invoice number for a user. However, reading this value will result in a database query, so you might as well just get a count of the user's invoices and add one, as you suggested. Either way, it's a database hit.
If the invoice numbers are independent for each user/customer then it seems like having "lastInvoice" field in some persistent store (eg. DB record) associated with the user is pretty unavoidable. However this could lead to some contention for the "latest" number.
Does it really matter if we send a user invoices 1, 2, 3 and 5, and never send them invoice
4? If you can relax the requirement a bit.
If the requirement is actually "every invoice number must be unique" then we can look at all the normal id generating tricks, and these can be quite efficient.
Ensuring that the numbers are sequenctial adds to the complexity, does it add to the business benefit?
I've just uploaded a gem that should resolve your need (a few years late is better than never!) :)
https://github.com/alisyed/sequenceid/
Not sure if this is the best solution, but you could store the last Invoice ID on the User and then use that to determine the next ID when creating a new Invoice for that User. But this simple solution may have problems with integrity, will need to be careful.
Do you really want to generate the invoice IDs in an incremental format? Would this not open security holes (where in, if a user can guess the invoice number generation, they can change it in the request and may lead to information disclosure).
I would ideally generate the numbers randomly (and keep track of used numbers). This prevents collisions as well (Chances of collision are reduced as the numbers are allocated randomly over a range).

Resources