CLI data gem project

I am revisiting an earlier attempt at the CLI data gem project. I went through Avi's related video carefully and feel l understand what we are doing here and how useful creating our own gems can be. The idea of my gem is to create a handy list of upcoming movies that will be released in theaters for movie fans interested in what films are on the horizon. 

In this project I've added pry and nokogiri to the gemspec so we can get website data in the terminal. Pry is an irb alternate that lets us browse source code and documents. And Nokogiri is a very helpful HTML parser so we can access pieces of an html page to use in our Ruby code.

My upcoming-movies rb file in my library folder requires Pry, Nokogiri and Open-Uri as well. Open-uri allows us to open a website as a file. I don't feel too familiar with this but hope to learn more about how it works in the future. We also require-relative the three ruby pages in my library>upcoming-movies folder. We use the a version.rb to keep track of our own versioning. Most of the code for the project is in the cli.rb and movies.rb files. It was great seeing Avi think through the logic for what we want the command line interface to do. I find it intimidating to write code from scratch still. I went through this carefully and reviewed a few procedural Ruby lessons but do need to think through a bit more how these two files work together. Some of the language feels abstract to me still.  

In the movies.rb file we set up attr_accessor (read/write) variables for all the things about an upcoming movie release we would like to display. I switched around a few of the options because I started with looking at the Box Office Mojo site list and the IMDB upcoming list was easier to scrape and did not have a large messy table to contend with. Not sure why we need both a self.today and self.scrape_movies.  I think it's because the today method stands for what we are doing and the scrape method is more the information itself that we push upwards to the today method. In the scrape_movies method we create an array of movies, shovel in information from the scrape_imdb and return this information. The last method is the self.scrape_imdb. We have a doc variable which connects us to an imdb page with help from Nokogiri. We create a new movie and use and list where and how we find movie names, dates, genre by scraping the imdb website. 

For me, scraping itself was the hardest part of the assignment. I definitely did some trial and error in searches to isolate information on what is a fairly complex live internet page. With a point in the right direction, the bottom bar in the Javascript console helps visualize the DOM path. One thing I ran into was a needing to point upwards to grab a few things like date and genre. Also found that I had oftentimes multiple genres to contend with, between one and three so one couldn't just call the first then the second or something as a straight list and still hope the connect to the movie titles which could be listed more linearly. I discovered you can call a "span:nth-child(1)" so you could access the first genre listed, etc. I also found out you can look at which movie on this updating movie page by referring to its array number. See image especially the last lines!  

 

 

 

 

 

 

 

 

 

 

 

One things was interesting to be was that what I scraped in Nokogiri didn't quite match up to what would display if I ran ./bin/upcoming-movies to see the final output. Not sure why this is. I had the best luck in terminal if I referred to each variable with an array number.

The cli.rb file has more connection to the actual operation of the CLI. We're adding the info from the upcoming-movies.rb file here via UpcomingMovies::Movies.today. The call method is currently a container for the other method. list_movies has an each.with_index which has two parameters the second is a number so we can have a numbered list of returns. I added an array to return 7 results but have managed to return the first movie seven times! Need a tiny bit of help to wire this to return not just the movie # + date, length, etc. but also multiple movies in order.  The next method asks us if we want to hear about any of the movies and prints the related movie description if we press a movie number. If there's no typed input we put to the terminal 'enter the movie you would like to hear about' and if the input is more than zero we put the proper movie description. We have an eslif that that if you enter 'list' we can return the original list of movies again. We have a message for an input we don't recognize and a goodbye message if you type exit to leave. This is the project process currently:

Screen Shot 2016-09-02 at 7.22.14 PM.png

 

Things I would be interested in working on:
1 - how to call multiple span:nth-child(1). Is there a better way than just a list here?  
2 - putting a variable into the arrays so I can display multiple movies. An array for a group of arrays?

lib>upcoming releases>cli.rb
3 - strange . after the movie.date?
4 - fixing the menu method in cli.rb so you only enter a number between 1-7.  
5 - hook up entering 'list' at the end of a movie description so someone can return to the beginning after reading a description.  
6 - Add a note to tell people you need to type 'exit' to quit and detach it from the bad input message.  
7 - The menu method feels messy in general. is there a way to simplify and clean up after changes have been made?  

video Block
Double-click here to add a video by URL or embed code. Learn more.

 

What else could be added:
A longer list of titles
The director, stars and rating from the page I'm scraping
Open a browser to the imdb page for the movie if someone wanted
List related upcoming titles by genre?
List previous movies by director?  
 

 

Angular Project

Working on a rails/angular recipe-maker project today with some help from Aaron Figueroa. I thought it might be useful to write out the steps we went through so I can look back and try this again! 

