Git Product home page Git Product logo

sinatra-restful-routes-lab's Introduction

Restful Routes Basic Lab

Objectives

  • Build RESTful routes to create, show, edit, and delete items from the database

Instructions

Instead of keeping all your recipes on index cards (just like your grandma did!), we're going to be building a web app to store those recipes for you!

  1. Create a new table in the database to store the recipes. Recipes should have a name, ingredients (which can be written as one string containing all the ingredients), and cook_time. These attributes should each be a string.

  2. Make sure you have a corresponding model for your recipes.

  3. In the application_controller.rb, set up a controller action that will render a form to create a new recipe. This controller action should create and save this new recipe to the database.

  4. Again in the application_controller.rb, create a controller action that uses RESTful routes to display a single recipe.

  5. Create a third controller action that uses RESTful routes and renders a form to edit a single recipe. This controller action should update the entry in the database with the changes, and then redirect to the recipe show page.

  6. Create a controller action (index action) that displays all the recipes in the database.

  7. Add to the recipe show page a form that allows a user to delete a recipe. This form should submit to a controller action that deletes the entry from the database and redirects to the index page.

sinatra-restful-routes-lab's People

Contributors

bhollan avatar cernanb avatar danielseehausen avatar dependabot[bot] avatar graciemcguire avatar ihollander avatar joshuabamboo avatar lizbur10 avatar maxwellbenton avatar pletcher avatar rishter avatar rrcobb avatar ruchiramani avatar sophiedebenedetto avatar sylwiavargas avatar victhevenot avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sinatra-restful-routes-lab's Issues

Rspec issue

I could not get the "redirects to the recipe show page" test to pass (line 120) even though everything seemed correct. I kept getting this error:

  1. Recipe App creating a new recipe redirects to the recipe show page
    Failure/Error: expect(last_request.url).to include("/recipes/#{Recipe.last.id}")
    expected "http://example.org/recipes" to include "/recipes/3"

"http://example.org/recipes" seemed to be the problem, so I changed line 121 in the test file to this:
from "expect(last_request.url…"
to "expect(last_response.body…"

Can someone please advise?

Passing the tests even though my form/post route do not match up

Passed tests without the correct name tag in my form.

My new.erb file should not have been passing given the recipe in the name fields below.
`

Make your Recipe Card!

Recipe Name: Recipe Ingredients: Recipe Cook Time: `

And here is the corresponding post route:

post '/recipes' do @recipe = Recipe.create(name: params['name'], ingredients: params['ingredients'], cook_time: params['cook_time']) redirect "/recipes/#{@recipe.id}" end

To work correctly in the browser the name:, ingredient: and cook_time: values need to also have the recipe[whatever], it does not work in the browser with this setup and yet I still pass the tests

Bundle install informs of errors in Gemfile from rspec, rack-test, database_cleaner

Your Gemfile lists the gem rspec (>= 0) more than once.
You should probably keep only one of them.
While it's not a problem now, it could cause errors if you change the version of just one of them later.
Your Gemfile lists the gem rack-test (>= 0) more than once.
You should probably keep only one of them.
While it's not a problem now, it could cause errors if you change the version of just one of them later.
Your Gemfile lists the gem database_cleaner (>= 0) more than once.
You should probably keep only one of them.
While it's not a problem now, it could cause errors if you change the version of just one of them later.

Original Gemfile

gem 'activerecord', :require => 'active_record'
gem 'sinatra-activerecord', :require => 'sinatra/activerecord'

gem 'sinatra'
gem 'sqlite3'
gem 'tux'
gem 'pry'
gem 'pry-nav'
gem 'rake'
gem 'rspec'
gem 'rack-test'
gem 'database_cleaner', git: 'https://github.com/bmabey/database_cleaner.git'
gem 'require_all'

group :test do
  gem 'rspec'
  gem 'capybara'
  gem 'rack-test'
  gem 'database_cleaner', git: 'https://github.com/bmabey/database_cleaner.git'
end

Suggested Edits

Eliminated dupes and grouped testing gems into test block.

source 'http://rubygems.org'

gem 'activerecord', :require => 'active_record'
gem 'sinatra-activerecord', :require => 'sinatra/activerecord'

gem 'sinatra'
gem 'sqlite3'
gem 'tux'
gem 'rake'
gem 'require_all'

