Repository: railsgirls/guides.railsgirls.com Branch: main Commit: dbc9fe93f372 Files: 86 Total size: 454.4 KB Directory structure: gitextract_3vukf4_h/ ├── .github/ │ ├── dependabot.yml │ └── workflows/ │ └── deploy.yml ├── .gitignore ├── .ruby-version ├── 404.html ├── Gemfile ├── LICENSE ├── README.md ├── _config.yml ├── _includes/ │ ├── analytics.html │ ├── footer.html │ ├── github-corner.html │ ├── header.html │ ├── main-guide-intro.html │ └── main_guides.md ├── _layouts/ │ ├── default.html │ ├── guide.md │ └── main_guide.md ├── _pages/ │ ├── activeadmin.md │ ├── app.md │ ├── coach.md │ ├── commenting.md │ ├── continuous-codeship.md │ ├── continuous-snap-ci.md │ ├── continuous-travis.md │ ├── contributing.md │ ├── deployment/ │ │ ├── anynines.md │ │ ├── digital-ocean.md │ │ ├── engineyard.md │ │ ├── fly-io.md │ │ ├── heroku.md │ │ └── openshift.md │ ├── deployment.md │ ├── design-using-html-and-css-chinese.md │ ├── design.md │ ├── devise.md │ ├── diary-app.md │ ├── github.md │ ├── gravatar.md │ ├── guide-to-the-guide.md │ ├── guide.md │ ├── how-to-continue-with-programming.md │ ├── html-and-css.md │ ├── install/ │ │ ├── linux.md │ │ ├── macos.md │ │ ├── replit.md │ │ ├── virtual-machine.md │ │ └── windows.md │ ├── install.md │ ├── new-homepage.md │ ├── new-page.md │ ├── passenger.md │ ├── remote-pairing-for-the-win.md │ ├── ruby-atm.md │ ├── ruby-game.md │ ├── ruby-intro.md │ ├── shoulda-matchers.md │ ├── simple-app.md │ ├── sinatra-app-tutorial.md │ ├── sinatra-html.md │ ├── sinatra.md │ ├── start.md │ ├── test-driven-development.md │ ├── testing-rspec.md │ ├── thumbnails.md │ ├── tools.md │ ├── touristic-autism_basic-app.md │ ├── touristic-autism_continuous-deployment.md │ ├── touristic-autism_design.md │ ├── touristic-autism_git.md │ ├── touristic-autism_google-map.md │ ├── touristic-autism_image-upload.md │ ├── touristic-autism_intro.md │ ├── touristic-autism_resource-modeling.md │ ├── touristic-autism_resource-rating.md │ ├── touristic-autism_static-pages-tdd.md │ ├── twitter-widget.md │ ├── uploads.md │ └── videos.md ├── _plugins/ │ └── coach.rb ├── css/ │ ├── code.css │ └── style.css ├── index.html └── js/ ├── guides.js ├── js.cookie.js └── mobile-menu.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/dependabot.yml ================================================ version: 2 updates: - package-ecosystem: 'github-actions' directory: '/' schedule: interval: 'weekly' ================================================ FILE: .github/workflows/deploy.yml ================================================ name: Deploy site on: # Runs on pushes targeting the default branch push: branches: ["main"] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: contents: read pages: write id-token: write # Allow one concurrent deployment concurrency: group: "pages" cancel-in-progress: true jobs: # Build job build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v6 - name: Setup Ruby uses: ruby/setup-ruby@6ca151fd1bfcfd6fe0c4eb6837eb0584d0134a0c # v1.290.0 with: bundler-cache: true # runs 'bundle install' and caches installed gems automatically cache-version: 0 # Increment this number if you need to re-download cached gems - name: Setup Pages id: pages uses: actions/configure-pages@v5 - name: Build with Jekyll # Outputs to the './_site' directory by default run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}" env: JEKYLL_ENV: production - name: Upload artifact # Automatically uploads an artifact from the './_site' directory by default uses: actions/upload-pages-artifact@v4 # Deployment job deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest needs: build steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 ================================================ FILE: .gitignore ================================================ .bundle/ _site/ .DS_Store *.swp ================================================ FILE: .ruby-version ================================================ 3.2.8 ================================================ FILE: 404.html ================================================ --- layout: default title: "Page not found" permalink: /404.html ---

Page not found

The page you are looking for does not exist.

It may have moved, renamed or deleted.

Please visit the guides homepage for a list of all available guides.

================================================ FILE: Gemfile ================================================ source "https://rubygems.org" gem "jekyll" gem "jekyll-redirect-from" gem "webrick" ================================================ FILE: LICENSE ================================================ Creative Commons Attribution-Share Alike 3.0 License. https://creativecommons.org/licenses/by-sa/3.0 ================================================ FILE: README.md ================================================ # Rails Girls Guides Rails Girls The purpose of Rails Girls is to give tools for women to understand technology. The Rails Girls events do this by providing a great first experience on building the Internet. Rails Girls was founded at the end of 2010 in Helsinki. Originally intended as a one-time event, we never thought to see so many chapters from all around the world! This guide will help you get started. You can use our materials and instructions to roll out your own workshop in your city, workplace or kitchen! Read more about Rails Girls at https://railsgirls.com ## Quick start View the guides at https://guides.railsgirls.com or clone this repo and install & run [jekyll](https://github.com/mojombo/jekyll) ### Installing jekyll ``` $ cd guides.railsgirls.com ``` ``` $ bundle install ``` ### Pygments and Code Highlighting The guides use the [pygments](https://pygments.org/) library to do syntax highlighting. If you don't have it installed you won't be able to see the highlight sections like the following: ``` {% highlight %} {% endhighlight %} ``` If you aren't editing the code blocks, you can safely ignore this. If you want pygments, you can follow the [install instructions](https://jekyllrb.com/docs/installation/) in the "Pygments" section. ### Coach highlights A custom Liquid tag is available for coach notes. Add these to guides when you want the coach to explain something. Use this tag to make sure the visual element is always the same and easy to recognize. ``` {% coach %} Add helpful text here for the coach! {% endcoach %} ``` ### Run jekyll ``` $ bundle exec jekyll server --watch ``` ### Styling Wrap keyboard shortcuts with [kbd](https://www.w3.org/wiki/HTML/Elements/kbd) HTML tag. To make posts consistent in style use `Ctrl+C` over `CTRL-c`/`ctrl+c` ``` To shut down the server you can hit Ctrl+C ``` ### Having trouble? You might find some useful hints in this jekyll issue if it's not working as expected: [Issue 503](https://github.com/mojombo/jekyll/issues/503) ## Contributing a Guide To contribute a guide, view the instructions at https://guides.railsgirls.com/contributing ## X For updates and more, follow [@railsgirls](https://twitter.com/railsgirls) on X ## Website & Blog Official website and blog for Rails Girls movement can be found at https://railsgirls.com ## E-mail list Global mailing list for Rails Girls events can be found at https://groups.google.com/group/rails-girls-team ## Credits * Karri Saarinen / [@karrisaarinen](https://twitter.com/karrisaarinen) / [github](https://github.com/ksaa) * Linda Liukas / [@lindaliukas](https://twitter.com/lindaliukas) / [github](https://github.com/lindaliukas) * Vesa Vänskä / [@vesan](https://twitter.com/vesan) / [github](https://github.com/vesan) * Terence Lee / [@hone02](https://twitter.com/hone02) / [github](https://github.com/hone) * Tom de Bruijn / [@tombruijn](https://mastodon.social/@tombruijn) / [GitHub](https://github.com/tombruijn) ..and all the other coaches and people making Rails Girls awesome. Please add yourself! ## LICENSE [![License: CC BY-SA 3.0](https://licensebuttons.net/l/by-sa/3.0/80x15.png)](https://creativecommons.org/licenses/by-sa/2.0/) ================================================ FILE: _config.yml ================================================ permalink: pretty markdown: kramdown include: - _pages exclude: - ".rvmrc" - ".rbenv-version" - ".ruby-version" - "CNAME" - "Gemfile" - "Gemfile.lock" - "README.md" - "node_modules/" - "vendor/bundle/" - "vendor/cache/" - "vendor/gems/" - "vendor/ruby/" url: https://guides.railsgirls.com source_url: https://github.com/railsgirls/guides.railsgirls.com/blob/main/ plugins: - jekyll-redirect-from site_title: "Rails Girls Guides" default_page_description: "Learn how to make your own web apps with the Rails Girls guides." ================================================ FILE: _includes/analytics.html ================================================ ================================================ FILE: _includes/footer.html ================================================ ================================================ FILE: _includes/github-corner.html ================================================ ================================================ FILE: _includes/header.html ================================================
{% include github-corner.html %}
================================================ FILE: _includes/main-guide-intro.html ================================================
This guide is a part of the Rails Girls workshop main guides. Make sure you follow the numbered guides in order before continuing.
================================================ FILE: _includes/main_guides.md ================================================
If you're ever stuck during a guide, please ask your coach for help and also consult this [handy cheatsheet for Ruby, Rails, the console, the Text Editor etc](https://www.pragtob.info/rails-beginner-cheatsheet/). ## Guides * Guide 1: [Start of the guide](/start) {% if page.permalink == 'start' %}(Current page!){% endif %} * Guide 2: [Get to know the tools](/tools) {% if page.permalink == 'tools' %}(Current page!){% endif %} * Guide 3: [Guide to install Rails](/install) {% if page.permalink == 'install' %}(Current page!){% endif %} - [Installation guide for macOS](/install/macos) {% if page.permalink == 'install/macos' %}(Current page!){% endif %} - [Installation guide for Windows](/install/windows) {% if page.permalink == 'install/windows' %}(Current page!){% endif %} - [Installation guide for Linux](/install/linux) {% if page.permalink == 'install/linux' %}(Current page!){% endif %} - [Installation guide for a Virtual Machine](/install/virtual-machine) {% if page.permalink == 'install/virtual-machine' %}(Current page!){% endif %} - [Installation guide for a Cloud service](/install/replit) {% if page.permalink == 'install/replit' %}(Current page!){% endif %} * Guide 4: [Build Your First App](/app) {% if page.permalink == 'app' %}(Current page!){% endif %} * Guide 5: [Style your app using HTML and CSS](/html-and-css) {% if page.permalink == 'html-and-css' %}(Current page!){% endif %} * Guide 6: [Add a new page to your app](/new-page) {% if page.permalink == 'new-page' %}(Current page!){% endif %} * Guide 7: [Add a new homepage to your app](/new-homepage) {% if page.permalink == 'new-homepage' %}(Current page!){% endif %} * Guide 8: [Add picture uploads](/uploads) {% if page.permalink == 'uploads' %}(Current page!){% endif %} * Guide 9: [Push Your App to GitHub](/github) {% if page.permalink == 'github' %}(Current page!){% endif %} * Guide 10: [Put your app online](/deployment) {% if page.permalink == 'deployment' %}(Current page!){% endif %} with one of these services: - [Fly.io](/deployment/fly-io) {% if page.permalink == 'deployment/fly-io' %}(Current page!){% endif %} - [Heroku](/deployment/heroku) {% if page.permalink == 'deployment/heroku' %}(Current page!){% endif %} - [DigitalOcean](/deployment/digitalocean) {% if page.permalink == 'deployment/digitalocean' %}(Current page!){% endif %} - [OpenShift](/deployment/openshift) {% if page.permalink == 'deployment/openshift' %}(Current page!){% endif %} - [Anynines](/deployment/anynines) {% if page.permalink == 'deployment/anynines' %}(Current page!){% endif %} - [Engine Yard](/deployment/engineyard) {% if page.permalink == 'deployment/engineyard' %}(Current page!){% endif %} * Guide 11: [Style the idea pages using HTML and CSS](/design) {% if page.permalink == 'design' %}(Current page!){% endif %} * Guide 12: [Add comments to your app](/commenting) {% if page.permalink == 'commenting' %}(Current page!){% endif %} * Guide 13: [Create picture thumbnails](/thumbnails) {% if page.permalink == 'thumbnails' %}(Current page!){% endif %} * Guide 14: [Test your app with RSpec](/testing-rspec) {% if page.permalink == 'testing-rspec' %}(Current page!){% endif %} [View all guides](/) ================================================ FILE: _layouts/default.html ================================================ {% capture page_title_capture %} {% if page.title == nil %} {{ site.site_title }} {% else %} {{ page.title }} - {{ site.site_title }} {% endif %} {% endcapture %} {% assign page_title = page_title_capture | strip %} {% capture page_description_capture %} {% if page.description == nil %} {{ site.default_page_description }} {% else %} {{ page.description }} {% endif %} {% endcapture %} {% assign page_description = page_description_capture | strip %} {% capture canonical_url %}{{ site.url }}/{{ page.permalink }}{% endcapture %} {{ page_title }} {% include header.html %}
{{ content }}
{% include footer.html %} {% include analytics.html %} ================================================ FILE: _layouts/guide.md ================================================ --- layout: default ---
{{ content }}
Want to learn more? View more guides!
================================================ FILE: _layouts/main_guide.md ================================================ --- layout: default ---
{{ content }} {% capture guides %} {% include main_guides.md %} {% endcapture %} {{ guides | markdownify }}
================================================ FILE: _pages/activeadmin.md ================================================ --- layout: guide title: Adding a back-end with Active Admin permalink: backend-with-active-admin --- # Adding a back-end with Active Admin *Created by [Rasmus Kjellberg](https://www.rasmuskjellberg.se)* **This guide assumes that you have already built a Rails Girls app by** [**following the app development guide**](/app). Active Admin is a Ruby on Rails plugin for generating administration style interfaces. It abstracts common business application patterns to make it simple for developers to implement beautiful and elegant interfaces with very little effort. You can read more about Active Admin [here](https://activeadmin.info/). ## Adding the "Active Admin" gem Open up your `Gemfile` and add these lines {% highlight ruby %} gem 'devise' gem 'activeadmin', github: 'activeadmin' gem 'inherited_resources', github: 'activeadmin/inherited_resources' {% endhighlight %} and run {% highlight sh %} bundle install {% endhighlight %} to install the gems. After updating your bundle, run the installer {% highlight sh %} rails generate active_admin:install {% endhighlight %} The installer creates an initializer used for configuring defaults used by Active Admin as well as a new folder at app/admin to put all your admin configurations. Migrate your db and start the server: {% highlight sh %} rails db:migrate rails server {% endhighlight %} ## Creating your first admin account Open up the Rails console and create your new user via the `AdminUser` model: {% highlight sh %} rails console {% endhighlight %} Once booted (the terminal shows `irb(main):001:0>`), you can run this command: {% highlight sh %} AdminUser.create(:email => 'admin@railsgirls.com', :password => 'password123', :password_confirmation => 'password123') {% endhighlight %} You should see something like: {% highlight sh %} # (0.3ms) begin transaction # SQL (0.4ms) INSERT INTO "admin_users" ... # (0.9ms) commit transaction {% endhighlight %} You can exit the console session with a simple `exit` command: {% highlight sh %} irb(main):002:0> exit {% endhighlight %} ## Accessing your admin panel Visit and log in using your created credentials. Voila! You're on your brand new Active Admin dashboard. ## Add "Ideas" to back-end To register your `Idea` model with Active Admin, run: {% highlight sh %} rails generate active_admin:resource Idea {% endhighlight %} Refresh your admin page and you will find [Ideas](http://localhost:3000/admin/ideas) in the navigation. *You can replace "Idea" with whatever model you like to register another model with Active Admin.* ### Setting up Strong Parameters To prevent **ActiveModel::ForbiddenAttributesError in Admin::IdeasController#update** exception when updating a model you have to use the [permit_params](https://activeadmin.info/2-resource-customization.html) method to define which attributes may be changed: Open up your `app/admin/idea.rb` file and add `:name`, `:description` and `:picture` to `permit_params`: {% highlight ruby %} ActiveAdmin.register Idea do permit_params :name, :description, :picture end {% endhighlight %} ## Remove "new", "edit" and "destroy" for users. If you don't want your non-admin users to update your ideas you can easy fix this by updating your route file to only allow "index" and "show". Add `only: [:show, :index]` to `config/route.rb`: {% highlight ruby %} resources :ideas, only: [:show, :index] {% endhighlight %} **Don't forget to remove now broken links from your front-end code such as:** `<%= link_to 'New Idea', new_idea_path %>`, `<%= link_to 'Edit', edit_idea_path(idea) %>`, `<%= link_to 'Destroy', idea, method: :delete, data: { confirm: 'Are you sure?' } %>` Voila! You can now manage your Ideas from your new admin panel! ## What next? * Add another resource to admin such as Blog and Comments ================================================ FILE: _pages/app.md ================================================ --- layout: main_guide title: Build your first app description: "Start building your first Ruby on Rails app with Rails generators." permalink: app --- # Build your first app *Originally created by Vesa Vänskä, [@vesan](https://twitter.com/vesan)* {% include main-guide-intro.html %} Welcome to the workshop! This is the guide you'll be starting with on the day of the workshop. Did you have trouble getting the installation to work? Ask your coach for help first. ## Help from the coach When you see the box below, ask your coach to read it and help out where necessary. {% coach %} Hi coach 👋 Thank you so much for helping out today! {% endcoach %} ## Learn about Ruby In these next couple guides you're going to create a new app. For this you'll be using the Ruby on Rails framework. The Rails framework is written in the Ruby programming language. To get a better idea of how Ruby works, read the [Rails Girls guide to Ruby](/ruby-intro) if you haven't ever written any Ruby, or go to the slightly more advanced [try.ruby-lang.org](https://try.ruby-lang.org/) course before you continue. ## Creating the application In this guide you're going to create a new app. For this you'll be using the Ruby on Rails framework. The app itself will be called *railsgirls*. First, open the Terminal app and type in these commands:
{% highlight sh %} mkdir projects {% endhighlight %}

You can verify that a directory named projects was created by running the list command: ls. You should see the projects directory in the output. Now you want to change the directory you are currently in to the projects folder by running:

{% highlight sh %} cd projects {% endhighlight %}

You can verify you are now in an empty directory or folder by again running the ls command. Now you want to create a new app called railsgirls by running:

{% highlight sh %} rails new railsgirls {% endhighlight %}

This will create a new app in the folder railsgirls, so we again want to change the directory to be inside of our Rails app by running:

{% highlight sh %} cd railsgirls {% endhighlight %}

If you run ls inside of the directory you should see folders such as app and config. You can then start the Rails server by running:

{% highlight sh %} rails server {% endhighlight %}
{% highlight sh %} mkdir projects {% endhighlight %}

You can verify that a directory named projects was created by running the list command: dir. You should see the projects directory in the output. Now you want to change the directory you are currently in to the projects folder by running:

{% highlight sh %} cd projects {% endhighlight %}

You can verify you are now in an empty directory or folder by again running the dir command. Now you want to create a new app called railsgirls by running:

{% highlight sh %} rails new railsgirls {% endhighlight %}

This will create a new app in the folder railsgirls, so we again want to change the directory to be inside of our Rails app by running:

{% highlight sh %} cd railsgirls {% endhighlight %}

If you run dir inside of the directory you should see folders such as app and config. You can then start the Rails server by running:

{% highlight sh %} rails server {% endhighlight %}
Open in your Browser. Clicking the link should open it in a new tab and show the `localhost:3000` in the address bar. If you are using a cloud service (e.g. Replit), use its preview functionality instead (see [installation guide](/install/replit) for details). You should see a page with the Rails logo, which means that your Rails app is up and running. The `rails new` generator created a lot of app code for you to get started and we'll be modifying it in the rest of this workshop. Notice in the Terminal window the command prompt is not visible because it is now running the Rails server. The command prompt will look something like this, but it may be different on your laptop:
{% highlight sh %} $ {% endhighlight %}
{% highlight sh %} > {% endhighlight %}
When the command prompt is not visible you cannot execute new commands. If you try running `cd` or another command it will not work. To stop the Rails server and return to the normal command prompt in the same Terminal window, press Ctrl+C in the Terminal to quit the Rails server. {% coach %} - Make sure it's clear what each command does: `cd`, `dir`/`ls`, `mkdir`. - Briefly explain what was generated by `rails new`. - Briefly explain what the `rails server` command does and why we need it. - Briefly explain how can you stop the server. Resources: Guide to the Guide [creating the application](https://guides.railsgirls.com/guide-to-the-guide#1_create_the_application), Rails Guides [rails new](https://guides.rubyonrails.org/getting_started.html#creating-the-blog-application) {% endcoach %} ## Create Idea scaffold You now have your own app, but it doesn't do anything yet. It only shows the Rails logo. Next you're going to use Rails' scaffold functionality to generate a starting point that allows you to list, add, remove, edit, and view things; in your case _ideas_. Run the following command in the Terminal app: {% highlight sh %} rails generate scaffold idea name:string description:text picture:string {% endhighlight %} {% coach %} - Explain what Rails scaffolding is. How does it help us create parts of an app quickly? - Briefly explain the `rails generate scaffold` command and how it works. What do they arguments mean? - What is the model name argument? - How do you specify database fields with `name:string` and what do they parts mean? Resource: Guide to the guide [scaffolding](https://guides.railsgirls.com/guide-to-the-guide#2_create_idea_scaffold) {% endcoach %} The scaffold creates new files in your project directory, but to get it to work properly we need to run a couple of other commands to update our database and restart the server. {% highlight sh %} rails db:migrate rails server {% endhighlight %} {% coach %} What are database migrations and why do you need them? Resource: Guide to the guide [scaffolding](https://guides.railsgirls.com/guide-to-the-guide#2_create_idea_scaffold) or Rails Beginner [rails commands](https://www.pragtob.info/rails-beginner-cheatsheet#rails-commands) {% endcoach %} Open in your Browser. Cloud service (e.g. Replit) users need to append `/ideas` to their preview URL instead (see [installation guide](/install/replit)). Click around and test what you got by running these few command-line commands. You should be able to make new ideas, view, edit and delete (destroy) them. ## Finetune the routes Open (or your preview URL). It will show a page with only the Rails logo. Let's make it redirect to the ideas page instead. Open the `config/routes.rb` file in your Text Editor. After the first line, add this line and save it: {% highlight ruby %} root to: redirect("/ideas") {% endhighlight %} Test the change by opening the root path (that is, or your preview URL) in your Browser. It should now open the ideas index page when you visit the root path. The label in the Browser's address bar should have automatically changed to . ## Next steps You have now created your first app! Congratulations! From here we will continuing working on the app to improve the design with HTML and CSS, add more pages, add picture uploads, put your app online so that others can see it as well, share the code with others, allow people to leave comments, etc. Talk with your coach about the steps you took in this guide. Do you have questions about any of the steps? Ask them before moving on to the next guide. ================================================ FILE: _pages/coach.md ================================================ --- layout: guide title: Guides descriptive: "The guide for coaches to prepare their participation in a Rails Girls workshop." permalink: coach --- # Being a Rails Girls coach *All your basic questions answered in one place* ### What do I need to be a Rails Girls coach? So, you've heard about [Rails Girls](https://railsgirls.com) and are wondering if you've got what it takes to be a coach at one of the workshops? That's awesome! Your interest in helping beginners dip their toes into web programming is already a great prerequisite! What else do you need? - Patience, willingness to help, and a friendly attitude :) - Being able to answer all sorts of questions in a beginner friendly way (even if the explanation isn't *technically* completely exact) throughout the duration of the workshop. - Experience with web programming (you know what MVC means, right?), not necessarily in Rails. - Some time to go through the [basic app tutorial][app] before the event. ### Why should I be a Rails Girls coach? You mean besides incredibly good karma? Here are some very likely outcomes: - You'll meet interesting new people outside your usual developer group. - You'll probably learn something new by answering questions you never thought of asking yourself. - Eternal gratitude from your group of girls and the Rails Girls community. - An epic #FridayHug like you've never seen before. - You'll help break down stereotypes about women not being interested in technology and programming and thus help your sisters, female friends and relatives, (future) daughters have more choices in their future. And you can add all that on your CV! ### Choice of technology Rails Girls workshops give the first experience in software craftsmanship through introducing the participants to Ruby, Rails and HTML/CSS. The curriculum has been built around these technologies. If the workshop is too difficult or deep, it will not encourage the beginners to continue as it's perceived too hard. Rails Girls workshops are not about learning programming fast and efficiently. It's about the open environment, excitement and getting to know the tools they can use, and having a great day learning about programming, the community, web apps and more. We would love to see other additions to e.g. follow up meetups. If you'd like to host a beginner-friendly, welcome event for women in other technologies or frameworks, we strongly encourage you to do so and use the existing materials. All Rails Girls content is licensed under creative commons. ### Time to complete app There's loads of time to complete the app, and so it is more important to slowly explain what is happening in each step, as it is a lot of copy pasting and if attendees rush through the guide, they will be done soon but not understand at all what happened.
There's a LOT (4-5) h reserved for the app, tweaking it and putting it online for others to see so there is no hurry :) ### Swag Believe it or not, for most, it is really important. It makes the environment different. You decide how, but little crafts (making buttons), stickers, cupcakes, balloons, posters, or anything you can come up with makes all the difference. ### Inclusivity Rails Girls is an inclusive, safe and welcoming experience to everyone. The workshops are primarily intended for beginner women and crafted for this specific user group, but we've always been open to including other skill-levels and genders. Rails Girls coaches are male and female. The end goal of Rails Girls is to enrich the entire Rails community by encouraging more diverse people to join it. If you want to make a different curriculum or group, all the material is online and you are welcome to use it under another name and brand. ### What if I've never done anything in Rails? Why haven't you yet? Just kidding. That's not a problem at all, we've had a lot of coaches just like you and they were *super awesome*. As long as you're comfortable with any other similar framework, you'll be fine. Take a look at the [basic app guide][app] and you'll probably be able to figure out what's going on pretty soon. Pay attention to the "**Coach**" bits that tell you what you should be able to explain. Usually there'll be at least somebody at the event who works with Rails on a regular basis, so don't be afraid to ask for help when bundle installs go all weird on you. Also, if you come across something unusual, just Google it with your group! It's ok to admit that you don't know everything and show the girls how you use Google to solve your everyday programming dilemmas. ### What exactly will I be doing as a coach? The structure of workshop varies a bit from city to city, so your local organizer group will be able to guide you through the details. Usually there's a pre-event meeting or dinner with coaches where you can ask all you questions. ### Answering questions Often coaches who are just one step ahead of attendees are the best at explaining :) Use real life metaphors and explain very high-level. Explaining too deep will cause a flood of information that is not necessary at the beginning. #### Installation Party Generally speaking, the Rails Girls workshops begin with an Installation party during which you'll be asked to help girls [install the required software][install] (Rails and a text editor). You don't have to be an expert on all operating systems, but you can help on those you are familiar with. #### Helping girls build their first app During the following day, you will be the star of the show and help your group of anywhere from 2 to 5 girls build their first [web app][app] in Rails with the help of the tutorial. Usually that happens just after the initial batch of lectures sometime after 11 AM (aka they'll serve you coffee first). Going through the tutorial on your own at home will usually be all the preparation you need. The girls will have the app guide open on their screens, so just guide them through the process, providing explanations of what's going on at each step. The explanations shouldn't be highly technical; try to simplify the answer by providing easy to remember metaphors. And remember that there is no such thing as a stupid question at a Rails Girls workshop! Let girls know they can ask you about anything along the way; you can spend more time on parts they find more interesting. Also, don't be discouraged if you'll sometimes need to try a few different explanations. Most girls will be beginners, so they won't have many existing points of reference (bonus point: nor will they have any bad habits some programmers tend to pick up along the way). If you get to the end of the basic app tutorial, you can explore additional guides at the end or work on whatever your group is most interested in; design is usually a popular choice, but some girls will want to try building another app. You can also prepare your own challenges for girls or explore helpful resources (documentation etc). If you need help with anything, don't be afraid to use Google or ask another coach to help you out. And don't be afraid to ask for a break if you need it, it's going to be a long day, but we can promise you'll get home with a big smile and a warm heart :) * Check Lucy Bain's additional [teaching notes to the app](https://github.com/lbain/railsgirls) ### Are you in? Good, we're happy to have you on board! Get in touch with organizers of your local event (if you aren't already) and they'll answer all the other questions you might have. You can usually find their contact info on the event's page. If you're traveling abroad at the time of a Rails Girls workshop, do feel free to contact the organizers of the city you'll be visiting; we're always happy to welcome additional coaches! Not to mention that a Rails Girls workshop is a great excuse to visit a new city ;) Some other great first-hand tips from Rails Girls coaches: - [4 lessons learned from teaching at Rails Girls Berlin](https://pragtob.wordpress.com/2012/08/14/4-lessons-learned-from-teaching-at-rails-girls-berlin/) - [I infiltrated #railsgirlslj, here’s what it was like](https://swizec.com/blog/i-infiltrated-railsgirlsj-heres-what-it-was-like/swizec/5717) - [8 ways to enable workshop attendees to keep learning](https://pragtob.wordpress.com/2013/06/14/8-ways-to-enable-workshop-attendees-to-keep-learning/) - [What I learned learning Rails / becoming a better teacher](https://floordrees.tumblr.com/post/58784746482/what-i-learned-learning-rails-becoming-a-better) - [Tips for coaching a programming study group](https://coaching.rubymonstas.org/) [app]: /app [install]: /install ================================================ FILE: _pages/commenting.md ================================================ --- layout: main_guide title: Add commenting functionality to your app description: "Allow other people to leave comments on your ideas by adding a commenting feature to your Rails app." permalink: commenting --- # Add comments to your app {% include main-guide-intro.html %} We are going to add the possibility to comment on ideas in your *railsgirls* application. Comments are short messages that people can leave on websites. In this guide we'll be relying less on the Rails generators to create scaffolding. We'll be writing more Ruby code to implement this feature. ## Add comment routes We'll start by creating a new route for the comments. This will be nested under the ideas routes, so we can derive which idea the comment belongs to from the route. Open the `config/routes.rb` file. Change the following line: {% highlight ruby %} resources :ideas {% endhighlight %} to these lines: {% highlight ruby %} resources :ideas do resources :comments end {% endhighlight %} ## Create comment model Next up, creating a comment model, like we did with the ideas before, but without the controller and a bunch of other things. In this guide we'll be making more changes ourselves, rather than relying on generated code. The command below will create a Comment model with a name, message body and with a reference to the ideas table. The latter will make it possible to leave comments on a specific idea, so they won't show on other idea pages. {% highlight sh %} rails generate model comment user_name:string body:text idea:references {% endhighlight %} A migration file has also been created. It lets your database know about the new comments table. Run the migrations using this command: {% highlight sh %} rails db:migrate {% endhighlight %} ## Add relations to models Your app needs to know about the relation between the two objects, ideas and comments, so you can fetch only the comments that belong to a specific idea. One idea can have many comments, but a comment can only belong to one idea. Open `app/models/idea.rb` and below the line: {% highlight ruby %} class Idea < ApplicationRecord {% endhighlight %} add this line to tell it there can be many comments attached to the Idea model: {% highlight ruby %} has_many :comments {% endhighlight %} The comment also has to know that it belongs to an idea. Open the `app/models/comment.rb` file. You'll find the following contents: {% highlight ruby %} class Comment < ApplicationRecord belongs_to :idea end {% endhighlight %} The comment already knows it "belongs to" an idea because of the line `belongs_to :idea`, which references back to the `Idea` model. This was automatically added by the migration we made earlier. ## Loading comments from the database In `app/controllers/ideas_controller.rb` find the line that says `def show`. This is what we call a Ruby method, and it is responsible for loading things from the database to be used in the views (files with HTML we've edited before). Change the `show` method so that it looks like this: {% highlight ruby %} def show @comments = @idea.comments end {% endhighlight %} This will load the comments that belong a specific idea object from the database. We can then access the comments using the `@comments` instance variable in the view later. ## Making a comments controller To store comments in the database, and remove them again later, we'll need a Rails controller. Like the IdeasController, this controller will perform databases queries, but for comments instead. Create a file in the `app/controllers/` directory named `comments_controller.rb`.
{% highlight sh %} touch app/controllers/comments_controller.rb {% endhighlight %}
{% highlight sh %} ni app/controllers/comments_controller.rb {% endhighlight %}
Open the file you just created in your Text Editor, it should be empty, and copy-paste in this code: {% highlight ruby %} class CommentsController < ApplicationController before_action :set_idea, only: %i[create destroy] before_action :set_comment, only: %i[destroy] def create @comment = @idea.comments.new(comment_params) if @comment.save redirect_to idea_path(@idea), notice: "Comment was successfully created." else render :new, status: :unprocessable_entity end end def destroy @comment.destroy redirect_to idea_path(@idea), notice: "Comment was successfully destroyed." end private def set_idea @idea = Idea.find(params[:idea_id]) end def set_comment @comment = @idea.comments.find(params[:id]) end def comment_params params.require(:comment).permit(:user_name, :body) end end {% endhighlight %} This controller will listen to requests to create and delete (destroy) comments. When it receives such a request, it will tell the database what to store or remove, and redirect you back to the page you came from. But first, let's make the pages that will talk to this controller. {% coach %} Explain how controllers work and interact with HTTP requests, models and views. {% endcoach %} ## Display the comments We can use the relationship between ideas and comments to fetch them from the database and show them in your app. Open `app/views/ideas/show.html.erb` and at the very bottom add these lines: {% highlight erb %}

Comments

<% if @comments.any? %> <% @comments.each do |comment| %>

<%= comment.user_name %>

<%= comment.body %>

<%= button_to "Destroy this comment", idea_comment_path(@idea, comment), method: :delete, class: "btn btn-danger", form: { data: { turbo_confirm: "Are you sure?" } } %>
<% end %> <% else %>

No comments found.

<% end %>

Add a new comment

<%= render partial: "comments/form", locals: { idea: @idea } %> {% endhighlight %} This code will show the comments, but first we'll need a way to create comments. For that the last two lines render a comment submission form, which we'll create next. ## Create the comment form To submit the form, we need to create a file with the form, so that it can be displayed. Create a new directory in the `app/views/` directory named `comments/`. Then, in that new directory, create a new file called `_form.html.erb`.
{% highlight sh %} mkdir -p app/views/comments/ touch app/views/comments/_form.html.erb {% endhighlight %}
{% highlight sh %} md app/views/comments/ ni app/views/comments/_form.html.erb {% endhighlight %}
In this new file copy-paste these lines: {% highlight erb %} <%= form_with(model: [idea, idea.comments.build]) do |form| %>
<%= form.label :user_name, "Your name", class: "form-label" %> <%= form.text_field :user_name, class: "form-control" %>
<%= form.label :body, "Comment message", class: "form-label" %> <%= form.text_area :body, class: "form-control" %>
<%= form.submit class: "btn btn-primary" %> <% end %> {% endhighlight %} When you refresh your browser, the idea detail page should now have a form for adding a comment. Fill in your name and add a message. Then click the "Create comment" button. It should now say "Comment was successfully created." at the top of the page in green. Congratulations! Your app now supports comments. We've added a new models for comments, named `Comment`, which talks to the database to store these comments. A new `CommentsController` controller that tells the model what to do, creating or deleting comments. The views are updated to show the comments per idea, create new comments with the form and delete them again with the delete buttons. If you're interested, check out the detail page of a different idea. If all goes well, you should not be seeing the same comments on that idea detail page as the other one. ================================================ FILE: _pages/continuous-codeship.md ================================================ --- layout: guide title: Continuous Deployment - cuz less hassle permalink: continuous --- # Continuous Deployment with the Codeship *Created by Floor Drees, [@floordrees](https://twitter.com/floordrees)* *Updated by Ely Flores, [@mignonnesaurus](https://twitter.com/mignonnesaurus)* ### What is this Continuous Deployment thing? Continuous deployment is part of the continuous delivery 'movement'. The idea behind continuous delivery is to automate the software delivery process as far as possible. With a working continuous deployment chain in place you'll enforce Git deployments (everything must be committed to be tested and everything must be tested to be deployed), making collaboration easier and deployment faster. So you can focus on making your app even more awesome! There are a few great companies sailing the continuous wave, in this guide we'll set up continuous deployment for our Ruby on Rails app from GitHub to Heroku, using the [Codeship](https://www.codeship.io). {% coach %} Talk about the benefits of continuous deployment. {% endcoach %} ### Sign up for Codeship First, you need [a Codeship account](https://www.codeship.io/). Sign in to the Codeship with GitHub. The Codeship needs access to your GitHub repositories to be able to set them up, so make sure you allow access. Back at the Codeship, let’s create your first project. The first step is to select GitHub as your repository provider. In the list of your GitHub repositories, search for the repository you want to set up and select it. In our case, that's the one called something like “railsgirls”. Now your repository is connected and you can set up your test commands. We've created a Ruby on Rails application. So choose “Ruby on Rails” as the framework used. This configures the setup commands and the test commands for you. By deleting the hash key (`#`) you can uncomment test commands you want to use for your application. For now you probably don't have tests set up yet, so you can skip this step and get back to it later. Now let's finish your setup and go to the dashboard. You can trigger a so-called 'new build' for your application by changing something and then pushing to your repository: {% highlight sh %} git add . git commit -m "test Codeship integration" git push origin master {% endhighlight %} You can access the build details by clicking the arrow on the right. Here you can follow the build while it's still running. Better than reality tv - promised. ... and a few seconds later your build succeeded! You see all the commands that were run. After a few initial preparation commands the Codeship ran the commands that you specified a few moments ago. You can inspect the output of a single command by clicking on it. You've already pushed to your repository, watched your build log and got a green build. So you can finish the assistant at the top by clicking on the "click to finish" button. ### Setup Continuous Deployment Now let's deploy your application to Heroku. Go to your project settings by clicking on the settings icon in the projects dropdown on the Codeship. Then navigate to the "Deployment" section. As you want to deploy to Heroku, click on the "Heroku" button. You are asked to enter the name of your Heroku application and your API key. I sure hope you wrote that down somewhere! Enter your application's name and API key (to retrieve your Heroku API key, go to your Heroku account and click "Show API key") and save your deployment configuration. From now on the Codeship will deploy your application to Heroku, every time you push to your GitHub repository. Neat! ### Give it a try Now let's push a change and see if it gets deployed. Change something in your application first, then commit and push the change. {% highlight sh %} git add . git commit -m "this changes everything" git push {% endhighlight %} And immediately another build will start running on the Codeship. Go back to your project overview and you'll see the commands we already know from your first build. Plus: your application gets deployed to Heroku now and should be online after a minute or two. #### Notes If the "build fails" and you see an error like the following when pushing to heroku: {% highlight sh %} Warning: Permanently added 'heroku.com,' (RSA) to the list of known hosts. ! Your account funalinot@someemail.com does not have access to app-name. ! ! SSH Key Fingerprint: fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists. {% endhighlight %} This means that the codeship SSH key needs to be added to heroku as well. To fix this issue: > 1. In Codeship, get your `SSH public key` from your project -> _General_ Tab. > 2. Go to your [Heroku account settings](https://dashboard.heroku.com/account) > 3. Go to the _SSH Keys_ section > 4. Click on _Add SSH Key_ > 5. Enter the `SSH public key` from step 1. > 6. To make sure this works, go back to Codeship. In the build that failed, click on the arrow next to the _Failed_ button and then click _Restart Build_. > 7. Celebrate when you see the Green _Success_ button meaning that the _Build Passed_ ! ================================================ FILE: _pages/continuous-snap-ci.md ================================================ --- layout: guide title: Continuous Deployment - cuz less hassle permalink: continuous-snap-ci --- # Continuous Deployment with the Snap CI *Created by Akshay Karle, [@akshay_karle](https://twitter.com/akshay_karle)* ### What is this Continuous Deployment thing? Continuous deployment is part of the continuous delivery 'movement'. The idea behind continuous delivery is to automate the software delivery process as far as possible. With a working continuous deployment chain in place you'll enforce Git deployments (everything must be committed to be tested and everything must be tested to be deployed), making collaboration easier and deployment faster. So you can focus on making your app even more awesome! There are a few great companies sailing the continuous wave, in this guide we'll set up continuous deployment for our Ruby on Rails app from GitHub to Heroku, using the [Snap CI](https://snap-ci.com). {% coach %} Talk about the benefits of continuous deployment. {% endcoach %} ### Sign up for Snap CI First, you need [a Snap CI account](https://snap-ci.com/). Sign in to the Snap CI with GitHub. Snap CI needs access to your GitHub repositories to be able to set them up, so make sure you allow access. Back at the Snap CI, let’s create your first pipeline. The first step is to select GitHub as your repository provider. In the list of your GitHub repositories, search for the repository you want to set up and select it. In our case, that's the one called something like “railsgirls”. Once you select the repository you wish to build, Snap CI will perform detections on your repository and makes a best attempt to automatically setup your [deployment pipeline](https://martinfowler.com/bliki/DeploymentPipeline.html) for you which will allow you to run your tests and deployments. After a few seconds, Snap CI will automatically start building your repository, at this point you can click through the stages setup by Snap to see what they commands they run. Sometimes, however, Snap CI may not be able to detect the right commands to build and test your repository. In such cases you can edit your pipeline configuration by visiting the Configuration page from the Builds page of your newly created pipeline and clicking 'Edit' to edit the pipeline. Now you can add or edit an existing stage which will build and run all the tests for your application. If you feel unsure what stages you should be adding, you can have a look at the different Build recipes provided under the Ruby sub-category when adding a stage to figure out what commands should be run to correctly build and test your application. You can also take a look at the [getting started guide](https://docs.snap-ci.com/getting-started/) in the Snap CI documentation. Once you've finished editing your pipeline configuration click 'Save'. This will save your configuration and automatically trigger a new build. You should now have a green build if all your tests pass of course :) In case you have any test failures however, you can fix those and push the changes to GitHub: {% highlight sh %} git add . git commit -m "fix tests" git push origin master {% endhighlight %} Snap CI will automatically detect the changes from GitHub and run a new instance of the pipeline. At this point you've already started testing your code. ### Setup Continuous Deployment The next step is to deploy your application. There are various platforms to deploy to, for now, let's look at how you can deploy to [Heroku](https://www.heroku.com/) as it is the easiest. Go to your pipeline configuration edit page again and add a new Stage. This time Select the 'Deploy' category from the recipes on the left. The select 'Basic' recipe in the Heroku sub-category. Enter a stage name of your choice (eg: deploy, go-live, etc.), keep the trigger automatic and then click 'Run as' dropdown to Sign into Heroku. Perform the sign in and authorise Snap CI. You should automatically comeback to Snap CI after the authorization. You can now select the Heroku application where you wish to deploy or create a new application from Snap CI itself. Check the 'Perform DB migrate' checkbox and save your configuration. This should trigger another new build in Snap CI, but this time it runs the stage you just created which deploys to Heroku. Once the pipeline goes green, visit the Heroku application page where you deployed from Snap CI and your rails application should be online in a few minutes. From here on, any new changes you make and push to your GitHub will be tested and deployed automatically by Snap CI. ================================================ FILE: _pages/continuous-travis.md ================================================ --- layout: guide title: Continuous Deployment - cuz less hassle permalink: continuous-travis --- # Continuous Deployment with Travis *Created by Floor Drees, [@floordrees](https://twitter.com/floordrees)* ### What is this Continuous Deployment thing? Continuous deployment is part of the continuous delivery 'movement'. The idea behind continuous delivery is to automate the software delivery process as far as possible. With a working continuous deployment chain in place you'll enforce Git deployments (everything must be committed to be tested and everything must be tested to be deployed), making collaboration easier and deployment faster. So you can focus on making your app even more awesome! There are a few great companies sailing the continuous wave, in this guide we'll set up continuous deployment for our Ruby on Rails app from GitHub to anynines, using [Travis-ci](http://about.travis-ci.org/). {% coach %} Talk about the benefits of continuous deployment. {% endcoach %} ### Github, Travis CI and anynines The first thing we need is an app in a Github repository. And we have just that! Next you'll need to make sure you followed the guide on how to deploy your app via anynines until the very last step. Then, we need to create a file called `manifest.yml` in the main directory of your app, so we can save some information about the deployment there. In your terminal run: {% highlight sh %} cf push {% endhighlight %} This will trigger a first deployment to anynines. The cf gem will notice that there is no `manifest.yml` and will ask you a standard set of configuration questions such as the desired number and memory size of your app instances, whether and which services to bind to them and most importantly, whether you want to store this information. Please answer this question with a 'hell yes' as it will create the desired `manifest.yml` file! Once your push was successful, you should be able to access your application using a browser of your choice, which means your are ready to setup Travis! For now we don't have 'real tests', so we will go ahead and create a Travis configuration file that will fake a succeeding test suite. Please go to your local app directory and create a ``.travis.yml`` file. At the moment, paste the following content. We’ll add some more information later on, using the Travis gem. {% highlight sh %} language: ruby script: 'true' {% endhighlight %} Your app now contains the Travis configuration but how should Travis know when to pull your code from Github and trigger test execution? This is where Github hooks come into play! #### Travis CI Github hook activation Commit and push a code change to your repository and check travis-ci.org to see if your test suite is being executed. You should also receive an email that your build succeeded. {% highlight sh %} git add . git commit -m "test Travis integration" git push origin master {% endhighlight %} Now we can configure the actual deployment. Let's use the travis gem: {% highlight sh %} gem install travis {% endhighlight %} Now use the `travis` command to setup the anynines deployment. {% highlight sh %} travis setup cloudfoundry {% endhighlight %} In case you don’t know the anynines target URL use {% highlight sh %} cf target {% endhighlight %} to gather all information required for Travis setup. This includes target url, username, the organization and space you are currently using. You can also take a look-see at the welcome mail you have received after signing up at anynines.com. After the `travis` command has finished, your ``.travis.yml`` should look somewhat like this: {% highlight sh %} language: ruby script: 'true' deploy: provider: cloudfoundry target: https://api.de.a9s.eu username: jane.doe@example.com password: secure: your encryped password determined by the travis gem= organization: railsgirls space: heaven on: repo: jane/railsgirls {% endhighlight %} Don’t forget to commit and push your changes to ``.travis.yml`` as it will be required in your Github repository to take effect. From now on whenever you commit changes to your Github repository, tests will be run and your app is being deployed. Travis will then show a log output similar to this: {% highlight sh %} Installing deploy dependencies Fetching: addressable-2.3.5.gem (100%) Successfully installed addressable-2.3.5 Fetching: multi_json-1.7.9.gem (100%) Successfully installed multi_json-1.7.9 Fetching: caldecott-client-0.0.2.gem (100%) Successfully installed caldecott-client-0.0.2 Fetching: i18n-0.6.5.gem (100%) Successfully installed i18n-0.6.5 Fetching: tzinfo-0.3.37.gem (100%) Successfully installed tzinfo-0.3.37 Fetching: minitest-4.7.5.gem (100%) Successfully installed minitest-4.7.5 Fetching: atomic-1.1.13.gem (100%) Building native extensions. This could take a while... Successfully installed atomic-1.1.13 Fetching: thread_safe-0.1.2.gem (100%) Successfully installed thread_safe-0.1.2 Fetching: activesupport-4.0.0.gem (100%) Successfully installed activesupport-4.0.0 Fetching: builder-3.1.4.gem (100%) Successfully installed builder-3.1.4 Fetching: activemodel-4.0.0.gem (100%) Successfully installed activemodel-4.0.0 Fetching: cf-uaa-lib-2.0.0.gem (100%) Successfully installed cf-uaa-lib-2.0.0 Fetching: multipart-post-1.2.0.gem (100%) Successfully installed multipart-post-1.2.0 Fetching: rubyzip-0.9.9.gem (100%) Successfully installed rubyzip-0.9.9 Fetching: cfoundry-4.3.6.gem (100%) Successfully installed cfoundry-4.3.6 Fetching: interact-0.5.2.gem (100%) Successfully installed interact-0.5.2 Fetching: json_pure-1.8.0.gem (100%) Successfully installed json_pure-1.8.0 Fetching: mothership-0.5.1.gem (100%) Successfully installed mothership-0.5.1 Fetching: mime-types-1.25.gem (100%) Successfully installed mime-types-1.25 Fetching: rest-client-1.6.7.gem (100%) Successfully installed rest-client-1.6.7 Fetching: uuidtools-2.1.4.gem (100%) Successfully installed uuidtools-2.1.4 Fetching: cf-5.2.2.gem (100%) Successfully installed cf-5.2.2 22 gems installed dpl.2 Preparing deploy Setting target to https://api.de.a9s.eu...... OK target: https://api.de.a9s.eu Authenticating.. . ... OK Switching to organization railsgirls... OK Switching to space heaven... OK dpl.3 Deploying application Using manifest file manifest.yml Uploading railsgirls... OK Stopping railsgirls... OK Preparing to start railsgirls... OK Checking status of app 'railsgirls'... 0 of 1 instances running (1 starting) 0 of 1 instances running (1 starting) 1 of 1 instances running (1 running) Push successful! App 'railsgirls' available at http://railsgirls.de.a9sapp.eu Logging out... OK {% endhighlight %} This means your are done and good to go! ================================================ FILE: _pages/contributing.md ================================================ --- layout: guide title: Contributing a Guide description: "Contribute back to the Rails Girls community with your own guide!" permalink: contributing --- # Contributing a Guide The guides site uses [Jekyll](https://github.com/mojombo/jekyll) to power the site and all the documents are written using [Markdown](https://daringfireball.net/projects/markdown/). To contribute a guide, you just need to follow these simple steps. 1. Fork the [repository on GitHub](https://github.com/railsgirls/railsgirls.github.com) by clicking on the "Fork" button. 2. Do a `git clone` of your fork. ## If you want to add a new guide: - Create a file named `guide_name.md` inside the `_pages` directory of your fork. - In this file, you'll need to add some YAML front matter at the top of the file so it looks like the following example, taken from this guide that you are currently viewing:
    ---
    layout: guide
    title: Contributing a Guide
    permalink: contributing
    ---
You can follow the structure of our [Rails Girls App Tutorial](https://github.com/railsgirls/railsgirls.github.com/blob/master/_pages/app.md). ## If you want to improve an existing guide: Make the change in the file you want to change! You don't need to make a new file if you want to change something in an existing file. ## Then... 1. Commit this new guide to your Git repo. 2. After you commit, push that to your fork. 3. You can now open a pull request explaining your guide. That's it! Thanks so much for taking the time to help us make Rails Girls awesome. ================================================ FILE: _pages/deployment/anynines.md ================================================ --- layout: main_guide title: Rails Girls on anynines description: "Deploy your app to Anynines by following this guide." permalink: deployment/anynines --- # Put your app online with anynines *Created by Floor Drees, [@floordrees](https://twitter.com/floordrees)* {% coach %} Talk about the benefits of deploying to anynines vs utilising US data centers. {% endcoach %} ### Get yourself some anynines 1. [Create an anynines account](https://anynines.com/). 2. [Download and install the Command Line Interface](https://anynines.zendesk.com/entries/60241846-How-to-install-the-CLI-v6) to interact with anynines. 3. Now select the anynines api endpoint as target and authenticate using your user credentials: {% highlight sh %} cf api https://api.de.a9s.eu cf login -u [your@email] -p [yourpassword] {% endhighlight %} Or if that doesn't work for you, use: {% highlight sh %} cf login {% endhighlight %} ... which will prompt you for your email address and password. Wonder what that `cf` stands for? It's short for [Cloud Foundry](https://www.cloudfoundry.org/), a system anynines is using behind the scenes. ### Push your app online Let's push this source code from your local machine to anynines: {% highlight sh %} $> cf push [application-name-of-your-choosing] {% endhighlight %} This will fail miserably since the example application needs a MySQL database to start. So, lets create one! The command below will create a MySQl service with a free service plan. After the plan name you have to specify a name for the service instance. This name will be used for further commands to refer to this service instance: $> cf create-service mysql Pluto-free [service-name-you-can-choose] (Really, you can use any name. Make it count!) Next, binding the MySQL service instance to the application, to grant the application access to the MySQL instance, type: {% highlight sh %} $> cf bind-service [app-name-you-have-chosen-above] [service-name-you-have-chosen-above] {% endhighlight %} Finally we have to restart the application to make sure the service binding takes effect: {% highlight sh %} $> cf restart [app-name-you-have-chosen-above] {% endhighlight %} You will see this: {% highlight sh %} Creating service postgresql-d2197... OK Binding postgresql-d2197 to railsgirls... OK {% endhighlight %} Ending with... `Push successful! App 'railsgirls' available at railsgirls.de.a9sapp.eu`. Score! ### Version Control We need to add our new code to version control. You can do this by running the following in the terminal: {% highlight sh %} git status git add . git commit -m "add anynines deployment" {% endhighlight %} {% coach %} This would be a great time to talk about version control systems and git, if you haven't already. {% endcoach %} ### Help You can check all available cf sub-commands by typing `cf help`. In case your terminal does not have all the answers, the anynines team probably does. Just shoot them a mail at support@anynines.com. Happy deploying! ================================================ FILE: _pages/deployment/digital-ocean.md ================================================ --- layout: main_guide title: Rails Girls on DigitalOcean description: "Deploy your app to DigitalOcean by following this guide." permalink: deployment/digitalocean --- # Put Your App Online With DigitalOcean App Platform *Created by [Colin Alston](https://github.com/calston)* ## Change the production database Locally your app uses SQLite as the database to store your ideas. It's easier to use another database on DigitalOcean deploys. To deploy with DigitalOcean we'll change the database in production to use PostgreSQL. ### Install the pg gem Open the `Gemfile` file in your Text Editor and change the following line: {% highlight ruby %} gem "sqlite3" {% endhighlight %} into these lines: {% highlight ruby %} group :development do gem "sqlite3" end group :production do gem "pg" end {% endhighlight %} Next, run the command below to setup the new database gem: {% highlight sh %} bundle install --without production {% endhighlight %} ### Update the database configuration Up next, you'll need to change the database configuration for the production environment. {% coach %} Explain what the different Rails environments are. What is "production"? {% endcoach %} Open the `config/database.yml` file in your Text Editor. Change the following lines in the file: {% highlight yaml %} production: <<: *default database: storage/production.sqlite3 {% endhighlight %} to these lines: {% highlight yaml %} production: adapter: postgresql encoding: unicode pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> database: railsgirls_production username: railsgirls password: <%= ENV["RAILSGIRLS_DATABASE_PASSWORD"] %> {% endhighlight %} Save the changes in Git by creating a new commit. We'll need to update our app in Git to deploy these changes. {% highlight sh %} git add . git commit -m "Use PostgreSQL as the production database" {% endhighlight %} ## Create an account Head to [https://www.digitalocean.com/go/app-platform](https://www.digitalocean.com/go/app-platform) and sign up for the 60 day free trial. ![Trial page](/images/digitalocean/1.png) Sign up using Github to link your account ![Github Authorization](/images/digitalocean/githuboauth.png) You will need a credit card but will receive $200 to start with if this is your first time using DigitalOcean. ![Complete signup](/images/digitalocean/2.png) ## Create an application Click on `Deploy a web application` to get started. ![Deploy a web application](/images/digitalocean/create-app-1.png) Choose "Deploy your web app" to add an existing GitHub repository ![Deply source](/images/digitalocean/create-app-2.png) Authorize DigitalOcean to read your repositories ![Authorize DigitalOcean](/images/digitalocean/create-app-3.png) Select the repository for your application ![Choose repo](/images/digitalocean/create-app-4.png) ![Choose branch](/images/digitalocean/create-app-5.png) Click `Next` to continue then `Edit Plan` to ensure we use the appropriate resources. We will start with a Basic plan and the smallest container size which should be sufficient. ![Container size](/images/digitalocean/create-app-7.png) Continue through the next steps until the end. We should not need to change anything else. ![Environment](/images/digitalocean/create-app-8.png) ![Region](/images/digitalocean/create-app-9.png) ## Deploying our Rails application Wait for the application to build, you can view realtime logs of the process while it happens. ![Build](/images/digitalocean/building.png) If all went well you should see your application is available, however it still needs to be initialized and have a database added. ![Deployment](/images/digitalocean/deploy.png) Click on `Create` and `Create/Attach Database` to connect a PostgreSQL database. ![Database](/images/digitalocean/database.png) The application will automatically be configured with the database credentials ## Configuration You can now head to the `Console` to access your application container and setup the database. Type `rails db:migrate` into the terminal and press Enter. You should see the database being setup with the Rails schema. ![Migrate](/images/digitalocean/migrate.png) If all went well you should now be able to click on the `Live App` button which links to the live server. ![Tada](/images/digitalocean/fin.png) ## Conclusion Your Rails app is now running in the cloud on DigitalOcean. You can push your changes to GitHub and they'll show up automatically the live URL after some time. Share the URL to show off your app to your friends! Keep an eye out when your free credits run out and delete the app if you no longer need it. ================================================ FILE: _pages/deployment/engineyard.md ================================================ --- layout: main_guide title: Rails Girls on Engine Yard description: "Deploy your app to Engine Yard by following this guide." permalink: deployment/engineyard --- # Put Your App Online With Engine Yard *Created by Mary Jenn, [@mfjenn](https://twitter.com/mfjenn)* #### Ensure You're Using PostGres for Your Database You'll need to get your database to work on Engine Yard, which uses a different database than the Rails default. Please change the following in the Gemfile: gem 'sqlite3' to group :development do gem 'sqlite3' end group :production do gem 'pg' end Run `bundle install --without production` to setup your dependencies. #### Version Control Systems You need to add your app to your Git repository. You can do this by running the following in the terminal: > `git init` > `git add .` > `git commit -m "initial commit"` {% coach %} This would be a good time to talk about version control systems and git. {% endcoach %} ### Be Sure to Have a Rails Application in a Repository on Github You will need to have a GitHub account and a repo we can pull an app from. Follow these directions on [GitHub](https://help.github.com/articles/create-a-repo) to create a repo and push your app to it. If you do not have a working Rails application, you can fork [Engine Yard's sample todo app](https://github.com/engineyard/todo) to your own repo. A coach can walk you through this if you need help. ### Sign up for a Free Trial Engine Yard Account Go to Engine Yard's [Website](https://www.engineyard.com/) and click on "GET STARTED FREE" to sign up for your Free 500 Hour Trial. The sign up will send you a confirmation email, so go check your email, click on the link and sign in to your account. Click on the link under "Your available applications" that says "Engine Yard Cloud". This will take you to your dashboard. ### Create your Engine Yard Cloud account 1. Choose a name for your account. We suggest picking something relevant to who you are, either as a developer, or as an organization if you will be having collaborators. Click the button "Start Trial" 2. Feel free to explore what is in the drop downs, but let's go with the defaults for now, since they are in line with a basic Rails app. 3. In the box labeled "Git Repository URI", paste the URI from your Github repo. Be sure to use the URI from the SSH version of your application. HINT: The format should be the same as the placeholder text on your Engine Yard application page (or like this: "git@github.com:mfjenn/blogotron.git") ### Putting Your Deploy Key in Place You should now be on a page that says "Allow Engine Yard access to private repository". 1. Copy the block of text in the box and go to your GitHub settings page. 2. Go to the SSH page 3. Click on the button that says "add a key" 4. Paste the block of text from your Engine Yard page here. Save it 5. Go back to your Engine Yard Page and Click the button that says, "My deploy key is in place". {% coach %} Talk about the difference between private and public repos and when to use either. {% endcoach %} ### Creating and Configuring Your Environment Once you click the "My deploy key is in place" button, you will be taken to a page that says, "Create New Environment for (Your Account Name) App". It is here where we will configure your application. Feel free to explore all the options in the drop downs, but let's use the defaults for now. You do not need to set a domain name. * Click the button that says, "Create Environment". #### Environment Setup On this page, let's select the staging configuration. * Click "Boot This Configuration". You will go to a new page where you see several status bars moving. Our Platform is provisioning your instances. We need to wait till these turn to green dots. This usually takes about 10 minutes, so does anyone need to take a break? It's a good time to go grab some water or a coffee. {% coach %} Talk about Staging vs. Production, and why it's important to have replicas. Talk about what is a master & Slave. How does Engine Yard's Failover work? Why is that important? {% endcoach %} #### Deploying Your Application 1. Once all of the lights are green, click "Deploy". 2. Once you see the phrase "YOUR NAME successfully deployed HEAD" you will know it has been deployed! Congratulations! 3. Click on the link that says "View your application" to visit your application online. 4. If you get a red notification that your deploy failed, we just have some debugging to do. Raise your hand and a coach can come over to to help. #### Stopping Your Instances to Save Your Hours Once you've got your app up & running, be sure to click the "stop" button to stop the instances so that your don't burn through all of your hours. You can always start them again. ### Additional Resources * [A video tutorial](https://support.cloud.engineyard.com/entries/21009937-Video-Tutorial-Set-up-an-Account-and-Deploy-an-Application) * [Another Tutorial From the Engine Yard Site](https://support.cloud.engineyard.com/entries/20996751-Tutorial-How-to-Deploy-the-ToDo-Application-on-a-Trial-Account) ================================================ FILE: _pages/deployment/fly-io.md ================================================ --- layout: main_guide title: Put your app online with Fly.io description: "Deploy your app to Fly.io by following this guide." permalink: deployment/fly-io --- # Put your app online with Fly.io In this guide you'll deploy your app with [Fly.io](https://fly.io) to make it available to everyone online. After this guide you can share the link with your friends and family to show what you have created during this workshop. Deploying a single small app with Fly.io is free, with some limitations. {% coach %} Talk about the benefits of deploying to Fly.io versus traditional servers. {% endcoach %} ## Change the production database Locally your app uses SQLite as the database to store your ideas. It's easier to use another database on Fly.io deploys. To deploy with Fly.io we'll change the database in production to use PostgreSQL. ### Install the pg gem Open the `Gemfile` file in your Text Editor and change the following line: {% highlight ruby %} gem "sqlite3" {% endhighlight %} into these lines: {% highlight ruby %} group :development do gem "sqlite3" end group :production do gem "pg" end {% endhighlight %} Next, run the command below to setup the new database gem: {% highlight sh %} bundle install --without production {% endhighlight %} ### Update the database configuration Up next, you'll need to change the database configuration for the production environment. {% coach %} Explain what the different Rails environments are. What is "production"? {% endcoach %} Open the `config/database.yml` file in your Text Editor. Change the following lines in the file: {% highlight yaml %} production: <<: *default database: storage/production.sqlite3 {% endhighlight %} to these lines: {% highlight yaml %} production: adapter: postgresql encoding: unicode pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> database: railsgirls_production username: railsgirls password: <%= ENV["RAILSGIRLS_DATABASE_PASSWORD"] %> {% endhighlight %} Save the changes in Git by creating a new commit. We'll need to update our app in Git to deploy these changes. {% highlight sh %} git add . git commit -m "Use PostgreSQL as the production database" {% endhighlight %} ## Create a Fly.io account Visit the [Fly.io sign up page](https://fly.io/app/sign-up) and fill in the form to make a new user account. On the next screen, click the "Try Fly.io for free" link. You do not need to enter your Credit Card to use Fly.io for free. ## Install the Fly.io CLI To deploy apps with Fly.io, you'll need to use the Fly.io CLI: a tool for the Terminal app. Follow the [installation instructions on this Fly.io docs page](https://fly.io/docs/hands-on/install-flyctl/). Continue with this guide when the Fly.io CLI has been installed. ## Login to the Fly.io CLI Run the following command to connect your Fly.io user account to your laptop and deploy your app with Fly.io in the Terminal app. {% highlight sh %} flyctl auth login {% endhighlight %} It will open your Browser with a new tab/window. Either login to your Fly.io user account you created earlier, or click the button starting with "Continue as ...". You are now logged into Fly.io with the CLI. ## Configure the app Run the following command create the necessary configuration in your app to deploy it. {% highlight sh %} fly launch {% endhighlight %} When prompted for questions, enter or select the following: - Choose an app name: - Enter: railsgirls-yourname - Change "yourname" to your (nick)name. - Choose a region for deployment: - Choose the region closest to you with the arrow keys and then press Enter. - Would you like to set up a Postgresql database now? - Press y and then press Enter. - Select configuration: - Choose "Development" from the list. - Would you like to set up an Upstash Redis database now?: - Press n and then press Enter. Your app is now configured to deploy with Fly.io. You'll need to commit these changes before you can deploy. Commit your changes with this command: {% highlight sh %} git add . git commit -m "Configure for Fly.io deployment" {% endhighlight %} ## Deploy the app in the future If you made any new changes to your app and want to deploy the changes in the future, run the following command: {% highlight sh %} fly deploy {% endhighlight %} You'll see a lot of text being printed about the results of the steps needed to deploy the app. Wait until it's done. It should say "v0 deployed successfully". ## View your deployed app Your app should now be deployed. This means it's online for people to see. To know where you can view it, run the following command to open it in your Browser: {% highlight sh %} fly open {% endhighlight %} You now have your first app deploy! Congratulations! Share the link you see in your Browser's address bar! --- You do not need to deploy your app on another services. Continue with the next numbered guide in the list below. ================================================ FILE: _pages/deployment/heroku.md ================================================ --- layout: main_guide title: Put your app online with Heroku description: "Deploy your app to Heroku by following this guide." permalink: deployment/heroku --- # Put your app online with Heroku *Created by Terence Lee, [@hone02](https://twitter.com/hone02)* ## Get Heroku Follow steps "Introduction" and "Set up" of the [Getting Started on Heroku with Ruby][heroku-guide] to sign up, install the Heroku CLI, and login. {% coach %} Talk about the benefits of deploying to Heroku vs traditional servers. {% endcoach %} [heroku-guide]: https://devcenter.heroku.com/articles/getting-started-with-ruby#introduction ## Updating our database First, we need to get our database to work on Heroku, which uses a different database. Please change the following in the Gemfile: {% highlight ruby %} gem "sqlite3" {% endhighlight %} to {% highlight ruby %} group :development do gem "sqlite3" end group :production do gem "pg" end {% endhighlight %} Run `bundle install --without production` to setup your dependencies. Next, update the `config/database.yml` file. Change the following lines in the file: {% highlight yaml %} production: <<: *default database: storage/production.sqlite3 {% endhighlight %} to these lines: {% highlight yaml %} production: adapter: postgresql encoding: unicode database: railsgirls_production pool: 5 {% endhighlight %} Then save the changes in Git by creating a new commit. We'll need to update our app in Git to deploy the new version to Heroku. {% highlight sh %} git add . git commit -m "Use postgres as production database" {% endhighlight %} {% coach %} You can talk about RDBMS and the different ones out there, plus include some details on Heroku's dependency on PostgreSQL. {% endcoach %} ## Deploying your app ### App creation We need to create our Heroku app by typing `heroku create` in the terminal and see something like this: {% highlight sh %} Creating app... done, ⬢ young-reaches-87845 https://young-reaches-87845.herokuapp.com/ | https://git.heroku.com/young-reaches-87845.git {% endhighlight %} In this case "young-reaches-87845" is your app name. ### Pushing the code Next we need to push our code to heroku by typing `git push heroku master`. You'll see push output like the following: {% highlight sh %} Counting objects: 115, done. Delta compression using up to 8 threads. Compressing objects: 100% (97/97), done. Writing objects: 100% (115/115), 25.62 KiB | 0 bytes/s, done. Total 115 (delta 10), reused 0 (delta 0) remote: Compressing source files... done. remote: Building source: remote: remote: -----> Ruby app detected remote: -----> Compiling Ruby/Rails remote: -----> Using Ruby version: ruby-2.2.4 remote: -----> Installing dependencies using bundler 1.11.2 remote: Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment remote: Fetching gem metadata from https://rubygems.org/.......... remote: Fetching version metadata from https://rubygems.org/... remote: Fetching dependency metadata from https://rubygems.org/.. remote: Installing concurrent-ruby 1.0.2 ... remote: -----> Launching... remote: Released v5 remote: https://young-reaches-87845.herokuapp.com/ deployed to Heroku remote: remote: Verifying deploy... done. To https://git.heroku.com/young-reaches-87845.git * [new branch] master -> master {% endhighlight %} You'll know the app is done being pushed, when you see the "Launching..." text like above. ### Migrate database Next we need to migrate our database like we did locally during the workshop: {% highlight sh %} heroku run rails db:migrate {% endhighlight %} When that command is finished being run, you can hit the app based on the url. For this example app, you can go to . You can also type `heroku open` in the terminal to visit the page. ### Closing notes Heroku's platform is not without its quirks. Applications run on Heroku live within an ephermeral environment — this means that (except for information stored in your database) any files created by your application will disappear if it restarts (for example, when you push a new version). ###### [Ephemeral filesystem][ephemeral-filesystem] > Each dyno gets its own ephemeral filesystem, with a fresh copy of the most > recently deployed code. During the dyno’s lifetime its running processes can > use the filesystem as a temporary scratchpad, but no files that are written > are visible to processes in any other dyno and any files written will be > discarded the moment the dyno is stopped or restarted. For example, this > occurs any time a dyno is replaced due to application deployment and > approximately once a day as part of normal dyno management. In the [App](/app) tutorial the ability to attach a file to the Idea record is added, which results in new files being written to your applications `public/uploads` folder. The ephemeral storage in Heroku can be seen with the following steps: 1. Launch the app with `heroku open` 2. Add a new Idea with an image 3. Restart the application by running `heroku restart` 4. Go back to your Idea and reload the page - the image should no longer be visible [ephemeral-filesystem]: https://devcenter.heroku.com/articles/dynos#ephemeral-filesystem #### Working around Ephemeral Storage Obviously this doesn't seem to be useful if you were running a real life application, but there are ways to work around this which is commonly used by a lot of popular websites. The most common method is to use an external asset host such as Amazon S3 (Simple Storage Service) or Rackspace CloudFiles. These services provide (for a low cost - usually less then $0.10 per GB) storage 'in the cloud' (meaning the files could potentially be hosted anywhere) which your application can use as persistent storage. While this functionality is a bit out of scope for this tutorial there are some resources available which you can use to find your way: * [How to: Make Carrierwave work on Heroku](https://github.com/carrierwaveuploader/carrierwave/wiki/How-to%3A-Make-Carrierwave-work-on-Heroku) * [Amazon S3 – The Beginner’s Guide](https://www.hongkiat.com/blog/amazon-s3-the-beginners-guide/) As always if you require any more information or assistance your coaches will be able to assist. ================================================ FILE: _pages/deployment/openshift.md ================================================ --- layout: main_guide title: Rails Girls on OpenShift description: "Deploy your app to OpenShift by following this guide." permalink: deployment/openshift --- # Put Your App Online With OpenShift *Created by Katie Miller, [@codemiller](https://twitter.com/codemiller)* ### Get OpenShift OpenShift is a cloud computing Platform as a Service (PaaS) that makes it easy to deploy apps online. It is open source and written in Ruby. To get started [create an OpenShift Online account](https://www.openshift.com/app/account/new), which allows you to put three apps online for free. Once you are signed up, install the OpenShift RHC Client Tools by running these commands in a terminal and following the prompts: {% highlight sh %} gem install rhc rhc setup {% endhighlight %} The above instructions assume you installed Ruby using RVM or RailsInstaller. If you used another approach, there is more info about installing RHC for different set-ups in [this guide](https://www.openshift.com/developers/rhc-client-tools-install) (you may need to do `sudo gem install rhc`). {% coach %} Talk about the benefits of deploying to a PaaS such as OpenShift, as opposed to traditional servers. Discuss SSH and why we need to upload a public key to communicate securely. {% endcoach %} ### Preparing your app #### Create OpenShift application We are going to create an OpenShift Ruby application with a PostgreSQL database, using a sample OpenShift Rails application as our starting point. Before we do that, in your terminal change to the parent directory of the one containing your `railsgirls` code, probably called `projects`. The `cd` command below will take you there if you are currently in your `railsgirls` directory; if not, substitute another `cd` command. {% highlight sh %} cd .. pwd {% endhighlight %} The output from the `pwd` or 'present working directory' command should show you are now in the `projects` directory (or whatever your parent directory was called). To create the OpenShift app in the cloud and make a local copy of its contents, run the following command in your terminal. _NB: This command is for those using Ruby 2.x and Rails 4. If you have installed Ruby 1.9.x, replace `ruby-2.0` in the command with `ruby-1.9`. For Rails 3, change the `--from-code` URL to `https://github.com/openshift/rails-example.git`._ {% highlight sh %} rhc app create openshiftapp ruby-2.0 postgresql-9.2 --from-code=https://github.com/openshift/rails4-example.git {% endhighlight %} If you see a message like `Are you sure you want to continue connecting (yes/no)?`, type `yes` and press enter. The terminal output should include a URL; open a browser window and go to the application URL to view the sample Rails application (the URL will have the form https://openshiftapp-*yourdomain*.rhcloud.com). {% coach %} Explain what Git is and why we use version control systems. {% endcoach %} #### Add version control We now have a sample app running in the cloud, but we actually need only a few pieces from its codebase. Before we copy across the bits we need, we should put our Rails Girls app under version control with Git. Change back to your `railsgirls` app directory and initialize it as a Git repository with the following commands: {% highlight sh %} cd railsgirls git init {% endhighlight %} We don't want the pictures uploaded during app development to be part of our repository, so run the following command to instruct Git to ignore them: {% highlight sh %} echo "public/uploads" >> .gitignore {% endhighlight %} Add and commit all your app files to the Git repository with the following commands: {% highlight sh %} git add --all git commit -m "First commit of Ideas app" {% endhighlight %} {% coach %} Explain the Git commands used and .gitignore. {% endcoach %} #### Copy sample app code We need the `.openshift` directory and `config/database.yml` file from the sample application for our Rails app to run on OpenShift. Copy these from the `openshiftapp` directory to the `railsgirls` directory. You can use Windows Explorer or another graphical file system tool to do this if you like, or alternatively run the following commands from the `railsgirls` directory in your terminal:
{% highlight sh %} cp -r ../openshiftapp/.openshift . cp ../openshiftapp/config/database.yml config {% endhighlight %}
{% highlight sh %} xcopy /e /i ..\openshiftapp\.openshift .openshift xcopy /y ..\openshiftapp\config\database.yml config {% endhighlight %}
Check that the copying has worked by looking in the `railsgirls` app directory. There should now be a subdirectory called `.openshift`. Open the file `config/database.yml`; it should now contain OpenShift environment variables such as `OPENSHIFT_APP_NAME`. If your `database.yml` file does not contain variables like this, try opening `.openshift/config/database.yml` or `openshiftapp/config/database.yml` in your editor and copying across the contents of the file. Add and commit the new and changed files in Git with the below commands. {% highlight sh %} git add --all git commit -m "Added OpenShift config" {% endhighlight %} #### Change database The next step is to change our Rails Girls app database from SQLite to PostgreSQL. Open your application's `Gemfile` and replace: {% highlight ruby %} gem 'sqlite3' {% endhighlight %} with {% highlight ruby %} gem 'sqlite3', :group => [:development, :test] gem 'pg', :group => [:production] {% endhighlight %} Do a bundle to set up your dependencies: {% highlight sh %} bundle install --without production {% endhighlight %} On some platforms, this may generate platform-specific versions of your Gems that cause issues when you push your app to the cloud. To prevent this, open your `Gemfile.lock` file and check the versions of the 'sqlite3' and 'pg' Gems. If they have a platform-specific suffix, such as `-x86-mingw32`, remove this (eg. change `pg (0.16.0-x86-mingw32)` to `pg (0.16.0)` and `sqlite3 (1.3.8-x86-mingw32)` to `sqlite3 (1.3.8)`). Save and close the file, and run the above bundle command again before continuing. Add and commit your changes in Git: {% highlight sh %} git add --all git commit -m "Changed production database to PostgreSQL" {% endhighlight %} {% coach %} Talk about relational databases and the differences between SQLite and PostgreSQL. {% endcoach %} ### Deploy app to OpenShift We are now ready to deploy the Rails Girls app to OpenShift. We need to tell our Git repository where to push the code. To get the location of your OpenShift code repository, run the following command, and copy the Git URL from the output. {% highlight sh %} rhc app show openshiftapp {% endhighlight %} Now run the following commands, replacing the SSH string with your Git URL. We are using '-f' for force here because we are happy to wipe away the history of the current OpenShift repository, which contains the sample Rails app. When you are pushing future changes, you can just use 'git push'. {% highlight sh %} git remote add openshift ssh://0123456789abcdef01234567@openshiftapp-yourdomain.rhcloud.com/~/git/openshiftapp.git/ git push -f --set-upstream openshift master {% endhighlight %} Refresh the app in your browser to see the result. {% coach %} Talk about Git remotes. {% endcoach %} ### Extra credit Congratulations - your Rails application is now online for the whole world to admire. The following sections explain optional further steps you can take to improve and share your app. #### Persist uploaded images The app should be looking pretty good now, but there is an issue lurking because of the ephemeral nature of the deployment. When we push a new version of the application, anything stored within OpenShift's copy of the repo will be wiped to make way for the new files. This includes the images uploaded by users. To fix this, we can store these files in a persistent directory on OpenShift instead. The filepath of the location we need is stored in an environment variable. {% coach %} Explain the motivation for using environment variables. {% endcoach %} The directory where uploaded pictures are currently stored is within the app repository, so it will be deleted when we rebuild. To switch the uploads directory to one that will persist, open `app/uploaders/picture_uploader.rb` and replace {% highlight ruby %} def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end {% endhighlight %} with {% highlight ruby %} def store_dir prefix = ENV['OPENSHIFT_DATA_DIR'] ? "#{ENV['OPENSHIFT_DATA_DIR']}/" : "" "#{prefix}uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end def url return "/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}/#{File.basename(file.path)}" if ENV['OPENSHIFT_DATA_DIR'] && file super end {% endhighlight %} Now uploaded images will be stored in a persistent directory, but they will still be available through the same URL as what we were using previously. To make this work, we also need to add a symbolic link on the filesystem from the repository location to the real storage location. To do this, open `.openshift/action_hooks/build` and add the following code: {% highlight sh %} mkdir -p $OPENSHIFT_DATA_DIR/uploads ln -sf $OPENSHIFT_DATA_DIR/uploads $OPENSHIFT_REPO_DIR/public/uploads {% endhighlight %} This action hook code will run every time the OpenShift app is built, so the link between the directories will always be there when it's needed. Commit your changes and push them to the cloud: {% highlight sh %} git add --all git commit -m "Added OpenShift environment variables" git push {% endhighlight %} The images you uploaded before making this change will no longer display, but anything uploaded now will stick around between app rebuilds. {% coach %} Explain symbolic links. {% endcoach %} #### Push code to GitHub Now that your application is under source control with Git, you may also wish to share a copy with others on a Git repository website such as GitHub. To push your code to a GitHub repository, [create a repository](https://github.com/new) on GitHub and copy the HTTPS string (something like *https://github.com/username/reponame.git*). Navigate to your OpenShift app repository in the terminal and enter the following commands, replacing the HTTPS location with the string you copied: {% highlight sh %} git remote add github https://github.com/username/reponame.git git push github master {% endhighlight %} The 'master' branch of the local copy of your repository will be pushed to GitHub. Go to the GitHub website to check it out. {% coach %} Talk about Git branches and the benefits of open source code. {% endcoach %} ### Conclusion Your Rails app is now running in the cloud on [OpenShift](https://www.openshift.com/developers). You can push whatever other changes you like and share the URL to show off your app to your friends. ================================================ FILE: _pages/deployment.md ================================================ --- layout: main_guide title: Put your app online description: "Publish your app online on one of the many available web hosting services." permalink: deployment --- # Put your app online {% include main-guide-intro.html %} Now that you have your very first app made, let's share it with others by putting it online! Once you're done with one of the following guides, you'll have a URL that people can enter in their browser and see what you made today. During the workshop you can continue working on your app (by following these guides), and deploying new and improved versions of your app. There are many services that can host your app. They all are slightly different. Ask your coach which service they recommend. {% coach %} Please help choose the best, and possibly free, service to deploy the app. Preferably a PaaS like Heroku. {% endcoach %} ================================================ FILE: _pages/design-using-html-and-css-chinese.md ================================================ --- layout: guide title: 使用HTML和CSS美化你的应用 permalink: design-html-css-chinese --- 1.美化header样式 + 打开文件 `app/assets/stylesheets/application.css` 并在最底端添加: ``` .navbar { min-height: 38px; background-color: #f55e55; } ``` 刷新页面,查看样式有什么变化。 此处解释什么是css选择器,学员可以尝试修改header的颜色,字体等。 简单的颜色选取参考网站: **教练:**解释`display`的属性,什么是内联元素,什么是块级元素 + 在文件底部加入下面的代码: ``` .navbar a.brand { font-size: 18px; } .navbar a.brand:hover { color: #fff; background-color: transparent; text-decoration: none; } ``` **教练:**解释css中链接的四种状态 2.美化表格样式 + 对于表格,我们可以使用[Bootstrap](https://www.bootcss.com/)的表格样式。打开`app/views/ideas/index.html.erb`文件,找到: ``` ``` 将其改为 ```
``` + 修改图片大小,找到这段代码 ``` <%= image_tag(idea.picture_url, :width => 600) if idea.picture.present? %> ``` 尝试修改width + 打开文件`app/assets/stylesheets/ideas.css.scss`,加入以下代码: ``` .container a:hover { color: #f55e55; text-decoration: none; background-color: rgba(255, 255, 255, 0); } ``` + 尝试为页面添加背景图片,使用`background-image`属性,背景纹理资源参考此网站 3.footer样式调整 + 打开文件 `app/assets/stylesheets/application.css` 并在最底端添加: ``` footer { background-color: #ebebeb; padding: 30px 0; } ``` 尝试在`footer`中加入更多内容,并调整位置 4.按钮样式 + 打开页面,可以看到页面上的`Create Idea`按钮。 在文件`app/assets/stylesheets/ideas.css.scss`最后加入 ``` .container input[type="submit"] { height: 30px; font-size: 13px; background-color: #f55e55; border: none; color: #fff; } ``` **教练:**解释css中`border`的使用,学员可以尝试修改按钮样式,加圆角,阴影,颜色等。 ================================================ FILE: _pages/design.md ================================================ --- layout: main_guide title: Style the idea pages using HTML and CSS description: "Make your app look even better using Bootstrap by styling the idea pages." permalink: design --- # Style the idea pages using HTML and CSS *Originally created by Alex Liao, @alexliao* {% include main-guide-intro.html %} ## Style the idea list page The default Rails scaffolding allow us to build pages very quickly and get our app working. The design could use some work. For this we're going to be using [Bootstrap](https://getbootstrap.com/docs/5.2/) again. We'll be using some existing Bootstrap classes to make our own components, style links and buttons. Open `app/views/ideas/index.html.erb` in your Text Editor and replace all the lines with these lines: {% highlight erb %}

<%= notice %>

Ideas

<%= link_to "Add a new idea", new_idea_path, class: "btn btn-primary mb-3" %>
<% @ideas.each do |idea| %> <%= render idea %> <% end %>
{% endhighlight %} This alone isn't all the styling we'll need, but this will show all the ideas in a nice list in a moment. At the top we'll have a new blue button with the label "Add a new idea". Open `app/views/ideas/_idea.html.erb` in your Text Editor and replace all the lines with these lines: {% highlight erb %}

<%= link_to idea.name, idea_path(idea) %>

<%= idea.description %>

Last updated <%= time_ago_in_words idea.updated_at %>
<%= image_tag(idea.picture_url, width: 150, height: 150, class: "img-thumbnail flex-shrink-0") if idea.picture? %>
{% endhighlight %} This will style each idea in the list to show their idea name as a link to the idea itself, it shows when the idea was last updated, the idea description and a thumbnail of the picture you uploaded. Visit the page to see your new idea app design. {% coach %} Explain how the design works line by line. What is HTML, what is CSS and what parts are Bootstrap? {% endcoach %} ## Style the idea detail page Click the title of an idea, and you will be brought to the details page of the idea. This still partially uses scaffold generated by Rails, and may look a bit broken right now. Let's improve the design. Open `app/views/ideas/show.html.erb` in your text editor and replace all lines with {% highlight erb %}

<%= notice %>

<%= @idea.name %>

<%= @idea.description %>

Last updated <%= time_ago_in_words @idea.updated_at %>
<%= image_tag(@idea.picture_url, width: 150, height: 150, class: "img-thumbnail flex-shrink-0") if @idea.picture? %>
<%= link_to "Edit this idea", edit_idea_path(@idea), class: "btn btn-primary" %> <%= link_to "Back to ideas", ideas_path, class: "btn btn-outline-secondary" %> <%= button_to "Destroy this idea", @idea, method: :delete, class: "btn btn-danger", form: { data: { turbo_confirm: "Are you sure?" } } %>
{% endhighlight %} The new page should look a lot better and a lot like how the ideas are shown on the index page. The actions you can perform on the idea now also are shown in highly visible buttons below the idea details. {% coach %} Explain how the design works line by line. What is HTML, what is CSS and what parts are Bootstrap? {% endcoach %} ## References To style the pages we've used the following Bootstrap components. Check out the documentation to learn more. - [Bootstrap list groups](https://getbootstrap.com/docs/5.2/components/list-group/) - [Bootstrap buttons](https://getbootstrap.com/docs/5.2/components/buttons/) - [Bootstrap images](https://getbootstrap.com/docs/5.2/content/images/) ## What next? Did the design and styling catch your eye? Do you want to unleash your inner designer and style more pages? * Use your new knowledge to design the new idea form located at `app/views/ideas/_form.html.erb` * Add more design to the other pages as you wish. ================================================ FILE: _pages/devise.md ================================================ --- layout: guide title: Adding Authentication with Devise description: "Let users of your Rails app sign in using Devise." permalink: devise --- # Adding Authentication with Devise *Created by Piotr Steininger, [@polishprince](https://twitter.com/polishprince). Updated by Ernesto Jimenez, [@ernesto_jimenez](https://twitter.com/ernesto_jimenez)*, and [Hasan Diwan](https://units.d8u.us/twitter?src`=railsgirlsGuide) **This guide assumes that you have already built a Rails Girls app by** [**following the app development guide**](/app). ## *1.* Add devise gem {% highlight sh %} bundle add devise bundle install {% endhighlight %} to install the gem. **Also remember to restart the Rails server**. ## *2.* Set up devise in your app Run the following command in the terminal. {% highlight sh %} rails g devise:install {% endhighlight %} ## *3.* Configure Devise Ensure you have defined default url options in your environments files. Open up `config/environments/development.rb` and add this line: {% highlight ruby %} config.action_mailer.default_url_options = { host: "localhost", port: 3000 } {% endhighlight %} before the `end` keyword. Open up `app/views/layouts/application.html.erb` and add: {% highlight erb %} <% if notice %>

<%= notice %>

<% end %> <% if alert %>

<%= alert %>

<% end %> {% endhighlight %} right above {% highlight ruby %} <%= yield %> {% endhighlight %} Open up `app/views/ideas/show.html.erb` and remove the line that says: {% highlight erb %}

<%= notice %>

{% endhighlight %} Do the same for `app/views/comments/show.html.erb`. These lines are not necessary as we've put the notice in the `app/views/layouts/application.html.erb` file. ## *4.* Setup the User model We'll use a bundled generator script to create the User model. {% highlight sh %} rails g devise user rails db:migrate {% endhighlight %} {% coach %} Explain what user model has been generated. What are the fields? {% endcoach %} ## *5.* Create your first user Now that you have set everything up you can create your first user. Devise creates all the code and routes required to create accounts, log in, log out, etc. Make sure your rails server is running, open and create your user account. ## *6.* Add sign-up and login links All we need to do now is to add appropriate links or notice about the user being logged in in the top right corner of the navigation bar. In order to do that, edit `app/views/layouts/application.html.erb` add: {% highlight erb %} {% endhighlight %} right after {% highlight erb %} {% endhighlight %} Finally, force the user to redirect to the login page if the user was not logged in. Open up `app/controllers/application_controller.rb` and add: {% highlight ruby %} before_action :authenticate_user! {% endhighlight %} after `class ApplicationController < ActionController::Base`. Open your browser and try logging in and out from. {% coach %} Talk about the `user_signed_in?` and `current_user` helpers. Why are they useful? {% endcoach %} ## What next? * Add extra fields to the User model * Add relationships between users and ideas * Restrict users to only be able to edit their own ideas and delete their own comments * Expand to use roles or permissions (use one of the popular authorization gem like CanCan) ================================================ FILE: _pages/diary-app.md ================================================ --- layout: guide title: Rails Girls Diary tutorial permalink: diary-app --- # Create your first diary app with Ruby on Rails *Created by Piotr Szotkowski ([chastell](https://chastell.net)) and Tomasz Stachewicz ([tomash](https://tomash.wrug.eu/))* We will create a little voting app from scratch using a web development framework for Ruby called Rails. Think what your first application should be about – ideally something simple that includes a collection of some sort: e.g., a to-do list, a diary, etc. We’ll use a diary as the base here. {% coach %} For the rationale behind this slightly different beginners tutorial, take a look at this [post](http://dotclass.org/rails-girls-warsaw-programme/). {% endcoach %} **Make sure you have Rails installed.** [**Follow the installation guide**](/install) to get set up. ### Important It is important that you select the instructions specific to your operating system - the commands you need to run on a Windows computer are slightly different to Mac or Linux. If you're having trouble check the Operating System switcher at the bottom of the commands. In case you're using a cloud service, you need to run the Linux commands even if you are on a Windows computer. ## Pure HTML ### File and folder Create a new directory (folder) and create a file named `index.html` in it. Open that file in your editor and web browser. {% coach %} Explain that browsers can open local files, only the URL looks stranger than usual. {% endcoach %} ### HTML skeleton Start by adding a general skeleton for your HTML by writing the below into the `index.html` file: {% highlight erb %} My Little Webapp: Coding Is Magic {% endhighlight %} {% coach %} Explain the two main parts of HTML, `` and ``. Explain the `` tag and (briefly) `<meta>` , `<link>` and `<script>` if needed. Bootstrap is there so that CSS can be skipped altogether (unless participants want to cover it). {% endcoach %} ### First visible content Add the following HTML between the `<body>` and `</body>` tags (feel free to adjust the contents…): {% highlight erb %} <h1>My Rails Girls Diary</h1> <div> <h2>Submitted a Rails Girls application</h2> <p>1.02.2014</p> <p>Just submitted an application to a Rails Girls workshop. Can’t wait to see whether I’ll get in!</p> <h2>Got in!</h2> <p>15.02.2014</p> <p>Received an email that my application got accepted! I’ll be at a RG workshop next week!</p> <h2>The first day starts…</h2> <p>22.02.2014</p> <p>Today is the first day of the Rails Girls workshop. My coach is quite strange but it seems we all have Rails installed now and can start learning.</p> </div> {% endhighlight %} These are your first three diary entries. Note how the different tags get displayed and note the recurring structure. {% coach %} Tell a bit about HTML tags and their semantic meaning. {% endcoach %} ### More HTML Add the following either before or after the above diary entries (again, do adjust to taste): {% highlight erb %} <div> <h1>My favourite websites</h1> <ul> <li><a href="https://railsgirls.com">Rails Girls</a></li> <li><a href="https://en.wikibooks.org/wiki/Ruby_Programming">Wikibooks</a></li> <li><a href="/">Ruby on Rails Guides</a></li> </ul> </div> <img src="https://railsgirls.com/images/rg-warsaw.png" /> {% endhighlight %} This is an HTML unordered list with some list items containing anchors (links) with hypertext references (URLs) to other pages. It’s followed by a paragraph containing an image – and the image’s source is at the given URL. {% coach %} Explain how the Web works and talk a bit about HTML elements and attributes. {% endcoach %} [Here](https://github.com/krzysztofbialek/Rails-Girls-Warsaw-App)'s a link to repo with styled basic app you can use. ## Moving to Rails ### New Rails application Open a terminal window (Command Prompt on Windows), change to the directory where your files are (using the `cd` command) and run `rails new diary` – this will take some time and end up creating a new Rails application. Run `cd diary` to change to the app’s directory. {% coach %} Explain how to navigate directories and run commands. {% endcoach %} ### Running the server Once in the `diary` directory run `rails server` and (once it finishes starting up) go to <http://localhost:3000> in your browser. You should see the ‘Welcome aboard’ page. Stop the server by pressing `ctrl-c`. {% coach %} Explain what has happened and what’s the output in the terminal window. If the server fails to start due to a missing JavaScript runtime, `gem install therubyracer` and uncomment the relevant line in `Gemfile`. {% endcoach %} ### First route and view Create the controller and the route Run `rails generate controller welcome index` – this will generate your first controller and a route that leads to it. Start your server and go to <http://localhost:3000> to see that your application indeed does support the `/welcome/index` route. Stop the server and run `rake routes` to see all the routes supported by your application. {% coach %} Explain URLs and the URL hierarchy. Explain how in Rails URLs map to ‘what happens behind the scene’. {% endcoach %} ### Move the view to be the top of your site Edit the `config/routes.rb` file and uncomment (remove the `#` from the front) the `root ’welcome#index’` line (this will probably be the 7th line). This will make the root of your application be the view rendered by the `Welcome#index` action. Go to <http://localhost:3000> and see that indeed the main page of your application now serves this view (rather than the ‘Welcome aboard’ page). {% coach %} Explain how the main page of an application is the root of the URL hierarchy and that it’s the page that people visit when they just put the host name into the browser’s address bar. {% endcoach %} ### Move the existing HTML to the right view Edit the `app/views/welcome/index.html.erb` file and copy the contents of the `<body>` tags from your original `index.html` file (i.e., the list of diary entries and the website links) there, replacing the two lines (with `<h1>` and `<p>`) in the view. Refresh the browser to see that the page now indeed contains the right contents. {% coach %} Explain that the view only contains the part between `<body>` and `</body>`, as the rest is common to the whole application and is defined elsewhere. {% endcoach %} ## Iteration ### Repeated content If you look at the structure of your list of links, it seems that every list item looks similar to the others – it contains a URL (where the link should take the user when clicked) and a name (what should the user see and be able to click on). Rather than writing the links as raw HTML (and potentially make a mistake with some of them) let’s abstract this a bit and iterate over a collection of URL-and-name pairs. Replace the contents of the `<ul>` tags with the following: {% highlight erb %} <% @websites = [ ["https://railsgirls.com", "Rails Girls"], ["https://en.wikibooks.org/wiki/Ruby_Programming", "Wikibooks"], ["https://guides.rubyonrails.org", "Ruby on Rails Guides"], ] %> <% for url, name in @websites %> <li><a href="<%= url %>"><%= name %></a></li> <% end %> {% endhighlight %} Refresh the browser window to see whether your page still has the same links. {% coach %} Explain what happened – what is an array, what do `<%` and `<%=` ERb tags mean (and how they differ), how iteration works. {% endcoach %} Keeping code or data (like the above `@websites` array) in views is simple, but a bad practice and can bite in the long run. For starters let’s move the `@websites` array from the view to the controller. Remove it from the view and put it in `app/controllers/welcome_controller.rb` in the `index` method so it looks like this: {% highlight ruby %} class WelcomeController < ApplicationController def index @websites = [ ["https://railsgirls.com", "Rails Girls"], ["https://en.wikibooks.org/wiki/Ruby_Programming", "Wikibooks"], ["https://guides.rubyonrails.org", "Ruby on Rails Guides"], ] end end {% endhighlight %} Note that after refreshing your browser window nothing should change – this is because variables starting with @ (called ‘instance variables’) can be accessed by both the view and the controller. {% coach %} Explain the connection between the `WecomeController#index` action and the view; note and emphasise the difference between @-starting `@websites` and plain `url` or `name`. {% endcoach %} ### Create the model With the website links out of the hard-coded way, let’s do something with the diary entries. This time we won’t (ab)use a simple Ruby structure like an array, but a proper model that represents a given entry’s data. Let’s start with generating the model – run `rails generate model Entry title:string date:date contents:text` to create an `Entry` model that can represent a diary entry with a title, a publication date and some contents. {% coach %} Explain what models are and the `field:type` notation for generating them; explain the difference between `string` and `text` types if necessary. {% endcoach %} ### Migrate the database Run `rails db:migrate` to migrate the database so that its structure contains a table for entries. {% coach %} Explain what databases are (in abstract terms, as vessels for storing our application’s data and providing model structures) and why they are needed. Explain that things which are in memory won’t get persisted by default and they need to be persisted explicitly to be available on the next request. {% endcoach %} ### Play with the model in the Rails console Now that we have a model, we can start creating instances of that model – i.e., actual diary entries that aren’t hard-coded in the HTML view. For this, we’ll learn a new tool: the Rails console. Start it with `rails console` and, once it boots and shows: you the `>>` prompt, create a few entries: {% highlight sh %} >> Entry.create "title" => "Submitted a Rails Girls application", "date" => Date.new(2014, 2, 1), "contents" => "Just submitted an application to a Rails Girls workshop. Can’t wait to see whether I’ll get in!" … >> Entry.create "title" => "Got in!", "date" => Date.new(2014, 2, 15), "contents" => "Received an email that my application got accepted! I’ll be at a RG workshop next week!" … >> Entry.create "title" => "The first day starts…", "date" => Date.new(2014, 2, 22), "contents" => "Today is the first day of the Rails Girls workshop. My coach is quite strange but it seems we all have Rails installed now and can start learning." {% endhighlight %} Note how the console – just like `rails server` – shows you a log of what happens in the background. You can always get an array of all existing entries via `Entry.all`. {% coach %} Explain what’s going on. Slowly. {% endcoach %} ## Viewing the persisted contents ### Add the model instances to the existing view Edit the `WelcomeController#index` action (in the `app/controllers/welcome_controller.rb` file) and add the following either before or after the lines containing `@websites` definition: {% highlight ruby %} @entries = Entry.all {% endhighlight %} Edit the `app/views/welcome/index.html.erb` view and replace the lines with the diary entries with the following: {% highlight erb %} <% for entry in @entries %> <h2><%= entry.title %></h2> <p><%= entry.date %></p> <p><%= entry.contents %></p> <% end %> {% endhighlight %} {% coach %} Discuss what happened; discuss what’s the order of the entries and how they can be reordered (say, by reverse date) and where it should happen. {% endcoach %} ### Create a controller for diary entries Now that we have a model we need to create a controller for handling actions related to the instances of the model (creating new entries, showing, editing and deleting existing ones). Run `rails generate controller Entries` – this should generate the `EntriesController` class. Check `rake routes` – notice that the controller isn’t enough, we still need to point URLs to the controller’s actions. Edit `config/routes.rb` and add a `resources "entries"` line somewhere inside the `Diary::Application.routes.draw` block. Run `rake routes` again: notice how now your application has all kinds of new routes. {% coach %} Explain how Rails’ route resources work and how they make URLs spring to existence and map to controller actions by default. {% endcoach %} ### A view of all the entries As can be seen in the `rake routes` output, the URLs are wired to their relative controller actions. Let’s see what’s missing – visit <http://localhost:3000/entries> in your browser. Uh-oh, it seems like the ‘index’ action is missing – let’s add it – open `app/controllers/entries_controller.rb` and add the below empty method inside the class definition: {% highlight ruby %} def index end {% endhighlight %} Now refresh the browser – we no longer have an ‘unknown action’ problem, we now have a ‘template is missing’ problem. Save an empty file as `app/views/entries/index.html.erb` (note it’s just like the `index.html.erb` file in the ‘welcome’ directory before, but this time it’s in the ‘entries’ directory) and refresh the browser again – it should display an empty page. This is good, as our view is quite empty at the moment. {% coach %} Explain how actions render the related views by default. {% endcoach %} Now go to the `app/controllers/welcome_controller.rb` file and find the `WelcomeController#index` method (the one that starts with `def index`). Find the line that sets the `@entries` variable (it should start with `@entries =`) and copy it to `EntriesController#index` (so to the `index` method of the `EntriesController`, which can be found in `app/controllers/entries_controller.rb`). Similarly, go to the `app/views/welcome/index.html.erb` view and copy the `@entries.each` block (all of the indented lines up to and including the matching `end`) to the `app/views/entries/index.html.erb` view. Refresh the browser: it should now show the list of all your diary entries. {% coach %} Explain that even though this might look like little to no progress, there is a significant change: we’re no longer operating in the context of the main page of our app, but rather a list of diary entries only (without the links to other websites, for example). {% endcoach %} ### A view of a single entry Note how, when you run `rake routes`, the output says that the `/entries/:id(.:format)` pattern maps to the `entries#show` controller action. Go to <http://localhost:3000/entries/1> – the URL for your first diary entry; notice how we’re, again, missing an action of the `EntriesController`. Add that (empty for now) action, then refresh the browser and add the (likewise, empty) missing view. {% coach %} Guide through adding the missing action and view if needed; make sure the process (all the way from deciphering the right `rake routes` line) is well understood. {% endcoach %} Now, let’s figure out how to interpret the `1` from the end of the URL to display the right entry. Make the `EntriesController#show` action look like this: {% highlight ruby %} def show @entry = Entry.find(params["id"]) end {% endhighlight %} This line means ‘take the `id` parameter and use it in the `Entry.find` method to find the right entry’. Now edit the `app/views/entries/show.html.erb` view and put there the following: {% highlight erb %} <h2><%= @entry.title %></h2> <p><%= @entry.date %></p> <p><%= @entry.contents %></p> {% endhighlight %} Visit <http://localhost:3000/entries/1> and compare it with <http://localhost:3000/entries/2> to see how using `params[’id’]` means that different diary entries get displayed. {% coach %} Explain that the `:id` part of the URL template from `rake routes` is made into a key for the `params` hash; discuss what else can be found in the `params` hash. {% endcoach %} ### Linking entries Run `rake routes` again; notice how the row for the `entries#show` action starts with `entry` in the ‘prefix’ column. Go to the `app/views/entries/index.html.erb` view and change the line responsible for displaying the title to the below: {% highlight erb %} <h2><%= link_to(entry.title, entry_path(entry)) %></h2> {% endhighlight %} Note how we use the `link_to` method that takes two parameters, the text to display (`entry.title`) and the path to link to. Check the source of the page to see what is the path for subsequent titles. Note how the path is created by calling the `entry_path` method with `entry` as its argument. {% coach %} Remind how the HTML for links looks like. Explain the relation between `entry_path` and the `entry` prefix from `rake routes`. Explain why the `entry_path` method needs the `entry` argument. Explain what the `entry_url` method does (and how it differs from the `entry_path` method) if you want to. {% endcoach %} Now let’s try to get back from an entry screen to the index of all entries: edit the `app/views/entries/show.html.erb` template and add a link to the entries index, like this: {% highlight erb %} <p><%= link_to("Back to all entries", entries_path) %></p> {% endhighlight %} Note, again, how the `entries` prefix from `rake routes` is used to construct the `entries_path` method name. Note how this method does not need a parameter. ## Creating entries via the UI ### Adding the ‘new entry’ form Now that we have a way to display a list of all entries and a single entry, let’s add a way to create new diary entries. Run `rake routes` and try to figure out which URL (and action) is responsible for new entry creation. Go to the index of all entries and add a link for creating new entry: {% highlight erb %} <%= link_to("New entry", new_entry_path) %> {% endhighlight %} Click the link – and add the missing action and view. {% coach %} Make sure this process is well understood by now. {% endcoach %} Edit the `app/views/entries/new.html.erb` view and paste in the below: {% highlight erb %} <%= form_for(Entry.new) do |form| %> <p><%= form.label("title") %></p> <p><%= form.text_field("title") %></p> <p><%= form.label("contents") %></p> <p><%= form.text_area("contents") %></p> <p><%= form.submit %></p> <% end %> <p><%= link_to("Back to all entries", entries_path) %></p> {% endhighlight %} **Note:** we can skip labels for now {% coach %} Show how the HTML produced by the `form_for` helper looks like and try to explain how it works. {% endcoach %} ### Handling the ‘new entry’ form Refresh the browser and try adding a new entry – you should see the well-known-by-now ‘unknown action’ error. Add the action to the `EntriesController`, but for starters let’s display what the action receives: {% highlight ruby %} def create render(:text => params.inspect) end {% endhighlight %} Refresh the browser and inspect what exactly the action gets as its params. {% coach %} Explain how filling a text field and a text area and submitting the form ends up with all the params being POSTed to the controller’s action. Explain what .inspect does. {% endcoach %} ### Creating and persisting the new entry Edit the `create` action and make it look like this: {% highlight ruby %} def create entry_params = params["entry"] entry = Entry.create(entry_params) redirect_to(entry_path(entry)) end {% endhighlight %} Note how we try to get the parameters of the new entry (its title and contents) from the `params` hash and then create a new entry from them, just like in the console. Try submitting the form again – notice that we’re still not there yet, as we get a `ActiveModel::ForbiddenAttributesError`. - Note: we can skip strong_parameters in the beginning, keeping the application not secure from parameter injection. - config.action_controller.permit_all_parameters = true - ^^ yeah, but it will be removed soon. - maybe not before workshops ;) This error is because of security measures – it’s relatively simple to POST whatever parameters a user wants to, and Rails protects us from a rogue user that would want to set parameters that they’re not supposed to set (like ‘id’). We need to declare which parameters can be set by the user; change the first line of the `create` action to the below: {% highlight ruby %} entry_params = params["entry"].permit("title", "contents") {% endhighlight %} Now try submitting the form again – this time it should work and you should get redirected to the newly-created entry. {% coach %} Make sure the plucking of the new entry’s parameters from `params` is well understood and that it’s accepted that certain fields need to be permitted explicitly. Editing via the UI {% endcoach %} ### Adding the ‘edit entry’ form Now that we can view and create entries, let’s also add the option to edit them. Run `rake routes` and try to guess which route is responsible for editing an entry. {% coach %} Make sure this is well understood by now. {% endcoach %} Edit the `app/views/entries/show.html.erb` view and add the below line somewhere: {% highlight erb %} <p><%= link_to("Edit this entry", edit_entry_path(@entry)) %></p> {% endhighlight %} Refresh a given entry’s view and click the link. Add the missing action and an empty view. {% coach %} Again, make sure this is well understood. {% endcoach %} Let’s first make sure our `edit` action exposes the right entry to the view. Make sure the `edit` action looks just like the `show` action – i.e., it grabs the right entry based on the id from the URL: {% highlight ruby %} def edit @entry = Entry.find(params["id"]) end {% endhighlight %} Now copy the contents of the `app/views/entries/new.html.erb` view to the `app/views/entries/edit.html.erb` view, but change the first line so that it’s a form for this particular entry – and, optionally, add a link back to this entry’s show screen: {% highlight erb %} <%= form_for(@entry) do |form| %> <p><%= form.label("title") %></p> <p><%= form.text_field("title") %></p> <p><%= form.label("contents") %></p> <p><%= form.text_area("contents") %></p> <p><%= form.submit %></p> <% end %> <p><%= link_to("Back to this entry", entry_path(@entry)) %></p> <p><%= link_to("Back to all entries", entries_path) %></p> {% endhighlight %} {% coach %} Make sure all of this is well understood. {% endcoach %} Now try to submit the form – which action is still missing? Create it in the controller: {% highlight ruby %} def update entry_params = params["entry"].permit("title", "contents") entry = Entry.find(params["id"]) entry.update(entry_params) redirect_to(entry_path(entry)) end {% endhighlight %} Check whether this all works and whether you can now edit the entries. {% coach %} Make sure the `update` action’s contents are well understood – from permitting params through finding entries to redirecting to the right path. {% endcoach %} ## Further ideas Play with your application! Here are some further ideas you might want to add: - extract form to a partial - links for editing an entry straight from the index of entries, - a way to delete an entry, - a way to edit entry dates, - a model for tracking website URLs and names (the list on the main page), - setting entry dates to the future and not displaying future entries in the index until their day comes, - automatic embedding of video URLs, - support for different entry authors, - support for different categories of entries, - upload and display of images. ================================================ FILE: _pages/github.md ================================================ --- layout: main_guide title: Push your app to GitHub description: "Share your code with others by pushing your app's code to GitHub." permalink: github --- # Push your app to GitHub *Originally created by Alyson La, [@realalysonla](https://www.twitter.com/realalysonla)* {% include main-guide-intro.html %} Git is a tool with which it's possible to save your app's source code, view changes over time, share code online and collaborate with others. {% coach %} Talk a little about Git, version control, collaborating with others using Git, GitHub, deployment techniques using Git and Open Source. {% endcoach %} ## Installing Git Before working with Git, we first need to check if Git is already installed. In the terminal type the following command: {% highlight sh %} git --version {% endhighlight %} The output should mention Git version 1.8 or higher. If it is not installed (indicated by a "command not found" or similar error), or the version is lower than 1.8, please install or upgrade Git. <div class="os-specific"> <div class="mac"> <p>Run this command in the Terminal to install or upgrade Git on macOS.</p> {% highlight sh %} brew install git {% endhighlight %} </div> <div class="nix"> <p>Follow the <a href="https://git-scm.com/download/linux">instructions for your Operating System</a> in the Git documentation.</p> </div> <div class="win"> <p>Please install Git by going to the <a href="https://git-scm.com/download/win">Git website</a>, download the Git installer for Windows and running the downloaded installer.</p> </div> </div> After installing or upgrading, run the `git --version` command again to make sure you are using a more recent version. ## Configuring Git Once we're sure Git is installed, we can set up our local profile in Git. This profile will be used to describe who made the changes to files we'll store in Git. You can see who made which change and when. Change "your name" and "your email" with your name and your email address. You can also use a nickname or an alias if you don't want to use your real name and email address. Be aware: the name and email address you configure here will be visible to others! {% highlight sh %} git config --global user.name "your-name" git config --global user.email "your-email" {% endhighlight %} To check if a profile is already set up in Git, you can run this command, and look for the `user.name` and `user.email` values in the output: {% highlight sh %} git config --list {% endhighlight %} ## Saving work in Git Open the Terminal app, navigate to your _railsgirls_ app directory and run the following command. This will list out all the changed files in your app directory, which should be all the files for your app. {% highlight sh %} git status {% endhighlight %} We want to save all these files in Git so they can be pushed to the GitHub repository you just created. By running the following command you will add all those files staging area in Git, ready to be saved (committed). {% highlight sh %} git add . {% endhighlight %} The `git commit` command shown below will save the staged files in Git, along with the message "First commit". {% highlight sh %} git commit -m "First commit" {% endhighlight %} (The `-m` in the above command stands for "message".) ## Create a GitHub account GitHub is a free, online, code-sharing platform. It is a _hub_ for source code saved in _Git_. We will use this to save and share our app's source code. Visit the [GitHub website](https://github.com) and create an account or login if you already have an account at Github. ## Securely sharing your code with GitHub The easiest method for managing authentication is creating a [Personal Access Token (PAT)](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) that will have matching parts stored on your computer and also on the GitHub site. Because you are trying to get the code on your computer into your account on the GitHub website, you'll need to connect via the internet. GitHub offers connections over HTTPS and SSH. Using a Personal Access Token (PAT) requires that you use an HTTPS connection. This will be important in the next section, when you'll create your PAT. ## Push your app to GitHub using the command line (part 1) Now that you have a GitHub account, you can push (Git terminology for _upload_) your saved work to GitHub and share it with others. Once signed in to GitHub, click on the plus icon (`+`) in the top right corner of the navigation bar. In the dropdown, choose "New repository". Having trouble finding the right link? Visit this [new repository page](https://github.com/new) directly. On the "Create a new repository" page, enter a repository name (like "railsgirls"), choose "public" for the repository's visibility and click the "Create repository" button. Leave the rest of the form untouched. The next page will list the repository URL we will need to tell Git where to push your app's source code to. Be certain you are viewing the instructions for HTTPS, so that it will work with the PAT. In the top "Quick setup" section, click on the "HTTPS" button if it is not already selected, and see that all the instructions change the links to start with `https`. You should use the "push an existing repository from the command line" instructions. Within that section, find the line that starts with `git remote add origin`. Copy the entire line and paste it into the Terminal app. Then press enter. This step creates a Git _remote_, a _connection_, named "origin" pointing to the GitHub repository you just created in the local repository. ## Create the Personal Access Token Next you need to [create the PAT](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token#creating-a-personal-access-token-classic). You can access your GitHub personal access tokens here: <https://github.com/settings/tokens>. Or, when you are logged in to GitHub, you can start on any page and click on your avatar in the top right. Then click "Settings", then "Developer settings", then "Personal access tokens", then "Tokens (classic)". Once you are on the "Personal access tokens (classic)" page, click on the "Generate new token" dropdown menu and select "Generate new token (classic)". If you have set up two-factor authentication in your GitHub account, you will need to 2FA authenticate now. When you can see the "New personal access token (classic)" form, use the "Note" to describe this repo (e.g. "RailsGirls") and then select an expiration date. (If you plan to use this project beyond the expiration date, you'll need to repeat these steps when the PAT expires.) Then, for scopes, select the top "repo" checkbox, that gives the PAT "Full control of private repositories". Click "Generate token" at the bottom of the page. On the next page you'll see your PAT. This is the only time you'll have access to it, so don't click away from this page until you have completed the _push_ step in the next section. Copy and save the PAT token, ideally in a secure password manager. Be careful not to copy any spaces before or after the token -- you can use the two-squares copy button at the end of the token to be certain. You can keep the browser window open until you've completed the next step. ## Push your app to GitHub using the command line (part 2) Now we want to _push_ the local changes in the Git repository to the repository on GitHub with the following command in your terminal. {% highlight sh %} git push -u origin master {% endhighlight %} _Your app's branch name may be different, like `main`. Change the "master" argument to the branch name listed in `git branch`. Your current branch is indicated with the `*` symbol at the start of the line._ When the authentication prompt appears in your terminal, use your PAT as the password, example below. Note that when you paste your PAT in the password, it will not show. Don't paste again, or you will be entering the token twice. {% highlight sh %} Username: <your GitHub username> Password: <paste in your personal access token> {% endhighlight %} You may need your PAT every time you want to push your code, or you can save the PAT on your computer. This process varies per operating system, so your coach can help you with this process if you plan to keep pushing your code to GitHub. {% coach %} Please help with caching the PAT, if the participants wants to. Find the latest guide for their operating system, or check out this guide for [storing the PAT on different Operating Systems](https://mgimond.github.io/Colby-summer-git-workshop-2021/authenticating-with-github.html#saving-tokens-in-windows). {% endcoach %} Congratulations your app is on GitHub! Refresh the page in the Browser and you should see a bunch of files there now. ## Saving more changes in Git If you want to continue making changes and pushing them to GitHub you'll need to use the following three commands. Add changes you want to save in Git to the _staging area_: {% highlight sh %} git add . {% endhighlight %} Save the changes with a commit message: {% highlight sh %} git commit -m "Type your commit message here" {% endhighlight %} Use a descriptive message so you can find back what you changed in which commit and why. {% coach %} Talk about what makes a good commit message (active, descriptive and short). {% endcoach %} And push the changes to GitHub: {% highlight sh %} git push origin master {% endhighlight %} _Your app's branch name may be different, like `main`. Change the "master" argument to the branch name listed in `git branch`. Your current branch is indicated with the `*` symbol at the start of the line._ ## What's next? ### Learn more about Git * Use a [Git Cheatsheet](https://training.github.com/downloads/github-git-cheat-sheet/) for frequently used commands ([also available as a PDF](https://github.github.com/training-kit/downloads/github-git-cheat-sheet.pdf)). * Look up more Git commands in [the Git documentation](https://git-scm.com/docs). * Try out a Graphical User Interface (GUI) if you prefer a more visual experience for using Git. Try out an app like [GitHub Desktop](https://desktop.github.com/). * In the future, as you'll work with more people on a project, you'll start working with branches and pull requests more often. ### Be a part of the Open Source community * Follow your fellow Rails Girls & coaches on GitHub and see what they're working on. * Star or watch their projects. * [Fork a repository](https://docs.github.com/en/get-started/quickstart/fork-a-repo) (a "repo"), then clone and push changes to your fork. Share the changes with the originator by sending them a [pull request](https://help.github.com/articles/using-pull-requests)! * Create an issue on a project when you find a bug. * Explore other Open Source projects - search by programming language or keyword. ================================================ FILE: _pages/gravatar.md ================================================ --- layout: guide title: Adding Gravatar to you app description: "Load user avatars using the Gravatar service. That way your users don't need to upload an avatar to your app." permalink: gravatar --- # Adding Gravatar to your App *Created by Catherine Jones* Gravatar is a service for hosting user avatars. If you sign up with Gravatar you don't need to upload your picture for a lot of services, as it automatically detects it from Gravatar. ## Important This guide assumes that you have already built a Rails Girls app by following this [app development guide](/app) and added authentication using [Devise](/devise). You need to have an e-mail address registered with Gravatar for this to work. If you do not already have one you can go to [gravatar.com](https://gravatar.com/). ## *1.* Add the Gravtastic gem {% coach %} At time of writing the [Gravtastic Ruby gem](https://rubygems.org/gems/gravtastic) is archived and no longer maintained. If you know of a maintained alternatives, please update the guide. {% endcoach %} Open up your gemfile and under your `devise` gem add {% highlight ruby %} gem 'gravtastic' {% endhighlight %} In the terminal run {% highlight sh %} bundle install {% endhighlight %} This will install the gravtastic gem. Then remember to restart your rails server. ## *2.* Set up Gravatar in your app Open `app/models/user.rb`, and add these lines {% highlight ruby %} include Gravtastic gravtastic {% endhighlight %} right after the first line. ## *3.* Configure Gravatar Open `app/views/layouts/application.html.erb` and in the {% highlight erb %} <% if user_signed_in? %> {% endhighlight %} section but before the {% highlight erb %} <% else %> {% endhighlight %} add {% highlight erb %} <%= image_tag current_user.gravatar_url, :class => "gravatar" %> {% endhighlight %} And, put the following code to the bottom of `app/assets/stylesheets/application.css`: {% highlight css %} .gravatar { height: 30px; width: auto; } {% endhighlight %} Now open you app in your browser and login with an e-mail address that is associated with a Gravatar. You should be able to see your Gravatar. ================================================ FILE: _pages/guide-to-the-guide.md ================================================ --- layout: guide title: The Guide to the Guide descriptive: "The guide for coaches to follow along with the guides the workshop participants are following." permalink: guide-to-the-guide --- # Your guide to the Rails Girls Guide! *Originally created by H Salmon to accompany the [app guide](/app).* This guide is an accompaniment to the first [main numbered Rails Girls guides](/#guides) you will be using to build your first Rails application. Its purpose is to provide background information about the structure of a Rails application, Rails terminology and commands, so you can understand what is happening when you are implementing the code in the Rails Girls Guide. We hope that this guide will provide you with a way to retain what you learn over the course of this workshop, and to maintain your interest in Rails development. Welcome! - [Creating the application](#1_create_the_application) Commands you need to know - [Creating Idea scaffold](#2_create_idea_scaffold) Scaffolding, models, migrations - [Finetuning the routes](#3_finetune_the_routes) Routes, HTTP Methods: GET, POST, PUT and DELETE - [Designing](#4_design) The design layers ( HTML, CSS, ERB) MVC Architecture - [Adding picture uploads](#5_add_picture_uploads) Libraries, gems and open-source <a id="1_create_the_application"></a> ## *1.* Create the application In the [build your first app guide](/app) we'll create our first Rails app. We'll start with these commands: - `mkdir projects` - makes a *directory* (folder) called “projects” in the folder you are currently in, most likely your home folder. - `mkdir` = **m**a**k**e **dir**ectory. - `cd projects` - navigates to the “projects” folder you just created. - `cd` = **c**hange **d**irectory. - `rails new railsgirls` - creates a new Ruby on Rails application called **railsgirls** containing various auto-generated folders, in your *working directory* (the folder you are working in at the moment). - `cd railsgirls` - navigates to the “railsgirls” folder. - `rails server` - starts a local web server on your computer. This web server is accessed through the web address <http://localhost:3000>. - "Localhost" refers specifically to your computer (considered the “local host”), from which a server is being launched. Localhost provides a way for developers to see their application in a browser and test the functionality while it is still in development. <a id="2_create_idea_scaffold"></a> ## *2.* Create Idea scaffold In the [build your first app guide](/app) we'll quickly make some Rails app code using scaffolding. ### What is Rails scaffolding? Every web application consists of many different concepts or resources (such as “users”, “ideas”, “posts”, “comments”, etc.). Rails scaffolding is a command (`rails generate scaffold`) for introducing a new resource into your application. It generates all of the code files necessary for representing and interacting with this resource. ### What is a model? In Rails, a model represents a definition of a resource in your application, and how it should interact with other parts of the application. Depending on the nature of the website, these resources could be users, posts, groups etc. When a model is generated, a corresponding *database table* is created. This database table contains information that represents specified attributes of the model, e.g. for a User model, there might be a ‘name’ column and an ‘email’ column, and there will be rows for each subsequent user created. In the application you are creating, these resources are ideas and the model is ‘Idea’. {% highlight rb %} rails generate scaffold idea name:string description:text picture:string {% endhighlight %} In order to create our idea model, we use the `scaffold` command which includes an argument with the singular version of the model name (`idea`), and an argument with parameters (specifications) for the model’s attributes. This means that the `idea` model corresponds to a table in the database with columns for the attributes specified in the command: `name`, `description` and `picture`. The `scaffold` command also auto-generates an `id` attribute, referred to as the `primary key`, which is used to establish relationships between database tables. - `rails generate scaffold` - this calls the scaffold command. - `idea` - this tells the scaffold command what we want to call our model. - `name:string description:text picture:string` - provides a list of attributes we want our model (and the database table that goes with it) to have. The `string` and `text` parts of the argument determine the nature of each attribute, i.e. each description needs to be ‘text’, and not, for example, an ‘integer’ (or any other type of information). ### The ideas table <table class="table table-hover table-bordered"> <thead> <tr> <th>id</th> <th>name</th> <th>description</th> <th>picture</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>“Money-spinner”</td> <td>“Open a moveable shop!”</td> <td>“GreatIdea.jpg”</td> </tr> <tr> <td>2</td> <td>“Champagne For Breakfast!”</td> <td>“We should do this every Friday!”</td> <td>“Champagne.jpg”</td> </tr> <tr> <td>3</td> <td>...</td> <td>...</td> <td>...</td> </tr> </tbody> </table> ### Naming conventions #### Active Record In Rails, the default system for communicating with an application’s database is called *Active Record*, which provides various methods for creating, saving, and finding data. To retrieve information from the database, *Active Record* establishes relationships between different parts of the application using naming conventions: - Table names have all lowercase letters and underscores between words, e.g. “ideas”, “invoice\_items” - The model is named using the convention of unbroken MixedCase and is always the singular of the table name, e.g. if the table name is “invoice\_items”, the model name would be “InvoiceItem”. So, in this case our table name is "ideas" and our model is "Idea". #### Model attributes and types As we’ve already discussed, a model can have attributes (properties) represented by columns in the corresponding database table. To be supported by the Active Record system, these attributes must conform to a list of appropriate types: - `:binary` - stores data such as images, audio files or movies - `:boolean` - stores true or false values (such as whether a particular user is an administrator of an application or not) - `:date` - stores only a date (year, month, day) - `:datetime` - stores both a date and a time - `:decimal` - stores decimal numbers with precision that varies according to your specifications - `:float` - stores decimal points with fixed precision i.e. you can’t specify the precision (`:decimal` is better for mathematical operations in which precision is required, but `:float` is processed faster and is better in situations where speed is required and accuracy is secondary) - `:integer` - stores whole numbers - `:primary_key` - the primary key of a table is assumed to be the id - `:string` - stores 255 characters of text information, i.e. is used for short text fields (names, emails etc) - `:text` - stores text information with no character limit (used for comments, blog posts etc) - `:time` - stores only a time - `:timestamp` - stores both a time and date. `:timestamp` is different from `:datetime` and serves a different purpose, but there’s no need to go into that here ### What are migrations and why do you need them? Migrations change the state of the database. When you run the `scaffold` command, a migration file containing instructions for the database table relevant to your command is added to the `db/migrate` folder of your application. For example, when you ran the `rails generate scaffold` command, a migration containing instructions for our ideas table was created. There are other commands that create migrations such as the `rails generate model` command and the `rails generate migration` command. The `rails db:migrate` command updates the database according to the specifications in the migration file. This command, known as “migrating up”, ensures that your idea model is added to the database. Migrations can also be undone (“migrating down”) using the command `rails db:rollback`. <a id="3_finetune_the_routes"></a> ## *3.* Finetune the routes In the [build your first app guide](/app) replace the Rails splash page with a redirect to our ideas scaffolding. In a functional Rails application, there is an inbuilt system in place for translating incoming requests from the browser in order to return the intended response. This system is called *routing*. Requests from the browser are interpreted as specific HTTP methods. HTTP (Hypertext Transfer Protocol) is the protocol that defines how information (usually webpages or webpage components composed of text with hyperlinks - ‘hypertext’), is formatted and transmitted across the internet. There are four primary HTTP methods, each of which is a request to perform an operation on a specific resource (e.g. users, posts); GET, POST, PUT and DELETE. Rails’ inbuilt routing system automatically generates routes for each resource that map to specific actions (index, show, new, edit, create, update, delete) defined in the controller. So, for each of our models, there are seven related actions defined in the associated controller, `ideas_controller.rb`. These actions specify the appropriate response (a ‘method’) which is most likely to render the corresponding view, e.g. `ideas/index.html.erb`. <table class="table table-bordered table-hover"> <thead> <tr> <td>HTTP Method</td> <td>Path</td> <td>Action</td> <td>used for</td> </tr> </thead> <tbody> <tr> <td>GET</td> <td>/ideas</td> <td>index</td> <td>displaying a list of all ideas</td> </tr> <tr> <td>GET</td> <td>/ideas/new</td> <td>new</td> <td>returning an HTML form for creating a new idea</td> </tr> <tr> <td>POST</td> <td>/ideas</td> <td>create</td> <td>creating a new idea</td> </tr> <tr> <td>GET</td> <td>/photos/:id</td> <td>show</td> <td>displaying a specific photo</td> </tr> <tr> <td>GET</td> <td>/photos/:id/edit</td> <td>edit</td> <td>returning an HTML form for editing a specific photo</td> </tr> <tr> <td>PUT</td> <td>/photos/:id</td> <td>update</td> <td>updating a specific photo</td> </tr> <tr> <td>DELETE</td> <td>/photos/:id</td> <td>destroy</td> <td>deleting a specific photo</td> </tr> </tbody> </table> If you look in your `ideas_controller.rb` you can see these actions and the associated behaviour, and the HTTP method that corresponds with each action: {% highlight rb %} def show @idea = Idea.find(params[:id]) respond_to do |format| format.html # show.html.erb format.json { render json: @idea } end end # GET /ideas/new # GET /ideas/new.json {% endhighlight %} `show` - the controller action {% highlight rb %} respond_to do |format| format.html # show.html.erb format.json { render json: @idea } {% endhighlight %} (This code is difficult to dissect with much clarity at this stage but if you persist with Rails you will get a better understanding as time progresses.) In the above definition of the show action, Rails is using a `respond_to` helper method, which tells Rails to execute the subsequent *block* of code (the code enclosed by the `do...end` syntax). This code contains two different formatting options depending on the nature of the request. If the browser requests HTML then the HTML code contained in the view that corresponds with this controller action (`show.html.erb`) is rendered. If JSON is requested then the view is bypassed and limited information is provided. `GET` - this is a comment to let us know which HTTP method is being executed. So, URL requests, translated into HTTP methods, are mapped to controller actions which tell Rails to return a view. When we insert the code `root :to => redirect("/ideas")` into our `config.rb`, it tells Rails to make the default root of our application <http://localhost:3000/ideas> (note Localhost is being used as the domain because our application is still in development, when you launch your application this domain will be different). This URL contains a path (`/ideas`) which, by default, maps the URL to the ‘index’ action of our ideas controller and renders the associated view; `index.html.erb`. The code `rm public/index.html` removes (`rm`) the `public/index.html` file, containing the “Welcome Aboard” code, which was the previous default root for our application. <a id="4_design"></a> ## *4.* Design In the [Style your app using HTML and CSS guide](/html-and-css) we'll add HTML and CSS to the app to customize it. In a Ruby on Rails application, the user interface (what someone visiting the website will see), is often written in HTML with Embedded Ruby (ERB) code. This code is contained in a specific directory called ‘views’, located in the `app` folder of your Rails application directory. ### HTML HTML, which stands for HyperText Markup Language, is the primary language for creating web pages and other information that can be displayed in a web browser. HTML is written using tags, angle brackets which tend to come in pairs (a “start tag” and an “end tag”), enclosing text-based content. In paired tags, the end tag also has a slash after the opening angle bracket, to distinguish it from the start tag. A paragraph (represented in HTML by the letter ‘p’) would use a start tag like this: `<p>` and an end tag like this: `</p>`, to enclose the text intended for display. Unpaired tags that are opened but don’t need to be closed (e.g. `<br>`, which defines a single line break) are known as “empty elements”. The web browser uses HTML tags to interpret how the contents will be displayed. ### ERB: Embedded Ruby ERB is a system supplied by Ruby that allows you to insert pure Ruby code into files written in other languages, such as Javascript or HTML. The Ruby code is contained within specific angle brackets (`<%` and `%>`) which instruct the system to execute the contents. If an `=` sign accompanies the angle brackets, (`<%=` and %`>`) then the contents are executed and rendered on the page. For example, if you had 25 active ideas in your application, the code: `There are currently <%= Idea.count %> active ideas` would render as: > There are currently 25 active ideas ### MVC Architecture In a standard Rails application (like you one you have generated), the `app/` folder of your application starts out with three folders (or directories): ‘models’ (which we have already discussed), ‘controllers’ and ‘views’. The relationship between these directories is the foundation (known as MVC Architecture) of the application, and of Rails development. When you ran the `rails generate scaffold` command, in addition to creating the idea model, you also created an accompanying ideas controller (`ideas_controller.rb`), located in the controllers folder, and an ideas views folder containing several files that you will use to create a dynamic application. When attempting to display a Rails website, a web browser sends a request via the server which eventually hits the Rails *controller*. *Controllers* act as mediators between the *views* and the *models*. When the *controller* receives the information, it communicates with a *model* representing a resource of the application (in our case, an “idea”) which in turn communicates with the database. Upon retrieving the required information from the *model*, the *controller* renders the *view* which returns the complete web page to the browser as HTML. ### CSS and layouts CSS (Cascading Style Sheets) is a language used to describe the formatting of pages written in a ‘markup language’, i.e. a language for processing, defining and presenting text with a prescribed formatting code e.g. tags, that distinguish it from plain text. The most common application of CSS is in conjunction with HTML. For each Rails application there is a default layout file called `application.html.erb`, located in the layouts folder of your views directory. With this file you can create a default format for all of the pages in your application. {% highlight html %} <link rel="stylesheet" href="https://railsgirls.com/assets/bootstrap.css"> {% endhighlight %} In the above code, the `link rel` (link relation) is defining the nature of the URL that the `href` (hypertext reference) attribute is requesting content from. This argument indicates that the external source requested is a stylesheet and the web browser will need to fetch this file to render the page properly. {% highlight erb %} <%= stylesheet_link_tag "application" %> {% endhighlight %} This code returns a stylesheet link tag for the source, in this case “application”, i.e. `application.css`. This means that the styling you implemented in application.css will be applied to the various pages of your application. {% highlight erb %} <div class="container"> <%= yield %> </div> {% endhighlight %} In this code: - The HTML `div` tag divides the code into parts. - The *container class* adds additional styling to everything inside the div tags - The `<%= yield %>` argument is responsible for inserting the unique content from each page into the container `div`. This means that in your application the overall layout can be consistent even though the content will differ from page to page. <a id="5_add_picture_uploads"></a> ## *5.* Add picture uploads In the [Add picture uploads](/uploads) we'll add a way to uploads pictures to ideas. ### Libraries Many programming languages, including Ruby, use a wide range of libraries. In Ruby’s case, most of these libraries are released in the form of self-contained packages called *gems*, which contain all the information required to install and implement them. These gems are contained in your application’s `Gemfile` and if you look in this file you’ll notice that when you created your first Rails application it came with several gems that ensure your application functions correctly. Gems help simplify and prevent repetition in a developer’s code, in keeping with the DRY (Don’t Repeat Yourself) principle of software development. Gems may solve specific problems, add specific functionality, or address specific requirements, meaning that should another developer encounter a similar scenario, instead of writing new code, they can install a gem containing pre-written code. For example, “CarrierWave”, the gem you are adding to your gemfile is designed to make it easy to upload files to your application. “Bundler” is the software Ruby uses to track and manage gems. The `bundle install` command runs Bundler and installs the gems specified in your Gemfile. You’ll notice the code `source "https://rubygems.org"` at the top of your Gemfile. Whenever you add a gem to your gemfile and run the `bundle install` command, this code tells your application to fetch the gem from <https://rubygems.org>. “RubyGems” is a Ruby-specific packaging system, the purpose of which is to simplify the creation, sharing and installation of gems. ### Open-source software Both the Rails framework and the Ruby language are examples of open-source software. Open-source software is released under a licence which ensures universal access; anyone has the right to change, study and distribute the software. Making the source code accessible enables the establishment of a diverse, reflexive, collaborative and consequently ever-evolving interactive community of programmers who all benefit from each others’ developments. ### More HTML The file `app/views/ideas/_form.html.erb` contains HTML code that determines the look and feel of the form used for editing and creating ideas (the `edit.html.erb` and `new.html.erb` views). A partial is a snippet of HTML and Ruby code that can be reused in multiple locations. The form for editing existing ideas and the form for creating new ideas will look pretty much the same, so it makes sense to have one form for both files to use. If you look in these files you’ll notice that they have a customised heading (e.g. `<h1>Editing idea</h1>`) and then they simply say `<%= render "form" %>` which tells Rails to render the partial `_form.html.erb`. If you take a look in the `_form.html.erb` file, you will see the code `form_for` in the first line of code. This is a block used to create an HTML form. Using this block, we can access methods to put different input fields in the form. The code we are implementing, `<%= f.file_field :picture %>`, tells Rails to create a file input on the form and map the submitted information to the ‘picture’ attribute of an ‘idea’ in our ideas database table. We changed the code from `<%= f.text_field :picture %>` to `<%= f.file_field :picture %>` because `file_field` makes it easier for the user to select the image they wish to upload. In the code `<%= @idea.picture %>`, `@idea` is known as an *instance variable*. Instance variables are prefixed with an @ symbol and are defined in the controller action that corresponds with the view in which they are referenced. For the purposes of the code we are implementing, `@idea` is defined in the ‘show’ action of the `Ideas` controller, with the code `@idea = Idea.find(params[:id])`. This makes it available for us to use in the view `show.html.erb`. It could be defined differently in different controller actions (e.g. index or new). The code `@idea = Idea.find(params[:id])` uses the Rails `find` method to retrieve specific ideas from the database. The code that follows the `@idea` variable (`.picture`) tells Rails to access the ‘picture’ attribute of our resource (idea). By replacing the code `<%= @idea.picture %>` with `<%= image_tag(@idea.picture_url...)` we are using the Ruby `image_tag` *helper* which translates to an HTML `<img>` tag (used to define images in HTML) but by default retrieves images from the folder public/images, which is where our uploaded images are stored. The `image_tag` helper also allows us to insert a block of code which creates a path to an image associated with a particular idea (`@idea.picture_url`). You will notice that within this block of code you are implementing we are also able to set a default width for each image (`:width => 600`). The final line of code `if @idea.picture?` tells Rails to check the corresponding database table to see whether a picture exists before rendering the code underneath. ================================================ FILE: _pages/guide.md ================================================ --- layout: guide title: Host your own Rails Girls event descriptive: "Want to organize your own Rails Girls workshop? Follow this guide to learn how." permalink: guide --- # The How to Guide ## Hosting your first Rails Girls event Our aim is to give tools for women to understand technology. The Rails Girls events do this by providing a great first experience on building the Internet. Rails Girls was founded in end of 2010 in Helsinki. Originally intended as a onetime event, we never thought we'd see so many local chapters all around the world! This guide has been put together to help you get started. If you want to organize an event, start by filling out <https://railsgirls.com/inyourcity> and you'll receive more instructions. A list of upcoming events can be viewed at [railsgirls.com](https://railsgirls.com). You are also welcome to join our [organizers' Slack discussion forum](https://rails-girls-slack.herokuapp.com/). ### The Basics Rails Girls events are non-profit. We don’t charge the participants and do not pay for coaches or speakers. Participants don’t need any previous knowledge about programming and there are no age-limitations. All the participants need is a laptop and some curiosity. The two-day event includes a lot of small group working and short focused talks on programming, design and web. No panel discussions or podium-talks - the spirit should be informal and hands-on. The more you can remove abstractions and add inclusivity the better. #### Rails Girls philosophy * Show spark, personality and keep in mind the big picture. Explain, repeat and always tie what you're telling into a larger context. * Internet was made by people and it doesn’t break by a little tinkering. Continuously show the human side: encourage coaches to talk about open source communities, their programming idols and their aspirations. * Copy-pasting rules. Programming per se isn’t central - you can't really learn to speak Chinese in one day, in a similar manner you can only learn the basic vocabulary and expressions in coding. The goal of every event is to make something visible! * Girls run this world! But also women, ladies, even boys are allowed in. More than semantics we're interested in a mindset. Both founders were born in the Spice Girls era, they don't see the word girl as condescending or cutesy-cute. #### Codes of Conduct Rails Girls events are inclusive, friendly and safe environments. They have zero tolerance of harassment or bullying. You can include a Code of Conduct to your event. Below are examples: * [Rails Girls Summer of Code Code of Conduct](https://railsgirlssummerofcode.org/about/code-of-conduct/) * [PyLadies Code of Conduct](https://www.pyladies.com/CodeOfConduct/) * [Geek Feminism Wiki Anti Harassment example](https://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy) * [Conf Code of Conduct](https://confcodeofconduct.com/) * [Rails Girls DC Code of Conduct](https://docs.google.com/document/d/1XEnFI3R30IiGXOpC4idb0ku3pw8OoJcBpG9mg3iKiAo/edit) * [Rails Girls NZ Code of Conduct](https://docs.google.com/document/d/1EiTZ-__VDuXpN1OqgVKnYr2Km_N3fD9WWN3g5cv5hAA/edit) ### Example Program Every Rails Girls event starts with an installation-fest where the setup is pre-installed to the girl's computers. See [the install guide](/install) for readymade instructions. The installation-fest can include short talks, but the main point is to offer some sparkling wine, get everything set for the next day and the women to know each other. The timeframe is tentative - you know your audience and what suits them best. We've hosted events both during weekend and weekdays. Also, doing two evenings (4PM - 22 PM) might be a more suitable solution for your community needs. #### Learning objectives of the workshop: * Understanding the difference between a dynamic and static web page. * Vocabulary of the web: developing a basic understanding of what components make a web application. Understanding the ABCs of coding: strings, methods, variables, arrays, exclamations, chaining, hashed, symbols, blocks.. as well as the tools (terminal, browser, text editor). Creating a conceptual understanding of the web's building blocks: programming languages, frameworks, databases, infrastructure. * Have an idea of how to move forward in the programming world: both online and offline. #### Friday evening: Installation 19:00 - 21:00 Installations and getting to know each other *Hint*: Have a coach table where problematic computers can be brought. Some installations will fail: be prepared to set women up in pairs, don't use endless amounts of time. Decorate the place with balloons and posters. Put a fun <a href="https://open.spotify.com/playlist/1fgkUFCFDrSn621kf4iHhr">playlist</a> together for the evening. Come up with activities to break the ice: ask the girls to write why they are attending the event on post-its or to draw and describe their dream web app. Remember to do a #FridayHug! 21:00 -> Coach dinner (optional) Go through the application with the coaches during dinner. #### Saturday: Workshop 09:00 - 10:00 Registration and coffee *Hint* Reserve enough time for people to mingle and to solve any problems there might be with installations. Give out workbooks, collect acronyms for the Bento exercise. 10:00 - 10:10 Welcoming words *Hint* Mention sponsors, show what we'll build, tell what programming is. 10:30 - 11:00 UX workshop 11:00 - 11:30 Introduction to programming *Hint* Ask one of the coaches to do this. Explain why learning Ruby basics is important even though they'll be using Rails. Themes to cover: + The difference between dynamic and static websites: what are web apps? + What are programming languages? What is Rails? + The tools we’ll be using: browser, terminal, code editor, folder structure Show & tell with <a href="https://ruby.github.io/TryRuby/">TryRuby</a>, first three-four exercises all together. 11:30 - 13:00 Workshop time Going (slowly!) through the curriculum at <a href="/app">guides.railsgirls.com/app</a>. Stop to explain what you’re doing and what the different concepts mean. Try to aim for simple explanations even with the cost of accuracy. You don’t need to talk about all underlying concepts. Just try to answer questions when they arise, or move on if they’re too hard or out of scope. You are not here to teach perfect coding skills but to show how to get stuff done. One has to learn how to build web apps before learning how to do it well. Concepts to cover: + Rails Generators + Scaffolds: Rails App Structure + Gem Management + MVC, REST/Resources + Models and Active Record + Controllers and ActionController + Views and ERB *Tips:* Coaches are people too. They are doing this for the first time too. Teaching might be hard and intimidating, so remember to be available to help coaches or groups with difficult situations or just provide support and encouragement. 13:00 - 14:00 Lunch 14:00 - 14:30 Bentobox exercise Putting technical jargon into a context with a conceptual model called Bentobox. Two exercises: 1) Going through the 10 technical concepts with the physical Bentobox boards. 2) Going through the words the women have themselves submitted with the coaches. + [Bentobox slidedeck](https://speakerdeck.com/railsgirls/rails-girls-bentobox-exercise) + [Instruction video](https://vimeo.com/39049632) 14:30 - 18:00 Workshop time. Time to continue working on the applications. Monitor the situation: when it seems like people have a hard time concentrating, have the coaches or other speakers give quick lightning talks. Example topics for lighting talks: + Real (female) programmers telling what their career has been like. + Design: UX & UI. Making mockups together either with paper or computer. + Fun ways of explaining technical concepts and recent frameworks: what is CoffeeScript explained in 80s pop songs? How would you describe GitHub? What coding and creative writing have in common? + Show us something real: don’t speak in abstractions, be specific and tell stories. Once everyone has finished their app, there is time to extend the application by modifying the CSS, implementing commenting systems etc. Allow enough time for experimentation. 19:00 After party *Hint:* Invite everyone, also the local developers, boys, those who weren't accepted, to join! [Fork this project on GitHub][github], add yourself, and send us a pull request. [github]: https://github.com/railsgirls/railsgirls.github.com "Fork on GitHub" #### Materials + [Download materials](https://speakerdeck.com/railsgirls) ### Promotion of Rails Girls Every Rails Girls workshop will get a custom website at railsgirls.com/city where the information is collected and then stored. For past cities, see <https://railsgirls.com/events.html> You can also set up your own Facebook and X page (remember to add links to your workshop's page!) or whatever service is popular in your community. Promoting the event through social media can go a long way these days, but make sure you have somebody to take care of the chosen channels. Some tips: * Keep the tone of posts friendly, positive and welcoming. Be direct in inviting fans/followers to share the event with their friends. * Photos are especially powerful messengers. Create your own graphics (*some ideas: "I'm a Rails Girl" Facebook cover for the event, word cloud with first names of women who signed up, an infographic of applications*) or promote photos from other workshops if this is your event. Follow other Rails Girls pages and account to get ideas for content and pass it along to your community. * Try various pitches for events to attract different types of women; some will be in it for the fun and meeting new people, some to learn new things, some will be fueled by the desire to show guys that women can do anything. No need to focus on just one group! * Don't be afraid to publicly thank women, coaches, blogs, media and other supporters who help you spread the word about your workshop for their support. * If your language supports it, use feminine forms when addressing women. While the event is underway, remember to take pictures, collect tweets and ask questions of the participants. You'll be thankful for all of that for your next event. We love to write blog posts about the speaker and participant experiences. A list of the coaches is also required. + [Download materials](https://speakerdeck.com/railsgirls) #### Website E-mail contact(a)railsgirls.com and ask to be included in the repo. Look for readme.txt for further instructions! Before making a site you should have at least two coaches and one sponsor onboard. + [Counter for the site](https://github.com/ys/rails-girls-count#readme) #### How to find local developers? * Google. Almost every country has some sort of a Rails or Ruby community (sometimes called Ruby Brigade or Ruby Tuesday). Look for [Hackernews](https://news.ycombinator.com) meetups, [GitHub](https://www.github.com) contributors or [Dribbble](https://dribbble) draftees. Find the local open source scene. Surf the technology conferences of [Ruby-themed ones](https://rubyconferences.org/), but others are cool too) and meetups at [meetup.com](https://www.meetup.com). Call software development houses, big and small. Don't forget IRC and podcasts! * Check out hashtags like #rails #ruby and #opensource from [Twitter search](https://twitter.com/#!/search-home). To find people from, say, close to NYC, use the following search operators "near:NYC within:15mi". Some countries have specific hashtags like #Rubysur and #RubyArg they use, remember to ask! * Startup community. Startup Digest is a good beginning point for events and communities. * Often there are one or two key people who will be able to introduce you further. The technology world is surprisingly connected. #### How to find participants? * Use social media: Facebook, X & local networks such as Weibo. Friends, girlfriends, co-workers! * Local [Girls in Tech](https://twitter.com/#!/gitweet), [DevChix](http://www.devchix.com/), [Geek Girl](https://www.geekgirlmeetup.com/) chapters etc. Check out also [Meetup.com](https://www.meetup.com/). X lists like @anitaborg's [Tech Women Programs](https://twitter.com/#!/anitaborg_org/tech-women-programs) and similar. * Think outside the box: universities, book clubs, music stores, design agencies, [Etsy](https://www.etsy.com). We want women who are interested in technology, but they can still have very varied backgrounds. #### How to get press? One of the big aims of Rails Girls is to make it more mainstream for women to build the web. That’s why we like to engage the local press and highlight the participants and their enthusiasm. We’d be happy to help prepare a press-release for the media. Check out [railsgirls.com/press](https://railsgirls.com/press) for more. If you're working with a big company as a sponsor, their PR department might be able to help you spread the message about the workshop. Send the press release to local blogs, find contact at various media outlets. The more doors you knock on, the greater you chance of getting through. Make a list of journalists and bloggers you contact, mark those that respond to your emails, so they can be the first ones to receive your next press release. You can also write a press release after the event that includes photos and statements from satisfied participants. ### Sponsorships Rails Girls talks to a demographic that might be hard to reach other ways: women who have an interest in technology, who are possible users, employees or partners of the sponsoring company. We are looking for sponsors who are active participants in the local technology scene, whether it’s a startup or a big corporation, a non-profit or a government organization. Also non-traditional technology companies can be approached: kids stores, universities, women's magazines, beverage brands etc. They all should however have some affiliation or interest in technology. Rails Girls should always be kept non-profit: if there's money left, it should be used to support the future activities of the attendees. Don’t forget that you don’t need that much funding and even a two-person startup could be very willing to chip in. We advice against having only one sponsor (cannabilize the event) or having a SPONSOR NAME edition of the Rails Girls workshop. The Rails Girls brand is not meant for the commercial advancement of a single company. ### Example letter for sponsors Dear xxx, We are organizing a Rails Girls programming workshop in (insert city) on (insert dates). Rails Girls is a two-day non-profit event for women of all ages to give them a great first experience in software craftsmanship. We aim to give the tools to understand technology along with the community and inspiration to get started. Rails Girls is not just about programming, it’s about building things. During the workshop, we’ll build an application and also have inspiring lightning talks and exercises. For a closer look, please see www.railsgirls.com for past events and coverage. Here’s also a short video on the Berlin event held in April 2012: <https://vimeo.com/40852182> We are now looking for sponsors to help us realize this all. We’d love to have your support! Yours, name ### How much does it cost? The costs below are estimated for 30 participants, 10 coaches - but they may vary a lot. It's easiest to try to get a local sponsor to pay the bills directly or partner with someone who has a set account to handle money. These calculations are done in Finland, in €, where food & alcohol is very expensive, but spaces are often free. All in all you should be able to organise an event easily for a little over a thousand euros. + **Sparkling wine + cups** for the installation festival. 6 bottles, 6 euros a bottle. 36 euros. + **Breakfast Coffee**, pastry. 40 times around 5 euros. 200 euros + **Lunch.** Catered lunch can be around 15 euros, but you can do with a lot less by cooking yourself. Add some water and coffee (50 euros). 650 euros. + **Marketing materials.** Printing workbooks, ordering stickers, posters and other swag. Again, varies a lot, maybe you can use someones printer, but at least around 200 should be reserved. + **Coach dinner.** At a restaurant or homemade. A way to say thank you to the coaches for their volunteer work. Around 20 euros per head. 200 euros. + **Space.** Try to get this one sponsored/free, they can be really expensive. Often startups are co-operative and can offer their space for use (esp. on weekends). 0 - XXXX euros. + **Afterparty.** It's nice if you can throw a good party with free beverages, but can also be done low-key in a local bar or on set in the park! 0 - XXXX euros. + **Travel expenses.** If you don't have any RG-team members in your country, consider inviting us over. We don't need fancy hotels, promise! Same if you want to invite speakers to your event. 0 - XXX + *Total 1286 euros*. __What do sponsors get?__ * Logo on event website * Table space at event, opportunity to distribute handouts and/or swag * A chance to speak to attendees for 5 minutes * In most events there are official pictures taken that the sponsors can use afterwards Don’t give out the participant info, but sponsors are free to hang out at the event and be sure to include a short message to the sponsor in a thank-you note. Sponsor swag may be included in the goodie bag to an extent, but it should be something tasteful, not trashy and/or related to women. --- ## FAQ #### Who can organise a Rails Girls workshop? Anyone. What we look for is a group of people dedicated in making this a stellar first experience in the world of web making for women. What we hope to see is some (not all) of the following: * Contacts to the local developer scene. We are pretty technology agnostic, so it doesn’t have to be purely Ruby & Rails people. In practice every event needs 5 or more coaches (the number of coaches depends on the number of women you're planning to accept) that have basic knowledge of Rails and two days to contribute. In general the events have been around 25 - 40 people strong. * Event organisation know-how. Not heaps, but some practicalities under the belt. * An inkling of an idea where to look for women interested in technology. University, literature, arts, sports - we try to look for people who are interested in Internet, but do not have experience in coding. * Willingness to guide the women in the future if they have questions or want to organize their own events or find local developer gatherings. Start by filling out <https://railsgirls.com/inyourcity> and someone from our team will be in contact #### Where can I find all the materials for posters, nametags, sample presentations and such? Check out below, and let us know if something is missing! + [Download materials](https://speakerdeck.com/railsgirls) #### What kind of venue is needed? We recommend choosing a venue with a built-in infrastructure for around 30-50 persons. For a programming event, this means: * High-speed, tested Internet. There’s going to be over 30 computers online all the time. Add to that mobilephones, streaming music, funny videos and you get the picture! * Space for 4-6 person groups to gather together: chairs and tables, sometimes big pillows will do! This doesn’t have to be in the same room. * Possibility to set up extension chords and a projector. * Enough electric outlets to spare. Some women might have older laptops that will need to be plugged in at all times. * Location for food and beverage setup - lunch space for catering or a nearby lunch venue. * External monitors for teams are encouraged but not mandatory, helps the coaches show what is happening in the code. * Whiteboards can be helpful for coaches to explain more abstract concepts. Alternatively, paper and pen work just fine. Just have something at hand people can draw on. Ask where local developer meetings are usually hosted. Often co-working spaces are also willing to negotiate deals to gain some visibility among new people. #### What is expected from the coaches? Rails Girls events are organized around small groups, maximum of 4-5 persons per one coach. If possible, try to have groups of 3 women for each coach. For instance, if you're doing an event for 30 women, aim for having 10 coaches (a few more for backup don't hurt). We know this isn't always possible, but do try not to have groups of more than 5 women, so the coach can still answer all questions in the group. The coaches don’t need to be hardcore experts on Rails - basic knowledge and willingness to explain trumps expertise. So, if your local Rails community isn't very strong, do expand your search. You can have a mix of Rails experts and people with web development expertise in other frameworks. We are looking for people who like answering questions and can keep an upbeat and positive atmosphere through a period of 8 hours! You can get to know the curriculum by checking out [the guides index](/). There is also always a pre-event coach dinner where we’ll go through some pedagogical suggestions and check everyone knows what is happening. Avoid jargon, tie examples to what your doing, encourage asking questions. The installation instructions can be found in [the install guide](/install). We also understand that coaches are human and that for most of the people this is the first time teaching something. Worry not - the women have always been really happy with whatever they learn and just the chance to ask questions is enough. We hope the coaches are ok with having their name and twitter-id/github/some mean of contact on railsgirls.com so the women always have a local face to answer their questions. In addition, we encourage coaches to come up with additional exercises for the group. After completing the ideation app many women will want to try tweaking the look & feel of the site, implementing commenting, Facebook sharing, pushing the app to Heroku, etc. #### How to find coaches? Ask around, ask sponsors (tech companies), ask anyone to help you out. Once you do get some coaches on board, they can help you out with their own contacts. Influential bloggers or X users in your local dev community can help you out by broadcasting a call for coaches. *Hint: You can also thank coaches for their help by providing a spot at the workshop for their girlfriends ;)* ##### Sample letter for potential coaches "Dear community member, We wish to invite you to take part in the Rails Girls event on (insert date). The event is aimed for women of all ages with no previous programming experience, but a lot of passion to building things. Rails Girls is an international non-profit, volunteer-based workshop. We've had events in Shanghai, Berlin, Helsinki, and Singapore. We expect to receive around a 100 applications. In addition to giving a safe and fun first experience to coding for the women we want to engage them with local developers, open source, and the startup scene. We've attached some information on what coaching requires in practice. In addition, we have room for small lightning talks on technical subjects. If you have something you'd like to speak about, let us know. For more information about the non-profit event, check railsgirls.com or guides.railsgirls.com (You can also include the chapter "What is expected from the coaches" to the mail)" --- #### What materials do I get? Each Rails Girls event gets a specific webpage. In addition we’ll help you out with the goodie bags, poster templates, workbooks and other swag like stickers, reflectors and so forward. All of the materials can be found on this site. You can also ask the sponsors to include some sponsor materials if they wish. We are always looking for creative outlets for the Rails Girls brand, if you have ideas, let us know! So far we've had * Stickers * Reflectors * Tattoos Also, check out: + [Download materials](https://speakerdeck.com/railsgirls) #### How do I choose attendees? In the form we ask only two questions: do you have any previous background in coding and why would you be a good participant for Rails Girls Rails Girls is intended for anyone and we want to keep it flexible enough for learners any age. However, make clear to the attendees what to expect: Rails Girls won’t make anyone into a coder, so people looking for i.e career change will be disappointed. On the other hand we like people with very diverse backgrounds and loads of enthusiasm. After selecting participants we generally split them into three groups: 1. people with no previous programming experience 2. people with some front-end experience (HTML, CSS, Javascript) and 3. people with a little experience in programming or a background in computer sciences. You can use the different name-tags for each group if you want to (rubies, foxes, octocats, rails..) ##### Sample letter of acceptance Title: Rails Girls workshop - welcome! Dear attendee, Congratulations! We’re happy to invite you to join in on the Rails Girls workshop in (insert city). We hope that this workshop will provide you a great first experience on building web apps. What happens next? (Insert date for installation fest) starts at (insert time) with an installation fest - so please bring your laptop with you! You should also try to pre-install Rails with instructions from </install> We will hold the event in (insert address) On (insert date) we’ll dive into development. We’ll work in small groups with four to six person teams. Your team members will have about the same experience level as you. We'll be all developing a simple listing application. We'll wrap the day around (insert time). There's also going to be an evening party. We have a lot of people wanting to get to the class, so if you can’t make it this time, let us know as soon as possible! If you have any questions, please don't hesitate to contact me. We'll also be updating the website at (insert address)! Best, (Signature) ##### Sample letter of not being accepted Title: Rails Girls - not accepted this time Dear applicant, Unfortunately we couldn’t fit you in the workshop this time. To be able to give personal guidance to each participant, we could only take a fraction of the applicants. This time we prioritized women with no previous programming experience. However, you're warmly welcome to the official afterparty. (Insert details). We'll also be most likely organizing more events in your city. Follow twitter.com/railsgirls or facebook.com/railsgirls for more information. There's always cancellations and we fill all available places, so we might still be taking in a couple of people! Best, (Signature) ##### Sample thank you letter for participants Dear Rails Girls, Thank you for taking part in the Rails Girls event. We truly felt lucky to have such a talented & enthusiastic crowd of people with us and hope many of you will continue working with Rails in the future - you have the tools, now build something cool! (Say a few words about the sponsors and coaches - thank you for the community) Three things we want to share: in Workshop Materials (Almost all) materials can be found in the guides section at <https://guides.railsgirls.com>. You can find presentations, materials and instructions from the workshop. If you took pictures or blogged about the event - let us know! We'll be publishing regularly on railsgirls.tumblr.com Make Rails Girls better - give us feedback! We want to hear from you! Give us feedback about the workshop or how we can make the event better – it’s really quick, and it’ll help us improve our workshop at railsgirls.com/feedback Keep on coding! We realize there was quite a lot of stuff in todays lecture and for most of you it all felt a little overwhelming. We strongly recommend trying out [Rails for Zombies exercise](https://www.pluralsight.com/codeschool) latest by next weekend, it'll refreshen all you've learned so far and teach you some more. Two things to keep you going: - (Insert here a couple of community events that the participants should take part in) There was a LOT of interest in doing follow-up events. If you have ideas for this or want to volunteer for the organizing team, let us know and sign up for the group e-mailing list at http://groups.google.com/group/rails-girls-team! And that’s all for now, Your Rails Girls team #### What happens after the event? Inviting real developers to coach is Rails Girls sessions not only gives the participants a chance for hands-on education, but also makes the barrier to enter the technology world lower. How to keep the women coding? * Encourage them to continue practicing by trying different exercises like Codecademy and such. * Mention at least two forthcoming developer events where the local coaches will be. Try to get the women to attend actual developer meetups. * Invite everyone to the Facebook Group where they can ask questions. * Invite the women together again within a month. You can host these meetups at the Rails Girls global meetup page <https://www.meetup.com/Rails-Girls/> - we’ll be happy to promote events. However, it doesn't matter under which brand you want to continue meeting - the important thing' * Write about your event for railsgirls.tumblr.com by [submitting a story](https://railsgirls.tumblr.com/submit) --- ## Checklist This is a small checklist for your event. Rails Girls can be thrown together in a matter of weeks, but to truly have time to make a good event, prepare at least two months. Not all of these steps are of course mandatory and they are here just to help you remember. ### Before the event: * Fill in the [application](https://railsgirls.com/inyourcity) and the team will contact you! * Start working with the project plan template on Google Docs * Decide dates and set a venue * Reach out for the local coaches - try finding five people who commit to taking part * Release the website: write the copy and suggest a theme 1. Dates and location. 2. Application deadlines. 3. Short introductory text, around 200 characters. Check out the past events for inspiration! 4. Speakers of the day 5. Partners - a two-paragraph sentence and a logo (100 x 100px or 250 x 90px and in png format) 6. Coaches with twitter-handle * Start marketing the event, you can use materials from [here](https://speakerdeck.com/railsgirls) * Start looking for sponsors * Reach out for press and write a pre-event story * E-mail accepted participants and non-accepted applicants * E-mail installation instructions and last minute event details * Set a date for coach dinner and send them instructions * Check if there are other events taking place the same weekend #### During the event * Tweet! * Remember to take photos * Interview participants and speakers about their experiences * Do a Friday Hug! Take a picture with everyone and share it on social media with the hashtag #FridayHug! * Have a Skype with other Rails Girls chapters hosting events at the same time #### After the event * Update website to include pictures and blogposts * Collect slides from the speakers and add them to the [Rails Girls presentation](https://github.com/railsgirls/presentations) repo * Upload your photos to our [official Flickr group](https://www.flickr.com/groups/railsgirls/) (preferably under a [Creative Commons](https://www.flickr.com/groups/railsgirls/discuss/72157634650757777/) licence!) * Invite active participants to [global e-mail list](https://groups.google.com/group/rails-girls-team) * Send a thank you note to participants and ask for [feedback](https://railsgirls.com/feedback) (you can also create your own feedback form in your local language) * Send a thank you note to coaches * Send a thank you note for organizers * Share the numbers of your event by filling out this short [Questionaire](https://railsgirls.wufoo.eu/forms/rails-girls-events-all-the-numbers/) * Write a blogpost to the global blog by [submitting your story](https://railsgirls.tumblr.com/submit) - or ask one of the participants or coaches to write one! ================================================ FILE: _pages/how-to-continue-with-programming.md ================================================ --- layout: guide title: "After The Event: How To Continue With Programming" description: "A guide to keep you going with learning how to program." permalink: how-to-continue-with-programming --- # After The Event: How To Continue With Programming *Created and edited for general use by Daniel Puglisi, [@danielpuglisi](https://twitter.com/danielpuglisi).* *This guide was originally written for the [Rails Girls Basel](https://railsgirls.com/basel) event and was published on [Daniel Puglisi's personal blog](http://danielpuglisi.com/articles/2013/04/rails-girls-after-the-event-how-to-continue-with-programming) (link is no longer working 2023-02-12).* ## How To Continue With Programming Unfortunately (!) the event is over. We'll hope this guide will help you find the best way to keep going with learning on how to program! There are 4 steps which Daniel has come up with and he encourage you to really take them to your heart and do them. ## 1. Keep on Coding Mastering a craft requires constant repeating and perseverance. This also applies to programming. I encourage you to repeat the Rails Girls tutorial which we did at the event and try to play around with it some more. After that here are some free and paid resources which will help you to take things to the next level: ### Courses * [Rails for Zombies](https://www.pluralsight.com/courses/code-school-rails-for-zombies) - A Rails Screencast which you can try for free. Pluralsight also provides a series of paid [Ruby and Rails](https://www.pluralsight.com/paths/ruby-language-fundamentals) courses which are awesome. You should really try them! * [Codecademy](https://www.codecademy.com/) - The world isn't just created with Ruby and Rails. There are also plenty of other languages like HTML/CSS, JavaScript, Python and so on. Try them out! ### Books * [Rails Tutorial](https://www.railstutorial.org/) - A awesome book which has a free HTML version and a paid print version. The book provides you with a lot of great material which we couldn't cover at the Rails Girls workshop. ### Screencasts & Videos * Confreaks - Talks from conferences all over the world. There are playlists for RubyConf and RailsConf on the [Confreaks YouTube channel](https://www.youtube.com/user/Confreaks/playlists). Learn about the latest in the Ruby! * [Richard Schneems Screencasts](https://www.youtube.com/user/schneems/videos) on YouTube. * [Railscasts](http://railscasts.com/) - Short and simple screencasts about Rails by Ryan Bates. (Note: Ryan is no longer updating RailsCasts.) ### Even more! * [Thoughtbot Trail-Map](https://github.com/thoughtbot/trail-map) - Guides to different topics. If you have any other good resources, please add them by [contributing](/contributing) to this guide. ## 2. Build something real Build something real means you should try to create something which is actually needed in the end. The hardest part will be to find a real project. If you have no idea, try to think of something that really upsets you. Do you have to use something in your daily life that pisses you off? Write an application for it and try to solve that pain. This way you will be more motivated than by just following tutorials. And don't forget to show your application to your friends and the world. Ask for feedback and keep on learning. If you still have trouble finding something you can work on I have an idea for you: Build a Rails Girls website for your country or city if there isn't one already. (Ask your organizers!) ## 3. Get in touch Its always easier when you have someone you can ask. With this in mind, go out and find someone who you can talk to. Now is the best time for it, because you just got to know a lot of like minded people which have more or less the same level as you. There are a lot of ways to communicate nowadays, e.g. attend a local meetup group, create Facebook Groups or write a good ol' letter :) From my experience, knowing some people who have the same interests as you is one of the most important parts. Try to convince people, that programming is fun. If you have a brother or a sister, show them what you've learned. Or show it to your parents, children or friends. Just try to build a circle of people with the same interest in programming and technology. Also try to find someone that can be a mentor to you. Programming can be really intimidating sometimes, so it can help to know someone which has more experience and can help you with your problems. For example: ask someone that was a coach at the workshop you attended. One of the girls at the Rails Girls Basel event (thanks [Helena](https://twitter.com/HBobbiRo)!) had the great idea that we could put up a list with all the attendees, coaches and organizers of the event. We created this list and it's on [GitHub](https://github.com/RailsGirlsSwitzerland/attendees) now, [check out the website](https://railsgirlsswitzerland.github.io/attendees/site/2013_04_basel.html). Feel free to fork the repository and adjust it to the needs of your Rails Girls event. Try to setup such a list for your event too, this way its a lot easier to stay in contact with everyone than just with the people who sat around the same table as you did. If you don't know how, ask someone of the organizers of the event if she or he could do it. ## 4. Have fun Last but not least, have fun. If you don't enjoy programming it is probably not the right thing for you. But thats the same story for every profession or hobby. Not only for technology related topics. But if you just read this I think you are perfectly made for programming, otherwise you wouldn't be here in the first place ;) So, if you liked the workshop and the event - you're in the right spot. If you have any further questions, don't hesitate to ask. You can do this via [Twitter](https://twitter.com/railsgirls) or email. Ask the organizers and coaches of your event for their email addresses and if they would like to help you. Thats it, keep on coding and let's build the future! ## 5. More resources - [8 ways to enable workshop attendees to keep learning](https://pragtob.wordpress.com/2013/06/14/8-ways-to-enable-workshop-attendees-to-keep-learning/) ================================================ FILE: _pages/html-and-css.md ================================================ --- layout: main_guide title: Style your app using HTML and CSS description: "Give your app a new look with HTML and CSS using Bootstrap." permalink: html-and-css --- # Style your app using HTML and CSS {% include main-guide-intro.html %} The app doesn't look very nice right now: it's the standard plain black text on a white background. Let's improve that using HTML and CSS! ## What is HTML? HTML (HyperText Markup Language) is used to structure your app. It tells the browser what is a heading, a list, a table, a link, etc. on the website. The scaffolding that was generated in the [previous guide](/app) is also made up of HTML, with some Ruby added to it to make it more dynamic. Open up the `app/views/ideas/index.html.erb` file and you should see something like the example below. The parts of the file that start with a `<name>` tag opens an HTML tag, and the one with the forward slash symbol in it `</name>`, closes it. You can add all kinds of properties to it, like `style`, `id` and `class`. {% highlight erb %} <h1>Ideas</h1> <div id="ideas"> <% @ideas.each do |idea| %> <%= render idea %> <% end %> </div> {% endhighlight %} There are also special kinds of parts in the file indicated with the `<%`, `<%=` and `%>` code. This looks a lot like HTML, but it's not. It is a flavor of Ruby that makes the HTML show things dynamically, like all the different ideas you added to your app's database. {% coach %} Talk about the relationship between HTML and Rails. - Explain a little bit more what HTML is and give some examples (like this website's source code). - What part of Rails views are HTML and what is Embedded Ruby (ERB)? - What is Model View Controller and how does this relate to it? - Models and controllers are responsible for generating the HTML views. Resources: Guide to the guide [Design](https://guides.railsgirls.com/guide-to-the-guide#4_design) {% endcoach %} ## What is CSS? CSS (Cascading Style Sheets) allows you to specify how the HTML should look like, what text and background color elements should have, what fonts to use, what size they are, where they are on the page, etc. In this guide you won't be writing CSS yourself to style your app, but rely on the [Bootstrap project][Bootstrap] to do the heavy lifting for you. It provides the framework for CSS to style and apply design to your app. There are many CSS classes available you can apply to your HTML. It helps you get started quickly. If you're interested in learning more about CSS, we suggest taking a look at this [getting started with CSS](https://developer.mozilla.org/en-US/docs/Learn/CSS/First_steps/Getting_started) tutorial after this workshop. [Bootstrap]: https://getbootstrap.com {% coach %} Talk about the relationship between HTML, CSS and Rails. - How does Bootstrap work and how does it style the app pages? - Briefly show some [Bootstrap examples](https://getbootstrap.com/docs/5.2/examples/) and show what you can accomplish with using a framework like Bootstrap. Resource: W3Schools [What is Bootstrap](https://www.w3schools.com/whatis/whatis_bootstrap.asp) {% endcoach %} ## Add Bootstrap to help style your app Bootstrap consists of a couple different parts, the first we'll use is the CSS. To use it, we need to add it to our app by adding some lines of code the HTML. Specifically the layout file. The layout file is the file that all your Rails views are wrapped in. It makes sure all pages have the same basic layout and CSS loaded. Open the `app/views/layouts/application.html.erb` file in your Text Editor and above the following line: {% highlight erb %} <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> {% endhighlight %} add this line to the file: {% highlight erb %} <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous"> {% endhighlight %} This loads Bootstrap from a server on the Internet. That way you don't have to install it locally before you can use it. In the same file, replace this line: {% highlight erb %} <%= yield %> {% endhighlight %} with these lines of code in the same file and save the file. {% highlight erb %} <div class="container"> <%= yield %> </div> {% endhighlight %} Refresh your app in the Browser. Already the app looks a bit better and has the app content front and center. Your app is now using the Bootstrap system for styling using its CSS. ## Add a navigation bar It's easy to get lost on a website that has very little of a User Interface (UI). Let's add a navigation bar and footer to the layout to give it more the appearance of an app and allow us to find our way around. In the same file, under the `<body>` tag add these lines of code. This will add a navigation bar to the app. {% highlight erb %} <nav class="navbar navbar-expand-lg navbar-dark bg-primary"> <div class="container-fluid"> <a class="navbar-brand" href="/">The idea app</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav me-auto mb-2 mb-lg-0"> <li class="nav-item"> <a class="nav-link <%= 'active' if current_page?(controller: 'ideas') %>" href="/ideas">Ideas</a> </li> </ul> </div> </div> </nav> {% endhighlight %} Before the `</body>` tag at the end of the file, add these lines of code. This will add a footer saying "Rails Girls" along with the current year, and include the Bootstrap JavaScript needed for the navigation bar functionality. {% highlight erb %} <footer class="mt-5 text-center"> <div class="container"> Rails Girls <%= Time.now.year %> </div> </footer> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script> {% endhighlight %} Make sure you saved your files and refresh the Browser to see what was changed. ## Add more styling! _This step is optional. We'll be updating more styling in future guides. If you want to move on, open the next guide in the list below._ To further style the app with HTML & CSS, you can edit the `app/assets/stylesheets/application.css` file in your Text Editor if you already know some CSS. It's also possible to reference the [Bootstrap documentation](https://getbootstrap.com/docs/5.2/getting-started/introduction/) for more information on how to use Bootstrap for styling the app. ================================================ FILE: _pages/install/linux.md ================================================ --- layout: main_guide title: Setup on Linux description: "Install Ruby and Rails on your Linux computer and get prepared for the Rails Girls workshop." permalink: install/linux --- # Setup for Linux {% include main-guide-intro.html %} To install the Ruby on Rails development environment you just need to copy the lines below for your Linux distribution (Ubuntu or Fedora), paste it in the Terminal and press Enter. Enjoy the text flying on the screen; it will take quite some time. Grabbing a refreshing drink before starting is encouraged. <div class="help-notice">Make sure you're familiar with <a href="/tools">the tools you'll need for this guides</a> before continuing.</div> ## _1._ Install dependencies ### For Ubuntu Install the curl program on your computer before continuing. This is required to run the install script in the next step. {% highlight sh %} sudo apt-get update sudo apt-get install curl {% endhighlight %} ## _2._ Install Rails ### For Ubuntu Run the following command for an automated install of Ruby and Rails on your computer. {% highlight sh %} bash < <(curl -sL https://raw.github.com/railsgirls/installation-scripts/master/rails-install-ubuntu.sh) {% endhighlight %} ## _3._ Check the environment Check that everything is working by running the application generator command. {% highlight sh %} rails new railsgirlsapp {% endhighlight %} Navigate into the app directory: {% highlight sh %} cd railsgirlsapp {% endhighlight %} Start the Rails server: {% highlight sh %} rails server {% endhighlight %} Go to <http://localhost:3000> in your Browser. You should see the Rails logo appear. If at any point during this guide you ran into a problem and can't continue. Not a problem! Contact the workshop organizers and let them know about your problem. Most workshops have dedicated set up evenings or they can help you on the day of the workshop itself. If you do see a Rails logo in your Browser, you now have a working Ruby on Rails programming setup. Congrats! You're ready for the workshop. If you are preparing before the workshop, you don't have to continue with guides until the day of the workshop. See you then! {% coach %} If there's a coach present, they can help verify the installation by using the scaffold command and inputting data with the generated page with coaches to ensure everything is working. Remove the test app `myapp` to make super sure no-one is working in the wrong folder, while following the steps of the workshop. {% endcoach %} ================================================ FILE: _pages/install/macos.md ================================================ --- layout: main_guide title: Setup on Mac description: "Install Ruby and Rails on your Mac computer and get prepared for the Rails Girls workshop." permalink: install/macos --- # Setup for Mac {% include main-guide-intro.html %} To build apps and other things with Ruby on Rails, we need to setup some software and the developer environment for your computer. <div class="help-notice">Make sure you're familiar with <a href="/tools">the tools you'll need for this guides</a> before continuing.</div> ## Install the Command Line Tools Most Mac users never get into programming, so Apple figured it'd be a good idea not to ship the tools needed to run programming languages with every laptop to save some space. They did make it easy to install them, running just a single command. Enter the following command in the Terminal app and press the <kbd>Enter</kbd> key. You may be asked to enter a password, this is the password of your user account on your Mac. Enter your password and press <kbd>Enter</kbd>. {% highlight sh %} xcode-select --install {% endhighlight %} A window will pop up asking you to confirm that you want to install these tools, and agree to the Terms and Conditions. Once you do, an installer will start downloading and installing the tools. This will take quite some time, so feel free to grab a tea or coffee. The steps following this one will only work after the Command Line Tools installer has completed, so no point in skipping ahead. ## Install Homebrew [Homebrew](https://brew.sh/), like the Command Line Tools, is a stepping stone towards being able to install Ruby. Homebrew allows us to install other tools using simple, standardised commands. Otherwise we'd have to figure out how each of these other tools needs to be installed. By having Homebrew figure that out for us, we can focus on the good stuff: building apps. Enter the following command in the Terminal app and press the <kbd>Enter</kbd> key. You will be asked to enter a password–this is the password you use to unlock your laptop. Enter your password and press <kbd>Enter</kbd>. {% highlight sh %} /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" {% endhighlight %} {% highlight sh %} brew update {% endhighlight %} ## Install Git Using Homebrew, we can now install Git, the version management system we'll be using for this workshop. A version management system gives you a particularly handy superpower: it allows us to travel back and forth in time. Well, at least while working with files on our computer. We'll show you how to use this during the workshop! {% highlight sh %} brew install git {% endhighlight %} ## Install rbenv Ruby, the programming language we use, releases new versions all the time. Some clever folks wrote a tool that allows us to easily install specific versions. We'll use this to make sure you're running the same version as the rest of us. Run the following commands to install [rbenv](https://github.com/rbenv/rbenv) via Homebrew: {% highlight sh %} brew install rbenv {% endhighlight %} {% highlight sh %} echo 'eval "$(rbenv init -)"' >> ~/.zshrc {% endhighlight %} {% highlight sh %} source ~/.zshrc {% endhighlight %} ## Install Ruby with rbenv Now that rbenv is installed, let's install Ruby! We'll be installing version 3.4.7, but it could be that during the event you'll be asked to install a different version. In that case, just replace the version number in the command. {% highlight sh %} rbenv install 3.4.7 {% endhighlight %} ## Set default Ruby rbenv allows us to manage a bunch of Ruby versions, but it doesn't always quite know which version you want to use. To help it with that, we'll tell it that the version we just installed is in fact the one we want to use. {% highlight sh %} rbenv global 3.4.7 {% endhighlight %} Check that your Ruby version matches what you installed. {% highlight sh %} ruby --version {% endhighlight %} The result should be something that includes the number `3.4.7`. If the version you get starts with `2.6`, first try restarting your terminal. If it still shows the wrong version something went wrong when setting up rbenv, and your Terminal is still using an older version of Ruby that ships with your Mac. Ask your coach, if present, for help, otherwise stop here and ask for help on the day of the workshop from one of the coaches. ## Install Rails Finally, we've arrived at the part where you'll install Rails, the tool we'll focus on during the workshop: {% highlight sh %} gem install rails --no-document {% endhighlight %} Just like we did with Ruby, let's check whether Rails also installed successfully: {% highlight sh %} rails --version {% endhighlight %} This should output `Rails 8.0.3`, but a higher version is also good. ## Test if Rails works Almost there! We've installed a chain of tools: Command Line Tools, Homebrew, Git, rbenv, Ruby and now finally: Rails. Let's see if everything works as intended. To test this, we'll create a new app. Don't expect too much, it will just show a single webpage showing the "Rails" logo. During the workshop you'll turn that page into an actual app. For now, we just need to make sure that you can see that logo. Let's get started with our final set of Terminal commands! Check that everything is working by first running the application generator command. This will create a new Rails app which we can test with. {% highlight sh %} rails new railsgirlsapp {% endhighlight %} The `rails new` command creates a new folder on your computer called "railsgirlsapp", containing all the code for your application. Let's open that directory in the Terminal using the `cd` command: {% highlight sh %} cd railsgirlsapp {% endhighlight %} Next, you'll start the Rails server briefly to make sure it starts properly. This is where the magic happens. {% highlight sh %} rails server {% endhighlight %} Unlike previous commands, this one will not stop until you press the <kbd>ctrl</kbd> + <kbd>c</kbd> keys together to stop it. You have just started a web server on your laptop, and it is ready to start taking visitors and show them your sample application. Let's not keep it waiting. Go to <http://localhost:3000> in your Browser. You should see the Rails logo appear. If at any point during this guide you ran into a problem and can't continue. Not a problem! Contact the workshop organizers and let them know about your problem. Some workshops have dedicated set up evenings and otherwise they can help you on the day of the workshop itself. If you do see a Rails logo in your Browser, you now have a working Ruby on Rails programming setup. Congratulations! You're ready for the workshop. If you are preparing before the workshop, you don't have to continue with guides until the day of the workshop. See you then! {% coach %} If there's a coach present, they can help verify the installation by using the scaffold command and inputting data with the generated page with coaches to ensure everything is working. Remove the test app `railsgirlsapp` to make super sure no-one is working in the wrong folder, while following the steps of the workshop. {% endcoach %} ================================================ FILE: _pages/install/replit.md ================================================ --- layout: main_guide title: Setup on Replit description: "Prepare development of your app on the Replit service to develop your app in the cloud." permalink: install/replit --- # Using a Cloud Service {% include main-guide-intro.html %} Instead of installing Ruby on Rails and an editor on your computer, you can use a webservice for development. All you need is a browser and an internet connection. This guide explains how to get started with [replit.com]. If you're using a different service, they may use a different wording, but the process is usually pretty similar. ## _1._ Create an account Go to [replit.com] and sign up for free. You will need to confirm your email and then fill in your details. ![Log in screen](/images/replit/create-account.png) ## _2._ Create a Ruby on Rails Repl The Ruby on Rails Repl has all the software we need for the workshop already preinstalled. <video width="100%" preload="auto" muted controls> <source src="/images/replit/replit-rails.mp4" type="video/mp4"> </video> To create one, log into [replit.com] and click on 'Create'. ![Dashboard with the Create button pointed to by arrows](/images/replit/create-app.png) In the field under Template, type in `rails`. ![Search dialog for Repl templates](/images/replit/search-rails.png) 1. Select the `Rails` option from Templates. 2. It generates a name for your Ruby on Rails app but you can change it in the Title field (maybe to "RailsGirls"). 3. Click the `+ Create Repl` button ![Create the Rails Repl dialog](/images/replit/create-rails-repl.png) ## 3. Coding with your project - On the left hand side, you find a file browser where you can navigate your directories and file. - In the middle, you find the editor where you can modify your files. - Click the `Run` bottom at the top to start up the freshly installed Ruby on Rails app. ![Run button highlighted to start the Rails app](/images/replit/run.png) - You'll see a mini web browser to the top right showing you your fresh Rails app running the default homepage with the Rails logo. ![Rails app running](/images/replit/rails-running.png) - At the bottom right, when you click the `Shell` button you'll find the terminal where you can run commands. ![Shell](/images/replit/shell.png) ## 4. Returning to your project When you log out and log back in to [replit.com], you can find your RailsGirls app in the middle of the dashboard. Just click it to go back into the project. ![Dashboard showing button to return to Rails project](/images/replit/re-open.png) [replit.com]: https://replit.com ================================================ FILE: _pages/install/virtual-machine.md ================================================ --- layout: main_guide title: Setup on a Virtual Machine description: "Prepare development of your app using a Virtual Machine." permalink: install/virtual-machine --- # Setup on a Virtual Machine <span class="muted">Cooking time: 15min active / 1 hour passive</span> {% include main-guide-intro.html %} <p class="warning-notice">This guide has been recently updated on the 19th of February, 2023. It has not been fully tested. Please continue with caution.</p> A development environment is a collection of applications and tools with which a developer can do their daily work. For Ruby on Rails development, we need a collection of tools like: Ruby, the Rails framework, a database, etc. There may be some problems unique to your laptop that prevent you from installing these tools. You and your coach run into an issue that has prevented you from preparing for the workshop. To help with this, it's possible to get the development environment ready on a Virtual Machine. A new machine in which you can start fresh with the installation. This requires the complete installation of a new computer, something which may be an advanced step for some. Ask a coach or someone else for help with this step. ## Limitations Virtualizing another Operating System requires more power from your laptop. We do not recommend virtualization if you do not own a computer with more than one CPU cores, at least 2 Gigabytes of available memory and 20 Gigabytes of free disk space. Ask your coach to help with this assesment. {% coach %} Please help check if the laptop can handle running a Virtual Machine before continuing. {% endcoach %} ## Install VirtualBox VirtualBox is Oracle's virtualization platform, which can be downloaded on all the supported Operating System (Win, Mac and Linux). Start by downloading the installer from [https://www.virtualbox.org/wiki/Downloads](https://www.virtualbox.org/wiki/Downloads). Once downloaded, double click it an follow the instructions. VirtualBox will look something like this once installed: ![VirtualBox / Starting VM](/images/virtualbox.png) ## Download Ubuntu Ubuntu is a Linux distribution that can be freely downloaded from the [Ubuntu download page](https://ubuntu.com/download/desktop). Pick the version with the LTS label (Long Term Support) and download it. At the time of writing this is "Ubuntu 22.04.1 LTS". ## Install Ubuntu In the VirtualBox app, click the "New" button in the menu ribbon. In the new window enter the following: - Give your Virtual Machine a name, like "RailsGirls". - In the ISO image dropdown, select "Other...". In the new window that opens, find the Ubuntu file that was just downloaded. It will be named something like `ubuntu-22.04.1-desktop-amd64.iso` in your downloads directory. - Upon selection the "Type" field should update to "Linux", but if not, select this value from the dropdown. - Click Next. Follow the rest of the instructions of the installation wizard. The defaults are most likely fine. Upon start of the Virtual Machine, it will start Ubuntu. Login with the password you configured during installation. ## Pasting text Note on pasting text into the Virtual Machine: On Linux and Windows you won't be able to paste any copied code with the ordinary <kbd>Ctrl</kbd>+<kbd>V</kbd> combination. Please use <kbd>shift</kbd>+<kbd>insert</kbd> instead, it should work. ## Set up development environment From here on, follow the [installation guide for Linux](/install/linux) to install Ruby, Rails and other required tools on the Virtual Machine. Once completed, return to this guide. ### Shared directory Your development environment is nearly ready. Only one thing left: we want to share a folder, which can be reached from our normal operating system and our VM, since we are going to code on the former, but we are going to run the code in the latter. Let's create a new folder called *railsgirls* on our machine (under our user's home folder). Next, shut down the VM: Close the window in which the Ubuntu VM is running and select Shut down from the available options. After the shutdown, select the VM in VirtualBox, and press *Settings*. Click on Shared Folders tab, and click on the little + icon on the right. In the appearing little window browse the created *railsgirls* forlder as a Folder Path. Give *railsgirls* as foldername and also select the option *Auto Mount* (all other options should be deselected). ### System check The shared folder can be found at the path `/media/sf_railsgirls`. Let's check if everything works as expected. Please enter to this directory: {% highlight sh %} cd /media/sf_railsgirls {% endhighlight %} Let's create an empty file: {% highlight sh %} touch test.txt {% endhighlight %} Check on your own Operation System, if the shared folder contains a file called `test.txt`. If so, we are ready with our virtual environment. Now you can continue with the guides. Edit the app code on your laptop, and run the app in the Virtual Machine. ================================================ FILE: _pages/install/windows.md ================================================ --- layout: main_guide title: Setup on Windows description: "Install Ruby and Rails on your Windows computer and get prepared for the Rails Girls workshop." permalink: install/windows --- # Setup for Windows {% include main-guide-intro.html %} To install Rails for Windows we'll need to install Ruby and several supporting tools such as Git and SQLite. Follow the steps below in order to install these tools on your computer. When you're done with these steps you will have a Rails app running on your computer. <div class="help-notice">Make sure you're familiar with <a href="/tools">the tools you'll need for this guides</a> before continuing.</div> During these steps we'll ask you to open and close the Windows Command Prompt every now and then. This can be either the "Command Prompt" or "Powershell" app. We ask you to close and re-open it, because when the Command Prompt starts it loads in the environment. When we install a new app, the environment does not get automatically updated in the Command Prompt. To test if the installation was successful we need to restart the Command Prompt and load the new environment. If you run into any problems during this guide, check the [Possible errors] section for solutions. ## Install Ruby We'll start by installing Ruby, the primary programming language used during the workshop. This can be done using the RubyInstaller described below. - Download the [RubyInstaller](https://rubyinstaller.org/downloads/) for Windows. - [Direct link to Ruby 3.4.7 installer with Devkit](https://github.com/oneclick/rubyinstaller2/releases/download/RubyInstaller-3.4.7-1/rubyinstaller-devkit-3.4.7-1-x64.exe) for 64-bit architecture. - Run the installer. Click through the installer using all the default options. - Make sure the "Run 'ridk install'" checkmark is checked partway through the installer before continuing. - When prompted with the "MSYS2" installer, enter `1` and press Enter. - When prompted with the same "MSYS2" installer again, only press Enter. ## Install Git You can now install Git, the version management system we'll be using for this workshop. A version management system gives you a particularly handy superpower: it allows us to travel back and forth in time. Well, at least while working with files on our computer. We'll show you how to use this during the workshop! - Visit the [Git installer for Windows](https://git-scm.com/download/win) download page. - Click the link for the "32-bit Git for Windows Setup" installer to download it. - Run the installer. Click through the installer using all the default options. ## Install SQLite Next you'll install the SQLite database on your laptop. This is a system in which you can store data into and fetch data from. It does not have an automatic installer unfortunately, like Ruby and Git, so you'll need to do a couple of more steps manually. - Visit the [SQLite download page](https://sqlite.org/download.html). - Scroll down to the "Precompiled Binaries for Windows" section. - Download the `sqlite-dll-win32-x86-xxxxxxx.zip` package (where `xxxxxxx` is the most recent version number). - Download the `sqlite-tools-win32-x86-xxxxxxx.zip` package (where `xxxxxxx` is the most recent version number). - Open the Downloads directory with Windows Explorer. - Extract the packages by double clicking the files in the Downloads directory that match the files you downloaded. These will create new directories with similar names in your Downloads directory. Remember these. - In Windows Explorer, open "This Computer" in the sidebar and open the `C:` local disk. - Create a new directory called `sqlite3` by clicking the right mouse button, "New" and "Folder". Enter the name `sqlite` and press <kbd>Enter</kbd>. - Copy the files from the extracted packages in your Downloads directory, into the `C:\sqlite3` directory. As a result you will have the following files in that directory: `sqldiff`, `sqlite3.def`, `sqlite3.dll`, `sqlite3` and `sqlite3_analyzer`. - Open the Windows Command Prompt and run the following command to add the `c:\sqlite3` directory to the system PATH so you can access it in the Command Prompt app. - For Command Prompt users run the following command: - `setx path "%path%;c:\sqlite3"` - For Powershell users run the following command: - `setx path "c:\sqlite3"` - Close the Windows Command Prompt app. - Re-open the Windows Command Prompt. - Run the following command to check if the installation was successful. It should output a version number like `3.41.1` (your version may differ). {% highlight sh %}sqlite3 --version{% endhighlight %} - Close the Windows Command Prompt app. These were a bunch more steps than you'll need to perform for these kinds of steps for the rest of the workshop. If you get stuck at any time, ask a coach or any of the organizers of your local workshop for help. ## Install Rails Finally, you've arrived at the part where you'll install Rails, the tool you'll focus on during the workshop. Open the Windows Command Prompt run the following command. This will install the Rails and bundler gems on your computer. {% highlight sh %} gem install rails bundler --no-document {% endhighlight %} Let's check whether Rails was installed successfully. Open the Windows Command Prompt and run the following command to check if the installation was successful. {% highlight sh %} rails --version {% endhighlight %} This should output `Rails 8.0.3`, but a higher version is also good. _If you run into any problems during this step, check the [Possible errors] section for possible solutions._ ## Check the environment Almost there! We've installed a chain of tools: Ruby, Git, SQLite and now finally: Rails. Let's see if everything works as intended. To test this, we'll create a new app. Don't expect too much, it will just show a single webpage showing the "Rails" logo. During the workshop you'll turn that page into an actual app. For now, we just need to make sure that you can see that logo. Let's get started with our final set of Terminal commands! Check that everything is working by first running the application generator command. This will create a new Rails app which we can test with. {% highlight sh %} rails new railsgirlsapp {% endhighlight %} The `rails new` command creates a new folder on your computer called "railsgirlsapp", containing all the code for your application. Let's open that directory in the Terminal using the `cd` command: {% highlight sh %} cd railsgirlsapp {% endhighlight %} Next, you'll start the Rails server briefly to make sure it starts properly. This is where the magic happens. {% highlight sh %} rails server {% endhighlight %} Unlike previous commands, this one will not stop until you press the <kbd>ctrl</kbd> + <kbd>c</kbd> keys together to stop it. You have just started a web server on your laptop, and it is ready to start taking visitors and show them your sample application. Let's not keep it waiting. Go to <http://localhost:3000> in your Browser. You should see the Rails logo appear. If at any point during this guide you ran into a problem and can't continue. Not a problem! Contact the workshop organizers and let them know about your problem. Some workshops have dedicated set up evenings and otherwise they can help you on the day of the workshop itself. If you do see a Rails logo in your Browser, you now have a working Ruby on Rails programming setup. Congrats! You're ready for the workshop. If you are preparing before the workshop, you don't have to continue with guides until the day of the workshop. See you then! {% coach %} If there's a coach present, they can help verify the installation by using the scaffold command and inputting data with the generated page with coaches to ensure everything is working. Remove the test app `railsgirlsapp` to make super sure no-one is working in the wrong folder, while following the steps of the workshop. {% endcoach %} [Possible errors]: /install#possible-errors-during-installation ================================================ FILE: _pages/install.md ================================================ --- layout: main_guide title: Setup recipe for Rails Girls description: "Install Ruby and Rails on your computer and get prepared for the Rails Girls workshop." permalink: install --- # Setup recipe for Rails Girls <span class="muted">Cooking time: 5min active / 15-30min passive</span> {% include main-guide-intro.html %} To build apps and other things with Ruby on Rails, we need to setup some software and the developer environment for your computer. Make sure you're familiar with [the tools you'll need for these guides](/tools) before continuing. From there we'll guide you through the steps needed to prepare for the workshop, and while doing so give you a bit of background info on what we're doing. Don't worry too much about the installation steps and understand everything about them. These are the required steps to get through to get to the real programming part of the workshop. These setup guides assume no prior knowledge. That's easier said than done. Things that may seem obvious to us might be _abracadabra_ to you. If this is the case, please: let your event organizers know. We can use your feedback to improve these guides! Please follow the instructions for your Operating System from the list below. If you run into any problems, don't panic. Check the [known errors section](#possible-errors-during-installation) or inform the organizers/coaches at the event and we can solve it together. - [Setup for Mac](/install/macos) - [Setup for Windows](/install/windows) - [Setup for Linux](/install/linux) - Alternative installation methods. Use these if the above guides do not work. - [Setup on a Virtual Machine](/install/virtual-machine) - [Using the Replit Cloud Service - No Installation Required](/install/replit) ## Possible errors during installation ### 'x64_mingw' is not a valid platform Error Sometimes you get the following error when running `rails server`: `'x64_mingw' is not a valid platform` If you experience this error after using the RailsInstaller you have to do a small edit to the file `Gemfile`: Look at the bottom of the file. You will probably see something like this as one of the last lines in the file: `gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw]`. If you have this line with `:x64_mingw`, then please delete the `:x64_mingw` part. In the end it should just say: `'tzinfo-data', platforms: [:mingw, :mswin]` After you did that, please use your Command Prompt again and type `bundle update`. ### The sqlite3 gem failed to install When running `rails new railsgirlsapp` the `sqlite3` gem may fail to install. When this happens, first close the Windows Command Prompt app. Then re-open the Windows Command Prompt. Next, install the `sqlite3` gem separately from the `rails` gem by running the following command: {% highlight sh %} gem install sqlite3 {% endhighlight %} If this succeeds, remove the `railsgirlsapp` directory the rails installer created and return to the installation instructions, to run `rails new railsgirlsapp` again. ================================================ FILE: _pages/new-homepage.md ================================================ --- layout: main_guide title: Add a new homepage description: "Customize your app's homepage with your own page." permalink: new-homepage --- # Add a new homepage {% include main-guide-intro.html %} In this guide we'll add another page. This will be our new homepage: the first page that will be shown when you open your app when you visit <http://localhost:3000>. Feel free to skip this guide if you know how Rails controllers, views and routes work. In the previous guide a "pages" controller was already generated, we do not need to do this again. Rails will stop us if we do try to. Instead, we'll need to add the page manually ourselves. ## Add a new view Instead we'll add another page on our own. Run the following command in the Terminal app to add another "view" file used to display page content. <div class="os-specific"> <div class="mac nix"> {% highlight sh %} touch app/views/pages/homepage.html.erb {% endhighlight %} </div> <div class="win"> {% highlight sh %} ni app/views/pages/homepage.html.erb {% endhighlight %} </div> </div> Then open the newly created file in your Text editor: `app/views/pages/homepage.html.erb` Add some content to it, like the following, and save the file: {% highlight erb %} <div class="px-4 py-5 my-5 text-center"> <h1 class="display-5 fw-bold">The ideas app</h1> <div class="col-lg-6 mx-auto"> <p class="lead mb-4">Welcome to my ideas app!</p> </div> </div> {% endhighlight %} ## Configuring the route To tell Rails when to show this page, open the `config/routes.rb` file in your Text Editor. Change the following line: {% highlight ruby %} root to: redirect("/ideas") {% endhighlight %} to this instead and save the file: {% highlight ruby %} root "pages#homepage" {% endhighlight %} When you now visit the root path of the app, <http://localhost:3000>, you should see your new homepage! ## Updating the navigation bar Lastly, to make the new root page accessible through the navigation bar, open the `app/views/layouts/application.html.erb` file in your Text Editor. Above the following lines: {% highlight erb %} <li class="nav-item"> <a class="nav-link <%= 'active' if current_page?(controller: 'ideas') %>" href="/ideas">Ideas</a> </li> {% endhighlight %} add a new link with the lines below, and save the file: {% highlight erb %} <li class="nav-item"> <a class="nav-link <%= 'active' if current_page?(controller: 'pages', action: 'homepage') %>" href="/">Home</a> </li> {% endhighlight %} When you refresh the page in the browser, and click the "The ideas app" link, it will open the new homepage. Try out all the links in the navigation bar. Do they take you to the page you expected? ================================================ FILE: _pages/new-page.md ================================================ --- layout: main_guide title: Add a new page to your app description: "Add more pages to your Rails app by generating controlelrs and changing routes." permalink: new-page --- # Add a new page to your app {% include main-guide-intro.html %} Let's add an about page to our app that will display information about the author of this application — you! ## Generate a new page In the Terminal app, run the following command: {% highlight sh %} rails generate controller pages about {% endhighlight %} This command will create a new directory under `app/views/` called `pages`. In that directory a file called `about.html.erb` will be created. This file contains the content that will be displayed on your "about" page. Open the `app/views/pages/about.html.erb` file. Add some information about yourself in the HTML. Something like the example below: {% highlight erb %} <h1>About me</h1> <p>Hello there! I am YOUR NAME HERE and this is my amazing app!</p> {% endhighlight %} The same `rails generate` command has also added a new route to your `config/routes.rb`. This route configuration tells Rails which page should be shown when visiting that URL. {% highlight ruby %} get "pages/about" {% endhighlight %} To see your new about page, take your browser to <http://localhost:3000/pages/about> (or append `/pages/about` to your preview URL). You should now see the new page you just created! {% coach %} Talk about routes for a moment. How does the `config/routes.rb` file define what routes Rails listens to? Explain that every page in the app needs a route in this file, otherwise Rails won't know how to show it. Resource: Guide to the guide [finetune the routes](https://guides.railsgirls.com/guide-to-the-guide#3_finetune_the_routes) or Rails Guides [first route](https://guides.rubyonrails.org/getting_started.html#say-hello-rails) {% endcoach %} ## Add a link to your navigation bar Now that we know the new page works, let's make sure people can visit it by creating a link for it in the navigation bar. That way they don't have to guess that page exists and try to find it on their own. Open `app/views/layouts/application.html.erb` in your Text Editor and under these lines of HTML: {% highlight erb %} <li class="nav-item"> <a class="nav-link <%= 'active' if current_page?(controller: 'ideas') %>" href="/ideas">Ideas</a> </li> {% endhighlight %} add the following lines of HTML to link to the new page: {% highlight erb %} <li class="nav-item"> <a class="nav-link <%= 'active' if current_page?(controller: 'pages', action: 'about') %>" href="/pages/about">About</a> </li> {% endhighlight %} Refresh the page in your Browser and click the newly created link to see if it works! You can now navigate between the ideas and the about pages in your app through one unified navigation bar. ## The changes in more detail By adding the new "nav item" to the navigation a new link has appeared in the navigation bar, styled by Bootstrap. This link points to the new about page. This link is made by using a `a`-element, which is the HTML for a link. Using the `href` property we tell the browser where to point to, in this case `/pages/about`. The "About" text between the `<a ... href="/pages/about">About</a>` link is what is shown as the label for the people looking at the page through the Browser. The middle part with the `class` property is what we use to indicate how the link should be displayed. If the link is "active", it is the page we're currently and it shows more brightly colored than the other link of the page we are currently not on. To check if the page is currently active, Rails provides a helper called `current_page?`. This condition will be "true" if it matches our page selection: `controller: 'pages', action: 'about'`. The `controller` is the entrypoint for anything in the `/pages` path of this part of the app, and the `action` is the specific page, which is "about". {% coach %} The above goes in a bit more technical detail about HTML works and how ERB can change what HTML is shown in the Browser. Help elaborate if things are unclear. Demonstrate how the page in the Browser changes by changing the HTML and ERB code. Resource: Rails Beginner [ERB](https://www.pragtob.info/rails-beginner-cheatsheet#rails-erb) {% endcoach %} Knowing how to add a new page and change the nav bar, you can also add a [new homepage](/new-homepage) (the next guide) to your app. ================================================ FILE: _pages/passenger.md ================================================ --- layout: guide title: Rails Girls on Passenger permalink: passenger --- # Ease up development with Phusion Passenger *Created by Floor Drees, [@floordrees](https://twitter.com/floordrees)* ### There's an app server for that Make sure you followed the [Push Your App to GitHub][github-guide] guide before you continue. What follows is a guide to eases up developing your app (you know, the adding functionality and then checking if it actually works), with Passenger. The Ruby on Rails framework provides a builtin server tool, which you can access with the `rails server` command. The "rails server" is not an application server by itself, but just a small wrapper that launches your application in an application server. People do not use "rails server" in production (where other people can access and use your app). They use an application server such as Passenger. {% coach %} Passenger is an open source web application server. It handles HTTP requests, manages processes and resources, and enables administration, monitoring and problem diagnosis. For big shot developers there's an Enterprise Edition as well. {% endcoach %} [github-guide]: /github ### Preparing your app #### Install the Passenger gem Open your app's Gemfile and add "passenger": {% highlight ruby %} gem "passenger" {% endhighlight %} By adding Passenger to your Gemfile, `rails server` will launch Passenger instead of Puma. You get virtual bonus points from the Phusion Passenger team for deleting the following lines (if present at all in your Gemfile): {% highlight ruby %} gem "unicorn" gem "thin" gem "puma" {% endhighlight %} Run `bundle install` to update your gem bundle. The text in your terminal should say something like this: {% highlight sh %} bundle install ... Installing passenger x.x.x ... Your bundle is complete! {% endhighlight %} Nginx and Apache are web servers. They provide HTTP transaction handling and serve static files. Application servers make it possible for Ruby apps to speak HTTP. Ruby apps (and frameworks like Rails) can't do that by themselves. In a typical production stack, one would use Nginx or Apache as the web server, Passenger as application server, and Capistrano as release automation tool. Passenger integrates with Nginx or Apache and manages the application and its resources. {% coach %} Sometimes you will need to specify the gem's version: `gem "passenger", ">= 5.0.25", require: "phusion_passenger/rack_handler"` {% endcoach %} #### Let's check if that worked Run the Passenger server with the following command: {% highlight sh %} bundle exec passenger start {% endhighlight %} Passenger is serving your app on <http://0.0.0.0:3000/>. Try and use your app a bit and then run `bundle exec passenger-status` to check your activity. Big (friendly, promised!) brother is watching you. There are two ways to stop the server. The first is by pressing Ctrl-C in the terminal. The second way is by running `passenger stop` in a new terminal window: {% highlight sh %} cd /path-to-your-app bundle exec passenger stop {% endhighlight %} When you switch back to the first terminal, you should see that Passenger has indeed stopped. Passenger restarts processes that crash, load balances traffic between processes and scales processes up and down in order to handle more traffic or to conserve resources. All this is handled automatically, without you having to specify anything in your code! It might not make too much sense right now, but your future developer you will thank us. For future reference you can use the `passenger-config restart-app` command to restart your application. This is more convenient than stopping and starting Passenger, which requires two commands. #### tmp/always_restart.txt Passenger also supports the magic file `tmp/always_restart.txt`. With this file, Passenger will restart your application after every request. This way you do not have to invoke the restart command often. Activate this mechanism by creating the file: {% highlight sh %} mkdir -p tmp touch tmp/always_restart.txt {% endhighlight %} Deactivate this mechanism by removing the file: {% highlight sh %} rm tmp/always_restart.txt {% endhighlight %} {% coach %} Sometimes the carrierwave gem causes trouble. Adding `require 'carrierwave/orm/activerecord'` to the `environment.rb` file will often do the trick. {% endcoach %} ### Deploying your app #### Hosting your app Before you select your host(ing infrastructure) and [follow the guide to put your app online][passenger-guide], let's commit the changes we've made: {% highlight sh %} git add . git commit -m "add passenger" git push {% endhighlight %} You can also choose to follow the [Heroku guide][heroku-guide] from here on. [passenger-guide]: https://www.phusionpassenger.com/library/walkthroughs/deploy/ruby/ [heroku-guide]: /deployment/heroku #### Troubleshooting Use the `passenger --help` command in your terminal to browse all available commands and their functionality. Most commands (like `passenger start`) have many 'sub-commands'. For instance: run `passenger start --help` to see all the add-ons for the 'start' command. Lost? Phusion Passenger has extensive documentation, including beginner's guides: [Passenger Guide][passenger-documentation] Knee-deep? Crawl through [Passenger's Troubleshooting guide][troubleshooting-guide] with your coach. [passenger-documentation]: https://www.phusionpassenger.com/library/ [troubleshooting-guide]: https://www.phusionpassenger.com/library/admin/nginx/troubleshooting/ruby/ ================================================ FILE: _pages/remote-pairing-for-the-win.md ================================================ --- layout: guide title: Remote Pairing For the Win! description: "Continue working together and learning remotely after the Rails Girls event." permalink: remote --- # Rails Girls Remote Pairing Tutorial *Originally created by Ed Drain, [@SoldierCoder](https://twitter.com/soldiercoder)* ## Why is Remote Pairing so great? First things first, what is my motivation for sharing this? If you are reading this, you are already aware of the power of [Rails Girls](https://railsgirls.com). In case you did not know, let me give you a few facts. Rails Girls is an organization that introduces women to web application development using Ruby on Rails. For many women around the world, it is a **powerful, emotional experience** that shows them that they can create something new for the Web and that they have support of other women who extended their privilege to them. I said "around the world", didn't I? Indeed, Rails Girls is on **every continent** and in **130 \+ cities!** I know this is true because, through the generosity of Ryan Bates ([@RBates](https://twitter.com/rbates)), I have had the honor of distributing coupons good for three months free of [RailsCasts.com](http://railscasts.com) to so many of those cities. So there is part of the promise of Rails Girls -- that women, around the world, who need some way of lifting themselves up out of possibly dire circumstances and thru study and application of what they have learned, get the pot of gold at the end of the rainbow -- a high paying job where they are **respected for their creations**. ## But seriously, why is Remote Pairing so great? Remote-pairing is so great because people who can benefit from people who would coach them are not always near to them. I know this because as a coach for [Rails Girls Summer of Code](https://railsgirlssummerofcode.org) who lived in Virginia, while the team I coached lived in London and Pennsylvania. If it weren't for remote pairing, I'd have to get on a plane or drive twelve hours just to show how to write a "hello, world!" example app! ## Ok, I'm sold! What do I need to remote pair? * An Internet connection. * One or more programming friends or mentors that want to remote pair with you. * To communicate with each other you'll need a calling service like [Google Meet](https://apps.google.com/meet/), [Signal app](https://signal.org/), [Whereby](https://whereby.com/) or anything other app you're familiar with. - Ideally the app you're using to call can also share your screen so the other person can see your screen. - It's even better if the other person can also control your screen from their end. If this is not possible in the call app itself, you can use the Visual Studio Code Text Editor plugin Live Share to share your code in your editor. Learn about how to [install the Live Share extension](https://learn.microsoft.com/en-us/visualstudio/liveshare/use/install-live-share-visual-studio-code) and how to [share your project with Live Share](https://learn.microsoft.com/en-us/visualstudio/liveshare/use/share-project-join-session-visual-studio-code). ## Last thoughts The Ruby community is such a great example of people helping others. One has only to look at the folks nominated every year as [Ruby Heros](http://rubyheroes.com/) to see this in action. What a great and generous world this would be, if all of us extended some of our privilege to someone who has less. It would be a world that reflects that most common of sayings that you probably hear at meetings of your local Ruby/Rails meet-up: "MINSWAN" -- Matz is nice, so we are nice! Let's get started being nice to each other! ================================================ FILE: _pages/ruby-atm.md ================================================ --- layout: guide title: Ruby ATM permalink: ruby-atm --- # Ruby ATM *Created by Joshua Paling, [@joshuapaling](https://twitter.com/joshuapaling)* In this exercise you will write a function to handle withdrawing money from an ATM. It is intended to challenge you! Be prepared to ask lots of questions, Google things, and take a step back from the computer. But you'll learn a lot! You should use pair, group, or remote programming so you have other programmers to bounce ideas off. You'll use Test Driven Development. However, all the tests have been pre-written for you, so you can focus on the code itself. We'll start simple, but ramp the difficulty up pretty steeply toward the end! ## Workflow For each step, you will need to take the following actions: **1. Run the new tests:** Delete tests from the previous step, and paste in the pre-written tests for the current step. *(Tests for each step are show at the bottom of that step.)* Run the tests to see which ones fail. In sublime text, you can hit <kbd>Ctrl</kbd>+<kbd>B</kbd> to run the tests. Or, you can open a terminal, `cd` into your working directory, and run `ruby atm.rb`. **2. Make the tests pass:** Edit your code to meet the functionality requirements of the current step. You'll know you've got it right when all your tests are green. **3. Refactor:** See if there are any edits you can make to ensure your code is as clean and easy to understand as possible. Some steps have discussion points. Discuss them with your pair - they'll help you moving forward. You may recognise these steps as the **red, green, refactor** workflow of TDD. ## *1.* $5 bills Imagine an ATM that holds only $5 notes. Write a function that returns `true` if an amount can be returned, and `false` otherwise. **Examples:** * `withdraw(15)` should return `true` * `withdraw(18)` should return `false`, because $18 cannot be made up of $5 notes **Tips for getting tests green:** The modulus operator, `%` gets the remainder of a division. Eg, `9 % 4` results in `1` (nine divided by four has a remainder of 1). **Starting code:** Create a file called `atm.rb`. paste the following code into it. This contains the shell of your `withdraw()` function, along with tests. {% highlight ruby %} def withdraw(amount) if amount <= 0 # this deals with some of the situations... return false end # ToDo: figure out this bit end {% endhighlight %} ### Tests for step 1: {% highlight ruby %} # import required testing libraries require 'minitest/spec' require 'minitest/autorun' # BELOW ARE THE TESTS FOR AUTOMATICALLY CHECKING YOUR SOLUTION. # THESE TESTS ARE FOR STEP 1. # THESE NEED TO BE REPLACED AFTER EACH STEP. describe 'atm' do [ [-1, false], [0, false], [1, false], [43, false], [17, false], [5, true], [20, true], [35, true], ].each do |input, expected| it "should return #{expected} when $#{input} is withdrawn" do withdraw(input).must_equal expected end end end {% endhighlight %} ## *2.* How many bills? Now, modify your function so that if the amount *can* be withdrawn, it will return the appropriate number of notes, rather than simply `true` **Examples:** * `withdraw(15)` should return `3`, since three $5 notes makes $15 * `withdraw(20)` should return `4`, since four $5 notes makes $20 * `withdraw(11)` should return `false`, because $11 cannot be made up of $5 notes **Tips for getting tests green:** The `/` operator performs a division. For example, if you wanted to get half your age, and store it in a variable, you'd do this: {% highlight ruby %} my_age = 28 half_my_age = my_age / 2 {% endhighlight %} In ruby, when you do division with two whole numbers (integers), the result is rounded down to the nearest whole number. {% highlight ruby %} new_number = 25/10 # new_number contains 2, because 25/10 = 2.5, and ruby will round that down to 2. {% endhighlight %} ### Tests for step 2: {% highlight ruby %} # Replace your existing tests with the ones below. describe 'atm' do [ [-1, false], [0, false], [1, false], [43, false], [7, false], [5, 1], [20, 4], [35, 7], ].each do |input, expected| it "should return #{expected} when $#{input} is withdrawn" do withdraw(input).must_equal expected end end end {% endhighlight %} ## *3.* Array of notes In programming, an `array` is basically a collection of things. It's like a list. Rather than returning the number of notes, modify the code so that it returns an array of notes (in this case, all $5's). **Examples** * `withdraw(15)` should return an array, `[5, 5, 5]`. (That's basically a collection of three $5 notes) * `withdraw(11)` should return `false`, because $11 cannot be made up of $5 notes **Tips for getting tests green:** `[]` defines an empty array. `[1, 2]` defines an array with two elements (1 and 2). The shovel operator (`<<`) adds an element to an array. Eg. `[10, 20] << 30` will add 30 to the array, resulting in `[10, 20, 30]`. The `times` method executes a block of code several times - eg. `5.times { puts 'hello' }` will print 'hello' 5 times. Bringing it all together: {% highlight ruby %} my_array = [] # create an empty array and store it in my_array my_array << 20 # now my array contains [20] my_array << 30 # now my_array contains [20, 30] remainder = 13 % 5 # remainder is 3 remainder.times { my_array << 5 } # now my_array contains [20, 30, 5, 5, 5] {% endhighlight %} ### Tests for step 3: {% highlight ruby %} # Replace your existing tests with the ones below. describe 'atm' do [ [-1, false], [0, false], [1, false], [43, false], [20, [5, 5, 5, 5]], [35, [5, 5, 5, 5, 5, 5, 5]], ].each do |input, expected| it "should return #{expected} when $#{input} is withdrawn" do withdraw(input).must_equal expected end end end {% endhighlight %} ## *4.* $10 notes Now imagine the ATM returns only $10 notes. Modify your function to accommodate this. **Examples** * `withdraw(20)` should return an array, `[10, 10]` * `withdraw(15)` should return `false`, because $15 cannot be made up of $10 notes ### Tests for step 4: {% highlight ruby %} # Replace your existing tests with the ones below. describe 'atm' do [ [-1, false], [0, false], [7, false], [45, false], [20, [10, 10]], [40, [10, 10, 10, 10]], ].each do |input, expected| it "should return #{expected} when $#{input} is withdrawn" do withdraw(input).must_equal expected end end end {% endhighlight %} ### Refactor Once you have your tests passing, it's time to refactor. In programming, ['Magic Numbers'](https://en.wikipedia.org/wiki/Magic_number_(programming)) are a bad thing (don't be fooled by the name!). They refer to a hard-coded value that just sort of *appears* out of thin air, with no clear explanation of what that particular number represents. Consider how easy / hard it is to understand the following code snippets: {% highlight ruby %} # BAD - magic number! balance = balance * 4.45 {% endhighlight %} {% highlight ruby %} # BAD - nondescript variable name is not much better! value = 4.45 balance = balance * value {% endhighlight %} {% highlight ruby %} # GOOD - isn't this much easier to understand? interest_rate = 4.45 balance = balance * interest_rate {% endhighlight %} Magic numbers are particularly troublesome when the same hard-coded value appears in multiple places. Did you use magic numbers? Can you refactor your code to eliminate them? ## *5.* $5 and $10 notes Imagine your ATM now holds $5 and $10. People want as few notes as possible. **Examples** * `withdraw(25)` should return `[10, 10, 5]` * `withdraw(11)` should return `false`, because $11 cannot be made up of $5 and $10 notes ### Tests for step 5: {% highlight ruby %} # Replace your existing tests with the ones below. describe 'atm' do [ [-1, false], [0, false], [7, false], [20, [10, 10]], [25, [10, 10, 5]], [35, [10, 10, 10, 5]], ].each do |input, expected| it "should return #{expected} when $#{input} is withdrawn" do withdraw(input).must_equal expected end end end {% endhighlight %} ## *6.* $5, $10, and $20 notes Your ATM now holds $5, $10, and $20 notes. Modify your function to accommodate this. **Note:** at this point, each higher denomination can be evenly divided by each lower denomination - eg. $20 / $10 = 2. Things get much trickier when that's not the case (eg, $50's and $20's). For this step, we'll intentionally not deal with this case to make it easier. **Examples** * `withdraw(15)` should return `[10, 5]` * `withdraw(25)` should return `[20, 5]` * `withdraw(35)` should return `[20, 10, 5]` * `withdraw(11)` should return `false`, because $11 cannot be made up of $5 and $10 notes **Tips for getting tests green:** To tell if an array is empty: `my_array.empty?` To tell if an array is not empty: `!my_array.empty?` To remove the first element off an array: `my_array.shift`. Eg, `[1, 2, 3].shift` results in `[2, 3]` ### Tests for step 6: {% highlight ruby %} # Replace your existing tests with the ones below. describe 'atm' do [ [-1, false], [0, false], [7, false], [53, false], [35, [20, 10, 5]], [40, [20, 20]], [65, [20, 20, 20, 5]], [70, [20, 20, 20, 10]], [75, [20, 20, 20, 10, 5]], ].each do |input, expected| it "should return #{expected} when $#{input} is withdrawn" do withdraw(input).must_equal expected end end end {% endhighlight %} ### Refactor * How many lines did you have to change, going from step 5 to step 6? * What if we made $100 notes available, as well? Could you do this in a single line? * Refactor your code so that you could change to $100, $20 and $10 notes, by changing a single line. * What is the most future-proof solution? ## *7.* Final Discussion Points * Given a particular solution *works*, what makes it 'good' or 'bad' code? * Can you think of any take-home best practices or principles? Is code structure important? Why? * Did you have any 'Aha!' moments? What were they? * Let's say you started a little ATM company, which quickly expanded to become a global success. How suitable is your code for dealing with all denominations of currency, in all nations of the world? Did it get more suitable with each step? ## Challenge! $50 and $20 notes Up til now, we've intentionally avoided the case where a smaller note cannot fit evenly into each larger one. For example, we've avoided the case of having only $50s and $20s (where 20 does not divide evenly into 50). Can you see why this case will be harder? If your current code were to include only $50s and $20s, what would happen when you try to withdraw $60, or $110? In your head, or on paper, can you think of what logic would be needed to be in place to handle these cases correctly? If you're up for a challenge, try to handle this case in your code! (You'll need to write the tests yourself for this step). ================================================ FILE: _pages/ruby-game.md ================================================ --- layout: guide title: Write a little game in Ruby! permalink: ruby-game --- # Write a little game in Ruby! *Created by Patrick Huesler, [@phuesler](https://twitter.com/phuesler) & Floor Drees, [@floordrees](https://twitter.com/floordrees) for [Rails Girls The Hague](https://railsgirls.com/thehague)* [Gosu](https://www.libgosu.org/) is a 2D game development library. Gosu features easy to use and game-friendly interfaces to 2D graphics and text (accelerated by 3D hardware), sound samples and music as well as keyboard, mouse and gamepad/joystick input. It also includes demos for integration with RMagick, Chipmunk and OpenGL. The actual source code, wiki, issue tracker etc. are all [hosted on GitHub](https://github.com/jlnr/gosu/). The best entry point into Gosu's documentation is the [wiki home page](https://github.com/jlnr/gosu/wiki). ## Install the Ruby gem Run the following command in the Terminal app: {% highlight sh %} gem install gosu {% endhighlight %} or add `gem "gosu", "~> 0.7.48"` to your Gemfile and run `bundle install`. Play around with the example games: {% highlight sh %} cd $GEM_HOME/gems/gosu-0.7.48/examples {% endhighlight %} and then: `ruby CptnRuby.rb` or: `ruby RMagickIntegration.rb` or: `ruby Tutorial.rb` ### Enough with those examples already! Copy the repository by opening (a new tab in your) terminal. If you were working on the Rails Girls app in the mean time, make sure you're in your home directory by running `cd`. Now run {% highlight sh %} git clone https://github.com/FloorD/gosu_tutorial_RG_TH.git {% endhighlight %} aaand change into the proper directory using {% highlight sh %} cd gosu_tutorial_RG_TH/jumpingem {% endhighlight %} ### Run! To play our little game, open it using the terminal: {% highlight sh %} ruby game.rb {% endhighlight %} ### So how does this work? Let's inspect some code, shall we? Open `game.rb` in your texteditor. See the {% highlight ruby %} #!/usr/bin/env ruby -w require 'rubygems' require 'gosu' include Gosu {% endhighlight %} ... right at the top of your file? Here we make sure we 'call' the necessary gem, so we can move on to our `class` (or multiple classes). So we have our {% highlight ruby %} class Game < Window end {% endhighlight %} ... thing going on. The `def`'s you see within this Game class, are methods. Here we **def**ine which instructions the program should follow. Just take a look at the following snippet: {% highlight ruby %} def draw draw_quad 0, 400, Color::WHITE, 640, 400, Color::WHITE, 640, 500, Color::WHITE, 0, 500, Color::WHITE if @dir == :left then offs_x = -25 factor = 1.0 else offs_x = 25 factor = -1.0 end @cur_image.draw(@x + offs_x, @y - 49, 0, factor, 1.0) end {% endhighlight %} Want to play around a bit? Copy the contents of `game.rb` in a new `.rb` file. Save it and name it as you'd like. Now try and change some stuff in the game and run it in your terminal to see the changes. Think you have more graphic skills than Patrick (you probably do)? Then you can try and create a new `sprites.png`! Don't forget to call it here: {% highlight ruby %} def initialize super(640, 480, false) self.caption = "Jump 'n Run" @standing, @walk1, @walk2, @jump = *Image.load_tiles(self, "sprites.png", 100, 160, false) @x, @y = 400, 0 @vy = 0 @dir = :left @cur_image = @standing end {% endhighlight %} And see the `Game.new.show`? That creates a new instance. It has no memory, so when you get stuck in the game, you can just start a new game. Have fun! #### Credits The assets used in vim adventures, you can find them [here](http://www.lostgarden.com/2007/05/dancs-miraculously-flexible-game.html) The sounds usedm you'll find over at [Matthew Klingensmith (www.matthewklingensmith.com)](https://opengameart.org/content/matts-creative-commons-music) ================================================ FILE: _pages/ruby-intro.md ================================================ --- layout: guide title: Introduction to Ruby description: "Learn how the Ruby language syntax works and how to make dynamic HTML in your Rails app views." permalink: ruby-intro --- # Introduction to Ruby In the Rails Girls workshop you'll be working with the Ruby programming language, among others. The Rails framework that will run your app is written in Ruby, and to change it you need to write Ruby code. Ruby is a language that's optimized for developer happiness, but like anything it will take some getting used to. In programming, there are a lot of different ways to builds apps. This guide will be focussing on a small set of Ruby concepts you need to write your app. It assumes you haven't written any code before. If you want to learn more after this workshop, there are a lot of resources out there. Ask you coach or the organizers. ## Hello world All good apps start with the "Hello world!" starter. You write your first code and your code greets you back. Create a new file on your laptop–anywhere will do for now, just remember where–and name it `app.rb`. The `.rb` extension tells you, your (future) team and the computer what kind of file it is: a Ruby program. In this `app.rb` file you can write Ruby code. Open the file in your Text Editor. Start by copying in this small example below to the new file and save the file. {% highlight ruby %} puts "Hello world!" {% endhighlight %} This app `puts` something. That means it will print something to the Terminal. In this case the text "Hello world!". Text values are indicated with double quotes (`"`) or single quotes (`'`) surrounding it. In the Terminal app you can run this app with the following command: {% highlight sh %} ruby app.rb {% endhighlight %} Make sure you're in the same directory in the Terminal app as you created your `app.rb` file in. (You can also type in `ruby` and drag the file to your Terminal. It should add the path to the file to the Terminal command.) If it ran successfully you should see this output in the Terminal app: {% highlight sh %} Hello world! {% endhighlight %} Your app is greeting you! ## Do some math To make your app more dynamic you can perform calculations on values: {% highlight ruby %} puts 100 + 23 # 123 {% endhighlight %} **Quick explanation about how to run Ruby apps**: Every time you see an example like the one above, you can copy the code into a local file, `app.rb` or a new one, to test it out. Then run it with the `ruby` command and the filename to see the output. For example: `ruby app.rb` **Quick explanation about comments**: If you see the hashtag symbol (`#`)—also known as the number or pound symbol–in a code example, everything after that is considered a comment. Comments won't be run as Ruby code in your program. When you see a line of text with `# some text`, this is there to help explain what's happening and can be left out of your app code. It shows the printed output or the result of a line of code. It is also used to explain what certain code is doing in code examples themselves, without interfering with how the code works. A couple other ways to perform calculations are shown below: {% highlight ruby %} puts 100 - 30 # 70 puts 5 * 10 # 50 puts 10 / 5 # 2 {% endhighlight %} In the Terminal app run the app with the following command. It should print the results of the different calculations below one another. {% highlight sh %} ruby app.rb {% endhighlight %} ## Variables Apps move around data as they process or change it. Data can get assigned to "variables". Variables hold data and point to a location in the computer's memory. When you reference a variable in our apps, you access the data in the computer's memory. In the example below the code has changed to define a variable named `greeting`. You can recognize this by the `greeting =` statement, ending with an equals sign. This form of statement assigns the value "Hello your name here" to the `greetings` variable. This variable holds some data, in this case the text value "Hello your name here". When we run this changed app, it will output "Hello your name here". {% highlight ruby %} greeting = "Hello your name here" puts greeting {% endhighlight %} Change the text between the quotes (`"`) to print your own text. ## If-statement A way to control the flow of your application is by using if-statements. These are branches in your code that do one thing or another based on one or more values. Using the `if` keyword, you can check if a condition is true. In the example below it checks if one value is larger than the other with the greater than symbol (`>`). {% highlight ruby %} if 20 > 10 # if 20 is larger than 10 puts "20 is larger than 10" end {% endhighlight %} An if-statement consists of a `if` and `end`keyword. The `if` keyword starts the if-statement, and the `end` keyword closes it. Every line of code between the `if` and `end` keywords is what Ruby will run if the condition after the `if` keyword is true. There are several ways to check values, some examples: {% highlight ruby %} # Compare two texts if "Matz" == "Matz" # Do something when the names match # The double equal sign checks if two values match exactly end if "Jim" != "Jane" # Do something when the names don't match # The exclamation mark with an equal sign checks if two values don't match end {% endhighlight %} In the examples above we've used values directly and these won't change, so an if-statement is not really necessary. In the real world, you'll most likely be using variables in if-statements. And the values in those variables will be based on some user input. {% highlight ruby %} value1 = 20 value2 = 10 if value1 > value2 puts "value1 is larger than value2" end {% endhighlight %} You may also want to do some other behavior if the if-statements condition does not match. {% highlight ruby %} if value1 > value2 puts "Yes" else # This code is run when the if-statement's condition isn't true puts "No" end {% endhighlight %} It's even possible to create more branches in the same if-statement. {% highlight ruby %} if value1 == value2 puts "The values match exactly" elsif value1 > value2 puts "value1 is bigger than value2" else puts "value1 is smaller than value2" end {% endhighlight %} ## Methods One way to organize the code of the app is to use methods. Methods are reusable blocks of code that can be called by their name. In the example below a method called `say_hello` has been defined with the `def` keyword for "define". The end of the method is indicated with the `end` keyword. When this method is called it performs everything between the line starting with `def` keyword and the line containing the `end` keyword. {% highlight ruby %} def say_hello puts "Hello world!" end {% endhighlight %} On its own, the method definition does nothing. This method is not called yet and the greeting is not printed. You can use its name to call the method like so: {% highlight ruby %} say_hello # Hello world {% endhighlight %} Once defined methods can be called many times. That makes it easier to do the same thing many times in an app. {% highlight ruby %} say_hello # Hello world say_hello # Hello world say_hello # Hello world {% endhighlight %} ### Method return values Methods return the value of the statement on the method's last line. If we don't want the method to always print the result to the Terminal, we can return it instead. {% highlight ruby %} def say_hello "Hello world!" end {% endhighlight %} To print the return value you need to pass the value returned by the method to the `puts` method like so: {% highlight ruby %} puts say_hello {% endhighlight %} This way of writing Ruby code is most commonly used, because it allows you to do more things than only print the return value, but perform other operations on it as well. In most apps you won't need to `puts`, or print, the values all the time. That's only for illustrative purposes in this guide. ### Method parameters To make the method more dynamic you can use define it with a parameter. Then when you call it, pass in the name you want it to print. {% highlight ruby %} def say_hello(your_name) "Hello #{your_name}!" end puts say_hello("Your name") # "Hello Your name" {% endhighlight %} When the `say_hello` method is called, the "Your name" value becomes the variable `your_name` in the method code. You can recognize this in the method definition line `def say_hello(your_name)`. The text `your_name` between the parentheses is the variable name. Then on the line with the `puts`, it's combined with the greeting: `"Hello #{your_name}!"`. **Quick explanation on the `#` symbol usage**: Previously, this guide said that the hashtag symbol is used to indicate code comments. There are a couple exceptions, the most common one being combing two text values. In combination with curly brackets in double quoted text values, a variable can be inserted into another text value: `Text #{variable}`. You'll notice that the way we call the method has changed, it now includes parentheses around the method parameters. The parentheses can be left out when no parameters are given. {% highlight ruby %} def say_hello_without_parameter "Hello world!" end # Both ways of calling the method will work puts say_hello_without_parameter puts say_hello_without_parameter() {% endhighlight %} Multiple method parameters can be defined. Use a comma between every parameter name. Parameters are added in order and can be referenced as such: the first value you give in will become the method's first parameter. {% highlight ruby %} def say_hello_and_hobby(your_name, your_hobby) "Hello #{your_name}! Your hobby is: #{your_hobby}" end puts say_hello_and_hobby("Your name", "tennis") # "Hello Your name! Your hobby is: tennis" puts say_hello_and_hobby("Yukihiro Matsumoto", "writing Ruby code") # "Hello Yukihiro Matsumoto! Your hobby is: writing Ruby code" {% endhighlight %} Calling the method with different method parameters changes the text that is printed. ## Classes The next step of organizing Ruby code is by using classes. By defining a class you can group several methods that relate to the same topic. We'll start with a class without methods to explain how classes work. In the example below we have a class called `Greeter`. To use this class, we can initialize it with the `new` method on the class. We tell Ruby we want to call a method on the class by using the dot notation: `object.method`. In the example below that is the method `new`. {% highlight ruby %} class Greeter end Greeter.new {% endhighlight %} Since our class doesn't do anything yet, let's add a method to it. In the example below, the `say_hello` method has been added to the class. We can tell because it's within the `class Greeter` and last `end` statement. Then, the Greeter class instance is assigned to a variable with `greeter =`. On the next line you can call the `say_hello` method on the `greeter` variable, which points to the class instance. {% highlight ruby %} class Greeter def say_hello "Hello world" end end greeter = Greeter.new puts greeter.say_hello # "Hello world" {% endhighlight %} ## Calling methods on values and variables Everything in Ruby is an object, a class or an instance of a class. That means you can call methods on those objects. The "Hello world" text is an object, the value `true` is, and even the number `10` is. Ruby has many types of objects that already have methods defined on them. In the example below you'll have Ruby calculate the number of individual characters in the text "Hello world". The result is 11. {% highlight ruby %} puts "Hello world".length # 11 {% endhighlight %} Using the dot notation you tell Ruby you want to call a method on the value, in this case `length`. It's also possible to first assign the value to a variable and then call the method on it. In this case you'll call the method `length` on the variable `text`. {% highlight ruby %} text = "Hello world" puts text.length # 11 {% endhighlight %} Some of these methods also accept parameters. In the example below you'll change the value stored on the `text` variable to output something different. For example, if you run the code below, it will replace "Hello" with "Hi there" in the `greeting` variable. {% highlight ruby %} text = "Hello your name here" puts text.sub("Hello", "Hi there") # "Hi there your name here" {% endhighlight %} Ruby has many built-in methods, making it possible to do all kinds of operations. A couple examples are shown below. {% highlight ruby %} puts "Hello world".upcase # Make all letters uppercase # HELLO WORLD puts "Hello world".reverse # Reverse the text # dlrow olleH puts "Hello world".count("l") # Count the number of occurrences of the letter "l" # 3 {% endhighlight %} ## Class instance variables Let's go back to your own Greeter class you created earlier. You previously added parameters to methods, let's add a parameter to the class now. {% highlight ruby %} greeter = Greeter.new("students") puts greeter.say_hello # Hello students! {% endhighlight %} Like the `say_hello` method, the `new` word also references a method. An object with the value `"students"` is given. This `new` method is a little different, it will eventually call the `initialize` method on the Greeter class. {% highlight ruby %} class Greeter def initialize(name) @name = name end def say_hello puts "Hello #{@name}!" end end {% endhighlight %} You'll notice something new in the example above. There are two types of variables, the `name` method parameter that becomes a variable, and the `@name` variable. The last one is called an instance variable. You can recognize it by the `@` symbol in front of it. Instance variables can be referenced all through a class where a normal variable cannot. Normal variables can only be referenced within the context of the method in which they are declared. Once declared in the `initialize` method of the Greeter class, you can reference it in the `say_hello` method later. ## Loops For the last topic we'll be briefly looking at loops. Loops are a way to run the same code for different values. Like greeting multiple people, as shown in the example below. {% highlight ruby %} names = ["students", "Rails Girls", "coaches"] names.each do |name| greeter = Greeter.new(name) puts greeter.say_hello end {% endhighlight %} The `names` list is called an Array, you can recognize them by the square brackets surrounding the several text values. Each value in the Array is separated by a comma. By calling the `each` method on the Array of names, you can perform a block of code for each value in the Array. Blocks are a common occurrence in Ruby. They can be recognized by the `do` keyword, like in `names.each do`. Block parameters look a little different, instead of parentheses, it uses what's called the pipe symbol `|`, like in `|name|`. As the block gets called multiple times, the value in the `name` variable will change with each time the loop is called. First it will be "students", then "Rails Girls" and finally "coaches". The output of this app will be: {% highlight text %} Hello students! Hello Rails Girls! Hello coaches! {% endhighlight %} ## Embedded Ruby (ERB) When writing Rails apps you'll encounter ERB (Embedded Ruby). This is a slightly different way of writing Ruby. This way of writing Ruby is embedded in HTML files. This helps make the Rails app show the content on webpages dynamically. You'll recognize it by the file extension ending with `.erb`. A full filename looks something like `index.html.erb`. In an ERB file you'll find HTML tags. You can recognize them by the lines that start with a smaller than symbol `<`, and end with a greater than symbol `>`. The letter or letters between those symbol indicate what type of element the page should render: a "p" for paragraph, an "a" for a link, an "img" for an image, an "ul" or "ol" for a list and many other types of elements. Each element has an opening tag like this: `<p>` and a closing tag with a slash symbol in it: `</p>`. You can nest these elements in on another to create webpages much like this one. {% highlight html %} <p>I am a paragraph</p> <p> <a href="https://guides.railsgirls.com/">I am a link!</a> </p> <div> <h1>I am a heading</h1> <p> I am a piece of text with <a href="https://guides.railsgirls.com/">a link</a>. </p> </div> {% endhighlight %} Where ERB comes in is to make the page show things dynamically. For example: when you enter a search phrase on Google.com, it shows different results for different phrases. That's done with some language like ERB, where ERB is one of the ways used by Ruby apps. In the example below the code will use a loop to render a list of ideas. The ERB elements can be recognized by the same HTML symbols, but they also include a percentage symbol: `<%` and `%>`. If you want to print something on the page, use the `<%=` tag opener with the percentage symbol and the equals symbol. {% highlight erb %} <% @ideas.each do |ideas| %> <p><%= item.title %></p> <% end %> {% endhighlight %} The output of which can be something like this: {% highlight html %} <p>Flying car</p> <p>Hoverboard</p> <p>Time travel</p> {% endhighlight %} A short reference of how ERB works: {% highlight erb %} # Use the <% and %> symbols for logic <% Ruby code here %> # For example an if-statement <% if a > b %> Show something if a is larger than b <% end %> # For example a loop <% @ideas.each do |ideas| %> <p><%= item.title %></p> <% end %> # Use the <%= and %> symbols for printing text on the webpage <%= variable_name %> <%= object.method_name %> <%= item.title %> {% endhighlight %} ## Next steps You've now read a short introduction to Ruby. This guide doesn't cover everything, but you should have an idea of the Ruby language syntax. Interested in learning more about Ruby and the different types of data Ruby supports? Try out Ruby on [Try Ruby](https://try.ruby-lang.org/). If you want to continue working on your app instead, follow the [main guides](/#guides). ================================================ FILE: _pages/shoulda-matchers.md ================================================ --- layout: guide title: Simplify your tests with shoulda matchers permalink: testing-shoulda-matchers --- # Simplifying your tests with Shoulda Matchers *Created by Ana Schwendler, [@anaschwendler](https://twitter.com/anaschwendler)* **This guide assumes that you have already built a Rails Girls app by** [**following the app development guide**](/app) **the RSpec tutorial by** [**this guide**](/testing-rspec) **and the Commenting tutorial by** [**this guide**](/commenting) [Shoulda Matchers](https://github.com/thoughtbot/shoulda-matchers) is a Ruby testing gem, that provides RSpec- and Minitest-compatible one-liners that test common Rails functionality. These tests would otherwise be much longer, more complex, and error-prone. {% coach %} Talk about testing and Behavior-Driven Development. {% endcoach %} ## *1.* Add Shoulda Matchers gem Open up your `Gemfile` and add this line to the `:test` group, above the end tag: {% highlight ruby %} group :test do ... gem 'shoulda-matchers' end {% endhighlight %} and run {% highlight sh %} bundle install {% endhighlight %} to install the gem. {% coach %} Talk about googling terminal output. {% endcoach %} ## *2.* Adjust your `rails_helper.rb` In our case, we will be using RSpec to test our project, so we need to say to our `rails_helper.rb` that we are using Shoulda Matchers: Place above the last end tag (check the indentation): {% highlight ruby %} Shoulda::Matchers.configure do |config| config.integrate do |with| # Choose a test framework: with.test_framework :rspec with.library :rails end end {% endhighlight %} {% coach %} Talk about why we are adjusting the gem inside `rails_helper.rb`. {% endcoach %} In your terminal run {% highlight sh %} rspec spec/models/idea_spec.rb {% endhighlight %} It should show that our test is running ok. ## *3.* Testing! It is pretty simple to test using Shoulda Matchers. For our first test we already stated that an Idea has many comments, in the [**Comments for Rails Girls App tutorial**](/commenting) To test if that is working properly, we can add the lines below to our `spec/lib/idea_spec.rb`, above the first test that we've created: {% highlight ruby %} describe "associations" do it{ is_expected.to have_many(:comments) } end {% endhighlight %} This is an association test. {% coach %} Talk about association tests. {% endcoach %} ## *4.* Test-Driven Development {% coach %} Talk about TDD, and how we start adding features to our app by testing it first. {% endcoach %} Another feature we can add to our app is to make ideas always named. How could we do that? Let's get started saying ideas should always have a name. Let's begin by creating a test for it. We can do that by adding the following lines to our `spec/lib/idea_spec.rb`: {% highlight ruby %} describe "validations" do it{ is_expected.to validate_presence_of :name } end {% endhighlight %} add it below our association test. After that, in your terminal run {% highlight sh %} rspec spec/models/idea_spec.rb {% endhighlight %} It should gives us that we are not properly validating it (and we really are not). So to validate that, we need to add the following lines to our model, so we can validate the presence of name in our Idea. {% highlight ruby %} validates :name, presence: true {% endhighlight %} add it below our has_many statement. now, back in your terminal run {% highlight sh %} rspec spec/models/idea_spec.rb {% endhighlight %} It should give the positive result. ## *5.* Do it by yourself! Can you continue this tutorial by doing a test to validate the presence of a description? Can you imagine another tests to make? Happy testing! ================================================ FILE: _pages/simple-app.md ================================================ --- layout: guide title: Simpler Rails Girls App Tutorial permalink: simpleapp --- # Rails Girls App Tutorial *Created by Vesa Vänskä, [@vesan](https://twitter.com/vesan)* *Edited to include [simple_scaffold](https://github.com/Ben-M/simple_scaffold) by Ben Maraney.* **Make sure you have Rails installed.** [**Follow the installation guide**](/install) to get set up. ### Important It is important that you select the instructions specific to your operating system - the commands you need to run on a Windows computer are slightly different to Mac or Linux. If you're having trouble check the Operating System switcher at the bottom of the commands. ## *1.* Creating the application We're going to create a new Rails app called *railsgirls*. First, let's open a terminal: * macOS: Open Spotlight, type *Terminal* and click the *Terminal* application. * Windows: Click Start and look for *Command Prompt*, then click *Command Prompt with Ruby and Rails*. * Linux (Ubuntu/Fedora): Search for *Terminal* on the dash and click *Terminal*. Next, type these commands in the terminal: <div class="os-specific"> <div class="mac nix"> {% highlight sh %} mkdir projects {% endhighlight %} <div> You can verify that a directory named <code>projects</code> was created by running the list command: <code>ls</code>. You should see the <code>projects</code> directory in the output. Now you want to change the directory you are currently in to the <code>projects</code> folder by running: </div> {% highlight sh %} cd projects {% endhighlight %} <div> You can verify you are now in an empty directory or folder by again running the <code>ls</code> command. Now you want to create a new app called <code>railsgirls</code> by running: </div> {% highlight sh %} rails new railsgirls -m https://railsgirls.com/simple_scaffold.rb {% endhighlight %} <div> <code>rails new railsgirls</code> tells Rails to generate a project called railsgirls with all the files that our application needs. </div> <div> <code>-m https://railsgirls.com/simple_scaffold.rb</code> tells Rails to download a special template from railsgirls.com which makes the files a bit simpler and easier for beginners to understand. </div> <div> This will create a new app in the folder <code>railsgirls</code>, so we again want to change the directory to be inside of our rails app by running: </div> {% highlight sh %} cd railsgirls {% endhighlight %} <div> If you run <code>ls</code> inside of the directory you should see folders such as <code>app</code> and <code>config</code>. You can then start the rails server by running: </div> {% highlight sh %} rails server {% endhighlight %} </div> <div class="win"> {% highlight sh %} mkdir projects {% endhighlight %} <div> You can verify that a directory named <code>projects</code> was created by running the list command: <code>dir</code>. You should see the <code>projects</code> directory in the output. Now you want to change the directory you are currently in to the <code>projects</code> folder by running: </div> {% highlight sh %} cd projects {% endhighlight %} <div> You can verify you are now in an empty directory or folder by again running the <code>dir</code> command. Now you want to create a new app called <code>railsgirls</code> by running: </div> {% highlight sh %} rails new railsgirls -m https://railsgirls.com/simple_scaffold.rb {% endhighlight %} <div> <code>rails new railsgirls</code> tells Rails to generate a project called railsgirls with all the files that our application needs. </div> <div> <code>-m https://railsgirls.com/simple_scaffold.rb</code> tells Rails to download a special template from railsgirls.com which makes the files a bit simpler and easier for beginners to understand. </div> <div> This will create a new app in the folder <code>railsgirls</code>, so we again want to change the directory to be inside of our rails app by running: </div> {% highlight sh %} cd railsgirls {% endhighlight %} <div> If you run <code>dir</code> inside of the directory you should see folders such as <code>app</code> and <code>config</code>. You can then start the rails server by running: </div> {% highlight sh %} ruby bin\rails server {% endhighlight %} </div> </div> **Windows users:** You may need to replace `bin\rails` with `script\rails`, depending on the version of Rails you have installed. Open <http://localhost:3000> in your browser. You should see "Welcome aboard" page, which means that the generation of your new app worked correctly. Notice in this window the command prompt is not visible because you are now in the Rails server, the command prompt looks like this: <div class="os-specific"> <div class="mac nix"> {% highlight sh %} $ {% endhighlight %} </div> <div class="win"> {% highlight sh %} > {% endhighlight %} </div> </div> When the command prompt is not visible you cannot execute new commands. If you try running `cd` or another command it will not work. To return to the normal command prompt: Hit <kbd>Ctrl</kbd>+<kbd>C</kbd> in the terminal to quit the server. {% coach %} Explain what each command does. What was generated? What does the server do? You can find more details about the special template on [GitHub](https://github.com/Ben-M/simple_scaffold). {% endcoach %} ## *2.* Create Idea scaffold We're going to use Rails' scaffold functionality to generate a starting point that allows us to list, add, remove, edit, and view things; in our case ideas. {% coach %} What is Rails scaffolding? (Explain the command, the model name and related database table, naming conventions, attributes and types, etc.) What are migrations and why do you need them? {% endcoach %} <div class="os-specific"> <div class="mac nix"> {% highlight sh %} rails generate scaffold idea name:string description:text picture:string {% endhighlight %} </div> <div class="win"> {% highlight sh %} rails generate scaffold idea name:string description:text picture:string {% endhighlight %} </div> </div> The scaffold creates new files in your project directory, but to get it to work properly we need to run a couple of other commands to update our database and restart the server. <div class="os-specific"> <div class="mac nix"> {% highlight sh %} rails db:migrate rails server {% endhighlight %} </div> <div class="win"> {% highlight sh %} rails db:migrate ruby bin\rails server {% endhighlight %} </div> </div> Open <http://localhost:3000/ideas> in your browser. Click around and test what you got by running these few command-line commands. Hit <kbd>Ctrl</kbd>+<kbd>C</kbd> to quit the server again when you've clicked around a little. ## *3.* Design {% coach %} Talk about the relationship between HTML and Rails. What part of views is HTML and what is Embedded Ruby (ERB)? What is MVC and how does this relate to it? (Models and controllers are responsible for generating the HTML views.) {% endcoach %} The app doesn't look very nice yet. Let's do something about that. We'll use the Twitter Bootstrap project to give us nicer styling really easily. Open `app/views/layouts/application.html.erb` in your text editor and above the line {% highlight erb %} <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %> {% endhighlight %} add {% highlight erb %} <link rel="stylesheet" href="//railsgirls.com/assets/bootstrap.css" /> <link rel="stylesheet" href="//railsgirls.com/assets/bootstrap-theme.css" /> {% endhighlight %} and replace {% highlight erb %} <%= yield %> {% endhighlight %} with {% highlight erb %} <div class="container"> <%= yield %> </div> {% endhighlight %} Let's also add a navigation bar and footer to the layout. In the same file, under `<body>` add {% highlight html %} <nav class="navbar navbar-default navbar-fixed-top" role="navigation"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/">The Idea app</a> </div> <div class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li class="active"><a href="/ideas">Ideas</a></li> </ul> </div> </div> </nav> {% endhighlight %} and before `</body>` add {% highlight html %} <footer> <div class="container"> Rails Girls 2013 </div> </footer> <script src="//railsgirls.com/assets/bootstrap.js"></script> {% endhighlight %} Now let's also change the styling of the ideas table. Open `app/assets/stylesheets/application.css` and at the bottom add {% highlight css %} body { padding-top: 100px; } footer { margin-top: 100px; } table, td, th { vertical-align: middle !important; border: none !important; } th { border-bottom: 1px solid #DDD !important; } {% endhighlight %} Now make sure you saved your files and refresh the browser to see what was changed. You can also change the HTML & CSS further. {% coach %} Talk a little about CSS and layouts. {% endcoach %} ## *4.* Adding picture uploads We need to install a piece of software to let us upload files in Rails. Open `Gemfile` in the project directory using your text editor and under the line {% highlight ruby %} gem 'sqlite3' {% endhighlight %} add {% highlight ruby %} gem 'carrierwave' {% endhighlight %} {% coach %} Explain what libraries are and why they are useful. Describe what open source software is. {% endcoach %} In the terminal run: {% highlight sh %} bundle {% endhighlight %} Now we can generate the code for handling uploads. In the terminal run: {% highlight sh %} rails generate uploader Picture {% endhighlight %} At this point you need to **restart the Rails server process** in the terminal. Hit <kbd>Ctrl</kbd>+<kbd>C</kbd> in the terminal to quit the server. Once it has stopped, you can press the up arrow to get to the last command entered, then hit enter to start the server again. This is needed for the app to load the added library. Open `app/models/idea.rb` and under the line {% highlight ruby %} class Idea < ApplicationRecord {% endhighlight %} add {% highlight ruby %} mount_uploader :picture, PictureUploader {% endhighlight %} Open `app/views/ideas/_form.html.erb` and change {% highlight erb %} <%= f.text_field :picture %> {% endhighlight %} to {% highlight erb %} <%= f.file_field :picture %> {% endhighlight %} Sometimes, you might get an *TypeError: can't cast ActionDispatch::Http::UploadedFile to string*. If this happens, in file `app/views/ideas/_form.html.erb` change the line {% highlight erb %} <%= form_for(@idea) do |f| %> {% endhighlight %} to {% highlight erb %} <%= form_for @idea, :html => {:multipart => true} do |f| %> {% endhighlight %} In your browser, add new idea with a picture. When you upload a picture it doesn't look nice because it only shows a path to the file, so let's fix that. Open `app/views/ideas/_idea.html.erb` and change {% highlight erb %} <%= @idea.picture %> {% endhighlight %} to {% highlight erb %} <%= image_tag(@idea.picture_url, :width => 600) if @idea.picture.present? %> {% endhighlight %} Now refresh your browser to see what changed. {% coach %} Talk a little about HTML. {% endcoach %} ## *5.* Finetune the routes If you try to open <http://localhost:3000> it still shows the "Welcome aboard" page. Let's make it redirect to the ideas page. Open `config/routes.rb` and after the first line add {% highlight ruby %} root :to => redirect('/ideas') {% endhighlight %} Test the change by opening the root path (that is, <http://localhost:3000/>) in your browser. {% coach %} Talk about routes, and include details on the order of routes and their relation to static files. {% endcoach %} **Rails 3 users:** You will need to delete the index.html from the `/public/` folder for this to work. ## Create static page in your app Lets add a static page to our app that will hold information about the author of this application — you! {% highlight sh %} rails generate controller pages info {% endhighlight %} This command will create you a new folder under `app/views` called `/pages` and under that a file called `info.html.erb` which will be your info page. It also adds a new simple route to your routes.rb. {% highlight ruby %} get "pages/info" {% endhighlight %} Now you can open the file `app/views/pages/info.html.erb` and add information about you in HTML and then take your browser to <http://localhost:3000/pages/info> to see your new info page. ## What next? * Add design using HTML & CSS * Add ratings * Use CoffeeScript (or JavaScript) to add interaction * Add picture resizing to make loading the pictures faster ## Additional Guides * Guide 0: [Handy cheatsheet for Ruby, Rails, console etc.](https://www.pragtob.info/rails-beginner-cheatsheet/) * Guide 1: [Add commenting by Janika Liiv](/commenting) * Guide 2: [Put your app online with Heroku by Terence Lee](/deployment/heroku) / [Put your app online with OpenShift by Katie Miller](/deployment/openshift) * Guide 3: [Build a map of workshop participants by Rails Girls Berlin](http://railsgirlsberlin.de/apptutorial/) * Guide 4: [Create thumbnail images for the uploads by Miha Filej](/thumbnails) * Guide 5: [Add design using HTML & CSS by Alex Liao](/design) * Guide 6: [Add Authentication (user accounts) with Devise by Piotr Steininger](/devise) * Guide 7: [Go through additional explanations for the App by Lucy Bain](https://github.com/lbain/railsgirls) ================================================ FILE: _pages/sinatra-app-tutorial.md ================================================ --- layout: guide title: Rails Girls Sinatra tutorial permalink: sinatra-app redirect_from: - sinatra-app-bg --- # Create your first voting app with Sinatra *Created by Piotr Szotkowski, [@chastell](https://twitter.com/chastell)* We will create a little voting app from scratch using a web development framework for Ruby called Sinatra, which is much like Ruby on Rails. Just another tool to get the job done really, and a fun one too! Imagine your group of friends is figuring out what to order for your weekly movie watching marathon. With the many fast food options out there, this can become quite a discussion. This is where our app comes into play! {% coach %} Explain shortly what [Sinatra](https://sinatrarb.com) is. {% endcoach %} ## Install Sinatra Remember how we needed to install Ruby on Rails? Similarly we need to install Sinatra: {% highlight sh %} gem install sinatra webrick {% endhighlight%} ### Create your first Sinatra app Create a `suffragist.rb` file with the following contents: {% highlight ruby %} require 'sinatra' get '/' do 'Hello, voter!' end {% endhighlight %} You can actually call your Ruby file whatever you'd like. `vote.rb` for instance would totally work as well, when used consistently. But [suffragist](https://www.vocabulary.com/dictionary/suffragist) actually references to a super important event in the women's rights movement, so let's just go with that for now! ### Run your app Go to the directory where you put your app and run `ruby suffragist.rb`. Now you can visit <a href="localhost:4567" target="_blank">localhost:4567</a>. You should see a 'Hello, voter!' page, which means that the generation of your new app worked correctly. Hit <kbd>Ctrl</kbd>+<kbd>C</kbd> in the terminal to shut down the server. If <kbd>Ctrl</kbd>+<kbd>C</kbd> does not work for you it means you are probably Windows user and <kbd>Ctrl</kbd>+<kbd>Z</kbd> / <kbd>Ctrl</kbd>+<kbd>Pause</kbd> / <kbd>Ctrl</kbd>+<kbd>Break</kbd> will fix the issue. {% coach %} Explain POST and GET methods, and how to communicate with the browser. {% endcoach %} ### Add the index view To keep everything in order let's make a directory for our views (and name it `views`). Put this code into an `index.erb` file in the `views` directory: {% highlight erb %} <!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Suffragist

What's for dinner?

<% Choices.each do |id, text| %>
<% end %>
{% endhighlight %} And into `suffragist.rb`: {% highlight ruby %} Choices = { 'HAM' => 'Hamburger', 'PIZ' => 'Pizza', 'CUR' => 'Curry', 'NOO' => 'Noodles', } {% endhighlight %} Change the `get` action: {% highlight ruby %} get '/' do erb :index end {% endhighlight %} Run `ruby suffragist.rb`, check your results and shut down the server with Ctrl+C. {% coach %} Talk a little about HTML and erb. Explain templates. Explain what global constants are. {% endcoach %} ### Templates Adjust the `index.erb` file in the `views` directory and add the `

` line: {% highlight erb %}

<%= @title %>

What's for dinner?

{% endhighlight %} Change the `get` action: {% highlight ruby %} get '/' do @title = 'Welcome to the Suffragist!' erb :index end {% endhighlight %} {% coach %} Explain what instance variables are and how Sinatra makes them visible in the views. {% endcoach %} ### Add the ability to POST results Put this into `suffragist.rb`: {% highlight ruby %} post '/cast' do @title = 'Thanks for casting your vote!' @vote = params['vote'] erb :cast end {% endhighlight %} Create a new file in the `views` directory, `cast.erb`, and put there some HTML with embedded Ruby code: {% highlight erb %} Suffragist

<%= @title %>

You cast: <%= Choices[@vote] %>

See the results!

{% endhighlight %} {% coach %} Explain how POST works. How to catch what was sent in the form? Where do `params` come from? {% endcoach %} ### Factor out a common layout Create a `layout.erb` file in the `views` directory. Put the following in there: {% highlight erb %} Suffragist

<%= @title %>

<%= yield %>
{% endhighlight %} Remove the above part from the other two templates (`index.erb` and `cast.erb` in the `views` directory). {% coach %} Talk about the structure of HTML documents and how factoring out common code work in general. Explain what `yield` does. {% endcoach %} ### Add the results route and the results view Paste the following code into `suffragist.rb`: {% highlight ruby %} get '/results' do @votes = { 'HAM' => 7, 'PIZ' => 5, 'CUR' => 3 } erb :results end {% endhighlight %} Create a new file in the `views` directory, called `results.erb`. {% highlight erb %}
<% Choices.each do |id, text| %> <% end %>
<%= text %> <%= @votes[id] || 0 %> <%= '#' * (@votes[id] || 0) %>

Cast more votes!

{% endhighlight %} Run `ruby suffragist.rb`, check your results and shut down the server with Ctrl+C. {% coach %} Explain HTML tables and how the missing values from the hash default to zero. {% endcoach %} ### Persist the results using YAML::Store Time for something new! Let's store our choices. Add the following to the top of `suffragist.rb`: {% highlight ruby %} require 'yaml/store' {% endhighlight %} Add some more code into `suffragist.rb` – replace `post '/cast'` and `get '/results'` with the following: {% highlight ruby %} post '/cast' do @title = 'Thanks for casting your vote!' @vote = params['vote'] @store = YAML::Store.new 'votes.yaml' @store.transaction do @store['votes'] ||= {} @store['votes'][@vote] ||= 0 @store['votes'][@vote] += 1 end erb :cast end get '/results' do @title = 'Results so far:' @store = YAML::Store.new 'votes.yaml' @votes = @store.transaction { @store['votes'] } erb :results end {% endhighlight %} {% coach %} Explain what YAML is. {% endcoach %} ### See how the YAML file changes when votes are cast Let's open `votes.yaml`. And vote. And check again. {% coach %} There will be situations when one or more students will forget to shut down the server before running it again. It's a good opportunity to search the Internet for a solution. They don't have to know everything about killing processes to find a solution. {% endcoach %} {% coach %} In the end explain shortly the differences between Sinatra and Rails. {% endcoach %} ## Play with the app Try to change things in the app in any way you see fit: * Add some additional logic to the views. * Redirect to the results outright. * Add other votings; how would the YAML file need to change? * Sort the results by the number of votes. * Try to style the file in different ways. ================================================ FILE: _pages/sinatra-html.md ================================================ --- layout: guide title: Coffee List Display permalink: sinatra-html --- # Coffee List Display *Created by Tim McEwan, [@tjmcewan](https://twitter.com/tjmcewan)* Using `.inspect` works for debugging, but we don’t want to use it in production. For one thing, it’s really hard to style the output. Let’s wrap our coffee list in proper HTML. ## *1.* Setup First let’s make a method that will return our coffees wrapped in HTML tags. We’ll name the method `coffees_html`, so that what it does is reasonably obvious. Define it like so: {% highlight ruby %} def coffees_html # Build HTML here end {% endhighlight %} And in your template method change your `#{ $coffees.inspect }` line to call our new method: {% highlight ruby %} #{ coffees_html } {% endhighlight %} ## *2.* Add some HTML Write something to turn the `$coffees` global variable into HTML that looks like this: {% highlight HTML %}
Flat White $3.50

Cappuccino $2.50
{% endhighlight %} **Hint:** Remember, the `$coffees` variable is an array of hashes. We’ll want to loop over the `$coffees` array and turn each hash into an HTML string, surrounded by `
`s, which should then be all joined together with `
`s. We’ll also need to ensure we’re returning a string. For some solution ideas, [check this out](https://tjmcewan.github.io/coffeecalc/snippets/coffees_html.rb.txt). ================================================ FILE: _pages/sinatra.md ================================================ --- layout: guide title: Web Fundamentals Tutorial permalink: sinatra --- # Web Fundamentals Tutorial *Created by Tim McEwan, [@tjmcewan](https://twitter.com/tjmcewan)* ## Goal Have you ever thought about how information gets to and from your web browser? In this tutorial we're going to look at how it all works by exploring HTTP. We're going to use [**Sinatra**](https://sinatrarb.com/) as a tool to demonstrate some basic web principles. Sinatra is a small framework for creating web applications in Ruby with minimal effort. You can find a list of [things built with Sinatra here](https://sinatrarb.com/wild.html). Sinatra is different from Rails. They're both frameworks for helping you to write web apps, but Sinatra contains fewer features and less magic. ## Introduction HTTP is used to send information between an application (like your Rails Girls app) and a browser. The basis of communication with HTTP is a request/response pair. Requests are sent by the browser to the server (e.g. your app) and the response is sent back from the server to your browser for a user to view. To make a request in a browser, you need to use a URL. A URL contains a lot of information about what information you are requesting so that the server can send you the correct response. A URL will contain; * The protocol you will communicate with * The domain that has the information you want * The path to the resource on that server * Optionally there might be parameters on the end of the url, as key/value pairs, containing extra information about the request * The // towards the beginning of the URL specifies that this request wants to make contact with a server. * The ? towards the end of the url signals the end of the file path, and the beginning of any optional parameters. Breakdown of a URL URLs reveal the resource you want, but the action that needs to be performed on that resource needs to be specified using HTTP verbs. The most common HTTP verbs are * GET: fetch an existing resource * POST: create a new resource. (Usually includes data needed to create the new resource) * PUT: update an existing resource. * DELETE: delete an existing resource. You would have used all these verbs on your Rails Girls app when you enabled it to show, create, edit and delete posts or notes. A request to a server needs to include both a URL and HTTP verb. In the following exercises you will build a small coffee listing application that uses a combination of resource folder names and HTTP verbs to show how browsers communicate with your application. Your app will look something like this in the browser: Sinatra Coffee App ## *0.* Install Sinatra - "Hello World" Let's start off by getting Sinatra running. In your terminal, install the gem: {% highlight sh %} gem install sinatra gem install sinatra-contrib {% endhighlight %} ## *1.* "Hello World" Create a file called `app.rb` and paste the following into your Text Editor: {% highlight ruby %} require "sinatra" require "sinatra/reloader" get "/" do "Hello world!" end {% endhighlight %} And back in your terminal, run this code with: {% highlight sh %} ruby app.rb {% endhighlight %} View your current site at: The information showing now in your browser is the response to a GET request. When you enter http://localhost:4567 you're sending a GET request to your Sinatra server. What you see in the browser is the response from your Sinatra server. Where you've written "/", you are just specifying the root url, but you can create any path name you want. In the same file, try creating more pages to visit, using the same syntax as the block above. You can add as many pages as you like, and have them say whatever you want. e.g. {% highlight sh %} get "/page-name" do "This is text on the page" end {% endhighlight %} If you need to you can hit Ctrl+C in your command prompt to stop your app. (Just like for your Rails app!), however you don't need to stop and start to see your changes. If you get stuck, make sure your app.rb looks like [this app.rb example](https://tjmcewan.github.io/coffeecalc/snippets/install_sinatra.rb.txt). ## *3.* HTML Form - Get Parameters To start listing coffees in our app, we'll need an HTML form to send through which coffee we want and how much it costs. This means sending a request to the Sinatra server, including some information. To send information to the server, we can use a form. Replace your `get "/"` from above with this: {% highlight ruby %} get "/" do "
What: Cost:
" end {% endhighlight %} For simplicity, this form sends the information to the same URL ("/"). Refresh your browser and you should see the form you just created. Now let's see what the browser sends to the server when you submit the form. Put some text into the form and click the 'add coffee' button. Check out your Sinatra logs back in your terminal and you should see something like this: {% highlight HTTP %} GET /?what=flat+white&cost=3.50 HTTP/1.1 {% endhighlight %} {% coach %} Talk about where the parameter names come from and what the question mark is doing. {% endcoach %} If it's not quite working, make sure your code looks like [this `html_form.rb` example](https://tjmcewan.github.io/coffeecalc/snippets/html_form.rb.txt). ## *4.* Web Inspector - Request Headers In your browser, open up your web console. (For most browsers, this can be accessed by *right clicking something on the page and choosing "Inspect Element"*.) I recommend you use Chrome for this; if you are using Chrome, you're looking for the 'Network' tab. Refresh your browser, then click on the 'localhost' line in the web inspector, then in the Headers tab, click 'view source'. You should see something similar to this: {% highlight HTTP %} GET / HTTP/1.1 Host: localhost:4567 Connection: keep-alive Cache-Control: max-age=0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.70 Safari/537.36 Accept-Encoding: gzip,deflate,sdch Accept-Language: en-US,en;q=0.8 {% endhighlight %} {% coach %} Explain what HTTP headers are and they mean. {% endcoach %} The important part to note is the first line, which shows you the HTTP verb and the URL it was called on. **Note:** If Sinatra says it has "backup from WEBrick", Ruby's built-in webserver, then you may see multiple GET requests each time you refresh. Only one request is actually being issued, you can safely ignore the other. ## *5.* Global Variable So our form is sending the coffee information to our app, but we're not doing anything with it yet. We should save the coffee information after it is sent to the server. For simplicity, let's just store the coffee details in a variable. So that they'll be available between requests, we'll need to use a [**global variable**](https://en.wikipedia.org/wiki/Global_variable). This is a drastically simplified version of what Rails calls the Model layer. Add this to your `app.rb` somewhere (convention says it should be near the top, under the `require` lines): {% highlight ruby %} $coffees = [] {% endhighlight %} This creates an empty array when your app first starts up. **Hint:** This global variable won't be around for very long - it will be reset to the empty array each time the server restarts. Because we're using Sinatra's reloader, this will be every time you save your `app.rb` file. Don't worry though, it will suit our purposes nicely. ## *6.* Receiving information - Storing Coffees Now you'll need to get the information into that `$coffees` array when the request is received. When you fill in your form and click the submit button, remember that your information is put on the end of the URL, after the ?, to be sent back to the server. Sinatra grabs that information from the end of the URL and makes it available as a Hash called `params`. For example: {% highlight ruby %} params = {coffee = 'flat white', value ='2'} {% endhighlight %} You will need to write some code to take them from the params hash and add them to your $coffees variable. Before you start, first replace `` in your form with: {% highlight ruby %} #{ $coffees.inspect } {% endhighlight %} This will display the `$coffees` variable in the HTML in your browser so we can tell if coffees are being added to your $coffees variable (i.e. that your code is working). **Hint:** Your global variable is an array, so if you get stuck, try [Ruby's Array documentation](https://ruby-doc.org/3.2.0/Array.html#method-i-3C-3C) to find out how you can add information to an array. If you're still stuck, [check here](https://tjmcewan.github.io/coffeecalc/snippets/store_coffees.rb.txt). If you're storing your params correctly, you should be able to refresh the browser and see that a new hash gets added to the `$coffees` array each time. ## *7.* Tidy Up That big chunk of HTML in our `get` code is making it a bit hard to see what our app does. Let's move it to its own method. Cut the HTML form out of your `get` code and paste it into a method called `template` (keep all your code in the same file). Like so: {% highlight ruby %} def template # put your HTML form string here end {% endhighlight %} Now replace the form from your `get` code with a simple call to the template method, like this: {% highlight ruby %} get "/" do $coffees << params template end {% endhighlight %} This will also make it easier to re-use the form, should we ever need to. **Hint:** [Check here](https://tjmcewan.github.io/coffeecalc/snippets/template_method.rb.txt) if something went awry. ## *8.* Moving Beyond GET As you saw in the store coffees section, if you refresh your browser, your app adds the information into the `$coffees` global variable repeatedly. This is because we're storing the params from the URL each time our `get` code is requested. This is a good point to mention that `GET` requests should not do things that add information to our app - while it does work, like in this instance, it's too easy for unintended side-effects to occur. In this case it's better to use a `POST` request. Remember `GET` requests are asking to fetch a resource, whereas POST requests are asking to create a resource. So armed with that knowledge, let's change our form's method to `POST`: * Locate the section in the form that specifies the method as `get` and change it to `post`. * Now refresh your browser and submit a new coffee. **Uh oh!** Welcome to Sinatra's lovely error page, if you haven't encountered it yet today. The message at the bottom should say this: {% highlight ruby %} Try this: post '/' do "Hello World" end {% endhighlight %} This is Sinatra's way of telling you that the route you requested doesn't exist. You may also know this as HTTP error number 404: *page not found*. ## *9.* Add Post Let's *add* our `post` code into Sinatra (don't remove the get one!): * Grab the "Hello world" `post` code from Sinatra's 404 page and put it after our `get`. (**Hint:** Do not copy from above; this page uses smart quotes & will break your code.) * Replace the "Hello world" with a call to our `template` method. (**Hint:** Don't remove the call to `template` from our `get` code.) * Now *move* the line that stores the coffee params over from the `get` code (ensure this goes *above* the call to `template`). As usual, you can check your progress [over here](https://tjmcewan.github.io/coffeecalc/snippets/get_vs_post.rb.txt). Now if you refresh the page after submitting a coffee, you should see a warning from your browser that it needs to resubmit the form in order to load the page: Chrome's confirm resubmission dialog You might have seen this sometimes when you've submitted forms online. Having this warning prompts us to think about the consequences of our refresh and we will probably avoid inadvertently adding the same coffee multiple times. Remember GET requests are asking to fetch a resource, whereas POST requests are asking to create a resource. If you refresh a page on a GET request, you are simply asking repeatedly to see the same page, which usually won't be a problem. However, if you refresh a page on a POST request, this means you are resending the POST request, and could be creating a new resource each time you refresh. That's why the browser gives you a warning before allowing you to do it. ## *10.* Add a Redirect In order to get around this form-resubmission problem, lets tell the browser to load a different page as soon as it receives the response to our `POST`. We do this using a special HTTP response known as a "redirect". Instead of the call to our `template` method, we can redirect the browser to another location. In Sinatra, it looks like this: {% highlight ruby %} redirect "/" {% endhighlight %} Try first, then [check it here](https://tjmcewan.github.io/coffeecalc/snippets/post_redirect.rb.txt). This sends back a special redirect response (HTTP 303) with a `location` header that specifies where the browser should go: {% highlight HTML %} HTTP/1.1 303 See Other <…> Location: http://localhost:4567/ {% endhighlight %} To see this in action, have a look in Chrome's Web Inspector (Network tab) and send your app a coffee: Chrome's network tab showing a post/redirect/get The first line shows the browser submitting the form via the `POST` request method. The response it receives is an HTTP 303, containing the `Location` header. It then issues a `GET` request for that location (which corresponds to our root URL, "/") and renders the response it gets from there - which is our HTML template. Now you can refresh all you want and all you're doing is requesting using `GET`, not `POST`. Your browser doesn't have to submit the form any more to display that page. This is the end of the tutorial - you've done an excellent job! Thanks for playing! ## Additional Guides If you were fast and would like to continue on, you can try: * [Rendering our coffee list in proper HTML](/sinatra-html) **LUCY-TODO** ================================================ FILE: _pages/start.md ================================================ --- layout: main_guide title: Start of the guide description: "Start your journey to building your first Ruby on Rails app here!" permalink: start --- # Start of the guide Welcome to the Rails Girls guides! In these guides you'll learn how to make an app using the Ruby on Rails framework (which is why this event is called _Rails_ Girls). When you have made your first app, you'll deploy it to a hosting service so that you can view it on the Internet and share it with others. Please follow the numbered guides in order. Each guide assumes you followed the previous guide. When you're done with the workshop and/or completed all the numbered guides, feel free to explore the [other guides](/#other-guides) as well. Ask you coach for suggestions! The first guides help you get set up with the tools you'll need and installing Rails on your machine. Use the __Guides__ list lower on this page to navigate your way to the next guide. ================================================ FILE: _pages/test-driven-development.md ================================================ --- layout: guide title: Test Driven Development permalink: test-driven-development --- # Test Driven Development *Written by Gregory McIntyre, [@gregmcintyre](https://twitter.com/gregmcintyre)* This exercise is intended to teach you what we're talking about when we say *Test Driven Development* (TDD). ## Background information **Roman Numerals** If you are not already familiar with Roman numerals, please read up on [how Roman numerals work][Roman numerals] before continuing. In summary, here are some examples of how Roman people wrote numbers:
Hindu-Arabic Roman
1 I
4 IIII (or IV)
5 V
6 VI
7 VII
9 VIIII (or IX)
10 X
50 L
100 C
500 D
1000 M
We are going to write a program that takes an integer value in the left column and calculates the equivalent string value in the right column. If we finish that, we will then make it work with the *subtractive digits* like *IV*. **Guide for working in a group** We encourage doing this exercise in a group of 2-4 people. The rules that govern how this works are very similar to how programmers do *pair programming* and this exercise is also intended to give you some exposure to that practice also. - Each group has one **hot seat** with laptop and *Sublime Text* ready. - Everybody else should **close their laptops** and sit around the hot seat chair. - You will all regularly stand up and **rotates chairs** so the next person is in the hot seat. The steps below explain when to do that. - Pick somebody to start in the hot seat. That person should follow all the steps until swapping seats is mentioned. {% coach %} Explain how pair programming can be useful. {% endcoach %} ## *1.* Initial code Copy this code into a file called `roman.rb`: {% highlight ruby %} def roman(n) return "?" end require "minitest/spec" require "minitest/autorun" describe "roman" do it "converts the number 1 to the string I" do roman(1).must_equal "I" end end {% endhighlight %} **Run your tests** Run the command following into the terminal: {% highlight sh %} ruby roman.rb {% endhighlight %} **Output** You should see the following output from the tests: {% highlight sh %} roman#test_0001_converts the number 1 to the string I [tdd1.rb:11]: Expected: "I" Actual: "?" 1 tests, 1 assertions, 1 failures, 0 errors, 0 skips {% endhighlight %} Take a moment to read this output carefully. It is quite a mouthful. Your tests are now **red**. i.e. One or more of the tests are failing. You can tell you have a failing test by checking the summary at the end: `1 tests, 1 assertions, 1 failures, 0 errors, 0 skips`. **Stand up** and give the hot seat to the next person. {% coach %} Explain how TDD can be useful. {% endcoach %} ## *2.* Make the tests pass It is time to make the test pass. Do this however you see fit. It's fine if the change is just an extra `if` statement or one extra character. In fact, that is encouraged: you generally shouldn't write unnecessary code. If you're stuck, you can ask the people around you for their opinions. Here is a way that you could make the first test pass, just to get you into the swing of things: {% highlight ruby %} def roman(n) return "I" end {% endhighlight %} If this seems facetious, you're right but it is a valid solution because it makes all the tests pass. When your tests all pass, we call them **green**. ## *3.* Refactor your code Look over the code and decide if it's a good idea to **refactor** it (clean up the code and make it easier to read). If you decide to not to refactor, skip this step. **Hint**: It's a good time to refactor when you notice *repetition*. If you like, you can also refactor the tests. Run your tests after refactoring. If they fail, you accidentally broke something. {% coach %} Explain how focusing on something small enough to test can be useful. {% endcoach %} ## *4.* Write a new failing test If you all agree that the code should work in general, and you can't think of any more cases to test and everything passes, you can stop here. You win! Otherwise, your last job in the hot seat is to write a new test. We currently have a test that checks that the number one is turned into an `"I"`, but we need more tests to verify that all other numbers convert as expected. When you add a new test for another number, be sure to run the tests to find your test fail. If you're stuck, there are some suggestions at the bottom of this page. You can copy and paste the previous test and alter it. You can change it to be anything you like. Your tests should probably test the next trickiest situation, but if you feel like going back and adding a simpler case, that's fine too as long as it fails. The other members of the group can chime in and ask questions or spot problems for you. Here is an example of an expanded test suite: {% highlight ruby %} describe "roman" do it "converts the number 1 to the string I" do roman(1).must_equal "I" end it "converts the number 2 to the string II" do roman(2).must_equal "II" end end {% endhighlight %} Your tests are now **red** again; at least one is failing. **Stand up** and offer the hot seat to the next person in your group. ## Repeat! Keep repeating steps 2 through 4, making sure to continue switching at the end of step 4. You are done when your team feels like they are done. Don't worry about finishing all cases. The goal is to practice the steps and learn to work together in this way. Get used to writing tests as well as getting them to pass. Practice. Good luck! ## Hints If you are stuck for ideas, here is a list of Roman numerals to write tests for, in this order. Note the way that the build up incrementally in complexity. :--------- | :----------- Input | Output :--------- | :----------- `1` | `"I"` `5` | `"V"` `4` | `"IIII"` `6` | `"VI"` `7` | `"VII"` `10` | `"X"` If you get this far, you earn partial credit. Romans used to use `IIII` for 4. That's why 4 on an analog watch is written as `IIII`. Later on, they added *subtractive* digits. These are harder to program. Once you feel confident that your program works with all the numbers above, try dealing with subtractive digits. :--------- | :----------- Input | Output :--------- | :----------- `4` | `"IV"` `14` | `"XIV"` `2896` | `"MMDCCCXCVI"` [Roman numerals]: https://www.onlineconversion.com/roman_numerals_advanced.htm ================================================ FILE: _pages/testing-rspec.md ================================================ --- layout: main_guide title: Test your app with RSpec description: "Make sure your app doesn't accidentally break by testing it using RSpec." permalink: testing-rspec --- # Test your app with RSpec *Originally created by Clemens Helm, [@clemenshelm](https://twitter.com/clemenshelm) and Floor Drees, [@floordrees](https://twitter.com/floordrees). Updated by Ana Schwendler, [@anaschwendler](https://twitter.com/anaschwendler)* {% include main-guide-intro.html %} [RSpec](https://rspec.info/) is a Ruby testing framework, that describes our application's behavior in a syntax that doesn't look much like Ruby. It outputs test results in your terminal, so you'll test your reading skills as well (pun intended). {% coach %} Talk about testing and Behavior-Driven Development. {% endcoach %} ## *1.* Add the RSpec gem Open up your `Gemfile` and add this line to the `:development` and `:test` groups, above the end tag: {% highlight ruby %} group :development, :test do ... gem "rspec-rails" end {% endhighlight %} and run the following command to install the Ruby gem. {% highlight sh %} bundle install {% endhighlight %} Then run the following command, in order to setup RSpec in your app: {% highlight sh %} rails generate rspec:install {% endhighlight %} This adds the following files which are used for configuration: - `.rspec` - `spec/spec_helper.rb` - `spec/rails_helper.rb` ## *2.* Create your first test! Rubyists often use the words 'test' and 'specification' interchangeably, that's why you'll store your tests in the 'spec' directory. To do that, do the following steps: We will be creating a test for our `Idea` model. Create a `models` directory in your `spec` directory. Then create a new file called `idea_spec.rb` (`_spec.rb`) in that directory. Inside the new test file, we will want to make sure our idea has a name. In order to do that let's describe one of our specifications: {% highlight ruby %} require "rails_helper" RSpec.describe Idea do it "has a name" do skip end end {% endhighlight %} In the Terminal app run: {% highlight sh %} rspec spec/models/idea_spec.rb {% endhighlight %} which will output that your test is "pending" as it's not yet implemented. Let's add something to our test to make sure the idea has a name! {% highlight ruby %} require "rails_helper" RSpec.describe Idea do it "has a name" do # yep, you can totally use 'it' idea = Idea.create!(name: "My Awesome Idea Name") # creating a new idea 'instance' expect(idea.name).to eq("My Awesome Idea Name") # this is our expectation end end {% endhighlight %} Run RSpec again, and you should see more satisfying green output this time, meaning all tests passed. {% highlight sh %} rspec spec/models/idea_spec.rb {% endhighlight %} ## *3.* Make to-do's with tests Yeah! Let's create to-do lists. Awesome! A nifty RSpec feature is the functionality to mark certain tests as pending like we saw before. In other words, first you think about what your models should do, before writing the implementation and the test. You have an idea of what your model should do beforehand, and then you can write the code and tests for it. Let's create our next test, by adding the lines below to our `idea_spec.rb` it will add another test and mark it as pending. {% highlight ruby %} it "has a description" {% endhighlight %} Can you finish this test? Can you think about other tests? Consult the [RSpec documentation](https://rspec.info/documentation/), or search for an RSpec tutorial online, to find out what kind of tests you can make. ## *4.* Add more tests We have our first test, we test if our idea has a name, but our idea can hold many more things. Let's test if it has comments or not. {% highlight ruby %} require "rails_helper" RSpec.describe Idea do # Your other tests here... it "has comments" do idea = Idea.create!(name: "My Awesome Idea Name") comment = Comment.create!( user_name: "My name", body: "My helpful comment", idea: idea # Link the comment to the idea ) expect(comment.idea).to eq(idea) end end {% endhighlight %} ## *5.* Behavior-Driven Development {% coach %} Talk a bit about Behavior-Driven Development. {% endcoach %} By now you can create more tests alone. Feel free to talk to your coach to do that, or ways to create more tests. Happy testing! ================================================ FILE: _pages/thumbnails.md ================================================ --- layout: main_guide title: Create picture thumbnails description: "Optimize image uploads by creating thumbnails: smaller versions of the original file uploads." permalink: thumbnails --- # Create picture thumbnails *Originally created by Miha Filej, [@mfilej](https://twitter.com/mfilej)* {% include main-guide-intro.html %} The Internet is all about speed. The faster your page loads, the less likely people are to click away. And we want people to stick around to share our great ideas with our ideas app! Also, people with data plans visiting your website will thank you for requiring less data to be transmitted. One way to speed up page loads is by displaying images in a smaller size. The smaller an image is, the fast it will be transmitted over the Internet. ## Install ImageMagick We'll be using the ImageMagick tool to resize the pictures uploaded to your ideas.

Run the following command in the Terminal app:

{% highlight sh %} brew install imagemagick {% endhighlight %}

If you are on Ubuntu, run the following command in the Terminal app:

{% highlight sh %} sudo apt-get update sudo apt-get install -y imagemagick {% endhighlight %}

Download and run the ImageMagick installer (use the first download link). In the installation wizard, make sure you check the checkbox to install legacy utilities.

{% coach %} Explain what is ImageMagick and how is it different from libraries/gems we used before? {% endcoach %} ## Install a Ruby gem for ImageMagick For Ruby to talk with ImageMagick, we'll be using the `mini_magick` Ruby gem. First we will need to add it to our app and install it. Open `Gemfile` in your Text Editor and add this line: {% highlight ruby %} gem "mini_magick" {% endhighlight %} below the line: {% highlight ruby %} gem "carrierwave" {% endhighlight %} In the Terminal app run this command: {% highlight sh %} bundle install {% endhighlight %} Make sure to (re)start your Rails server after installation. ## Tell your app to create thumbnails Now that we have a way to talk to ImageMagick through the `mini_magick` Ruby gem, we can tell the file upload gem `carrierwave` to create thumbnails for every picture you upload. Open `app/uploaders/picture_uploader.rb` and find the line that looks like this: {% highlight ruby %} # include CarrierWave::MiniMagick {% endhighlight %} Remove the `#` sign at the front of the line. {% coach %} Explain the concept of comments in code. {% endcoach %} Below the line you just changed, add these lines: {% highlight ruby %} version :thumb do process :resize_to_fit => [150, 150] end {% endhighlight %} The images uploaded from now on will be resized to a smaller size, but the ones we already have haven't been updated. Instead, let's edit an idea and add a new picture. When saved the idea now has a thumbnail for the uploaded picture. ## Display the thumbnail We haven't changed how the idea pictures are displayed, so it should still be showing the original larger image. Let's change the views to display the thumbnail instead. Open `app/views/ideas/_idea.html.erb` and change the line: {% highlight erb %} <%= image_tag(idea.picture_url, width: 150, height: 150, class: "img-thumbnail flex-shrink-0") if idea.picture? %> {% endhighlight %} to this line: {% highlight erb %} <%= image_tag(idea.picture_url(:thumb), width: 150, height: 150, class: "img-thumbnail flex-shrink-0") if idea.picture? %> {% endhighlight %} Take a look at the [list of ideas](http://localhost:3000/ideas) in the Browser to see if your ideas now have a thumbnail. {% coach %} Explain what specifying the image width in HTML and how it differs from resizing images on the server. Both images may look small, but only one is resized as a thumbnail. {% endcoach %} ================================================ FILE: _pages/tools.md ================================================ --- layout: main_guide title: Get to know the tools description: "Install the required tools to make your first Ruby on Rails app. A Text Editor, find the Terminal app and launch a web Browser." permalink: tools --- # Get to know the tools {% include main-guide-intro.html %} Start by getting familiar with the tools you'll be using in this workshop. Please install the tools you do not have yet installed and move on to the next guide. ## Instructions per Operating System Before we get started, it is important that you select the instructions specific to your Operating System. This website should detect it automatically, but if you're unsure, ask your coach. We have detected you're using: Error: JavaScript not loaded. It should already be selected as the Operating System in the "Choose your Operating System:" element below here. No need to change it if it's correct.
This step is important, because the commands you need to run on a Windows computer are different from Mac or Linux. The instructions for Windows will not work on Mac and vice versa. If you're using a cloud service to build your app (like Replit), you'll need to run the Linux commands even if you are on a Windows computer. ## Text Editor {#text-editor} To create your app you'll need to write code. This can be done with a Text Editor made for writing code. Listed below are examples of text editors you can use for writing code and editing files. We recommend Visual Studio Code as it's a very complete package that works out of the box. Choose an editor, go to the website linked below and install it following the instructions on the website. * [Visual Studio Code](https://code.visualstudio.com) (Recommended) * [Sublime Text](https://www.sublimetext.com) ## Terminal {#terminal} The Terminal is a tool to run commands on your system for applications that do not have a Graphical User Interface (GUI), like many of the tools we'll be using today. The Terminal is also known as PowerShell or Command Prompt on Microsoft Windows, we'll be referring to this as the Terminal throughout these guides. In the Terminal app you'll do things like: * Install the required tools (Ruby, databases, and others); * Start your Rails app; * Run database migrations; * etc. Open the Terminal like so for your Operating System:
  • Open Spotlight:
    • Click the Magnifying glass icon in the menu bar at the uppermost top right of your screen, or;
    • Press command + space bar (The command key can be recognized by the symbol).
  • Type in "Terminal" or "iTerm".
  • Press Enter to open the Terminal app.
  • Open the "Start" menu by:
    • Clicking on the Windows icon in the bottom left, or;
    • press the Window flag key on the keyboard.
  • Type in "PowerShell" or "Command Prompt", whichever is available.
  • Press Enter to open the Terminal app.

Please consult your Linux distribution's documentation about how to open apps, and open the Terminal app.

If the options above are not available, press the Window flag key + R, type in `cmd` and press Enter to open the Command Prompt Terminal app. ## Code examples Throughout this guide you will see bits of text formatted like the block below. The icon next to the text will let you know which tool to use. The text in the block below is a terminal command. This can be recognized by the Terminal icon on its left side. It needs to be run in the Terminal. Copy it from the page, paste it in the Terminal app and press the Enter key. {% highlight sh %} Some terminal command example {% endhighlight %} The text in the block below is source code. This can be recognized by the Text Editor icon on its left side. It needs to be inserted into one of your project files. {% highlight erb %} Some source code example {% endhighlight %} ## Web browser {#web-browser} You should already have a webbrowser installed. It's what you use to view this page on your laptop. You should not have to install any of these, one should already be installed, but just so you know what they're named. - Edge (this is preinstalled on Microsoft Windows laptops) - Safari (this is preinstalled on macOS laptops) - Alternatives you may be using instead: - [Google Chrome](https://www.google.com/chrome/index.html) - [Firefox](https://www.mozilla.org/firefox/) --- You should now have a Text Editor installed, you know where to find the Terminal and you have your browser open. On to the next guide to [install Rails](/install)! ================================================ FILE: _pages/touristic-autism_basic-app.md ================================================ --- layout: guide title: Touristic Autism-friendly Spots App permalink: touristic-autism_basic-app --- # Basic Web Application *Created by Myriam Leggieri, [@iammyr](https://twitter.com/iammyr)* *for [Rails Girls Galway](https://github.com/RailsGirlsGalway)* The basic guides that have been merged and adapted are the [Ruby on Rails Tutorial](https://www.railstutorial.org/book), the [basic RailsGirls app](/app) and the tutorials for [creating thumbnails](/thumbnails), [authenticating users](/devise), [adding design](/design), [deploying to OpenShift](/deployment/openshift) and [adding comments](/commenting).

GitHub

[Slides - by Kevin Lyda @]() ### Important It is important that you select the instructions specific to your operating system - the commands you need to run on a Windows computer are slightly different to Mac or Linux. If you're having trouble check the Operating System switcher at the bottom of the commands. ## *1.* Creating the application We're going to create a new Rails app called *railsgirls-galway-2014*. First, let's open a terminal: * macOS: Open Spotlight, type *Terminal* and click the *Terminal* application. * Windows: Click Start and look for *Command Prompt*, then click *Command Prompt with Ruby and Rails*. * Linux (Ubuntu/Fedora): Search for *Terminal* on the dash and click *Terminal*. Next, type these commands in the terminal:
{% highlight sh %} mkdir projects {% endhighlight %}

You can verify that a directory named projects was created by running the list command: ls. You should see the projects directory in the output. Now you want to change the directory you are currently in to the projects folder by running:

{% highlight sh %} cd projects {% endhighlight %}

You can verify you are now in an empty directory or folder by again running the ls command. Now you want to create a new app called railsgirls by running:

{% highlight sh %} rails new railsgirls-galway-2014 {% endhighlight %}

This will create a new app in the folder railsgirls, so we again want to change the directory to be inside of our rails app by running:

{% highlight sh %} rvm rubygems latest cd railsgirls-galway-2014 {% endhighlight %}

If you run ls inside of the directory you should see folders such as app and config. You can then start the rails server by running:

{% highlight sh %} rails server {% endhighlight %}
{% highlight sh %} mkdir projects {% endhighlight %}

You can verify that a directory named projects was created by running the list command: dir. You should see the projects directory in the output. Now you want to change the directory you are currently in to the projects folder by running:

{% highlight sh %} cd projects {% endhighlight %}

You can verify you are now in an empty directory or folder by again running the dir command. Now you want to create a new app called railsgirls by running:

{% highlight sh %} rails new railsgirls-galway-2014 {% endhighlight %}

This will create a new app in the folder railsgirls, so we again want to change the directory to be inside of our rails app by running:

{% highlight sh %} cd railsgirls {% endhighlight %}

If you run dir inside of the directory you should see folders such as app and config. You can then start the rails server by running:

{% highlight sh %} rails server {% endhighlight %}
Open in your browser. You should see "Welcome aboard" page, which means that the generation of your new app worked correctly. Notice in this window the command prompt is not visible because you are now in the Rails server, the command prompt looks like this:
{% highlight sh %} $ {% endhighlight %}
{% highlight sh %} > {% endhighlight %}
When the command prompt is not visible you cannot execute new commands. If you try running `cd` or another command it will not work. To return to the normal command prompt: Hit Ctrl+C in the terminal to quit the server. {% coach %} Explain what each command does. {% endcoach %} [What is a web application and a server - Slides by @]() The skeleteon generated by "rails new" reflects the [Model-View-Controller - Slides by @]() architectural pattern. ================================================ FILE: _pages/touristic-autism_continuous-deployment.md ================================================ --- layout: guide title: Touristic Autism-friendly Spots App permalink: touristic-autism_continuous-deployment --- # Continuous Deployment *Created by Myriam Leggieri, [@iammyr](https://twitter.com/iammyr)* *for [Rails Girls Galway](https://github.com/RailsGirlsGalway)* The basic guides that have been merged and adapted are the [Ruby on Rails Tutorial](http://www.railstutorial.org/book), the [basic RailsGirls app](/app) and the tutorials for [creating thumbnails](/thumbnails), [authenticating users](/devise), [adding design](/design), [deploying to OpenShift](/deployment/openshift) and [adding comments](/commenting). We’re going to deploy our (still-empty) Rails application to production. Deploying early and often allows us to catch any deployment problems early in our development cycle or else there could be troubles during the integration phases. Several shared hosts, virtual private servers, full-service deployment companies and cloud deployment services all provide facilities that makes it very easy to deploy Rails applications. OpenShift is one of the cloud deployment services offering such facilities. It is a cloud computing Platform as a Service (PaaS) that makes it easy to deploy apps online. It is open source and written in Ruby. [Create an OpenShift Online account](https://openshift.redhat.com/app/account/new?web_user[promo_code]=railsgirls), which allows you to put three apps online for free. Once you are signed up, install the OpenShift RHC Client Tools by adding the rhc gem in the production environment. Add the following to the Gemfiile (which is written in Ruby ndr):
{% highlight sh %} group :production do gem 'rhc' end {% endhighlight %}
If you are not using RVM or RailsInstaller then follow [this guide](https://www.openshift.com/developers/rhc-client-tools-install) (you may need to do "sudo gem install rhc").
Then run in the terminal:
{% highlight sh %} bundle install --without production rhc setup {% endhighlight %}
The --without production option prevents the local installation of any production gems. If Bundler complains about a readline error, try adding gem ’rb-readline’ to your Gemfile. Because the only gems we’ve added are restricted to a production environment, right now this command doesn’t actually install any additional local gems, but it’s needed to update Gemfile.lock. Now, let's commit these changes to GitHub!
{% coach %} Explain the benefits of deploying to a PaaS such as OpenShift, as opposed to traditional servers. What "production" means. Discuss SSH and why we need to upload a public key to communicate securely. [Slides by Gerry Kavanagh @gerryk]() {% endcoach %} Navigate to the "projects" folder. Run in the prompt:
{% highlight sh %} rhc app create openshiftapp ruby-1.9 postgresql-9.2 --from-code=https://github.com/openshift/rails-example.git {% endhighlight %}
We need the .openshift directory and config/database.yml file from the sample application in order for our Rails app to run on OpenShift. Copy these from the openshiftapp directory to the railsgirls directory.
{% highlight sh %} cd railsgirls-galway-2014 cp -r ../openshiftapp/.openshift . cp ../openshiftapp/config/database.yml config {% endhighlight %}
Now add and commit in Git the new changes!
OpenShift uses the PostgreSQL database, which means that we need to add the pg gem in the production environment to allow Rails to talk to Postgres. Note also the addition of the rails_12factor gem, which is used to serve static assets such as images and stylesheets. Substitute "gem sqlite" in Gemfile with the following:
{% highlight sh %} gem 'sqlite3', :group => [:development, :test] gem 'pg', :group => [:production] gem 'rails_12factor', :group => [:production] {% endhighlight %}
Now do a bundle excluding the gems in production. On some platforms, this may generate platform-specific versions of your Gems that cause issues when you push your app to the cloud. To prevent this, open your Gemfile.lock file and check the versions of the ‘sqlite3’ and ‘pg’ Gems. If they have a platform-specific suffix, such as -x86-mingw32, remove this (eg. change pg (0.16.0-x86-mingw32) to pg (0.16.0) and sqlite3 (1.3.8-x86-mingw32) to sqlite3 (1.3.8)). Save and close the file, and run the above bundle command again before continuing. Add and commit your changes in Git
{% coach %} Talk about relational databases and the differences between SQLite and PostgreSQL. {% endcoach %} We are now ready to deploy the Rails Girls app to OpenShift. We need to tell our Git repository where to push the code. To get the location of your OpenShift code repository, run the following command, and copy the Git URL from the output.
{% highlight sh %} rhc app show openshiftapp {% endhighlight %}
Now run the following commands, replacing the SSH string with your Git URL. We are using ‘-f’ for force here because we are happy to wipe away the history of the current OpenShift repository, which contains the sample Rails app. When you are pushing future changes, you can just use ‘git push’.
{% highlight sh %} git remote add openshift ssh://5387bff65973cadf3c000323@openshiftapp-railsgirlsgalway.rhcloud.com/~/git/openshiftapp.git/ git push -f --set-upstream openshift master {% endhighlight %}
Refresh the app in your browser to see the result. If the app fails to visualize (500 Internal Server Error) often (error from the rhc tail openshiftapp : "Missing `secret_key_base` for 'production' environment, set this value in `config/secrets.yml`") the following solves. Get a secret with "rake secret" assign it to the environment variable 'SECRET_KEY_BASE' and export the variable to ~/.bash_profile. OpenShift (but also Heroku) needs to serve static assets like images and CSS:
{% highlight sh %} $ rake assets:precompile $ git add . $ git commit -am "Add precompiled assets for OpenShift" git push -f --set-upstream openshift master {% endhighlight %}
To be used only if OpenShift fails without it. We'll cover "rake" and "assets" later on.
When we push a new version of the application, anything stored within OpenShift’s copy of the repo will be wiped to make way for the new files. This includes some log files and the images uploaded by users. To fix this, we can store these files in persistent directories on OpenShift instead; the filepaths of the locations we need are stored in environment variables. To change the location of the production log, open config/environments/production.rb. Beneath the comment line:
{% highlight sh %} config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) {% endhighlight %}
Add the line:
{% highlight sh %} config.logger = ActiveSupport::Logger.new(File.join(ENV['OPENSHIFT_RUBY_LOG_DIR'], "production.log")) {% endhighlight %}
Rails 3 users: Change ‘ActiveSupport::Logger’ to ‘ActiveSupport::BufferedLogger’.
You can tail your application’s logs with the command rhc tail openshiftapp (the output from the change you just made won’t show up until the new file has been committed and pushed to OpenShift). {% coach %} {% endcoach %} Discuss the value of application logging. ================================================ FILE: _pages/touristic-autism_design.md ================================================ --- layout: guide title: Touristic Autism-friendly Spots App permalink: touristic-autism_design --- # Design *Created by Myriam Leggieri, [@iammyr](https://twitter.com/iammyr)* *for [Rails Girls Galway](https://github.com/RailsGirlsGalway)* The basic guides that have been merged and adapted are the [Ruby on Rails Tutorial](https://www.railstutorial.org/book), the [basic RailsGirls app](/app) and the tutorials for [creating thumbnails](/thumbnails), [authenticating users](/devise), [adding design](/design), [deploying to OpenShift](/deployment/openshift) and [adding comments](/commenting). {% coach %} Talk about the relationship between HTML and Rails. What part of views is HTML and what is Embedded Ruby (ERB)? What is MVC and how does this relate to it? (Models and controllers are responsible for generating the HTML views.) {% endcoach %} The app doesn't look very nice yet. Let's do something about that. We'll use the Twitter Bootstrap project to give us nicer styling really easily. Open `app/views/layouts/application.html.erb` in your text editor and above the line {% highlight erb %} <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %> {% endhighlight %} add {% highlight erb %} {% endhighlight %} and replace {% highlight erb %} <%= yield %> {% endhighlight %} with {% highlight erb %}
<%= yield %>
{% endhighlight %} Let's also add a navigation bar and footer to the layout. In the same file, above `
` add {% highlight html %} {% endhighlight %} and before `` add {% highlight html %}
Rails Girls Galway 2014
{% endhighlight %} Now let's also change the styling of the places table. Open `app/assets/stylesheets/application.css` and at the bottom add {% highlight css %} body { padding-top: 100px; } footer { margin-top: 100px; } table, td, th { vertical-align: middle; border: none; } th { border-bottom: 1px solid #DDD; } {% endhighlight %} Now make sure you saved your files and refresh the browser to see what was changed. You can also change the HTML & CSS further. In case your Terminal shows you an error message that *sort of* implies there is something wrong with your JavaScript or CoffeeScript, install [nodejs](https://nodejs.org/download/). This issue should not appear when you've used the RailsInstaller (but when you've installed Rails via ```gem install rails```). {% coach %} Talk a little about CSS and layouts. {% endcoach %} 1.Design your header + put the following code to the bottom of `app/assets/stylesheets/application.css`: ``` .navbar { min-height: 38px; background-color: #f55e55; } ``` Now refresh the page and check the changes. You can try change the color or font of the header. You can check the color reference from . {% coach %} Talk about the property `display`, inline and block element. {% endcoach %} + Then put these lines at the bottom: ``` .navbar a.brand { font-size: 18px; } .navbar a.brand:hover { color: #fff; background-color: transparent; text-decoration: none; } ``` {% coach %} Explain the 4 states of a link {% endcoach %} 2.Design your table + We simply use the twitter [Bootstrap](https://getbootstrap.com/) to polish our table。find this line from app/views/places/index.html.erb and replace: ``` ``` with ```
``` + Modify size of the picture using the following lines ``` <%= image_tag(idea.picture_url, :width => 600) if idea.picture.present? %> ``` try to change the width and see what's gonna happen + add the following lines to the bottom of file app/assets/stylesheets/places.css.scss: ``` .container a:hover { color: #f55e55; text-decoration: none; background-color: rgba(255, 255, 255, 0); } ``` + try add some background style with property `background-image`, reference to for some patterns. 3.add style to footer + add the lines to bottom of app/assets/stylesheets/application.css: ``` footer { background-color: #ebebeb; padding: 30px 0; } ``` try put more things into `footer`, then adjust it's position. 4.add style to button + open and find the `Create Place` button. add these lines to app/assets/stylesheets/places.css.scss ``` .container input[type="submit"] { height: 30px; font-size: 13px; background-color: #f55e55; border: none; color: #fff; } ``` {% coach %} Explain how to use `border` in css, try modify the style of button like round the corner, add shadow or color etc. {% endcoach %} Open `app/views/layouts/application.html.erb` in your text editor and replace the line {% highlight html %} {% endhighlight %} with {% highlight html %} {% endhighlight %} Open `app/assets/stylesheets/application.css`, replace the line {% highlight html %} body { padding-top: 100px; } {% endhighlight %} with {% highlight html %} body { padding-top: 60px; } {% endhighlight %} Finally, delete the file `app/assets/stylesheets/scaffolds.css.scss` because we don't really need the default style generated by Rails. Now refresh the page at . You will not find much change but it's good preparation for the following steps. Considering "place" is the most important object in your app, we are going to put the "New Place" button on the navigation bar to make it always available. Open `app/views/layouts/application.html.erb`, under the line {% highlight erb %}
  • Places
  • {% endhighlight %} add {% highlight erb %}
  • <%= link_to 'New Place', new_place_path %>
  • {% endhighlight %} Now it's time to make the place list page look professional. For that, we are going to replace the table layout with a div layout. {% coach %} Talk a little about table vs div. {% endcoach %} Open `app/views/places/index.html.erb` in your text editor and replace the table with {% highlight erb %} <% @places.in_groups_of(3) do |group| %>
    <% group.compact.each do |place| %>
    <%= image_tag(place.picture_url, :width => '20%') if place.picture.present? %>

    <%= link_to place.name, place %>

    <%= place.description %> <%= place.address %> <%= place.latitude %> <%= place.longitude %> <%= place.user_id %> <%= link_to 'Show', place %> | <% if user_signed_in? %> <% if current_user.id == place.user_id %>. <%= link_to 'Edit', edit_place_path(place) %> | <%= link_to 'Destroy', place, method: :delete, data: { confirm: 'Are you sure?' } %> <% end %> <% end %>
    <% end %>
    <% end %> {% endhighlight %} {% coach %} Explain what the new code means line by line, and talk a little about Bootstrap 12 grids layout. {% endcoach %} Refresh it! We get a nice looking idea list. Click the "New Idea" button, and create more ideas with real text and pretty pictures - the page will look much better with content. There is a principle of contemporary web design: content is the best decoration. Click the title of a place, and you will be brought to the details page of the place. Now it is still scaffold generated by Rails, so let's make it better. Open `app/views/places/show.html.erb` in your text editor and replace all lines with {% highlight erb %}

    Places created

    <%= image_tag(@place.picture_url, :width => "100%") if @place.picture.present? %>

    Name: <%= @place.name %>

    User Rating as Autism-friendly: <%= rating_for @place, "autism_friendly" %>

    User Overall Rating: <%= rating_for @place, "overall" %>

    Your Vote as Autism-friendly: <%= rating_for_user @place, current_user, "autism_friendly", :star => 7 %>

    Your Overall Vote: <%= rating_for_user @place, current_user, "autism_friendly", :star => 7 %>

    Description: <%= @place.description %>

    Address: <%= @place.address %>

    Latitude: <%= @place.latitude %>

    Longitude: <%= @place.longitude %>

    Creator ID: <%= @place.user_id %>

    <%= link_to 'Edit', edit_place_path(@place) %> | <%= link_to 'Back', places_path %>

    Comments

    <% @comments.each do |comment| %>
    <%= comment.user_id %>

    <%= comment.body %>

    <% if user_signed_in? %> <% if current_user.id == comment.user_id %>

    <%= link_to 'Delete', comment_path(comment), method: :delete, data: { confirm: 'Are you sure?' } %>

    <% end %> <% end %>
    <% end %> <%= render 'comments/form' %> {% endhighlight %} Continue experimenting with Design changes! ;) ================================================ FILE: _pages/touristic-autism_git.md ================================================ --- layout: guide title: Touristic Autism-friendly Spots App permalink: touristic-autism_git --- # Version Control with Git *Created by Myriam Leggieri, [@iammyr](https://twitter.com/iammyr)* *for [Rails Girls Galway](https://github.com/RailsGirlsGalway)* The basic guides that have been merged and adapted are the [Ruby on Rails Tutorial](https://www.railstutorial.org/book), the [basic RailsGirls app](/app) and the tutorials for [creating thumbnails](/thumbnails), [authenticating users](/devise), [adding design](/design), [deploying to OpenShift](/deployment/openshift) and [adding comments](/commenting). Navigate to the root directory of the first app and initialize a new repository:
    {% highlight sh %} $ git init {% endhighlight %}
    Before adding the project to the repository, let's tell Git which files to ignore - because too frequently subject to changes - by listing them in the .gitignore file. The "rails new" command already create a .gitignore file but let's extend it with the following.
    {% highlight sh %} # Ignore other unneeded files. database.yml # Ignore Rails documentation files doc/ # Ignore Vim and Emacs swap files *.swp *~ .project # Ignore (for macOS users) the .DS_Store directories created by the Mac Finder application .DS_Store .idea .secret {% endhighlight %}
    Add the changes (recursively adding every sub-directory, too).
    {% highlight sh %} git add . {% endhighlight %}
    The "git add" command adds the project files to a staging area, which contains pending changes to your projectbu; you can see which files are in the staging area using the status command:
    {% highlight sh %} $ git status {% endhighlight %}
    Now commit the changes while justifying them with a message:
    {% highlight sh %} $ git commit -m "Initialize repository" {% endhighlight %}
    Git commits are local, recorded only on the machine on which the commits occur. You can view a list of all the commit messages with "git log" typing "q" to quit.
    Now we want our changes to be pushed from our local machine to a remote repository. [Create a repository](https://github.com/new) called "railsgirls-galway-2014" and fill in the information. Do not to initialize the repository with a README file since "rails new" already created that automatically. Push up your local changes to the remote repository as follows:
    {% highlight sh %} $ git remote add origin https://github.com//railsgirls-galway-2014.git $ git push -u origin master {% endhighlight %}
    The result is a page at GitHub (for instance, [here's mine](https://github.com/iammyr/railsgirls-galway-2014)) for our application repository, which provides nice rendering, sharing functionalities and statistics: take a look by yourself at https://github.com//railsgirls-galway-2014
    {% coach %} Explain the branch-edit-commit-merge workflow on GitHub: modify the README file to be more descriptive. ([Slides by Myriam Leggieri @iammyr]()) {% endcoach %} ================================================ FILE: _pages/touristic-autism_google-map.md ================================================ --- layout: guide title: Touristic Autism-friendly Spots App permalink: touristic-autism_google-map --- # Show All Places in a Google Map *Created by Myriam Leggieri, [@iammyr](https://twitter.com/iammyr)* *for [Rails Girls Galway](https://github.com/RailsGirlsGalway)* The basic guides that have been merged and adapted are the [Ruby on Rails Tutorial](https://www.railstutorial.org/book), the [basic RailsGirls app](/app) and the tutorials for [creating thumbnails](/thumbnails), [authenticating users](/devise), [adding design](/design), [deploying to OpenShift](/deployment/openshift) and [adding comments](/commenting). We need to install a piece of software to let us display and interact with Google Maps. Open `Gemfile` in the project directory using your text editor and add {% highlight ruby %} gem 'gmaps4rails' {% endhighlight %} Bundle as usual. Then add to a new app/model/marker.rb file: {% highlight sh %} class Marker include ActiveModel::Validations include Gmaps4rails::ActsAsGmappable acts_as_gmappable :position => :location attr_accessor :location def gmaps4rails_infowindow 'foo' end end {% endhighlight %} Then add to config/application.rb within your project block: {% highlight sh %} config.active_support.escape_html_entities_in_json = true config.encoding = "utf-8" config.filter_parameters += [:password] config.assets.enabled = true config.assets.version = '1.0' {% endhighlight %} Create your app/controllers/google_controller.rb: {% highlight sh %} class GoogleController < ApplicationController def index; end def markers @marker ||= (1..10).map { m = Marker.new m.location = [ (Random.new.rand(-5000..5000) / 100.0),(Random.new.rand(-5000..5000) / 100.0) ] m }.to_gmaps4rails end helper_method :markers end {% endhighlight %} Create your view/google/index.html.erb: {% highlight sh %}

    See some marker on your map by default

    <%= gmaps("markers" => {"data" => markers}, 'last_map' => false, "map_options" => { "center_on_user" => true, "detect_location" => true, "provider" => "google", :id => 'google_map'}) %>

    See on OpenLayer

    <%= gmaps("markers" => {"data" => markers}, "map_options" => { "center_on_user" => true, "detect_location" => true, "provider" => "openlayers", :id => 'openlayer_map'}) %> {% endhighlight %} Add the following in app/views/application.html.erb after "<%= yield %>": {% highlight sh %} <%= yield :scripts %> {% endhighlight %} Finally add the following to your config/routes.rb: {% highlight sh %} get '/google' => 'google#index' root :to => 'google#index' {% endhighlight %} ================================================ FILE: _pages/touristic-autism_image-upload.md ================================================ --- layout: guide title: Touristic Autism-friendly Spots App permalink: touristic-autism_image-upload --- # Image Upload and Thumbnails *Created by Myriam Leggieri, [@iammyr](https://twitter.com/iammyr)* *for [Rails Girls Galway](https://github.com/RailsGirlsGalway)* The basic guides that have been merged and adapted are the [Ruby on Rails Tutorial](https://www.railstutorial.org/book), the [basic RailsGirls app](/app) and the tutorials for [creating thumbnails](/thumbnails), [authenticating users](/devise), [adding design](/design), [deploying to OpenShift](/deployment/openshift) and [adding comments](/commenting). We need to install a piece of software to let us upload files in Rails. Open `Gemfile` in the project directory using your text editor and add {% highlight ruby %} gem 'carrierwave' {% endhighlight %} In the terminal run: {% highlight sh %} bundle {% endhighlight %} Now we can generate the code for handling uploads. In the terminal run: {% highlight sh %} rails generate uploader Picture {% endhighlight %} At this point you need to **restart the Rails server process** in the terminal. Hit Ctrl+C in the terminal to quit the server. Once it has stopped, you can press the up arrow to get to the last command entered, then hit enter to start the server again. This is needed for the app to load the added library. Open `app/models/place.rb` and add {% highlight ruby %} mount_uploader :picture, PictureUploader {% endhighlight %} Open `app/views/places/_form.html.erb` and change {% highlight erb %} <%= f.text_field :picture %> {% endhighlight %} to {% highlight erb %} <%= f.file_field :picture %> {% endhighlight %} Sometimes, you might get an *TypeError: can't cast ActionDispatch::Http::UploadedFile to string*. If this happens, in file `app/views/places/_form.html.erb` change the line {% highlight erb %} <%= form_for(@place) do |f| %> {% endhighlight %} to {% highlight erb %} <%= form_for @place, :html => {:multipart => true} do |f| %> {% endhighlight %} Now if you run your server, and try adding a new place with a picture, you'll notice that the picture doesn't look nice because it only shows a path to the file. Let's fix that. Open `app/views/places/show.html.erb` and change {% highlight erb %} <%= @place.picture %> {% endhighlight %} to {% highlight erb %} <%= image_tag(@place.picture_url, :width => 600) if @place.picture.present? %> {% endhighlight %} Now refresh your browser to see what changed. {% coach %} Talk a little about HTML. Explain what specifying the image width in HTML at the end of Step 4 does and how it differs from resizing images on the server. {% endcoach %} ## Installing ImageMagick * macOS: run `brew install imagemagick`. If you don't have the brew command, you can [install Homebrew here][in-homebrew]. * Windows: download and run the [ImageMagick installer][im-win] (use the first *download* link). Reopen your Rails Command Shell afterwards. * Linux: On Ubuntu and Debian, run `sudo apt-get install imagemagick`. Use the appropriate package manager instead of `apt-get` for other distributions. [im-win]: https://imagemagick.org/script/download.php#windows [in-homebrew]: https://brew.sh/ {% coach %} What is ImageMagick and how is it different from libraries/gems we used before? {% endcoach %} Open `Gemfile` in the project and add {% highlight ruby %} gem 'mini_magick', '3.5.0' {% endhighlight %} In the Terminal run: {% highlight sh %} bundle {% endhighlight %} ## Telling our app to create thumbnails when an image is uploaded Open `app/uploaders/picture_uploader.rb` and find the line that looks like this: {% highlight ruby %} # include CarrierWave::MiniMagick {% endhighlight %} Remove the `#` sign. {% coach %} Explain the concept of comments in code. {% endcoach %} Below the line you just changed, add: {% highlight ruby %} version :thumb do process :resize_to_fill => [50, 50] end {% endhighlight %} The images uploaded from now on should be resized, but the ones we already have weren't affected. So edit one of the existing places and re-add a picture. ## Displaying the thumbnails To see if the uploaded picture was resized open `app/views/places/index.html.erb`. Change the line {% highlight erb %}
    {% endhighlight %} to {% highlight erb %} {% endhighlight %} Take a look at the list of ideas in the browser to see if the thumbnail is there. ================================================ FILE: _pages/touristic-autism_intro.md ================================================ --- layout: guide title: Touristic Autism-friendly Spots App permalink: touristic-autism_intro --- # Rails Girls Touristic Autism-friendly Spots App Tutorial *Created by Myriam Leggieri, [@iammyr](https://twitter.com/iammyr)* *for [Rails Girls Galway](https://github.com/RailsGirlsGalway)* This guide merges, adapts and extends some of the basic RailsGirls guides **for the scenario**: description, displaying and commenting touristic places and rate them with respect to their autism-friendliness. This application was requested by the [Galway Autism Partnership](https://galwayautismpartnership.com/) to support autistic adults during their travelings. The extension comprises of the following **new features**: * TDD using Guide * Resource Rating * Authenticated User (via devise) permission setting The basic guides that have been merged and adapted are the [Ruby on Rails Tutorial](https://www.railstutorial.org/book), the [basic RailsGirls app](/app) and the tutorials for [creating thumbnails](/thumbnails), [authenticating users](/devise), [adding design](/design), [deploying to OpenShift](/deployment/openshift) and [adding comments](/commenting). ### [*0.* Installation](/install) **Make sure you have Rails and Git installed.** [**Follow the installation guide**](/install), the [**Installing Git section of Pro Git**](https://www.git-scm.com/book/en/Getting-Started-Installing-Git) to get set up. Then configure GitHub by typing the following in your terminal: {% highlight sh %} git config --global user.name "Your Name" git config --global user.email your.email@example.com {% endhighlight %}

    one-time setup steps for GitHub.

    Sign up for a [free GitHub account](https://github.com/signup/free) if you don’t have one already. ### [*1.* Basic Web Application](/touristic-autism_basic-app) ### [*2.* Version control with Git](/touristic-autism_git) ### [*3.* Resource Modeling](/touristic-autism_resource-modeling) ### [*4.* Resource Rating](/touristic-autism_resource-rating) ### [*5.* Design](/touristic-autism_design) ### [*6.* Image upload and Thumbnails](/touristic-autism_image-upload) **Optional - for advanced Rails Girls:** ### [*7.* Continuous Deployment](/touristic-autism_continuous-deployment) ### [*8.* Continuous Testing and Integration](/touristic-autism_static-pages-tdd) ## Additional Guides * Guide 0: [Handy cheatsheet for Ruby, Rails, console etc.](https://www.pragtob.info/rails-beginner-cheatsheet/) * Guide 1: [Put your app online with Heroku by Terence Lee](/deployment/heroku) / [Put your app online with OpenShift by Katie Miller](/deployment/openshift) / [Put your app online with anynines](/deployment/anynines) * Guide 2: [Adding profile pictures with Gravatar](/gravatar) * Guide 3: [Go through additional explanations for the App by Lucy Bain](https://github.com/lbain/railsgirls) # Appendices ## Undoing things Rails has some facilities to help you recover from mistakes. For instance, you may decide to change the name of a controller. Since, when generating a controller, Rails creates many more files than the controller file itself, undoing the generation means removing a whole set of files. In Rails, this can be accomplished with rails destroy. In particular, these two commands cancel each other out: {% highlight sh %} rails generate controller FooBars baz quux rails destroy controller FooBars baz quux {% endhighlight %} Similarly, after we generate a model as follows: {% highlight sh %} rails generate model Foo bar:string baz:integer {% endhighlight %} This can be undone using {% highlight sh %} rails destroy model Foo {% endhighlight %} Migrations change the state of the database using {% highlight sh %} rails db:migrate {% endhighlight %} We can undo a single migration step using {% highlight sh %} rake db:rollback {% endhighlight %} To go all the way back to the beginning, we can use {% highlight sh %} rails db:migrate VERSION=0 {% endhighlight %} As you might guess, substituting any other number for 0 migrates to that version number, where the version numbers come from listing the migrations sequentially. To drop a table from the db enter {% highlight sh %} rails console {% endhighlight %} Then just type: {% highlight ruby %} ActiveRecord::Migration.drop_table(:) {% endhighlight %} You can browse directly the database (if sqlite3 type ".quit" to exit afterwards) by typing {% highlight sh %} rails db {% endhighlight %} ================================================ FILE: _pages/touristic-autism_resource-modeling.md ================================================ --- layout: guide title: Touristic Autism-friendly Spots App permalink: touristic-autism_resource-modeling --- # Resource Modeling *Created by Myriam Leggieri, [@iammyr](https://twitter.com/iammyr)* *for [Rails Girls Galway](https://github.com/RailsGirlsGalway)* The basic guides that have been merged and adapted are the [Ruby on Rails Tutorial](https://www.railstutorial.org/book), the [basic RailsGirls app](/app) and the tutorials for [creating thumbnails](/thumbnails), [authenticating users](/devise), [adding design](/design), [deploying to OpenShift](/deployment/openshift) and [adding comments](/commenting). What do we want our app to do? As a first thing, we would like to * authenticate **users** * allow authenticated users to create a new touristic **place** description * allow authenticated users to **comment** those places * allow authenticated users to **rate** up to which extent those places are autism-friendly or not. Note that these requirements help us identify 4 different resources: user, place, comment, rating. We are now going to model them specifying their properties and their associations with each other. We will enable the rating in the next tutorial. ## Authenticated Tourists/Users Let's generate our first resource: user and require its authentication. ## Step 0: Add devise gem Open up your `Gemfile` and add this line {% highlight ruby %} gem 'devise' {% endhighlight %} and run {% highlight sh %} bundle install {% endhighlight %} to install the gem. **Also remember to restart the Rails server**. ## Step 1: Set up devise in your app Run the following command in the terminal. {% highlight sh %} rails g devise:install {% endhighlight %} ## Step 2: Configure Devise Ensure you have defined default url options in your environments files. Open up `config/environments/development.rb` and add this line: {% highlight ruby %} config.action_mailer.default_url_options = { :host => 'localhost:3000' } {% endhighlight %} before the `end` keyword. Open up `app/views/layouts/application.html.erb` and add: {% highlight erb %} <% if notice %>

    <%= notice %>

    <% end %> <% if alert %>

    <%= alert %>

    <% end %> {% endhighlight %} right above {% highlight ruby %} <%= yield %> {% endhighlight %} ## Step 3: Setup the User model We'll use a bundled generator script to create the User model. {% highlight sh %} rails g devise user rails db:migrate {% endhighlight %} {% coach %} Explain what user model has been generated. What are the fields? Note that a model inherits abilities to interact with the DB from its ApplicationRecord super-class (ref. MVC). {% endcoach %} ## Step 4: Create your first user Now that you have set everything up you can create your first user. Devise creates all the code and routes required to create accounts, log in, log out, etc. Make sure your rails server is running, open and create your user account. ## Step 5: Add sign-up and login links All we need to do now is to add appropriate links or notice about the user being logged in in the top right corner of the navigation bar. In order to do that, edit `app/views/layouts/application.html.erb` by adding at the beginning of the body: {% highlight erb %} {% endhighlight %} Finally, force the user to redirect to the login page if the user was not logged in. Open up `app/controllers/application_controller.rb` and add: {% highlight ruby %} before_action :authenticate_user! {% endhighlight %} after `class ApplicationController < ActionController::Base`. Open your browser and try logging in and out from. {% coach %} Talk about the `user_signed_in?` and `current_user` helpers. Why are they useful? {% endcoach %} Let's add-commit-push to your GitHub repo! See how nicely all the changes are now on your GitHub profile? :) ## Touristic Places We now use Rails' scaffold functionality to generate and set up all that is necessary to list, add, remove, edit, and view our second resource: "touristic places".
    {% highlight sh %} rails generate scaffold place name:string address:string latitude:decimal longitude:decimal description:text picture:string user_id:integer {% endhighlight %}
    Note the column user:references that is created to support the 1-to-many association with Users.
    The scaffold creates new files in your project directory. However, we have defined (modeled) a "structure" for our "place" resource and we want all the future instances of this resource to stick to this structure and get stored somewhere, i.e., in a database. We are already using a database (see `gem 'sqlite'` in your Gemfile). Let's add the structure of "place" as a table to our database with the following.
    {% highlight sh %} bin/rails db:migrate {% endhighlight %}
    {% highlight sh %} ruby bin/rails db:migrate {% endhighlight %}
    Then start the server again. Open (https://localhost:3000/places) in your browser and check out all the new functionalities that our web application is now providing to handle "place" resources. All thanks to what Ruby on Rails automatically generates with `generate scaffold`. Each new instance of "place" that will be stored in the database, will be automatically assigned a unique identifier called "primary key", with no need for us to specify it as one of the fields (along with picture, name, etc.)
    {% coach %} What is Rails scaffolding? What are migrations and why do you need them? {% endcoach %} Note the pages that have been created to manipulate the "place" resources and their naming convention. Look at the server logging and explain it as a report of the following interaction (in the context of the MVC pattern): * The browser issues a request for the /places URL. * Rails routes /places to the index action in the Places controller. * The index action asks the Place model to retrieve all places (Place.all). * The Place model pulls all the places from the database. * The Place model returns the list of places to the controller. * The controller captures the users in the @users variable, which is passed to the index view. * The view uses embedded Ruby to render the page as HTML. * The controller passes the HTML back to the browser Note that the controller created is RESTful (explain) Note that the controller inherits abilities (large amount of functionality, such as the ability to manipulate model objects, filter inbound HTTP requests, and render views as HTML) from its ApplicationController super-class (ref. MVC). Open up `app/views/places/show.html.erb` and remove the line that says: {% highlight erb %}

    <%= notice %>

    {% endhighlight %} This line is not necessary as we've already put the authenticated user notice in the `app/views/layouts/application.html.erb` file. Let's add-commit-push to your GitHub repo! ### Resource Associations Note that places aren't yet properly associated with users. For instance, when creating a new place the field "User" is expected to be filled by ourselves and when viewing a user profile there isn't any list of places created by him/her and viceversa. Also, when deleting a user account all the places he/she created do not get deleted automatically. Let's properly create the 1-to-many association between User and Places. #### Step 1. Add 1-to-many association You need to make sure that Rails knows the relation between the User and Place resources. As one user can create many places we need to make sure the user model knows that. Open app/models/user.rb and after the row {% highlight ruby %} class User < ApplicationRecord {% endhighlight %} add {% highlight ruby %} has_many :places {% endhighlight %} The place also has to know that it belongs to a user. So open app/models/place.rb and after {% highlight ruby %} class Place < ApplicationRecord {% endhighlight %} add the row {% highlight ruby %} belongs_to :user {% endhighlight %} #### Step 2: Render the views Open app/views/places/_form.html and after {% highlight erb %}
    <%= f.label :user_id %>
    <%= f.number_field :user_id %>
    {% endhighlight %} add the row {% highlight erb %} <%= f.hidden_field :user_id, :value => current_user.id %> {% endhighlight %} next, remove {% highlight erb %}
    <%= f.label :user_id %>
    <%= f.number_field :user_id %>
    {% endhighlight %} ## Step 3: Set edit/delete permissions Allow only the place creator to edit/delete a place. Open app/views/places/index.html.erb and substitute {% highlight sh %}
    {% endhighlight %} with {% highlight sh %} <% if user_signed_in? %> <% if current_user.id == place.user_id %> <% end %> <% end %> {% endhighlight %} That's it. Now view a user you have inserted to your application and there you should see the form for creating a place as well as deleting older places. ## Place's Comments Just as well as we created a "place" resource and associated it with users, we can create a "comment" resource and associate it with places 9and with its author).
    {% highlight sh %} rails generate scaffold comment body:text user_id:integer place_id:integer bin/rails db:migrate {% endhighlight %}
    Start the server, check out the new service in your browser. Then, add-commit-push to github.
    {% coach %} Show that the scaffold generator has updated the Rails routes file with a rule for the Review resource {% endcoach %} ##Resource Association #### Step 1. Add 1-to-many association Open app/models/place.rb and after the row {% highlight ruby %} belongs_to :user {% endhighlight %} add {% highlight ruby %} has_many :comments {% endhighlight %} Open app/models/comment.rb and after {% highlight ruby %} class Comment < ApplicationRecord {% endhighlight %} add the rows {% highlight ruby %} belongs_to :user belongs_to :place {% endhighlight %} #### Step 2: Render the views Open app/views/comments/_form.html and substitute {% highlight erb %}
    <%= f.label :user_id %>
    <%= f.number_field :user_id %>
    {% endhighlight %} with the row {% highlight erb %} <%= f.hidden_field :user_id, :value => current_user.id %> {% endhighlight %} next, substitute {% highlight erb %}
    <%= f.label :place_id %>
    <%= f.number_field :place_id %>
    {% endhighlight %} with the row {% highlight erb %} <%= f.hidden_field :place_id%> {% endhighlight %} Open app/views/places/show.html.erb and just before the bottom links add {% highlight erb %}

    Comments

    <% @comments.each do |comment| %>
    <%= comment.user_id %>

    <%= comment.body %>

    <%= link_to 'Delete', comment_path(comment), method: :delete, data: { confirm: 'Are you sure?' } %>

    <% end %> <%= render 'comments/form' %> {% endhighlight %} In app/controllers/places_controller.rb add to show action after the row {% highlight ruby %} @place = Place.find(params[:id]) {% endhighlight %} this {% highlight ruby %} @comments = @place.comments.all @comment = @place.comments.build {% endhighlight %} ## Step 3: Set edit/delete permissions Allow only the comment creator to edit/delete a comment. Open app/views/places/show.html.erb and substitute {% highlight sh %}

    <%= link_to 'Delete', comment_path(comment), method: :delete, data: { confirm: 'Are you sure?' } %>

    {% endhighlight %} with {% highlight sh %} <% if user_signed_in? %> <% if current_user.id == comment.user_id %>

    <%= link_to 'Delete', comment_path(comment), method: :delete, data: { confirm: 'Are you sure?' } %>

    <% end %> <% end %> {% endhighlight %} ## Resource Field Validation At the moment comments, places and users are characterized by information that is never validated for its correctness. Still, for instance, there should be a limit on the length of comments in review or on the format of a user's email address. Then let's add a constraint over the length of the comment's body field (we'll use the 'validates' keyword). Open app/models/comment.rb and add between 'class' and 'end':
    {% highlight sh %} validates :body, length: { maximum: 140 } {% endhighlight %}
    If we now try to enter more than 140 characters we'll get an error. (try it out! ;) )
    ## Finetune the routes If you try to open (https://localhost:3000) it still shows the "Welcome aboard" page. Let's make it redirect to the places page. Open `config/routes.rb` and after the first line add {% highlight ruby %} root :to => redirect('/places') {% endhighlight %} Test the change by opening the root path (that is, ) in your browser. {% coach %} Talk about routes, and include details on the order of routes and their relation to static files. {% endcoach %} **Rails 3 users:** You will need to delete the index.html from the `/public/` folder for this to work. ================================================ FILE: _pages/touristic-autism_resource-rating.md ================================================ --- layout: guide title: Touristic Autism-friendly Spots App permalink: touristic-autism_resource-rating --- # Resource Rating *Created by Myriam Leggieri, [@iammyr](https://twitter.com/iammyr)* *for [Rails Girls Galway](https://github.com/RailsGirlsGalway)* The basic guides that have been merged and adapted are the [Ruby on Rails Tutorial](https://www.railstutorial.org/book), the [basic Rails Girls app](/app) and the tutorials for [creating thumbnails](/thumbnails), [authenticating users](/devise), [adding design](/design), [deploying to OpenShift](/deployment/openshift) and [adding comments](/commenting). What do we want our app to do? As a first thing, we would like to * authenticate **users** * allow authenticated users to create a new touristic **place** description * allow authenticated users to **comment** those places * allow authenticated users to **rate** up to which extent those places are autism-friendly or not. We modeled and deployed comment, user and place resources, so far. Let's now enable the rating for places. ## Rating Places ## Step 0: Add letsrate gem Open up your `Gemfile` and add this line {% highlight ruby %} gem "letsrate", :git => "git://github.com/iammyr/letsrate.git" {% endhighlight %} and run {% highlight sh %} bundle install {% endhighlight %} to install the gem. **Also remember to restart the Rails server**. ## Step 1: Set up letsrate in your app Run the following command in the terminal. (we are assuming that we had already enabled authenticated users using the `devise` gem) {% highlight sh %} rails g letsrate user {% endhighlight %} ## Step 2: Apply letsrate to your resource You should add the `letsrate_rateable` function with its dimensions option, to the model of the resource you wish to rate, i.e., place. You can have multiple dimensions. In `app/models/place.rb` add {% highlight ruby %} letsrate_rateable "autism_friendly", "overall" {% endhighlight %} Then you need to add a call `letsrate_rater` in the user model: {% highlight ruby %} letsrate_rater {% endhighlight %} ## Step 3: Render the Views There is a helper method which name is `rating_for` to add the star links. By default `rating_for` will display the average rating and accept the new rating value from authenticated user. Open `app/views/places/show.html.erb` and add {% highlight html %}

    Votes:
    Autism_friendly : <%= rating_for @place, "autism_friendly" %>
    Overall : <%= rating_for @place, "overall" %>


    Your votes:
    Autism_friendly : <%= rating_for_user @place, current_user, "autism_friendly", :star => 7 %> Overall : <%= rating_for_user @place, current_user, "overall", :star => 7 %>


    {% endhighlight %} You can use the `rating_for_user` helper method to show the star rating for the user. That's it! ^__^ Try it out by restarting the server, add, commit and push on GitHub. If all it's working then you can also deploy ;) ================================================ FILE: _pages/touristic-autism_static-pages-tdd.md ================================================ --- layout: guide title: Touristic Autism-friendly Spots App permalink: touristic-autism_static-pages-tdd --- # Test-Driven Development *Created by Myriam Leggieri, [@iammyr](https://twitter.com/iammyr)* *for [Rails Girls Galway](https://github.com/RailsGirlsGalway)* The basic guides that have been merged and adapted are the [Ruby on Rails Tutorial](https://www.railstutorial.org/book), the [basic RailsGirls app](/app) and the tutorials for [creating thumbnails](/thumbnails), [authenticating users](/devise), [adding design](/design), [deploying to OpenShift](/deployment/openshift), [adding comments](/commenting) and [Mark McDonnell's tutorial](https://code.tutsplus.com/tutorials/testing-your-ruby-code-with-guard-rspec-pry--cms-19974). Rails includes a default Test::Unit framework used to test your code. We will use a more advanced testing framework called RSpec to write a thorough test suite. We need to be able to write tests that are fast and give us instant feedback on problems with our code. We will use Guard and RSpec to monitor some of our files and run tests over them as soon as they get modified, so to be sure that the latest changes are not breaking the app anywhere. If any error is found, then we are going to dig into it so to understand the cause and fix it, by using Pry. Finally, since we are assuming to be developing in collaboration with other via GitHub, we will also make sure that each contribution does not conflict when integrating with the others' ones. For this very reason, we will also commit, push and test the integration often, in a process called "Continuous Integration". We will use Travis-CI to support us. ##Continuous testing with Guard In your Gemfile, add {% highlight sh %} group :test do gem 'rspec' end group :development do gem 'guard' gem 'guard-rspec' end {% endhighlight %} Then run "bundle install". Then create a file called Rakefile in your main project directory and add {% highlight sh %} require 'rspec/core/rake_task' RSpec::Core::RakeTask.new do |task| task.rspec_opts = ['--color', '--format', 'doc'] end {% endhighlight %} When you install RSpec, it gives you access to a built in Rake task and that's what we're using here. We create a new instance of RakeTask which by default creates a task called spec that will look for a folder called spec and will run all the test files within that folder, using the configuration options we've defined (here color and format of the test output on the command line). Note: to run the tests just enter "rake spec" in your command line. You'll get zero failures because we haven't written either any test or any code, yet. Now add the following to a new file (in your main project directory) called "Guardfile": {% highlight sh %} guard 'rspec' do # watch /app/views files watch(%r{^app/views/(.+).html.rb$}) do |m| "spec/features/#{m[1]}_spec.rb" end # watch /spec/ files watch(%r{^spec/features/(.+).rb$}) do |m| "spec/features/#{m[1]}.rb" end end {% endhighlight %} The contents of this file tells Guard what to do when we run the guard command. If we ran guard rspec then Guard would watch the specified files and execute the specified commands once any changes to those files had occurred. Note: because we only have one guard task, rspec, then that is run by default if we ran the command guard. In this instance, we're telling Guard to watch all the files within our app/views and spec/features folders and if any changes occur to any of those files then to execute the test files within our spec/features folder to make sure no changes we made broke our tests (and subsequently didn't break our code). Now, as in proper Test-Driven Development(TDD), let's create a test for our static "Home" page, before we even create the Home page. We're going to create a file titled home_spec.rb and place it in the spec/feature folder (as this is what we told Guard to expect). The purpose of this file is to become our specification file (in other words, this is going to be our test code and will represent the expected functionality). Note: in Ruby the words "test" and "specification" are often considered interchangeable. ###TDD: Writing Test Code Before Application Code Typically, if you write your application code first (so you're not doing TDD), then you will find yourself writing code that at some point in the future is over engineered and potentially obsolete. Through the process of refactoring or changing requirements, you may find that some functions will fail to ever be called. This is why TDD is considered the better practice and the preferred development method to use, because every line of code you will produce has been produced for a reason: to get a failing specification (your actual business requirement) to pass. Let's write the test "home.html.erb_spec.rb as: {% highlight sh %} require 'spec_helper' describe "test for the static page Home" do it "displays the text attribute of the message" do render rendered.should contain("Hello world!") end end {% endhighlight %} To help us reduce the boilerplate code, we'll place it inside of a special helper file that we'll load from our specification files. This file will be titled spec_helper.rb. This file will do a couple of things: * tell Ruby where our main application code is located * load our application code (for the tests to run against) * load the pry gem (helps us debug our code; if we need to). Here is the code: {% highlight sh %} $ << File.join(File.dirname(FILE), '..', 'app/views') require 'pry' require 'home' {% endhighlight %} Let's open a new command line, enter "guard" and leave it running: it will monitor our views in app/views and run tests from spec/features against them. If we now create an empty file "app/views/home.html.erb" guard will run the test and the test will unsurprisingly fail. The point of TDD is to have a tight feedback loop, also known as 'red, green, refactor'). What this means in practice is: * write a failing test * write the least amount of code to get it to pass * refactor the code The error is telling us that... Then let's create our static page Home. We create a PagesController whose purpose is to deal with static pages (e.g., Home, About, Help). Each page is represented by one action in the controller "pages_controller.rb". {% highlight sh %} class PagesController < ApplicationController def home end def about end def help end end {% endhighlight %} Now we have to tell the server to match the browser requests for each different page to our actions: {% highlight sh %} match '/home' => 'pages#home' match '/about' => 'pages#about' match '/help' => 'pages#help' {% endhighlight %} We then create home.html.erb, about.html.erb, and hrlp.html.erb views under app/views/pages. These views contain whatever content you want on your static pages. They'll by default use your app's application.html.erb layout. For now, we'll leave them empty and only add the following to home.html.erb, in order to satisfy our test. {% highlight sh %} Hello world! {% endhighlight %} Now, if we check the command line window where "guard" was running, we'll see it automatically did run our test as soon as we saved the changes to our home.html.erb file, and that the test is now succeeding. *Note:* if we wanted to run the test manually rather than via Guard, we would have had to run "rspec spec/features/home.html.erb_spec.rb" ## Debugging with Pry For the purpose of demonstrating Pry we are going to add more code to our controller (this extra code doesn't effect our test in any way). {% highlight sh %} class PagesController < ApplicationController attr_accessor :test @@class_property = "I'm a class property" def home binding.pry @instance_property = "I'm an instance property" pubs privs "Hello RSpec!" end def about test_var = "I'm a test variable" test_var end def help end private def privs puts "I'm private" end end {% endhighlight %} A break-point is a place within your code where execution will stop. You can have multiple break-points set within your code and you create them using "binding.pry" (note it's been included above). When you run your code you'll notice that the terminal will stop and place you inside your application's code at the exact spot your binding.pry was placed. From this point Pry has access to the local scope. You can type "exit" to exit Pry and for your code to continue executing. **Note:** Try finding where you are: (by typying) whereami; Stack Trace: wtf; Inspecting (available methods and properties): ls; Changing Scope: cd. ##Continuous Integration (CI) with Travis-CI The principle of CI is to commit/push early and often to avoid conflicts between your code and the master branch. When you do (in this case we're committing to GitHub) then that should kick off a 'build' on your CI server which runs the relevant tests to ensure all is working as it should be. Travis CI is a hosted continuous integration service for the open source community. It offers free CI services for open-source projects and also has a paid model for businesses. We'll be using the free open-source model on our GitHub repository. The process is this: * Sign into Travis-CI using your GitHub account * Go to your "Accounts" page * Turn "on" any repositories you want to run CI on * Create a .travis.yml file within the root directory of your project and commit it to your GitHub repository The .travis.yml file determines the configuration settings for Travis-CI so it knows how to handle running the tests for your project. Let's create it as follows: {% highlight sh %} language: ruby cache: bundler rvm: - 1.25.26 script: 'bundle exec rake spec' bundler_args: --without development branches: only: - master notifications: email: - you@example.com {% endhighlight %} We need to add "gem 'rake'" to our Gemfile within the ":test" group, as this is a requirement of Travis-CI. Travis-CI uses RVM (Ruby Version Manager) for installing Rubies on their servers. So we need to specify what Ruby versions we want to run our tests against. Also, let's add to spec/spec_helper.rb the following: {% highlight sh %} require 'pry' if ENV['APP_ENV'] == 'debug'" {% endhighlight %} and make clear in our Gemfile which gems are required for testing and which for development: {% highlight sh %} group :test do gem 'rake' gem 'rspec' end group :development do gem 'guard' gem 'guard-rspec' gem 'pry' # Adds debugging steps to Pry # continue, step, next gem 'pry-remote' gem 'pry-nav' end {% endhighlight %} **Note:** if you have any issues regarding Travis-CI then you can join the "#travis" channel on IRC freenode to get help answering any questions you may have. ================================================ FILE: _pages/twitter-widget.md ================================================ --- layout: guide title: Twitter widget permalink: twitter-widget --- # Twitter widget *Written by Asta Bevainyte, [@astux7](https://twitter.com/astux7)* This exercise is intended to teach how to use twitter widget and how to add it to the Where is 2 ways to do it, if you want to do it quick just adding a prepared code, go to paragraph 2. {% coach %} Explain what is widget. {% endcoach %} 1. Twitter widget configuration + Login to [Twitter](https://twitter.com/) + Go to [https://publish.twitter.com/#](https://publish.twitter.com/#) + Select what you would like to embed, .i.e your *profile* then the link should look like (https://twitter.com/_your_twitter_username) + Select display options between 'Embedded Timeline' or 'Twitter Buttons' + Copy code 2. Add Twitter generated code to your info page + You have Twitter copied code which looks like this if you selected ```profile``` and ```embedded timeline``` options (*_your_twitter_username* - you need to change to your twitter name) ``` ``` + Add this code to app/views/pages/info.html.erb at the end of the file + Save and run ```rails server``` + Open your browser and go to and check your Twitter profile ================================================ FILE: _pages/uploads.md ================================================ --- layout: main_guide title: Add picture uploads description: "Make your ideas pop with image uploads in your Rails app." permalink: uploads --- # Add picture uploads {% include main-guide-intro.html %} The ideas we added in the previous guide can benefit from a visual element, like a picture or drawing to spark the imagination. We can attach pictures by adding a file upload to the Idea model. ## Installing a Ruby gem To let us upload files in Rails app, we'll need to install a piece of software in the app first. Open the `Gemfile` file in your Text Editor. Below the following line: {% highlight ruby %} gem "sqlite3" {% endhighlight %} add this line to the file and save it: {% highlight ruby %} gem "carrierwave" {% endhighlight %} Open the Terminal app and press Ctrl+C to quit the Rails server. Then run the following command in the Terminal: {% highlight sh %} bundle install {% endhighlight %} This will install the "carrierwave" gem we added to the `Gemfile` file. {% coach %} Explain what libraries (Ruby gems) are and why they are useful. Describe what Open Source software is. Resources: RubyGems GitHub [introduction](https://github.com/rubygems/rubygems#rubygems-) and Wikipedia [OSS](https://en.wikipedia.org/wiki/Open-source_software) {% endcoach %} ## Generating a picture uploader We can now generate the code for handling file uploads. In the Terminal run the following command: {% highlight sh %} rails generate uploader Picture {% endhighlight %} If an error is shown that the uploader cannot be found also add the following line: {% highlight ruby %} gem "net-ssh" {% endhighlight %} If you added this gem, please run this command in the Terminal app to install the missing gem, and try again: {% highlight sh %} bundle install {% endhighlight %} ## Attaching the picture uploader to the idea model Rails now knows about a way to upload pictures in your app. It needs a bit of help to understand where you want to attach these uploads to. Open the `app/models/idea.rb` file in your Text Editor. This file is used to store your ideas in the database and fetch the ideas to show them. We'll change it to tell Rails which field is a file upload. Under the following line: {% highlight ruby %} class Idea < ApplicationRecord {% endhighlight %} add this line and save the file: {% highlight ruby %} mount_uploader :picture, PictureUploader {% endhighlight %} This `mount_uploader` line tells the Idea model that the `picture` field is a file upload. It will store information about the file upload on that field to display it later. ## Uploading pictures Now that your Idea model knows that the `picture` field is a file upload, we can change the form to create and edit pictures to select a picture. Open the `app/views/ideas/_form.html.erb` file in your Text Editor and change the following line: {% highlight erb %} <%= form.text_field :picture %> {% endhighlight %} to this line and save it: {% highlight erb %} <%= form.file_field :picture %> {% endhighlight %} Run `rails server`. In your browser open . Your "New idea" form will now show a different element on the page for the "Picture" field. Instead of a text field a file chooser is visible, recognizable by either a "Browse..." or "Choose File" button. Fill in the form to create a new idea, but this time select a picture as well using this new element/button. Any random image you have on your laptop will do, it's just a test. ## Displaying the picture You've now added a picture to your idea! You can't see it yet after creating the idea, it will only show the filename right now. Let's change it so it shows the picture. To show the picture in the page of the idea itself, open the `app/views/ideas/_idea.html.erb` in the Text editor and change the following line: {% highlight erb %} <%= idea.picture %> {% endhighlight %} to this line and save the file: {% highlight erb %} <%= image_tag(idea.picture_url, width: 600) if idea.picture? %> {% endhighlight %} Using the `image_tag` we have told Rails to display the file upload as an image if it is present on the idea. Ideas without a picture will not show one. Refresh the Browser. Your uploaded image should now be visible! ## Configure Git to ignore uploads By default your app saves all your images locally, which is fine during development, but we don't want to save them with your app source code. Open the `.gitignore` file add add this line at the bottom: {% highlight erb %} public/uploads/ {% endhighlight %} ================================================ FILE: _pages/videos.md ================================================ --- layout: guide title: Rails Girls on video permalink: videos --- # Rails Girls Happiness All Around the World This is a selection of Rails Girls videos from around the world. Have one to share? Add it here. ### Rails Girls Ljubljana 2014 ### Rails Girls Taipei-02 2013.11 ### Rails Girls Taipei-01 2013.09 ### Rails Girls Brno 2013 ### Rails Girls Summer of Code 2013 ### Rails Girls Helsinki 2010 ### Rails Girls Beograd 2013 ### Rails Girls Rheinland 2013 ### Rails Girls Maribor 2013 ### Rails Girls Sofia 2013 ### Rails Girls Ljubljana 2013
    ### Rails Girls Warsaw 2012 ### Rails Girls Berlin 2012 ### Rails Girls Zurich 2012 ### Rails Girls Cologne 2012 ### Rails Girls Ljubljana 2012

    Watch all Rails Girls Ljubljana lectures (in Slovenian)

    ================================================ FILE: _plugins/coach.rb ================================================ module Jekyll # A coach tag with its own styling. # Content is rendered as Markdown. class CoachTag < Liquid::Block def render(context) site = context.registers[:site] converter = site.find_converter_instance(::Jekyll::Converters::Markdown) <<~COACH_ELEMENT
    Help from the coach
    #{converter.convert(super)}
    COACH_ELEMENT end end end Liquid::Template.register_tag("coach", Jekyll::CoachTag) ================================================ FILE: css/code.css ================================================ .highlight .hll { background-color: #ffffcc } /*.highlight { background: #f0f0f0; }*/ .highlight .c { color: #60a0b0; font-style: italic } /* Comment */ .highlight .err { border: 1px solid #FF0000 } /* Error */ .highlight .k { color: #007020; font-weight: bold } /* Keyword */ .highlight .o { color: #666666 } /* Operator */ .highlight .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */ .highlight .cp { color: #007020 } /* Comment.Preproc */ .highlight .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */ .highlight .cs { color: #60a0b0; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #A00000 } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #FF0000 } /* Generic.Error */ .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ .highlight .gi { color: #00A000 } /* Generic.Inserted */ .highlight .go { color: #808080 } /* Generic.Output */ .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ .highlight .gt { color: #0040D0 } /* Generic.Traceback */ .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #007020 } /* Keyword.Pseudo */ .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #902000 } /* Keyword.Type */ .highlight .m { color: #40a070 } /* Literal.Number */ .highlight .s { color: #4070a0 } /* Literal.String */ .highlight .na { color: #4070a0 } /* Name.Attribute */ .highlight .nb { color: #007020 } /* Name.Builtin */ .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ .highlight .no { color: #60add5 } /* Name.Constant */ .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ .highlight .ne { color: #007020 } /* Name.Exception */ .highlight .nf { color: #06287e } /* Name.Function */ .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #bb60d5 } /* Name.Variable */ .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mf { color: #40a070 } /* Literal.Number.Float */ .highlight .mh { color: #40a070 } /* Literal.Number.Hex */ .highlight .mi { color: #40a070 } /* Literal.Number.Integer */ .highlight .mo { color: #40a070 } /* Literal.Number.Oct */ .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ .highlight .sc { color: #4070a0 } /* Literal.String.Char */ .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ .highlight .s2 { color: #4070a0 } /* Literal.String.Double */ .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ .highlight .sx { color: #c65d09 } /* Literal.String.Other */ .highlight .sr { color: #235388 } /* Literal.String.Regex */ .highlight .s1 { color: #4070a0 } /* Literal.String.Single */ .highlight .ss { color: #517918 } /* Literal.String.Symbol */ .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ .highlight .il { color: #40a070 } /* Literal.Number.Integer.Long */ ================================================ FILE: css/style.css ================================================ html { --highlight: #e0330c; background: #f4f4f4; } body { margin: 0px; background: #fff; color: #333; text-rendering: optimizeLegibility; font-size: 15px; line-height: 1.6; } h1 { font-weight: normal; font-size: 3em; margin: 0.5em 0 1em; } h2 { font-weight: normal; font-size: 2em; margin: 1em 0 0.5em; } h2 em { position: absolute; display: inline-block; margin-left: -1.5em; font-style: normal; font-weight: bold; color: #ccc; } h3 { font-weight: normal; font-size: 1.5em; line-height: 1.2em; margin: 2em 0 0.8em; } h4 { font-size: 1.2em; margin: 2em 0 0.5em; } p { font-size: 16px; margin-bottom: 1em; line-height: 1.5; } ul li { margin-bottom: 0.5em; line-height: 1.5; } a { color: var(--highlight); } a:hover { color: #e0330c; text-decoration: underline; } hr { border-top-color: #ddd; margin: 2em 0; } table { margin-bottom: 1em; } header { min-height: 60px; color: #fff; padding-top: 20px; background: #d3360b; position: sticky; top: 0; overflow: hidden; z-index: 1; } header .container .visible-desktop { margin-right: 4rem; } header #logo { width: 240px; float: left; } nav { margin: 0 0 0 250px; } nav a, nav a:focus { color: #fff; text-decoration: none; font-weight: 300; font-size: 20px; letter-spacing: 1px; margin-left: 10px; } nav a:after { margin-left: 15px; content: url(../images/star.png); } nav a:focus { outline-offset: 10px; outline: 2px dashed white; } nav a:last-child:after { content: none; } nav a:hover { text-decoration: underline; } footer { color: #666; overflow: hidden; width: 100%; padding: 40px 0; background: #f4f4f4; line-height: 1.5; text-align: center; } footer a { color: #111; border-color: #111; } footer p:last-child { margin-bottom: 0; } .nav { margin-bottom: 0; } .visible-desktop .span3 { margin-left: 0; } .guides-list { margin: 0; padding: 0; list-style: none; } .guides-list li { padding: 20px 0; min-height: 84px; } .guides-list li:not(:last-child) { border-bottom: 1px solid #ddd; } .guides-list h3 { margin: 0; margin-left: 90px; color: var(--highlight); } .guides-list p { margin-left: 90px; font-size: 18px; } .guide-icon { position: relative; top: 3px; margin-right: 20px; width: 70px; height: 70px; float: left; color: #fff; font-size: 1.8em; line-height: 70px; font-weight: bold; text-align: center; background-color: #d0d0d0; border-radius: 70px; transition: 0.1s background-color ease-in; -webkit-transition: 0.1s background-color ease-in; -moz-transition: 0.1s background-color ease-in; } .guide-icon:before { content: attr(data-icon); font-size: 120%; } .guide-icon-meta:before { content: "?"; position: relative; } .guide-icon-other:before { content: "❯"; position: relative; } a:hover .guide-icon, .guide-icon:hover { background-color: #d3360b; transition: 0.1s background-color ease-in; -webkit-transition: 0.1s background-color ease-in; -moz-transition: 0.1s background-color ease-in; } .columns { display: flex; flex-wrap: wrap; gap: 40px; } .column { flex: 1; } .column-40 { flex-basis: 30%; } .column-60 { flex-basis: 60%; } .workshop-image { margin: 40px 0; height: 130px; background: url(../images/guides-hero.png); background-position: center; background-repeat: no-repeat; background-size: contain; } @media (max-width: 980px) { .columns { display: block; gap: 0; } .workshop-image { display: none; } } i.icon-text-editor, i.icon-prompt, i.icon-browser { background-position: 0 0; margin-left: -70px; float: left; width: 50px; height: 50px; line-height: 50px; } i.icon-text-editor { background-image: url("/images/icon-text-editor.png"); } i.icon-prompt { background-image: url("/images/icon-prompt.png"); } i.icon-browser { background-image: url("/images/icon-browser.png"); } .text-center { text-align: center; } .guides-intro { margin-top: 40px; margin-bottom: 20px; } .guides-intro h1 { margin-top: 0; margin-bottom: 20px; } .guides-intro h2 { margin-top: 0; margin-bottom: 10px; } .guide { padding-bottom: 40px; } .guide > *:last-child { margin-bottom: 0; } .box { margin-top: 40px; margin-bottom: 40px; } .highlight { margin-left: 30px; margin-right: 0; } .highlight pre { overflow-x: auto; } .highlight pre code { white-space: pre; } i.icon-small-text-editor, i.icon-small-prompt, i.icon-small-browser { background-position: 0 0; margin-left: 0px; margin-top: 15px; display: block; width: 50px; height: 20px; line-height: 20px; float: left; } i.icon-small-text-editor { background-image: url("/images/icon-small-text-editor.png"); } i.icon-small-prompt { background-image: url("/images/icon-small-prompt.png"); } i.icon-small-browser { background-image: url("/images/icon-small-browser.png"); } .os-specific .picker { display: block; text-align: right; } .os-specific .picker-options .active { font-weight: bold; } .os-specific .picker-options > span:not(:last-child):after { content: " | "; } .os-specific.big { margin-bottom: 20px; } .os-specific.big .picker { display: block; text-align: center; } .os-specific.big .picker > span { display: block; } .os-specific.big .picker-label { font-size: 1.2rem; font-weight: bold; } .os-specific.big .picker-options > span:not(:last-child) { margin-right: 15px; } .os-specific.big .picker-options > span:after { content: ""; } .os-specific.big .picker-options { padding-top: 20px; font-size: 1.3rem; } .os-specific.big .picker-options a { display: inline-block; margin-bottom: 20px; padding: 2px 10px; border: 2px solid #ddd; border-radius: 10px; } .os-specific.big .picker-options a.active, .os-specific.big .picker-options a:focus, .os-specific.big .picker-options a:hover { border-color: currentcolor; } /* Correct padding on smaller screens */ @media (max-width: 767px) { header, footer { margin-left: -20px; margin-right: -20px; padding-left: 20px; padding-right: 20px; } } kbd { padding: 0.1em 0.6em; border: 1px solid #ccc; font-size: 11px; font-family: Arial, Helvetica, sans-serif; background-color: #f7f7f7; color: #333; -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 2px #fff inset; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 2px #fff inset; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 2px #fff inset; border-radius: 3px; display: inline-block; margin: 0 0.1em; text-shadow: 0 1px 0 #fff; line-height: 1.5em; white-space: nowrap; } .github-corner:hover .octo-arm { animation: octocat-wave 560ms ease-in-out; } @keyframes octocat-wave { 0%, 100% { transform: rotate(0); } 20%, 60% { transform: rotate(-25deg); } 40%, 80% { transform: rotate(10deg); } } @media (max-width: 500px) { .github-corner:hover .octo-arm { animation: none; } .github-corner .octo-arm { animation: octocat-wave 560ms ease-in-out; } } .navbar .brand { height: 24px; line-height: 24px; font-size: 22px; font-weight: 400; color: #fff; text-shadow: none; } .navbar .btn-navbar { display: block; float: left; height: 24px; padding: 7px 10px; margin-right: 5px; margin-left: 5px; color: #ffffff; text-shadow: none; background-color: inherit; border: none; box-shadow: none; background-image: none; } .navbar .btn-navbar:hover, .navbar .btn-navbar:focus, .navbar .btn-navbar:active, .navbar .btn-navbar.active, .navbar .btn-navbar.disabled, .navbar .btn-navbar[disabled] { color: #ffffff; background-color: inherit; *background-color: inherit; } .navbar .btn-navbar .icon-bar { display: block; width: 18px; height: 4px; background-color: #fff; box-shadow: none; } .navbar .nav > li > a { float: none; color: #fff; font-weight: 400; text-decoration: none; text-shadow: none; } .navbar .nav > li > a:focus, .navbar .nav > li > a:hover, nav a:hover { color: #f6e58d; text-decoration: none; background-color: transparent; } [class*="-notice"] { margin-bottom: 20px; padding: 10px 15px; font-size: 120%; border-radius: 10px; } [class*="-notice"] :last-child { margin-bottom: 0; } .guide-notice { background-color: #fef8ea; } .help-notice { background-color: #fef8ea; } .help-notice:before { content: "ℹ️"; margin-right: 10px; } .coach-notice { border: 2px solid #8102bb; } .coach-notice > div { cursor: help; } .warning-notice { border: 2px solid var(--highlight); } .warning-notice:before { content: "Warning"; display: block; font-weight: bold; } .go-to-top-arrow { visibility: hidden; opacity: 0; position: fixed; bottom: 20px; right: 30px; width: 45px; height: 45px; z-index: 99; font-size: 18px; border: none; outline: none; background-color: red; color: white; cursor: pointer; padding: 14px; border-radius: 30px; transition: all .4s; } .go-to-top-arrow:hover { background-color: #555; } .go-to-top-arrow.active{ visibility: visible; opacity: 1; opacity: 99; } .arrow{ position: absolute; top: 16px; left: 13px; width: 15px; height: 15px; display: inline-block; border: solid #FFF; border-width: 0 5px 5px 0; transform: rotate(-135deg); -webkit-transform: rotate(-135deg); } ================================================ FILE: index.html ================================================ --- layout: default description: "Learn how to make your first web app with Ruby on Rails! Sign up for a Rails Girls workshop in your area and follow these guides." ---

    Rails Girls Guides

    These guides are built to provide tools and a community for women to understand technology and how to build their ideas. Organize your own events, submit new guides, or just use them to learn Rails. For more, add yourself to the team mailing list.

    Want to learn more about Rails Girls events?

    Are you a coach or looking to organize a workshop? Have a look at the Guides about Rails Girls.

    Welcome to Rails Girls!

    These are the main Rails Girls workshop guides. Start here and follow the guides in order.

    Learn more topics with these Rails Girls guides. These are not in any particular order. Choose a guide that sounds interesting and try it out!

    Let's have more fun with Rails Girls

    Guides about Rails Girls itself

    ================================================ FILE: js/guides.js ================================================ function saveOs(os) { Cookies.set("os", os, { expires: 1825, path: '/' }); // expires in 5 years } function loadOs() { var osFromCookie = Cookies.get("os"); if(osFromCookie) { $(".os-specific").find("." + osFromCookie + "-link").click(); } else if(detectOs()) { $(".os-specific").find("." + detectOs() + "-link").click(); } else { $(".os-specific").find(".win-link").click(); } } function detectOs() { try { var browserVersion = navigator.appVersion; if (browserVersion.match(/Win/i)) { return "win"; } else if (browserVersion.match(/Macintosh/i)) { return "mac"; } else { return "nix"; } } catch(e) { return false; } } function addIcons() { $("code.language-sh, code.language-bat").closest('.highlight').before(''); $("code.language-erb, code.language-html, code.language-ruby, code.language-css").closest('.highlight').before(''); $("code.language-browser").closest('.highlight').before(''); } function initializeOsSwitchers() { var osInstructions = $(".os-specific"); var switcher = osInstructions.prepend( "Choose your Operating System: " + "" + "Windows" + "Mac" + "Linux" + "" + "" ); switcher.find(".win-link").click(function(event) { event.preventDefault(); saveOs("win"); $(".os-specific .os-link").removeClass("active"); $(".os-specific .win-link").addClass("active"); $(".os-specific").children("div").hide().filter(".win").show(); }); switcher.find(".mac-link").click(function(event) { event.preventDefault(); saveOs("mac"); $(".os-specific .os-link").removeClass("active"); $(".os-specific .mac-link").addClass("active"); $(".os-specific").children("div").hide().filter(".mac").show(); }); switcher.find(".nix-link").click(function(event) { event.preventDefault(); saveOs("nix"); $(".os-specific .os-link").removeClass("active"); $(".os-specific .nix-link").addClass("active"); $(".os-specific").children("div").hide().filter(".nix").show(); }); } $(document).ready(function() { addIcons(); initializeOsSwitchers(); loadOs(); var osLabelElement = $(".js-detected-os-label"); if (osLabelElement.length > 0) { var osLabel; switch (detectOs()) { case "win": osLabel = "Windows"; break; case "mac": osLabel = "Mac"; break; case "linux": osLabel = "Linux"; break; default: osLabel = "Error: Unknown Operating System" } osLabelElement.text(osLabel); } }); function topFunction() { window.scrollTo({ top: 0, left: 0, behavior: "smooth", }); } window.addEventListener("scroll", function() { if (window.scrollY > 100) { $(".go-to-top-arrow").addClass("active"); } else { $(".go-to-top-arrow").removeClass("active"); } }); ================================================ FILE: js/js.cookie.js ================================================ /*! js-cookie v3.0.1 | MIT */ /* https://github.com/js-cookie/js-cookie */ ; (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = global || self, (function () { var current = global.Cookies; var exports = global.Cookies = factory(); exports.noConflict = function () { global.Cookies = current; return exports; }; }())); }(this, (function () { 'use strict'; /* eslint-disable no-var */ function assign (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { target[key] = source[key]; } } return target } /* eslint-enable no-var */ /* eslint-disable no-var */ var defaultConverter = { read: function (value) { if (value[0] === '"') { value = value.slice(1, -1); } return value.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent) }, write: function (value) { return encodeURIComponent(value).replace( /%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g, decodeURIComponent ) } }; /* eslint-enable no-var */ /* eslint-disable no-var */ function init (converter, defaultAttributes) { function set (key, value, attributes) { if (typeof document === 'undefined') { return } attributes = assign({}, defaultAttributes, attributes); if (typeof attributes.expires === 'number') { attributes.expires = new Date(Date.now() + attributes.expires * 864e5); } if (attributes.expires) { attributes.expires = attributes.expires.toUTCString(); } key = encodeURIComponent(key) .replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent) .replace(/[()]/g, escape); var stringifiedAttributes = ''; for (var attributeName in attributes) { if (!attributes[attributeName]) { continue } stringifiedAttributes += '; ' + attributeName; if (attributes[attributeName] === true) { continue } // Considers RFC 6265 section 5.2: // ... // 3. If the remaining unparsed-attributes contains a %x3B (";") // character: // Consume the characters of the unparsed-attributes up to, // not including, the first %x3B (";") character. // ... stringifiedAttributes += '=' + attributes[attributeName].split(';')[0]; } return (document.cookie = key + '=' + converter.write(value, key) + stringifiedAttributes) } function get (key) { if (typeof document === 'undefined' || (arguments.length && !key)) { return } // To prevent the for loop in the first place assign an empty array // in case there are no cookies at all. var cookies = document.cookie ? document.cookie.split('; ') : []; var jar = {}; for (var i = 0; i < cookies.length; i++) { var parts = cookies[i].split('='); var value = parts.slice(1).join('='); try { var foundKey = decodeURIComponent(parts[0]); jar[foundKey] = converter.read(value, foundKey); if (key === foundKey) { break } } catch (e) {} } return key ? jar[key] : jar } return Object.create( { set: set, get: get, remove: function (key, attributes) { set( key, '', assign({}, attributes, { expires: -1 }) ); }, withAttributes: function (attributes) { return init(this.converter, assign({}, this.attributes, attributes)) }, withConverter: function (converter) { return init(assign({}, this.converter, converter), this.attributes) } }, { attributes: { value: Object.freeze(defaultAttributes) }, converter: { value: Object.freeze(converter) } } ) } var api = init(defaultConverter, { path: '/' }); /* eslint-enable no-var */ return api; }))); ================================================ FILE: js/mobile-menu.js ================================================ function toggleMobileMenu() { var navbarList = document.getElementById("navbar-list"); if (navbarList.style.height === "auto") { navbarList.style.height = "0"; } else { navbarList.style.height = "auto"; } }
    <%= place.picture %><%= image_tag place.picture_url(:thumb) if place.picture? %><%= link_to 'Edit', edit_place_path(place) %> <%= link_to 'Destroy', place, method: :delete, data: { confirm: 'Are you sure?' } %><%= link_to 'Edit', edit_place_path(place) %> <%= link_to 'Destroy', place, method: :delete, data: { confirm: 'Are you sure?' } %>