1. Rails new project:

rails new recipe-maker --skip-javascript

Then bundle install. We didn't add a --database=postgresql.

 

2. Rails models. Created these models including a join: 

rails g model Recipe name:string --no-test-framework
rails g model Ingredient name:string --no-test-framework
rails g model RecipeIngredient recipe_id:integer ingredient_id:integer--no-test-framework

 

3. Migrate. In Rails 5 you can now run (rails -v to see version):

rails db:migrate

 

4. Seeding. Aaron stubbed out seed info 

recipe = Recipe.create(name: "poundcake")
recipe2 = Recipe.create(name: "pad thai")

ingredient = Ingredient.create(name: "noodles")
ingredient2 = Ingredient.create(name: "milk")

recipejoin = RecipeIngredient.create(recipe_id:recipe.id, ingredient_id: ingredient2.id)
recipejoin2 = RecipeIngredient.create(recipe_id: recipe2.id, ingredient_id: ingredient.id)

then: rails db:seed

 

5. Test to see if seed data is accessible:

rails c
recipe = recipe.first  

this returns: 

Recipe Load (0.2ms)  SELECT"recipes".* FROM "recipes" ORDER BY "recipes"."id" ASC LIMIT ?  [["LIMIT", 1]]

 => #<Recipe id: 1, name: "poundcake", created_at: "2016-08-29 17:33:51", updated_at: "2016-08-29 17:33:51"> 

 

6. Pretty sure next we created models with activerecord associations. 

ingredient.rb: 

class Ingredient < ApplicationRecord
  has_many :recipe_ingredients
  has_many :recipes, through: :recipe_ingredients
end

recipe.rb

class Recipe < ApplicationRecord
has_many :recipe_ingredients
  has_many :ingredients, through: :recipe_ingredients
end

 

recipe_ingredient.rb

class RecipeIngredient < ApplicationRecord
  belongs_to :recipe
  belongs_to :ingredient
end

 

7. Create serializers. I need to review serializers as I'm not 100% on their role right at the moment. 

rails g serializer Recipe
rails g serializer Ingredient

and inside the files:  

ingredient_serializer.rb:
class IngredientSerializer < ActiveModel::Serializer
  attributes :id, :name
  has_many :recipes
end

recipe_serializer.rb:
class RecipeSerializer < ActiveModel::Serializer
  attributes :id, :name
  has_many :ingredients
end

 

8. Create controllers. We added a bunch of the crud methods on in definition which I haven't done much. Good idea Aaron. 

rails g controller Recipes index create show update destroy --no-test-framework
rails g controller Ingredients index create show update destroy --no-test-framework
 

 

9. Rails Routes to see if our restful routes are lookin good.  

rails routes

 

10. Run our server for the first time to see if we're connected with rails. We are!

rails s (or rails server) 

 

11. In app>javascripts we need an application.js file our manifest file with information on all the files we require to run our app. 

//= require jquery

//= require angular.min

//= require angular-ui-router
//= require angular-rails-templates
//= require angular-sanitize.min
//= require bootstrap-sprockets
//= require_tree .

 

12. Routes.rb Add resources to routes. This might have happened a little earlier!  

 resources :recipes
 resources :ingredients

 

13. RecipesController. connecting our recipes controller to render json like this (I know a few of these method can be removed):

class RecipesController < ApplicationController
  def index
    recipes = Recipe.all
  respond_to do |format|
      format.html
      format.json { render json: recipes}
    end
  end

  def create
  end

  def show
    recipe = Recipe.find(params[:id])
    render json: recipe
  end

  def update
  end

  def destroy
  end
end

 

14. We have added the following to the Gemfile. I don't know what they all do and don't remember the order we added them. It'd be worth looking up each one again and thinking through why we need it.   

gem 'jbuilder', '~> 2.5'
gem 'jquery-rails'
gem 'active_model_serializers', '~> 0.10.0'
gem 'jbuilder', '~> 2.5'
gem 'rack-cors'
gem 'angular-rails-templates'
gem 'bootstrap-sass', '~> 3.3.6'
gem 'autoprefixer-rails'

 

 

15. Find these files (ie, angular-ui-router.js) and add to app>javascripts. From here we are testing against the server and beginning to set up angular. Hoping I have the order of events right here. Let's see if I can remember.

 

16. Routes.rb. We have already added resources to our routes. get and root we added in here as well:

Rails.application.routes.draw do
  get 'home/index'

 resources :recipes
 resources :ingredients

 root 'home#index'

  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

 

17. Added a home controller manually. Not sure how central this is to our operations. I might have done this in the beginning?  

class HomeController < ApplicationController
  def index
  end
