@@ -0,0 +1,3 @@ | |||||
# Place all the behaviors and hooks related to the matching controller here. | |||||
# All this logic will automatically be available in application.js. | |||||
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ |
@@ -41,37 +41,7 @@ class FeedsController < ApplicationController | |||||
@feed = Feed.find(params[:id]) | @feed = Feed.find(params[:id]) | ||||
end | end | ||||
# POST /feeds | |||||
# POST /feeds.json | |||||
def create | |||||
Rails.logger.debug "Feed URL: %s" % params['feed']['feed_url'] | |||||
if Feed.where(:feed_url => params['feed']['feed_url']).size == 1 # ensure this test returns the values we expect | |||||
Rails.logger.debug "Adding existing feed to a new layer" | |||||
@feed = Feed.where(:feed_url => params['feed']['feed_url']).first | |||||
@layer = Layer.find(params['feed']['new_layer_id']) # assumes that the specified layer exists | |||||
# Attach the existing feed to the specified layer (making sure we only add each one once) | |||||
@feed.layers << @layer unless @feed.layers.include?(@layer) | |||||
else | |||||
# Create a new feed | |||||
Rails.logger.debug "Creating a new feed" | |||||
@feed = Feed.new(params[:feed]) | |||||
@layer = Layer.find(params['feed']['new_layer_id']) # assumes that the specified layer exists | |||||
@feed.layers << @layer unless @feed.layers.include?(@layer) | |||||
end | |||||
respond_to do |format| | |||||
if @feed.save | |||||
format.html { redirect_to @layer, notice: 'Feed added OK' } | |||||
format.json { render json: @feed, status: :created, location: @feed } | |||||
else | |||||
format.html { render action: "new" } | |||||
format.json { render json: @feed.errors, status: :unprocessable_entity } | |||||
end | |||||
end | |||||
end | |||||
# Feeds are created through the Subscriptions controller | |||||
# PUT /feeds/1 | # PUT /feeds/1 | ||||
# PUT /feeds/1.json | # PUT /feeds/1.json | ||||
@@ -16,8 +16,7 @@ class LayersController < ApplicationController | |||||
# GET /layers/1.json | # GET /layers/1.json | ||||
def show | def show | ||||
@layer = Layer.find(params[:id]) | @layer = Layer.find(params[:id]) | ||||
@feed = Feed.new | |||||
@feed.new_layer_id = @layer.id | |||||
@subscription = Subscription.new(:layer_id => @layer.id) | |||||
respond_to do |format| | respond_to do |format| | ||||
format.html # show.html.erb | format.html # show.html.erb | ||||
@@ -0,0 +1,46 @@ | |||||
class SubscriptionsController < ApplicationController | |||||
def create | |||||
Rails.logger.debug "Feed URL: %s" % params['subscription']['feed_url'] | |||||
if Feed.where(:feed_url => params['subscription']['feed_url']).size == 1 # ensure this test returns the values we expect | |||||
Rails.logger.debug "Adding existing feed to a new layer" | |||||
@feed = Feed.where(:feed_url => params['subscription']['feed_url']).first | |||||
@layer = Layer.find(params['subscription']['layer_id']) # assumes that the specified layer exists | |||||
# Attach the existing feed to the specified layer (making sure we only add each one once) | |||||
# @feed.layers << @layer unless @feed.layers.include?(@layer) | |||||
else | |||||
# Create a new feed | |||||
Rails.logger.debug "Creating a new feed" | |||||
@feed = Feed.create(:feed_url => params[:subscription][:feed_url]) | |||||
@layer = Layer.find(params['subscription']['layer_id']) # assumes that the specified layer exists | |||||
# @feed.layers << @layer unless @feed.layers.include?(@layer) | |||||
end | |||||
@subscription = Subscription.new(:feed => @feed, :layer => @layer) | |||||
begin | |||||
respond_to do |format| | |||||
if @subscription.save | |||||
format.html { redirect_to @layer, notice: 'Feed added OK' } | |||||
format.json { render json: @feed, status: :created, location: @feed } | |||||
else | |||||
format.html { render action: "new" } | |||||
format.json { render json: @feed.errors, status: :unprocessable_entity } | |||||
end | |||||
end | |||||
rescue ActiveRecord::RecordNotUnique | |||||
redirect_to @layer, alert: 'That feed is already on this layer' | |||||
end | |||||
end | |||||
def destroy | |||||
@subscription = Subscription.find(params[:id]) | |||||
@layer = @subscription.layer | |||||
@subscription.destroy | |||||
respond_to do |format| | |||||
format.html { redirect_to @layer, notice: 'Subscription deleted OK' } | |||||
format.json { head :no_content } | |||||
end | |||||
end | |||||
end |
@@ -0,0 +1,2 @@ | |||||
module SubscriptionsHelper | |||||
end |
@@ -1,6 +1,7 @@ | |||||
class Feed < ActiveRecord::Base | class Feed < ActiveRecord::Base | ||||
has_many :posts, :dependent => :destroy | has_many :posts, :dependent => :destroy | ||||
has_and_belongs_to_many :layers | |||||
has_many :subscriptions | |||||
has_many :layers, :through => :subscriptions, :uniq => true | |||||
attr_accessible :title, :url, :description, :generator, :last_fetched, :feed_url | attr_accessible :title, :url, :description, :generator, :last_fetched, :feed_url | ||||
attr_accessor :new_layer_id # non model attribute used when creating new feeds from within a layer | attr_accessor :new_layer_id # non model attribute used when creating new feeds from within a layer | ||||
@@ -1,4 +1,5 @@ | |||||
class Layer < ActiveRecord::Base | class Layer < ActiveRecord::Base | ||||
attr_accessible :name | attr_accessible :name | ||||
has_and_belongs_to_many :feeds | |||||
has_many :subscriptions | |||||
has_many :feeds, :through => :subscriptions, :uniq => true | |||||
end | end |
@@ -0,0 +1,5 @@ | |||||
class Subscription < ActiveRecord::Base | |||||
attr_accessor :feed_url | |||||
belongs_to :feed | |||||
belongs_to :layer | |||||
end |
@@ -8,17 +8,8 @@ | |||||
- @feed.errors.full_messages.each do |msg| | - @feed.errors.full_messages.each do |msg| | ||||
%li= msg | %li= msg | ||||
.field | |||||
-# | |||||
= f.label :title | |||||
= f.text_field :title | |||||
.field | .field | ||||
= f.label "URL" | = f.label "URL" | ||||
= f.text_field :feed_url, :size => 120 | = f.text_field :feed_url, :size => 120 | ||||
= f.hidden_field :new_layer_id, :value => @feed.new_layer_id | |||||
= f.submit 'Save', :id => 'submit' | = f.submit 'Save', :id => 'submit' | ||||
-# | |||||
.field | |||||
= f.label :last_fetched | |||||
= f.datetime_select :last_fetched | |||||
.actions | .actions |
@@ -10,7 +10,7 @@ | |||||
%h2 Feeds | %h2 Feeds | ||||
#new_feed | #new_feed | ||||
= render 'feeds/form' | |||||
= render 'subscriptions/form' | |||||
%p= link_to "Fetch all", :fetch_all, :class => "button" | %p= link_to "Fetch all", :fetch_all, :class => "button" | ||||
@@ -23,20 +23,20 @@ | |||||
%th | %th | ||||
%th | %th | ||||
- @layer.feeds.each do |f| | |||||
- @layer.subscriptions.each do |s| | |||||
%tr | %tr | ||||
%td | %td | ||||
.feed_title | .feed_title | ||||
= link_to f.title, f | |||||
%td.right= f.posts.count | |||||
= link_to s.feed.title, s.feed | |||||
%td.right= s.feed.posts.count | |||||
%td | %td | ||||
- if f.last_fetched.nil? | |||||
- if s.feed.last_fetched.nil? | |||||
never | never | ||||
- else | - else | ||||
= (time_ago_in_words(f.last_fetched) + " ago").gsub(/ +/, " ").html_safe | |||||
%td= link_to "Fetch", fetch_feed_url(f), :class => "button" | |||||
%td= link_to 'Edit', edit_feed_path(f), :class => "button" | |||||
%td= link_to 'Delete', f, :confirm => "Delete #{f.title} and all its posts?", :method => :delete, :class => "button" | |||||
= (time_ago_in_words(s.feed.last_fetched) + " ago").gsub(/ +/, " ").html_safe | |||||
%td= link_to "Fetch", fetch_feed_url(s.feed), :class => "button" | |||||
%td= link_to 'Edit', edit_feed_path(s.feed), :class => "button" | |||||
%td= link_to 'Delete', s, :confirm => "Delete #{s.feed.title}?", :method => :delete, :class => "button" | |||||
%tr | %tr | ||||
%td | %td | ||||
@@ -0,0 +1,16 @@ | |||||
= form_for @subscription do |f| | |||||
%h2 Add a feed | |||||
-if @subscription.errors.any? | |||||
#error_explanation | |||||
%h2= "#{pluralize(@subscription.errors.count, "error")} prohibited this feed from being saved:" | |||||
%ul | |||||
- @subscription.errors.full_messages.each do |msg| | |||||
%li= msg | |||||
.field | |||||
= f.label "URL" | |||||
= f.text_field :feed_url, :size => 120 | |||||
= f.hidden_field :layer_id, :value => @subscription.layer.id | |||||
= f.submit 'Save', :id => 'submit' | |||||
.actions |
@@ -75,6 +75,7 @@ module Apollo | |||||
# http://mongomapper.com/documentation/getting-started/rails.html | # http://mongomapper.com/documentation/getting-started/rails.html | ||||
config.generators do |g| | config.generators do |g| | ||||
g.template_engine :haml | g.template_engine :haml | ||||
g.stylesheets false | |||||
end | end | ||||
# Time.zone = 'London' | # Time.zone = 'London' | ||||
end | end | ||||
@@ -6,10 +6,11 @@ Apollo::Application.routes.draw do | |||||
resources :users | resources :users | ||||
resources :sessions | resources :sessions | ||||
resources :password_resets | resources :password_resets | ||||
resources :subscriptions | |||||
get "posts/near" | get "posts/near" | ||||
resources :feeds do | |||||
resources :feeds, :except => :create do | |||||
member do | member do | ||||
get 'fetch' | get 'fetch' | ||||
end | end | ||||
@@ -0,0 +1,7 @@ | |||||
class ConvertFeedsLayersTableToSubscriptions < ActiveRecord::Migration | |||||
def change | |||||
rename_table :feeds_layers, :subscriptions | |||||
add_column :subscriptions, :id, :primary_key | |||||
add_index :subscriptions, :id, :name => "id" | |||||
end | |||||
end |
@@ -0,0 +1,5 @@ | |||||
class AddTimestampsToSubscriptions < ActiveRecord::Migration | |||||
def change | |||||
add_timestamps :subscriptions | |||||
end | |||||
end |
@@ -11,7 +11,23 @@ | |||||
# | # | ||||
# It's strongly recommended to check this file into your version control system. | # It's strongly recommended to check this file into your version control system. | ||||
ActiveRecord::Schema.define(:version => 20130320181527) do | |||||
ActiveRecord::Schema.define(:version => 20130408142010) do | |||||
create_table "delayed_jobs", :force => true do |t| | |||||
t.integer "priority", :default => 0 | |||||
t.integer "attempts", :default => 0 | |||||
t.text "handler" | |||||
t.text "last_error" | |||||
t.datetime "run_at" | |||||
t.datetime "locked_at" | |||||
t.datetime "failed_at" | |||||
t.string "locked_by" | |||||
t.string "queue" | |||||
t.datetime "created_at", :null => false | |||||
t.datetime "updated_at", :null => false | |||||
end | |||||
add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority" | |||||
create_table "feeds", :force => true do |t| | create_table "feeds", :force => true do |t| | ||||
t.string "title" | t.string "title" | ||||
@@ -24,13 +40,6 @@ ActiveRecord::Schema.define(:version => 20130320181527) do | |||||
t.datetime "last_fetched" | t.datetime "last_fetched" | ||||
end | end | ||||
create_table "feeds_layers", :id => false, :force => true do |t| | |||||
t.integer "feed_id" | |||||
t.integer "layer_id" | |||||
end | |||||
add_index "feeds_layers", ["feed_id", "layer_id"], :name => "index_feeds_layers_on_feed_id_and_layer_id" | |||||
create_table "layers", :force => true do |t| | create_table "layers", :force => true do |t| | ||||
t.string "name" | t.string "name" | ||||
t.datetime "created_at", :null => false | t.datetime "created_at", :null => false | ||||
@@ -52,14 +61,27 @@ ActiveRecord::Schema.define(:version => 20130320181527) do | |||||
t.datetime "published" | t.datetime "published" | ||||
end | end | ||||
create_table "subscriptions", :force => true do |t| | |||||
t.integer "feed_id" | |||||
t.integer "layer_id" | |||||
t.datetime "created_at" | |||||
t.datetime "updated_at" | |||||
end | |||||
add_index "subscriptions", ["feed_id", "layer_id"], :name => "index_feeds_layers_on_feed_id_and_layer_id", :unique => true | |||||
add_index "subscriptions", ["id"], :name => "id" | |||||
create_table "users", :force => true do |t| | create_table "users", :force => true do |t| | ||||
t.string "email" | t.string "email" | ||||
t.string "crypted_password" | t.string "crypted_password" | ||||
t.string "salt" | t.string "salt" | ||||
t.datetime "created_at", :null => false | |||||
t.datetime "updated_at", :null => false | |||||
t.datetime "created_at", :null => false | |||||
t.datetime "updated_at", :null => false | |||||
t.string "remember_me_token" | t.string "remember_me_token" | ||||
t.datetime "remember_me_token_expires_at" | t.datetime "remember_me_token_expires_at" | ||||
t.string "reset_password_token" | |||||
t.datetime "reset_password_token_expires_at" | |||||
t.datetime "reset_password_email_sent_at" | |||||
end | end | ||||
add_index "users", ["remember_me_token"], :name => "index_users_on_remember_me_token" | add_index "users", ["remember_me_token"], :name => "index_users_on_remember_me_token" | ||||
@@ -0,0 +1,11 @@ | |||||
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html | |||||
# This model initially had no columns defined. If you add columns to the | |||||
# model remove the '{}' from the fixture names and add the columns immediately | |||||
# below each fixture, per the syntax in the comments below | |||||
# | |||||
one: {} | |||||
# column: value | |||||
# | |||||
two: {} | |||||
# column: value |
@@ -0,0 +1,7 @@ | |||||
require 'test_helper' | |||||
class SubscriptionsControllerTest < ActionController::TestCase | |||||
# test "the truth" do | |||||
# assert true | |||||
# end | |||||
end |
@@ -0,0 +1,4 @@ | |||||
require 'test_helper' | |||||
class SubscriptionsHelperTest < ActionView::TestCase | |||||
end |
@@ -0,0 +1,7 @@ | |||||
require 'test_helper' | |||||
class SubscriptionTest < ActiveSupport::TestCase | |||||
# test "the truth" do | |||||
# assert true | |||||
# end | |||||
end |