Permalink
Browse files

Add tags support and the ability to remotely import them.

  • Loading branch information...
mcolyer committed Dec 3, 2010
1 parent 2fd45d8 commit ab11e3677ee4e46e3b50deb3b57418ac02255b95
View
@@ -9,6 +9,7 @@ gem "aws-s3", :require => "aws/s3"
gem "httparty"
gem "devise", :git => "git://github.com/plataformatec/devise.git", :branch => "v1.2.oauth"
gem "oauth2"
+gem "nokogiri"
gem "capybara", :group => [:test, :cucumber]
gem "cucumber-rails", :group => [:test, :cucumber]
View
@@ -185,6 +185,7 @@ DEPENDENCIES
haml
httparty
launchy
+ nokogiri
oauth2
rails
rspec-rails
@@ -0,0 +1,10 @@
+class TagsController < ApplicationController
+ respond_to :json, :only => [:create]
+ skip_before_filter :verify_authenticity_token
+ before_filter :authenticate_user!, :only => :create
+
+ def create
+ @tag = Tag.create(params[:tag])
+ respond_with(@tag, :location => @tag)
+ end
+end
@@ -0,0 +1,2 @@
+module TagsHelper
+end
View
@@ -0,0 +1,42 @@
+class Tag < ActiveRecord::Base
+
+ def self.remote_create(attributes)
+ data = { :tag => attributes, :auth_token => TownhallConfig.system_user_token }
+ new_tag_url = TownhallConfig.base_url + "/tags/"
+ HTTParty.post(new_tag_url, :body => data, :headers => {"Accept" => "application/json"})["tag"]
+ end
+
+ def self.fetch(url, method=:create_tags_from_granicus_player)
+ html = Net::HTTP.get_response(URI(url)).body
+ self.send(method, html)
+ end
+
+ # Public: Parses the Granicus player HTML for meeting segment information.
+ # It's currently used in a dropdown in their web player. However they have
+ # convieniently included the number of seconds in the html and the labels
+ # right next to it.
+ #
+ # Returns a list of hashes representing tag attributes sorted by start time.
+ def self.create_tags_from_granicus_player(html)
+ doc = Nokogiri::HTML(html)
+
+ tags = doc.css('#IndexDropdown option').map do |item|
+ _,time = item['value'].split(':')
+ next unless time
+
+ {:name => item.content, :start => time}
+ end.compact
+
+ # Set the stop time to the next item
+ tags.each_slice(2) do |ts|
+ t1, t2 = ts
+ if t2
+ t1[:stop] = t2[:start]
+ else
+ t1[:stop] = t1[:start]
+ end
+ end
+
+ tags
+ end
+end
View
@@ -2,61 +2,7 @@
devise_for :users
resources :meetings
+ resources :tags
- # The priority is based upon order of creation:
- # first created -> highest priority.
-
- # Sample of regular route:
- # match 'products/:id' => 'catalog#view'
- # Keep in mind you can assign values other than :controller and :action
-
- # Sample of named route:
- # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
- # This route can be invoked with purchase_url(:id => product.id)
-
- # Sample resource route (maps HTTP verbs to controller actions automatically):
- # resources :products
-
- # Sample resource route with options:
- # resources :products do
- # member do
- # get :short
- # post :toggle
- # end
- #
- # collection do
- # get :sold
- # end
- # end
-
- # Sample resource route with sub-resources:
- # resources :products do
- # resources :comments, :sales
- # resource :seller
- # end
-
- # Sample resource route with more complex sub-resources
- # resources :products do
- # resources :comments
- # resources :sales do
- # get :recent, :on => :collection
- # end
- # end
-
- # Sample resource route within a namespace:
- # namespace :admin do
- # # Directs /admin/products/* to Admin::ProductsController
- # # (app/controllers/admin/products_controller.rb)
- # resources :products
- # end
-
- # You can have the root of your site routed with "root"
- # just remember to delete public/index.html.
root :to => "meetings#index"
-
- # See how all your routes lay out with "rake routes"
-
- # This is a legacy wild controller route that's not recommended for RESTful applications.
- # Note: This route will make all actions in every controller accessible via GET requests.
- # match ':controller(/:action(/:id(.:format)))'
end
@@ -0,0 +1,16 @@
+class CreateTags < ActiveRecord::Migration
+ def self.up
+ create_table :tags do |t|
+ t.integer :meeting_id
+ t.integer :start
+ t.integer :stop
+ t.string :name
+
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :tags
+ end
+end
View
@@ -10,7 +10,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20101130062325) do
+ActiveRecord::Schema.define(:version => 20101201155528) do
create_table "meetings", :force => true do |t|
t.date "meeting_date"
@@ -19,8 +19,17 @@
t.datetime "updated_at"
end
+ create_table "tags", :force => true do |t|
+ t.integer "meeting_id"
+ t.integer "start"
+ t.integer "stop"
+ t.string "name"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
create_table "users", :force => true do |t|
- t.integer "sign_in_count", :default => 0
+ t.integer "sign_in_count", :default => 0
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
View
@@ -38,4 +38,15 @@ namespace :townhall do desc "Create a meeting from the following video"
FileUtils.rm_r(WORKING_DIRECTORY)
end
+
+ task :import_tags, :url, :meeting_id, :needs => :environment do |t, args|
+ puts "Downloading #{args.url}"
+ tags = Tag.fetch(args.url)
+
+ puts "Saving"
+ tags.each do |tag|
+ tag[:meeting_id] = args.meeting_id
+ Tag.remote_create(tag)
+ end
+ end
end
@@ -0,0 +1,16 @@
+require 'spec_helper'
+
+describe TagsController do
+ fixtures :users
+
+ it "can create a tag using json" do
+ body = { :tag => { :name => "BarbaraHunter:Person", :start => 1, :stop => 10}, :auth_token => users(:admin).authentication_token }
+ xhr :post, :create, body
+
+ response.should be_success
+ results = JSON.parse(response.body)["tag"]
+ results.should have_key "name"
+ results.should have_key "start"
+ results.should have_key "stop"
+ end
+end
View
@@ -0,0 +1,8 @@
+# Read about factories at http://github.com/thoughtbot/factory_girl
+
+Factory.define :tag do |f|
+ f.meeting_id 1
+ f.start 1
+ f.stop 60
+ f.name "BarbaraHunter:Person"
+end
Oops, something went wrong.

0 comments on commit ab11e36

Please sign in to comment.