Coder Social home page Coder Social logo

rails_bog_app's Introduction

Rails Bog App

Overview

Everyone does blog apps. Now, you're going to work on a bog app. Researchers are collecting data on a local bog and need an app to quickly record field data.

Objectives

It's time to put all your Rails knowledge into practice! In this project, you will:

  • Review CRUD in the context of a Rails application.
  • Implement form helpers in a Rails application.
  • Build memory for the steps required to create a Rails app.

Workflow

You'll work through this project as a "time trial." You will be building the app 4 times, each time gaining skills through repetition. Here's how we want you to work:

  1. Start by making a first-run branch: git checkout -b first-run. Move through the instructions below to build your bog app. Use as many hints as you'd like to check your work and make sure you get through the lab smoothly. Commit your work along the way and at the conclusion. If you get stuck at any point, feel free to reference the solution branch.
  2. Reset your progress to the beginning by checking out master again git checkout master then make a second-run branch: git checkout -b second-run. Go through the lab another time. This time, time yourself on how long it takes you. Push yourself to peek at the hints more sparingly and code as much as you can on your own. Try not reference the solutions branch; you can look at your own first branch if you're stuck. Again, make sure to commit your work. Note: you will need to drop your database on each new run during this lab, since the old DB will already exist on your machine! Run rake db:drop db:create db:migrate to do so, or restart the project from scratch.
  3. Reset your progress to the beginning by checking out master again git checkout master then make a third-run branch: git checkout -b third-run. Repeat the lab a third time. Try not to use the instructions to build your bog app and refer to them only when very stuck. Time yourself again and aim to build the app faster than you built it the second time around. Make sure you have roughly the same number of commits as you had on your second run. Version control isn't the place to cut corners!
  4. Reset your progress to the beginning by checking out master again git checkout master then make a fourth-run branch: git checkout -b fourth-run. Time yourself. This is the fourth time; streamline your process. Squash bugs faster and try not to look at the resources. Commit often and build it as fast as you can!

Submission

When you're finished with your timed runs, edit the README on your master branch with an introduction paragraph that includes:

  • a 3-5 sentences reflection on how this went for you
  • a tip for others to help conquer some part of the app that used to trip you up
  • the times for your first and fourth runs

Background

A bog is a mire that accumulates peat, a deposit of dead plant material โ€” often mosses.

You may hear bog and think of Yoda and Luke...

Or maybe Sir Didymus and The Bog of Eternal Stench...

CRUD and REST Reference

REST stands for REpresentational State Transfer. We will strictly adhere to RESTful routing for Rails.

Verb Path Action Used for
GET /creatures index displaying list of all creatures
GET /creatures/new new displaying an HTML form to create a new creature
POST /creatures create creating a new creature in the database
GET /creatures/:id show displaying a specific creature
GET /creatures/:id/edit edit displaying an HTML form to edit a specific creature
PUT or PATCH /creatures/:id update updating a specific creature in the database
DELETE /creatures/:id destroy deleting a specific creature in the database

Part I: Display all creatures with index

1. Set up a new Rails project

Fork this repo, and clone it onto your local machine. Change directories into rails-bog-app, and create a new Rails project:

$  rails new bog_app -T -d postgresql
$  cd bog_app
$  rails db:create
$  rails s

Your app should be up and running at localhost:3000.

2. Add Bootstrap or Materialize to your project

Rails handles CSS and JavaScript with a system called the asset pipeline. We'll go over it more next week, but for now, here's how to add a CSS library (just CSS) using the asset pipeline.

Third-party libraries belong in the vendor/assets sub-directory of your Rails app. You'll need to download a your library's CSS file and add it to this directory.

One way you can do that is to use the Terminal. You can use curl to make HTTP requests, like GETing the file from a CDN. Then, you can use the > command to save the result of curl to a new file inside the vendor/assets/stylesheets sub-directory. The entire Terminal bash command will have this format: curl INSERT YOUR CDN LINK HERE > vendor/assets/stylesheets/YOUR NEW FILE NAME.

Examples for Boostrap and Materialize are below, but you may want to find and use the most recent version your CDN if it's no longer the version in the example.