end 

 

18. App.js in app>assets>javascripts>app>app.js. We've rerouted this to look for template files but the rails views we did I've listed next.  

angular
  .module('app', ['ui.router', 'templates', 'ngSanitize'])
  .config(function($stateProvider, $urlRouterProvider){

    $stateProvider
      .state('home', {
        url: '/',
        templateUrl:'home.html',
        controller: 'HomeController as vm'
      })
      .state('home.recipes', {
        url: 'recipes',
        templateUrl: 'recipes.html',
        controller: 'RecipesController as vm'
      });

    $urlRouterProvider.otherwise('/');
  });

 

19. Views. views>layouts>application.html.erb:

<!DOCTYPE html>
<html>
  <head>
    <title>RecipeMaker</title>
    <%= csrf_meta_tags %>

    <%= stylesheet_link_tag    'application', media: 'all' %>
      <%= javascript_include_tag 'application'%>
  </head>

  <body ng-app="app">
    <%= yield %>
  </body>
</html>

and views>recipes index.html.erb:

<h1>Recipes#index</h1>
<p>Find me in app/views/recipes/index.html.erb</p>

<div ng-controller="RecipesController as vm">
    <div ng-repeat ="recipe in vm.recipes">
      {{recipe.name}}
    </div>
  </div>

 

20. I don't really appreciate yet the different between using templates vs rails views. The angular ones keep things in the front end. I need to research this some. In app>assets>javascripts>app we create a home folder and a recipe folder for these files. app>assets>javascripts>app>home:

home.controller.js:

angular
  .module('app')
  .controller('HomeController', HomeController)

function HomeController() {
 console.log('this is the home controller');

}

and 

app>assets>javascripts>app>recipes>recipes.controller.js
 

function RecipesController($scope){

  var vm = this;
  debugger;

  vm.recipes =
  [
{
    id: 1,
    name: "poundcake",
    ingredients: [
      {
        id: 2,
        name: "milk"
      }
    ]
  },
  {
    id: 2,
    name: "pad thai",
  ingredients: [
      {
      id: 1,
      name: "noodles"
      }
      ]
  }
]


}

angular
.module('app')
.controller('RecipesController', RecipesController);

 

21. Templates. app>assets>javascripts>templates. Important. Not the app folder. recipes.html (currently emtpy)

and home.html:
This is the home.html file in angular
<ui-view></ui-view>

 

Things I need to work on 

1. Review everything we added to the gemfile and what it does

2. Review everything we added to the manifest file and what it does

3. Review serializers and what they do. 

4. Rethink the routing. How do the template files, app.js and controller.js files work together?

5. Writing states in app.js  

6. What is postgresql?

7. How and what do we build on this structure?

8. Nav bar stuff 

 

 

 

 

 

Recipe Manager

Ok, here goes. Going back to work on the Rails Assessment. I decided to work on a recipe manager. I created a new app using rails 'new recipe-manager'. This is preferable to copying an old lesson and rebuilding. Add spec.md file from the assessment repository with a list of required elements for the assessment.  

I filled out some basic CRUD information for my users controller and I set up models for user, recipe, ingredients and items. The models generator in rails creates files inheriting from ApplicationRecord and I think I'd rather have them inherit from ActiveRecord::Base so making those changes. A little unclear about how to wire everything together so I am referring back to the amusement park live example and solution. I understand all the pieces. I think it will help me think about what all a recipe manager needs to do.  

Working on creating the home page with signin and signup information. I need to think through the signin_path and the new_user_path and where we are defining these. Switching gears slightly to setting up Devise for some of the authentication.  

Travel Places

Hello! I started working on Rails already but I'm back in Sinatra to do the final project as I don't want to get further ahead. This is fun! I am enjoying working on how to make a real world Sinatra application. Following the suggestions given, I am trying to make something that I would like to use. I have a notebook of places I would like to visit and things I would like to do in those places so I am building an app to replicate and store this information online. I am hewing closely to the golf club example given as I was having a little trouble getting started, some blank slate hesitancy. But I'm glad I dove in and this makes sense as a way not only to think through the concepts but also see how they interrelate via shotgun. I hope to move further from the golf club example as I grasp the whole picture here thoroughly. I copied the golf club example to my computer and pushed to github and deleted most of the files to start fresh. Making lots of commits!

CSS - I plan to come back to styling CSS at the end. I started working on some styling because I thought some rainbow text might enliven things up but I wasn't getting it to display with Shotgun. I think it's because of the links in my views layout page which I copied over from the golf club example overriding the CSS page I built. Will return to this later.   

 

Application Controller: 