group :test do
  gem 'rspec'
  gem 'pry'
  gem 'pry-nav'
  gem 'capybara'
  gem 'rack-test'
  gem 'database_cleaner', git: 'https://github.com/bmabey/database_cleaner.git'
end

Test run fine after edits so far. still haven't completed lab just started.

third lab that wont allow migrate

I worked with yet another tc session was need to resolve a lab that cloned, but its file were too outdated to migrate the required database.

Also for db issues Have you tried deleting the db file and re-running the migrations? Also try rake db:rollback STEP=5, then do rake db:migrate If that doesn't work delete your db file (probably ending in .sqlite) and run migrate again.
User avatar
Tao Liu 8 MINUTES AGO
Sure
Renee Sims 2 MINUTES AGO
thanks deleted the db folder and had to reinstall activerecord 5.1 and sqlite3 ~> 1.3.13.

unfortunately, the lab loaded active record 4.2.5 and sequel 1.3.6 which would not run.

Specs are out of order compared to README\Lab instructions

From the README

  1. In the application_controller.rb, set up a controller action that will render a form to create a new recipe. This controller action should create and save this new recipe to the database.
  2. Again in the application_controller.rb, create a controller action that uses RESTful routes to display a single recipe.

This implies we build our create logic first before the show logic. However the specs have creation logic last.

Original Code

require 'spec_helper'

describe "Recipe App" do
  let(:recipe_name) { "Bomb.com Mac and Cheese" }
  let(:recipe_ingredients) { "milk, butter, cheese, elbow pasta" }
  let(:recipe_cook_time) { "20 minutes" }

  before do
    @recipe1 = Recipe.create(:name => recipe_name, :ingredients => recipe_ingredients, :cook_time => recipe_cook_time)
    @recipe2 = Recipe.create(:name => "waldorf salad", :ingredients => "apples, cabbage, oil, vinegar", :cook_time => "0")
  end

  describe "Index page '/recipes'" do
    before do
      get "/recipes"
    end

    it 'responds with a 200 status code' do
      expect(last_response.status).to eq(200)
    end

    it "displays a list of recipes" do
      expect(last_response.body).to include(recipe_name)
      expect(last_response.body).to include(@recipe2.name)

    end

    it "contains links to each recipe's show page" do
      expect(last_response.body).to include("/recipes/#{@recipe1.id}")
    end
  end


  describe "show page '/recipes/:id'" do
    before do
      get "/recipes/#{@recipe1.id}"
    end

    it 'responds with a 200 status code' do
      expect(last_response.status).to eq(200)
    end

    it "displays the recipe's name" do
      expect(last_response.body).to include(recipe_name)

    end

    it "displays the recipe's ingredients" do
      expect(last_response.body).to include(recipe_ingredients)
    end

    it "displays the recipe's cook time" do
      expect(last_response.body).to include(recipe_cook_time)
    end

    it "contains a links to delete the recipe" do
      expect(last_response.body).to include("/recipes/#{@recipe1.id}/delete")
    end

    it 'deletes via a DELETE request' do
      expect(last_response.body).to include('<input id="hidden" type="hidden" name="_method" value="delete">')
    end
  end

  describe "edit page '/recipes/:id/edit'" do
    before do
      get "/recipes/#{@recipe1.id}/edit"
    end

    it 'responds with a 200 status code' do
      expect(last_response.status).to eq(200)
    end

    it "contains a form to edit the recipe" do
      expect(last_response.body).to include("</form>")

    end

    it "displays the recipe's ingredients before editing" do
      expect(last_response.body).to include(recipe_ingredients)
    end

    it "submits via a patch request" do
      expect(last_response.body).to include('<input id="hidden" type="hidden" name="_method" value="patch">')
    end

  end

  describe "new page '/recipes/new'" do
    before do
      get "/recipes/new"
    end

    it 'responds with a 200 status code' do
      expect(last_response.status).to eq(200)
    end

    it "contains a form to create the recipe" do
      expect(last_response.body).to include("</form>")
    end
  end

  describe "creating a new recipe" do 
    before do 
      params = {
        "name" => "pumpkin pie",
        "ingredients" => "pumpkin, flour, butter, sugar",
        "cook_time" => "1 hour"
      }

      post '/recipes', params
      follow_redirect!
    end
    it "creates a new recipe and saves to the database" do 
      expect(Recipe.all.count).to eq(3)
      expect(Recipe.last.name).to eq("pumpkin pie")
    end

    it "redirects to the recipe show page" do 
      expect(last_request.url).to include("/recipes/#{Recipe.last.id}")
    end
  end

  describe "updating a recipe" do
    before do
      @cookie = Recipe.create(
        name:   "Chocolate Chip Cookies", 
        ingredients:  "chocolate chips, flour, sugar, butter", 
        cook_time:  "30 minutes", 
      )
      visit "/recipes/#{@cookie.id}/edit"
      fill_in "recipe_name", :with => "Double chocolate chip cookies"
      fill_in "ingredients_names", :with => "chocolate chips, flour, sugar, butter, cocoa powder"
      fill_in "cook_time", :with => "30 minutes"
      click_button "submit"
    end

    it "redirects to the recipe show page" do
      expect(page.current_path).to eq("/recipes/#{@cookie.id}")
      expect(page).to have_content("Double chocolate chip cookies")
      expect(page).to have_content("chocolate chips, flour, sugar, butter, cocoa powder")
      expect(page).to have_content("30 minutes")
    end
  end

  describe "deleting a recipe" do
    before do
      @cookie = Recipe.create(
        name:   "Chocolate Chip Cookies", 
        ingredients:  "chocolate chips, flour, sugar, butter", 
        cook_time:  "30 minutes", 
      )
      visit  "/recipes/#{@cookie.id}"
      click_button "delete"
    end

    it "deletes a recipe" do
      expect(Recipe.find_by_id(@cookie.id)).to eq(nil)
    end
  end