$  curl https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css > vendor/assets/stylesheets/bootstrap-3.3.7.min.css
$  curl https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.2/css/materialize.min.css > vendor/assets/stylesheets/materialize-0.98.2.min.css

You should see that that file is now in your project's directory.

To include the CSS from the library file you just downloaded into your pages, require it in app/assets/stylesheets/application.css:

/*
 * app/assets/stylesheets/application.css
 */

/*
 *
 *= require bootstrap-3.3.7.min
 *= require_tree .
 *= require_self
 */

or

/*
 * app/assets/stylesheets/application.css
 */

/*
 *
 *= require materialize-0.98.2.min
 *= require_tree .
 *= require_self
 */

3. Define the root and creatures index routes

In your text editor, open up config/routes.rb. Inside the routes draw block, erase all the commented text.

You're about to see a hint! Throughout the instructions, there will be hints like this one that show you parts of the code. When you're running through the project a second time, try to use these less. The third time, try not to use them at all.

Hint: config/routes.rb should now look exactly like this...

#
# config/routes.rb
#
Rails.application.routes.draw do

end


Your routes tell your app how to direct HTTP requests to controller actions. Define your root route and your creatures index route to refer to the index method in the creatures controller:

Hint: updated routes

#
# config/routes.rb
#

Rails.application.routes.draw do
  root "creatures#index"

  get "/creatures", to: "creatures#index", as: "creatures"

end


In the Terminal, running rails routes will list all your routes. You'll see that some routes have a "prefix" listed. These routes have associated route helpers, which are methods Rails creates to generate URLs. The format of a route helper is prefix_path. For example, creatures_path is the full route helper for GET /creatures (the creatures index). We often use route helpers to generate URLs in forms, links, and controllers.

4. Set up the creatures controller and index action

Run the following command in the Terminal to generate a controller for creatures:

$  rails g controller creatures

Next, define the creatures#index action in the creatures controller. The variable @creatures should be all of the creatures in the db:

Hint: updated controller
#
# app/controllers/creatures_controller.rb
#
class CreaturesController < ApplicationController
# display all creatures
  def index
    # get all creatures from db and save to instance variable
    @creatures = Creature.all
    # render the index view (it has access to instance variable)
    # remember the default behavior is to render :index
  end
end

5. Set up the creature model

Run the following command in the Terminal to generate the Creature model:

$  rails g model creature name description

Run the migration to update the database with this change:

$  rails db:migrate

6. Create a creature

In the Terminal, enter the Rails console. The Rails console is built on top of irb, and it has access to your Rails project. Use it to create a new instance of a creature. This just lets us confirm that the model class is set up and the migration has run successfully.

$  rails c
irb(main):001:0> Creature.create({name: "Yoda", description: "Little green man"})

7. Seed your database

When you create an application in development, you typically want some mock data to play with. In Rails, you can just drop this into the db/seeds.rb file.

Back in Atom, add some seed data to db/seeds.rb:

#
# db/seeds.rb
#

Creature.create({name: "Luke", description: "Jedi"})
Creature.create({name: "Darth Vader", description: "Father of Luke"})

In the Terminal (not inside rails console!), run rails db:seed. Note that the seed file will also run every time you run rails db:reset to reset your database.

8. Set up the creatures index view

If you look inside the app/views directory, the /creatures folder has already been created (this happened when you ran rails g controller creatures). Add an index.html.erb file to the app/views/creatures folder.

Inside your creatures index view, iterate through all the creatures in the database, and display them on the page:

Hint: Here's one way that could look:

<!-- app/views/creatures/index.html.erb -->

<% @creatures.each do |creature| %>
  <p>
    <strong>Name:</strong> <%= creature.name %><br>
    <strong>Description:</strong> <%= creature.description %>
  </p>
<% end %>


9. Update the layout to use Bootstrap or Materialize classes.

You've set up a CSS library in this project, but you haven't used it yet. In your application's main layout (app/views/layouts/application.html.erb), add the basic container/row/column structure your library uses, around the <%= yield %>.

