I'm building an application that is based on a calendar and (with basic functionality expected from a calendar).
As the calendar will have such a fundamental part of the application I don't want to rely on any gem but build the calendar myself.
I don't know which route to go: to have a day-model representing each day with a unique record (that events can reference by day_id) OR render the calendar "on the fly" based on a Date class (and events would then reference the date).
In short: What model design would be the most efficient to render a calendar?
You don't need to have a model at all. The following code below will do the trick.
Grab the code from https://gist.github.com/RichIsOnRails/5535564 and drop it in a helper, use like so (haml below, so adapt it to meet your own needs.) Note that i'm rendering events in this calendar, but you don't have to.
= calendar #date do |date|
.text-left=date.day
- if #events_by_date[date]
- #events_by_date[date].each do |event|
.event=event.title
I will do an article on my website in the near future that goes over this in detail. Good luck!
Unless there is something specific about the days you would like to model, you may be able to just have an events model, with each event having a date field. This approach is simpler and I think preferable. Since there are a practically infinite number of dates, one big advantage of this approach is that you won't need to manage all the logical inconsistencies of keeping a finite subset of dates in your database.
Even if you find a need for a day model, you can do this without tying the model to the database, and thus avoid having a record in your database for every possible date. This might be useful if you want a method that tells you if a day is a work day, or if you want to find a collection of days. For more on how to make a model that doesn't require a database table behind it, see this stackoverflow question: Tableless model in rails 3.1
Related
I am using Rails 4. I have a Room model with hour_price day_price and week_price attributes.
On the index, users are able to enter different times and dates they would like to stay in a room. Based on these values, I have a helper method that then calculates the total price it would cost them using the price attributes mentioned above.
My question is what is the best way to sort through the rooms and order them least to greatest (in terms of price). Having a hard time figuring out the best way to do this, especially when considering the price value is calculated by a helper and isn't stored in the database.
You could load all of them and do an array sort as is suggested here, and here. Though that would not scale well, but if you've already filtered by the rooms that are available this might be sufficient.
You might be able to push it back to the database by building a custom sql order by.
Rooms.order("(#{days} * day_price) asc")
I'm writing a super simple web application that presents different counters for different events. My database table is filled with records representing the different events. the table has 2 colums name and date
Now before I can present the counters for every event, I need to
calculate the time left to its date
and make a string that either says something like 5d, 4h, 23m or completed
Where would you guys put this logic? Please bear with me, I'm a beginner.
ps. I'm trying to make a proper MVC application with Ruby on Rails
Sometimes the answer to "does this go in the model, the view, or the controller?" is "no".
Like others have said - you want the controller to be as thin as possible. It's job is to relay 'events' and do basic set up of other objects. According to conventional wisdom, the model should encapsulate your business logic. In Rails, a model usually does both persistence and business logic. In other words, if you have rules for how data is to be manipulated or how it is to be aggregated, that goes in the model. On the other hand, people have started arguing that managing both persistence and business logic is too much responsibility for one object.
The responsibilities you describe are about presenting values. To do this you could use the Presenter or Decorator pattern. In essence, you create a class of object whose responsibility is to take data from another object and prepare it for presentation. The Draper gem provides some utilities for doing just this.
In your event.rb, create a method called time_left (taken from https://stackoverflow.com/a/19596579/1489088):
def self.time_left
# Calculate time left for event start
current_time = Time.now
# date is retrieving the date for your model, but it has to be a datetime field and not a date field.
seconds_diff = (date - current_time).to_i.abs
hours = seconds_diff / 3600
seconds_diff -= hours * 3600
minutes = seconds_diff / 60
seconds_diff -= minutes * 60
seconds = seconds_diff
"#{hours.to_s.rjust(2, '0')}:#{minutes.to_s.rjust(2, '0')}:# {seconds.to_s.rjust(2, '0')}"
end
Why in your model, simply because this calculation is specific to your events, and you want to be "playing" with your model data here and most of your data behavior to be handled here. I can't really dig in into this, others can do it better and there is a lot of ressources on the subject if you search for it (Search for example "Fat Model, Skinny Controller" in Google).
Now assuming you want the time left to be calculated every time you load the event page, you must specify it in your controller :
events_controller.rb :
def show
set_event
#time_left = #event.time_left
end
Then basically call #time_left in your view.
I'm not sure what #CaffeineCoder meant by "Put as much minimum logic in model , models are meant for only relationships", but along similar lines i would say:
Keep as much of your logic in your models as possible.
Models should hold all your business logic, controllers should do as little as possible, and views should handle anything which is to do with formatting data and presenting it to the user. Repeated bits of formatting can go in helpers, which is like a subsection of the View.
You don't tell us much about your schema so i can't advise on specifics, but you could for example have a method in Event like "time_remaining", which returns a number of seconds, and then have helpers which take this value and return "5d" or "4h" or whatever.
I built a small site where I gather information of some cultural events happening in the area. I want to extend the Event model so it can handle 3 different 'case scenario' of events.
'i.e. Single'. Normal event with start date and finish date.
'i.e. Band on tour'. Same event but happening at different times.
'i.e. Museum'. Monday to Sunday timetable.
I thought that the best approach for the 1 and 2 types will be:
Event model
# holds title, description, price....
has_many :dates
accepts_nested_attributes_for :dates
Date model
# holds start_time(:datetime) and finish_time(:datetime)
belongs_to :events
I am not sure how to approach the 3rd type. Or what is more important, how to build it in a way that makes future interactions easier to code... like building a SEARCH engine.
Idea:
Building another model called Timetable?
This could hold:
boolean types -> Mon - Tue... -Sun
time type -> Mon_start - Tue_start... - Sun_start - Mon_finish - Tue_finsih... - Sun_finish.
However, this seems pretty complicated to update the search engine(which has a date field/parameter) to iterate through all these 3 types.
Any ideas/experience which may clarify the path to take? Many thanks in advance!
One way that would work well would be to make Date abstract, and then make three more models that extend Date.
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.
I have an ASP.NET MVC site and I am trying to figure out separation of controller and model (repository) and HTML helper functionality.
The goal is to query a database table of photo albums information and display it grouped by year.
The steps are:
Query database and return datatable of the database information.
Convert Datatable to AlbumCollection (List)
Bucket albums by year into ALbumDictionary
Render each year in a seperate HTML table.
Given this request, I could see:
1,2,3 all in the model and the controller simply binds the View to the AlbumDictionary model
or
1,2 in the model and bind to the AlbumCollection and 3 in a HTML ViewHelper
or
1,2 in the model 3 in the controller and bind to the Albumdictionary
Thoughts?
Doing every conversion in the first loop would have the best performance but I am not sure it is the best separation of concerns.
In particular to the above question, generic feedback would be interesting: when does separation of concerns overrule performance or vise versa?
Having been a user of some truly horrendous software that I'm sure looked good from an object-oriented perspective to the designers and was even possibly easy to maintain, I want to point out that the users will come down on the side of performance almost every time.
If the performance difference is negligible, follow the separation of concerns, if it is not, do what it takes to get the best performance. We need to stop worrying as much about the extra few minutes to possibly maintain (maybe touching that code once a year once it's in prod) and more about slowness for all the users every day issue. We like to say that development time is so expensive that we need to minimize it, but the truth is that development time is often far cheaper than the amount of time we are asking our users to waste daily.
I would try to keep the Model clear of anything that has to do with rendering.
I see the grouping by year pretty close to rendering. Thats why I would not put it into Model and also not into the Controller. A common aproach is to have a Model of Poco and DAL/BLL and anonther Model called ViewModel (the Model used by the strongly typed View). This is a good place to prepare the objects for rendering.
In ViewModel I would use Linq to group the albums by years. This will hopefully be fast enough.
I would do the bucketing in the controller only if either:
the bucketing occurs just once and I can do that with one or two simple statements;
It occurs more than once but I can do that with just a AlbumDictionary.BucketByYear() statement.
Otherwise I'd use models to do that.