end

Suggested Edits

moved creation logic above show logic and removed newline code smell

require 'spec_helper'

describe "Recipe App" do
  let(:recipe_name) { "Bomb.com Mac and Cheese" }
  let(:recipe_ingredients) { "milk, butter, cheese, elbow pasta" }
  let(:recipe_cook_time) { "20 minutes" }

  before do
    @recipe1 = Recipe.create(:name => recipe_name, :ingredients => recipe_ingredients, :cook_time => recipe_cook_time)
    @recipe2 = Recipe.create(:name => "waldorf salad", :ingredients => "apples, cabbage, oil, vinegar", :cook_time => "0")
  end

  describe "Index page '/recipes'" do
    before do
      get "/recipes"
    end

    it 'responds with a 200 status code' do
      expect(last_response.status).to eq(200)
    end

    it "displays a list of recipes" do
      expect(last_response.body).to include(recipe_name)
      expect(last_response.body).to include(@recipe2.name)
    end

    it "contains links to each recipe's show page" do
      expect(last_response.body).to include("/recipes/#{@recipe1.id}")
    end
  end

  describe "new page '/recipes/new'" do
    before do
      get "/recipes/new"
    end

    it 'responds with a 200 status code' do
      expect(last_response.status).to eq(200)
    end

    it "contains a form to create the recipe" do
      expect(last_response.body).to include("</form>")
    end
  end

  describe "creating a new recipe" do 
    before do 
      params = {
        "name" => "pumpkin pie",
        "ingredients" => "pumpkin, flour, butter, sugar",
        "cook_time" => "1 hour"
      }

      post '/recipes', params
      follow_redirect!
    end

    it "creates a new recipe and saves to the database" do 
      expect(Recipe.all.count).to eq(3)
      expect(Recipe.last.name).to eq("pumpkin pie")
    end

    it "redirects to the recipe show page" do 
      expect(last_request.url).to include("/recipes/#{Recipe.last.id}")
    end
  end

  describe "show page '/recipes/:id'" do
    before do
      get "/recipes/#{@recipe1.id}"
    end

    it 'responds with a 200 status code' do
      expect(last_response.status).to eq(200)
    end

    it "displays the recipe's name" do
      expect(last_response.body).to include(recipe_name)
    end

    it "displays the recipe's ingredients" do
      expect(last_response.body).to include(recipe_ingredients)
    end

    it "displays the recipe's cook time" do
      expect(last_response.body).to include(recipe_cook_time)
    end

    it "contains a links to delete the recipe" do
      expect(last_response.body).to include("/recipes/#{@recipe1.id}/delete")
    end

    it 'deletes via a DELETE request' do
      expect(last_response.body).to include('<input id="hidden" type="hidden" name="_method" value="delete">')
    end
  end

  describe "edit page '/recipes/:id/edit'" do
    before do
      get "/recipes/#{@recipe1.id}/edit"
    end

    it 'responds with a 200 status code' do
      expect(last_response.status).to eq(200)
    end

    it "contains a form to edit the recipe" do
      expect(last_response.body).to include("</form>")
    end

    it "displays the recipe's ingredients before editing" do
      expect(last_response.body).to include(recipe_ingredients)
    end

    it "submits via a patch request" do
      expect(last_response.body).to include('<input id="hidden" type="hidden" name="_method" value="patch">')
    end

  end

  describe "updating a recipe" do
    before do
      @cookie = Recipe.create(
        name:   "Chocolate Chip Cookies", 
        ingredients:  "chocolate chips, flour, sugar, butter", 
        cook_time:  "30 minutes", 
      )
      visit "/recipes/#{@cookie.id}/edit"
      fill_in "recipe_name", :with => "Double chocolate chip cookies"
      fill_in "ingredients_names", :with => "chocolate chips, flour, sugar, butter, cocoa powder"
      fill_in "cook_time", :with => "30 minutes"
      click_button "submit"
    end

    it "redirects to the recipe show page" do
      expect(page.current_path).to eq("/recipes/#{@cookie.id}")
      expect(page).to have_content("Double chocolate chip cookies")
      expect(page).to have_content("chocolate chips, flour, sugar, butter, cocoa powder")
      expect(page).to have_content("30 minutes")
    end
  end

  describe "deleting a recipe" do
    before do
      @cookie = Recipe.create(
        name:   "Chocolate Chip Cookies", 
        ingredients:  "chocolate chips, flour, sugar, butter", 
        cook_time:  "30 minutes", 
      )
      visit  "/recipes/#{@cookie.id}"
      click_button "delete"
    end

    it "deletes a recipe" do
      expect(Recipe.find_by_id(@cookie.id)).to eq(nil)
    end
  end