Hint: Here's one way that could look for Bootstrap:

<!-- app/views/layouts/application.html.erb -->
<!--  ...  -->
<body>
  <div class="container">
    <div class="row">
      <div class="col-md-6 col-md-offset-3">
        <%= yield %>
      </div>
    </div>
  </div>
</body>


Hint: Here's one way that could look for Materialize:

<!-- app/views/layouts/application.html.erb -->
<!--  ...  -->
<body>
  <div class="container">
    <div class="row">
      <div class="col m6 offset-m3">
        <%= yield %>
      </div>
    </div>
  </div>
</body>


Go to localhost:3000 in the browser. What do you see on the page? If you haven't already, git add and git commit the work you've done so far.

Part II: Make a creature with new (form) and create (database)

1. Define a route for the new creature form

The Rails convention is to make a form for new creatures at the /creatures/new path in our browser.

Hint: updated routes

#
#/config/routes.rb
#

Rails.application.routes.draw do
  root to: "creatures#index"

  get "/creatures", to: "creatures#index", as: "creatures"
  get "/creatures/new", to: "creatures#new", as: "new_creature"
end


2. Set up the creatures new action

When a user sends a GET request to /creatures/new, your server will search for a creatures#new action, so you need to create a controller method to handle this request. creatures#new should render the view new.html.erb inside the app/views/creatures folder.

Hint: updated controller

#
# app/controllers/creatures_controller.rb
#

class CreaturesController < ApplicationController

  ...

  # show the new creature form
  def new
    # remember the default behavior is to render :new
  end

end

3. Set up the view for the new creature form

Create the view new.html.erb inside the app/views/creatures folder. On this view, users should see a form to create new creatures in the database.

Hint: here's one way that could look:

<!-- app/views/creatures/new.html.erb -->

<%= form_for :creature, url: "/creatures", method: "post" do |f| %>
  <%= f.text_field :name %>
  <%= f.text_area :description %>
  <%= f.submit "Save Creature" %>
<% end %>

Note: The URL you're submitting the form to is /creatures because it's the database collection for creatures, and the method is post because you're creating a new creature.

Go to localhost:3000/creatures/new in the browser, and inspect the HTML for the form on the page. form_for is a "form helper", and it generates more than what you might guess from the erb you wrote in the view. Note the method and action in the form - what route do you think you should define next?

4. Define a route to create creatures in the database

Your new creature form has action="/creatures" and method="POST". The POST /creatures route doesn't exist yet, so go ahead and create it!

Hint: updated routes

#
#/config/routes.rb
#

Rails.application.routes.draw do
  root to: "creatures#index"

  get "/creatures", to: "creatures#index", as: "creatures"
  get "/creatures/new", to: "creatures#new", as: "new_creature"
  post "/creatures", to: "creatures#create"

end

5. Set up the creatures create action

The POST /creatures maps to the creatures#create controller action, so the next step is to define the controller method to handle this request. creatures#create should add a new creature to the database.

Hint: pseudocode

#
# app/controllers/creatures_controller.rb
#

class CreaturesController < ApplicationController

  # ...

  def create
    # whitelist params
    # create a new creature in the database from the params
    # if creature saves, redirect to route that displays all creatures
  end
end


Hint: the code:

#
# app/controllers/creatures_controller.rb
#

class CreaturesController < ApplicationController

  # ...

  # create a new creature in the database
  def create
    # whitelist params and save them to a variable
    creature_params = params.require(:creature).permit(:name, :description)

    # create a new creature from `creature_params`
    creature = Creature.new(creature_params)

    # if creature saves, redirect to route that displays all creatures
    if creature.save
      redirect_to creatures_path
      # redirect_to creatures_path is equivalent to:
      # redirect_to "/creatures"
    end
  end
end

6. Refactor the new creature form

Update your creatures#new action to send a new instance of a Creature to the new creature form.

Hint: updated controller

#
# app/controllers/creatures_controller.rb
#

class CreaturesController < ApplicationController

  ...

  # show the new creature form
  def new
    @creature = Creature.new
    # remember the default behavior is to render :new
  end

end