We are requiring our environment.rb file and the ApplicationController class inherits from Sinatra::Base. In the configure block I am enabling sessions and generating a session_id with these lines: 

configure do
enable :sessions
set :session_secret, "travelspots"
end

Then a Sinatra get method to erb: index to render views/index.erb. In Rails we work on seperate helper files. Here we have a helpers method to display an error message if someone hasn't logged in. Setting up a user_id key in the session hash for later use. I am researching other ways to verify login here.

Views:

So far I have an Index view file that just has welcome html and a more extensive layout view. Curious how these two files relate in priority. It seems that the layout view is above or before the index view. The application controller renders the index view. How does the layout view know to display?

In the body of the HTML on the layout page we have a nav bar. The nav bar has Sign Up and Sign In links (directing links  <a href="/signup"> to users/new.erb which creates a formand <a href="/login"> to users/login.erb which also creates a form). Where does it know to look in the views/users folder? How does it know /signup refers to users/new.erb? The users controller! If we are already logged in <% if logged_in? %> we have two different links in the nav bar. <a href="/activity/new"> to create a new activity or <a href="/logout">  to logout. I quit and restarted Shotgun to see that we're still in the same login session. 

I need to study up on routes! The golf bag example gets a little further into sinatra routes than I feel completely comfortable with. I understand the if/else statements and using redirect to. I need a little help making sure I comprehend the pairs of get and post methods. For instance, in my users_controller.rb file, I have a get '/login' and a post '/login'. 

I've added some user views. Hoping to test the site with shotgun but my signup and login links are still broken. I might need to add view folders for locations and activities first? Might be why they are breaking. I am going to put up my app and what I have thus far but I am still working on it and do not consider it complete.  

 

 

 

 

CLI Data Gem Project

I've been enjoying Learning with Learn. This lesson was useful as a chance to get used to putting the pieces together. I created a gem to extract the current local weather from weather.com. Avi's video helped a lot here and it was great to see how one can think on the fly and try things out in this context. And I learned from watching him put to together methods which helps underscore how the pieces work together. I liked laying down a concept for the gem in notes and stepping back for a second to think through the aims of the gem. 

I think I chose a difficult site for this project as it uses angular js. I really struggled with scraping and needed online chat help on several occasions. On the recommendation of Adam King (ADAMKING0126), I looked into Phantomjs to scrape the text I am interested in. I installed it on my computer and also followed some online instructions for installing into my gem via command line. Unfortunately, after a rather long install I received a number of messages about Phantomjs not being able to be installed on my system. 

1 warning generated.
g++ -c -pipe -fvisibility=hidden -O2 -arch i386 -Wall -W -DHAVE_CONFIG_H -DHAVE_FCNTL_H -DHAVE_STDARG_H -DHAVE_STDINT_H -DHAVE_UNISTD_H -DUSE_UTF8 -DSTATIC_BUILD -DQCOMMANDLINE_STATIC -DQT_NO_DEBUG -DQT_WEBKIT_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -Iqt/mkspecs/macx-g++ -I. -Iqt/include/QtCore -Iqt/include/QtNetwork -Iqt/include/QtGui -Iqt/include/QtWebKit -Iqt/include -Igif -Imongoose -Ilinenoise/src -Iqcommandline -Ibreakpad/src -I. -o moc_config.o moc_config.cpp
In file included from moc_config.cpp:10:
In file included from ./config.h:34:
In file included from qt/include/QtCore/QString:1:
In file included from qt/include/QtCore/qstring.h:1:
In file included from qt/include/QtCore/../../src/corelib/tools/qstring.h:45:
In file included from qt/include/QtCore/qchar.h:1:
In file included from qt/include/QtCore/../../src/corelib/tools/qchar.h:45:
In file included from qt/include/QtCore/qglobal.h:1:
qt/include/QtCore/../../src/corelib/global/qglobal.h:372:6: warning: "This version of Mac OS X is
unsupported" [-W#warnings]

warning "This version of Mac OS X is unsupported"

And a message that I cannot load phantomjs:

// ♥ ./bin/console
/Users/peterjacobson/Development/code/weather_now/lib/weather_now.rb:4:in require': cannot load such file -- phantomjs (LoadError) from /Users/peterjacobson/Development/code/weather_now/lib/weather_now.rb:4:in'
from ./bin/console:4:in require' from ./bin/console:4:in

'

I don't feel great about stopping here but I did spend several days on it and I did get something out of using Nokogiri, conceptualizing a gem, working with requirements and building methods. The next steps would be to work on zipcode search functionality and add something like a 5 day forecast.   

Storehouse

New Blog! Trying out new iPad app Storehouse which has been great fun and is well made. Going back to some collage work which I made to try out the app.