end

"Creating a new recipe" test gives wrong value for params

The rspec file contains the following test:

describe "creating a new recipe" do 
    before do 
      params = {
        "name" => "pumpkin pie",
        "ingredients" => "pumpkin, flour, butter, sugar",
        "cook_time" => "1 hour"
      }

      post '/recipes', params
      follow_redirect!
    end
    it "creates a new recipe and saves to the database" do 
      expect(Recipe.all.count).to eq(3)
      expect(Recipe.last.name).to eq("pumpkin pie")
    end

    it "redirects to the recipe show page" do 
      expect(last_request.url).to include("/recipes/#{Recipe.last.id}")
    end
  end

However, it sets params equal to only the hash

      {
        "name" => "pumpkin pie",
        "ingredients" => "pumpkin, flour, butter, sugar",
        "cook_time" => "1 hour"
      }

rather than a properly formatted nested params hash, such as

{
  "recipes" =>  {
    "name" => "pumpkin pie",
    "ingredients" => "pumpkin, flour, butter, sugar",
    "cook_time" => "1 hour"
  }
}

Therefore, in order to pass the test, one would have to provide an answer such as Recipe.create(params), which is counterintuitive to how we've been taught to format a params hash.

The Pry gem needs to be moved outside of the "test" group in the Gemfile

Hi. I tried to use rake console when I wanted to test out my database. However, I got an error because of an "uninitialized constant Pry".

It turns out that the the Pry gem in the Gemfile is only inside of the "test" environment, but the Rakefile (where rake console is defined) uses the "development" environment. Because of that, I can't use rake console from the terminal.

Instead of putting gem 'pry' inside of the "test" group in the Gemfile, put it with the other ("default" environment) gems above it.

Thanks as always for looking into this!

---Sdcrouse

Possible typo in the spec tests

The test set "creating a new recipe" seems to have a typo on line 127. The code shows the following:

describe "creating a new recipe" do 
    before do 
      params = {
        "name" => "pumpkin pie",
        "ingredients" => "pumpkin, flour, butter, sugar",
        "cook_time" => "1 hour"
      }
      post '/recipes', params
      follow_redirect!
    end

Believe that post'/recipes', params should be post '/recipes/new', params. I've changed line 127 in the tests and moved on with the lab.

Tests for inputs do not include closing tag

The tests for this lesson look for an input tag without a proper closing tag, eg. include("<input>") instead of include("<input/>"). This can become problematic when using Capybara to test form submission, so these tests should not be reinforcing it.

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.