This sets @creature to a new instance of a Creature, which is automatically shared with the form in views/creatures/new.html.erb. This allows you to refactor the code for the form_for helper.

Hint: It might look something like this:

<!-- app/views/creatures/new.html.erb -->

<%= form_for @creature do |f| %>
  <%= f.text_field :name %>
  <%= f.text_area :description %>
  <%= f.submit "Save Creature" %>
<% end %>

Go to localhost:3000/creatures/new again in the browser, and inspect the HTML for the form on the page. Did anything change?

7. Define a route to show a specific creature

Right now, your app redirects to /creatures after creating a new creature, and the new creature shows up at the bottom of the page. Let's make a route for users to see a specific creature. Then, you'll be able to show a new creature by itself right after it's created.

First, define a show route.

Hint: updated routes

#
# config/routes.rb
#

Rails.application.routes.draw do
  root to: "creatures#index"

  get "/creatures", to: "creatures#index", as: "creatures"
  get "/creatures/new", to: "creatures#new", as: "new_creature"
  post "/creatures", to: "creatures#create"
  get "/creatures/:id", to: "creatures#show", as: "creature"
end

Now that you have your show route, set up the controller action for creatures#show.

Hint: updated controller

#
# app/controllers/creatures_controller.rb
#

class CreaturesController < ApplicationController

  ...

  # display a specific creature
  def show
    # get the creature id from the url params
    creature_id = params[:id]

    # use `creature_id` to find the creature in the database
    # and save it to an instance variable
    @creature = Creature.find_by_id(creature_id)

    # render the show view (it has access to instance variable)
    # remember the default behavior is to render :show
  end

end

Next, create the view to display a single creature:

Hint: It might look like this:

<!-- app/views/creatures/show.html.erb -->

<h3><%= @creature.name %></h3>
<p><%=  @creature.description %></p>

8. Refactor the creatures#create redirect

The creatures#create method currently redirects to /creatures. Again, this isn't very helpful for users who want to verify that they successfully created a single creature. The best way to fix this is to have it redirect to /creatures/:id instead.

Hint: updated pseudocode

#
# app/controllers/creatures_controller.rb
#

class CreaturesController < ApplicationController

  ...

  def create
    # whitelist params 
    # create a new creature from `creature_params`
    # if creature saves, redirect to route that displays ONLY the newly created creature
  end
end


Hint: updated code

#
# app/controllers/creatures_controller.rb
#

class CreaturesController < ApplicationController

  ...

  # create a new creature in the database
  def create
    # whitelist params and save them to a variable
    creature_params = params.require(:creature).permit(:name, :description)

    # create a new creature from `creature_params`
    creature = Creature.new(creature_params)

    # if creature saves, redirect to route that displays
    # ONLY the newly created creature
    if creature.save
      redirect_to creature_path(creature)
      # redirect_to creature_path(creature) is equivalent to:
      # redirect_to "/creatures/#{creature.id}"
    end
  end

end

Make sure to git add and git commit again once you have new, create, and show working.

Part III: Change a creature with edit (form) and update (database)

Don't Give Up!!!

Editing a specific creature requires two methods:

  • edit displays a form with the existing creature info to be edited by the user
  • update changes the creature info in the database when the user submits the form

1. Define a route for the edit creature form

Hint: updated routes

#
# config/routes.rb
#

Rails.application.routes.draw do
  root to: "creatures#index"

  get "/creatures", to: "creatures#index", as: "creatures"
  get "/creatures/new", to: "creatures#new", as: "new_creature"
  post "/creatures", to: "creatures#create"
  get "/creatures/:id", to: "creatures#show", as: "creature"
  get "/creatures/:id/edit", to: "creatures#edit", as: "edit_creature"
end

2. Set up the creatures edit action

Using your creatures#new and creatures#show methods as inspiration, you can write the creatures#edit method in the creatures controller:

Hint: updated controller pseudocode

#
# app/controllers/creatures_controller.rb
#

class CreaturesController < ApplicationController

  ...

  # show the edit creature form
  def edit
    # get the creature id from the url params
    
    # use `creature_id` to find the creature in the database
      # and save it to an instance variable
    # render the edit view (it has access to instance variable)
  end
