# Simple Calendar ### 📆 A calendar for your Ruby on Rails app. [![Build Status](https://github.com/excid3/simple_calendar/workflows/Tests/badge.svg)](https://github.com/excid3/simple_calendar/actions) [![Gem Version](https://badge.fury.io/rb/simple_calendar.svg)](https://badge.fury.io/rb/simple_calendar) Simple Calendar is designed to do one thing really really well: render a calendar. It lets you render a calendar of any size. Maybe you want a day view, a 4 day agenda, a week view, a month view, or a 6 week calendar. You can do all of that with the new gem, just give it a range of dates to render. It doesn't depend on any ORM so you're free to use it with ActiveRecord, Mongoid, any other ORM, or pure Ruby objects. Thanks to all contributors for your wonderful help! ![calendar](https://s3.amazonaws.com/f.cl.ly/items/1T0t1s0W212d28282V2M/Screen%20Shot%202013-03-28%20at%209.44.49%20AM.png) Installation ------------ Just add this into your Gemfile followed by a bundle install: ```ruby gem "simple_calendar" ``` If you're using Bootstrap, the calendar should already have a border and nice spacing for days. Optionally, you can include the default stylesheet for the calendar in your `app/assets/stylesheets/application.css` file: ```scss *= require simple_calendar ``` or in your SCSS `app/assets/stylesheets/application.scss` file: ```scss @import "simple_calendar"; ``` Usage ----- Generating calendars is extremely simple with simple_calendar. The first parameter is a symbol that looks up the current date in `params`. If no date is found, it will use the current date. In these examples, we're using `:start_date` which is the default. ### Month Calendar You can generate a calendar for the month with the `month_calendar` method. ```erb <%= month_calendar do |date| %> <%= date %> <% end %> ``` To show the day of the month instead of the date, use `<%= date.day %>` ### Week Calendar You can generate a week calendar with the `week_calendar` method. ```erb <%= week_calendar(number_of_weeks: 2) do |date| %> <%= date %> <% end %> ``` Setting `number_of_weeks` is optional and defaults to 1. ### Custom Length Calendar You can generate calendars of any length by passing in the number of days you want to render. ```erb <%= calendar(number_of_days: 4) do |date| %> <%= date %> <% end %> ``` Setting `number_of_days` is optional and defaults to 4. ### Custom Parameter Name You can pass in `start_date_param` to change the name of the parameter in the URL for the current calendar view. ```erb <%= calendar(start_date_param: :my_date) do |date| %> <%= date %> <% end %> ``` ### Custom Partial You can set a different partial name for calendars by passing the partial path. ```erb <%= calendar(partial: 'products/calendar') do |date| %> <%= date %> <% end %> ``` ### Internationalization (I18n) The default views are prepared to do translation lookups for month names and weekdays. To profit from that, you can take advantage of the [`rails-i18n`](https://github.com/svenfuchs/rails-i18n/) gem which comes with translations for many languages already. In a Rails 6 app, the configuration could look like the following: * Add `gem 'rails-i18n'` to your `Gemfile` and run `bundle`. * Define the available and default locale e.g. in `config/application.rb`: ```ruby # config/application.rb config.i18n.available_locales = [:en, :de, :fr] config.i18n.default_locale = :en ``` * Define the following translation keys: ```yaml # e.g. config/locales/de.yml de: simple_calendar: previous: "<<" next: ">>" week: Woche ``` See the [Rails I18n Guide](https://guides.rubyonrails.org/i18n.html) for further information. ## Rendering Events What's a calendar without events in it? There are two simple steps for creating calendars with events. The first step is to add the following to your model. We'll be using a model called Meeting, but you can add this to any model or Ruby object. Here's an example model: ```bash # single day events $ rails g scaffold Meeting name start_time:datetime # multi-day events $ rails g scaffold Meeting name start_time:datetime end_time:datetime ``` By default it uses `start_time` as the attribute name. **If you'd like to use another attribute other than start_time, just pass it in as the `attribute`** ```erb <%= month_calendar(attribute: :starts_at) do |date| %> <%= date %> <% end %> ``` Optionally the `end_time` attribute can be used which enables multi-day event rendering. **Just pass in the `attribute` and `end_attribute` options respectively** ```erb <%= month_calendar(attribute: :start_date, end_attribute: :end_date) do |date| %> <%= date %> <% end %> ``` **If you already have a model with a start time attribute called something other than `start_time` or accesses it through a relationship, you can alias the attribute by defining a `start_time` method in the my_model.rb file and not have to specify it separately as in the above example** ```ruby class MyModel ## Other code related to your model lives here def start_time self.my_related_model.start ##Where 'start' is a attribute of type 'Date' accessible through MyModel's relationship end end ``` In your controller, query for these meetings and store them in an instance variable. Normally you'll want to search for the ones that only show up inside the calendar view (for example, you may only want to grab the events for the current month). We'll just load up all the meetings for this example. ```ruby def index # Scope your query to the dates being shown: start_date = params.fetch(:start_date, Date.today).to_date @meetings = Meeting.where(starts_at: start_date.beginning_of_month.beginning_of_week..start_date.end_of_month.end_of_week) end ``` Then in your view, you can pass in the `events` option to render. The meetings will automatically be filtered out by day for you. ```erb <%= month_calendar(events: @meetings) do |date, meetings| %> <%= date %> <% meetings.each do |meeting| %>