end

Hint: updated controller code

#
# app/controllers/creatures_controller.rb
#

class CreaturesController < ApplicationController

  ...

  # show the edit creature form
  def edit
    # get the creature id from the url params
    creature_id = params[:id]

    # use `creature_id` to find the creature in the database
    # and save it to an instance variable
    @creature = Creature.find_by_id(creature_id)

    # render the edit view (it has access to instance variable)
    # remember the default behavior is to render :edit
  end

end

3. Set up the view for the edit creature form

Create an edit.html.erb view inside views/creatures. Jump-start the edit form by copying the form from views/creatures/new.html.erb into views/creatures/edit.html.erb:

Hint: it might look like this

<!-- app/views/creatures/edit.html.erb -->

<%= form_for @creature do |f| %>
  <%= f.text_field :name %>
  <%= f.text_area :description %>
  <%= f.submit "Save Creature" %>
<% end %>

Go to localhost:3000/creatures/1/edit in the browser to see what it looks like so far. Check the method and action of the form. Also look at the hidden input with name="_method". What is it doing? The Rails form helper knows to turn this same code into an edit form because you're on the edit page!

4. Define a route to update a specific creature

The update route will use the id of the creature to be updated. In Express, you decided between PUT /creatures/:id and PATCH /creatures/:id, depending on the type of update you wanted to do. In Rails, the default assumption is that you'll have both! However, we'll only need to add PATCH /creatures/:id to our routes.

Hint: updated routes

#
# config/routes.rb
#

Rails.application.routes.draw do
  root to: "creatures#index"

  get "/creatures", to: "creatures#index", as: "creatures"
  get "/creatures/new", to: "creatures#new", as: "new_creature"
  post "/creatures", to: "creatures#create"
  get "/creatures/:id", to: "creatures#show", as: "creature"
  get "/creatures/:id/edit", to: "creatures#edit", as: "edit_creature"
  patch "/creatures/:id", to: "creatures#update"
  # put "/creatures/:id", to: "creatures#update"    # optional
end

Run rails routes in the Terminal to see the newly created update routes.

5. Set up the creatures update action

In the CreaturesController, define an update method:

Hint: pseudocode

#
# app/controllers/creatures_controller.rb
#

class CreaturesController < ApplicationController

  ...

  # update a creature in the database
  def update
    # get the creature id from the url params
    # use `creature_id` to find the creature in the database and save to variable
    # whitelist params 
    # update the creature based on params
    # redirect to show page for the updated creature
  end

end


Hint: code

#
# app/controllers/creatures_controller.rb
#

class CreaturesController < ApplicationController

  ...

  # update a creature in the database
  def update
    # get the creature id from the url params
    creature_id = params[:id]

    # use `creature_id` to find the creature in the database
    creature = Creature.find_by_id(creature_id)

    # whitelist params and save them to a variable
    creature_params = params.require(:creature).permit(:name, :description)

    # update the creature
    creature.update_attributes(creature_params)

    # redirect to show page for the updated creature
    redirect_to creature_path(creature)
    # redirect_to creature_path(creature) is equivalent to:
    # redirect_to "/creatures/#{creature.id}"
  end

end

6. Refactor whitelisted params.

Now that params are whitelisted in two different places in the CreaturesController, refactor so that these params are set up in their own method. This method can (and should!) be private because it will only ever be used inside the CreaturesController class definition.

Hint: pseudocode

#
# app/controllers/creatures_controller.rb
#

class CreaturesController < ApplicationController

  ...

  # update a creature in the database
  def update
    # get the creature id from the url params
    # use `creature_id` to find the creature in the database
      # and save it to an instance variable
    # update the creature based on whitelisted params returned by private method
    # redirect to show page for the updated creature
  end
  
  private
  
  def creature_params
    # whitelist params return whitelisted version
  end

end


Hint: code

#
# app/controllers/creatures_controller.rb
#

class CreaturesController < ApplicationController

  ...

  # update a creature in the database
  def update
    # get the creature id from the url params
    creature_id = params[:id]

    # use `creature_id` to find the creature in the database
    # and save it to an instance variable
    creature = Creature.find_by_id(creature_id)

    # update the creature
    creature.update_attributes(creature_params)  # this now calls the private method below!

    # redirect to show page for the updated creature
    redirect_to creature_path(creature)
    # redirect_to creature_path(creature) is equivalent to:
    # redirect_to "/creatures/#{creature.id}"
  end
  
  private
  
  def creature_params
    # whitelist params return whitelisted version
    params.require(:creature).permit(:name, :description) 
  end

end

Refactor the create action to use this private method as well.

Manually re-test your creatures#create method in the browser. Then, test your creatures#update method in the browser by editing the creature with an id of 1 (go to localhost:3000/creatures/1/edit). Then, git add and git commit your work.

Part IV: Delete a creature with destroy (database)

1. Define a route to destroy a specific creature

Following a similar pattern to our other routes, create a route to destroy (delete) a specific creature based on its id.

Hint: updated routes

#
# config/routes.rb
#

Rails.application.routes.draw do
  root to: "creatures#index"

  get "/creatures", to: "creatures#index", as: "creatures"
  get "/creatures/new", to: "creatures#new", as: "new_creature"
  post "/creatures", to: "creatures#create"
  get "/creatures/:id", to: "creatures#show", as: "creature"
  get "/creatures/:id/edit", to: "creatures#edit", as: "edit_creature"
  patch "/creatures/:id", to: "creatures#update"
  delete "/creatures/:id", to: "creatures#destroy"
end

At this point, you're using all the required RESTful routes for creatures (feel free to add optional PUT).

2. Set up the creatures destroy action

In the CreaturesController, define an destroy method:

Hint: pseudocode

#
# app/controllers/creatures_controller.rb
#

class CreaturesController < ApplicationController

  ...

  # delete a creature from the database
  def destroy
    # get the creature id from the url params
    # use `creature_id` to find the creature in the database and save it to a variable
    # destroy the creature
    # redirect to creatures index
  end

end


Hint: code

#
# app/controllers/creatures_controller.rb
#

class CreaturesController < ApplicationController

  ...

  # delete a creature from the database
  def destroy
    # get the creature id from the url params
    creature_id = params[:id]

    # use `creature_id` to find the creature in the database
    # and save it to a variable
    creature = Creature.find_by_id(creature_id)

    # destroy the creature
    creature.destroy

    # redirect to creatures index
    redirect_to creatures_path
    # redirect_to creatures_path is equivalent to:
    # redirect_to "/creatures"
  end

end

3. Add a delete button

Add a delete button to the view that displays a single creature:

Hint: It could look something like:

<!-- app/views/creatures/show.html.erb -->

<h3><%= @creature.name %></h3>
<p><%=  @creature.description %></p>
<%= button_to "Delete", @creature, method: :delete %>

Visit localhost:3000/creatures/1 in the browser, and inspect the HTML for the delete button. Click the delete button to manually test this feature.

At this point, you've created all the RESTful routes, implemented controller actions for each route, and made views for index, show, new, and edit. You've also created the Creature model in the database and manually tested that everything works.

Additional Development Ideas for after Version 4

  • Add links to other pages to help users navigate your site. For instance, a creature show page might have a link to the creatures index page. Use link_to. Also link each creature on creatures#index to its individual show page.
  • If you'd like, add a navbar with links to the homepage (/) and the new creatures page (/creatures/new). This navbar should show up on every page. Take advantage of whichever CSS library you chose to include!
  • Read about Active Record Validations, and add validations to the Creature model to make sure a new creature can't be created without a name and description.
  • Read the docs for the Paperclip gem, and incorporate it into your Bog App to upload photos of creatures locally.

CONGRATULATIONS! You have created a Bog App! Take a break, you look Swamped!

rails_bog_app's People

Contributors

cameronjacoby avatar bgveenstra avatar ajbraus avatar cofauver avatar jeanmw avatar nathanallen avatar justincastilla avatar rycwilson avatar nick-brennan avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.