adva-categories 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ class Admin::CategoriesController < Admin::BaseController
2
+ belongs_to :site
3
+ belongs_to :section
4
+ end
@@ -0,0 +1,9 @@
1
+ require_dependency 'base_controller'
2
+
3
+ BaseController.class_eval do
4
+ include do
5
+ def collection
6
+ params[:category_id] ? super.categorized(params[:category_id]) : super
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ require_dependency 'url_helper'
2
+
3
+ UrlHelper.module_eval do
4
+ include do
5
+ def public_url_for(resources, options = {})
6
+ reject = lambda { |resource| resource.is_a?(Category) }
7
+ rejected = resources.select(&reject)
8
+ rejected.map! { |resource| [resource.class.name.foreign_key, resource.id] }
9
+
10
+ resources.reject!(&reject)
11
+ options.merge!(Hash[*rejected.flatten])
12
+ super
13
+ end
14
+ end
15
+ end
16
+
@@ -0,0 +1,5 @@
1
+ class Categorization < ActiveRecord::Base
2
+ belongs_to :category
3
+ accepts_nested_attributes_for :category
4
+ end
5
+
@@ -0,0 +1,8 @@
1
+ class Category < ActiveRecord::Base
2
+ acts_as_nested_set :scope => :section_id
3
+ has_slug :scope => :section_id
4
+
5
+ belongs_to :section
6
+
7
+ validates_presence_of :section, :name
8
+ end
@@ -0,0 +1,15 @@
1
+ require_dependency 'category'
2
+ require_dependency 'content'
3
+
4
+ Category.has_many_polymorphs :categorizables, :through => :categorizations, :foreign_key => 'category_id', :from => [:contents]
5
+
6
+ Content.class_eval do
7
+ has_many :categories, :through => :categorizations, :as => :categorizable
8
+ accepts_nested_attributes_for :categorizations, :allow_destroy => true
9
+
10
+ class << self
11
+ def categorized(category_id)
12
+ includes(:categorizations).where(:categorizations => { :category_id => category_id })
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ class Admin::Categories::Form < Adva::View::Form
2
+ include do
3
+ def fields
4
+ fieldset do
5
+ form.input :name
6
+ end
7
+ end
8
+
9
+ def sidebar
10
+ tab :options do
11
+ form.input :slug
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+
@@ -0,0 +1,19 @@
1
+ class Admin::Categories::Menu < Adva::View::Menu::Admin::Actions
2
+ include do
3
+ def main
4
+ label("#{parent_resource.class.name}:")
5
+ item(:'admin.categories.menu.categories', index_path)
6
+ item(:'admin.categories.menu.edit', edit_parent_path)
7
+ end
8
+
9
+ def right
10
+ item(:'.new', new_path)
11
+ if resource.try(:persisted?)
12
+ item(:'.destroy', resource_path, :method => :delete, :confirm => t(:'.confirm_destroy', :model_name => resource.class.model_name.human))
13
+ else
14
+ item(:'.reorder', show_parent_path, :class => 'reorder', :'data-resource_type' => parent_resource.class.name.underscore, :'data-sortable_type' => 'categories')
15
+ end
16
+ end
17
+ end
18
+ end
19
+
@@ -0,0 +1,9 @@
1
+ class Admin::Categories::Edit < Adva::View::Form
2
+ include do
3
+ def to_html
4
+ h2 :'.title'
5
+ render :partial => 'form'
6
+ end
7
+ end
8
+ end
9
+
@@ -0,0 +1,19 @@
1
+ class Admin::Categories::Index < Minimal::Template
2
+ include do
3
+ def to_html
4
+ table_for collection do |t|
5
+ t.column :category, :actions
6
+
7
+ t.row do |r, category|
8
+ r.options[:id] = dom_id(category)
9
+ r.cell capture { link_to_edit(category.name, category) }
10
+ r.cell links_to_actions([:edit, :destroy], category)
11
+ end
12
+
13
+ t.empty :p, :class => 'categories list empty' do
14
+ self.t(:'.empty', :link => capture { link_to(:'.create_item', new_path(:category)) }).html_safe
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ class Admin::Categories::New < Adva::View::Form
2
+ include do
3
+ def to_html
4
+ h2 :'.title'
5
+ render :partial => 'form'
6
+ end
7
+ end
8
+ end
9
+
10
+
@@ -0,0 +1,30 @@
1
+ en:
2
+ categories:
3
+ columns:
4
+ category: Category
5
+ actions: ""
6
+ admin:
7
+ categories:
8
+ menu:
9
+ categories: Categories
10
+ products: Products
11
+ new: New Category
12
+ edit: Settings
13
+ destroy: Delete
14
+ reorder: Reorder
15
+ confirm_destroy: Do you really want to delete this category?
16
+ columns:
17
+ category: Category
18
+ actions:
19
+ index:
20
+ create_item: Create Category
21
+ edit: Edit
22
+ destroy: Delete
23
+ confirm_destroy: Do you really want to delete this category?
24
+ empty: "There are no categories. %{link}"
25
+ new:
26
+ title: Create a Category
27
+ edit:
28
+ title: Edit Category
29
+ tabs:
30
+ categories: Categories
@@ -0,0 +1,4 @@
1
+ Adva::Registry.set :redirect, {
2
+ 'admin/categories#create' => lambda { |c| c.edit_url },
3
+ 'admin/categories#update' => lambda { |c| c.edit_url }
4
+ }
data/config/routes.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'adva/routing_filters/categories'
2
+
3
+ Rails.application.routes.draw do
4
+ filter :categories
5
+
6
+ namespace :admin do
7
+ resources :sites do
8
+ resources :sections do
9
+ resources :categories
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ require 'adva'
2
+
3
+ module Adva
4
+ class Categories < ::Rails::Engine
5
+ include Adva::Engine
6
+
7
+ initializer 'adva-categories.configure_routing_filters' do
8
+ RoutingFilter::SectionRoot.anchors << 'categories'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,81 @@
1
+ require 'routing_filter'
2
+
3
+ module RoutingFilter
4
+ class Categories < Filter
5
+ cattr_accessor :default_port
6
+ self.default_port = '80'
7
+
8
+ cattr_accessor :exclude
9
+ self.exclude = %r(^/admin)
10
+
11
+ def around_recognize(path, env, &block)
12
+ # p "#{self.class.name}: #{path}"
13
+ unless excluded?(path)
14
+ category_id = extract_category_id(env, path)
15
+ yield.tap do |params|
16
+ params[:category_id] = category_id if category_id
17
+ end
18
+ else
19
+ yield
20
+ end
21
+ end
22
+
23
+ def around_generate(params, &block)
24
+ category_id = params.delete('category_id') || params.delete(:category_id)
25
+ yield.tap do |path|
26
+ # p "#{self.class.name}: #{path}"
27
+ insert_category_path(path, category_id) if !excluded?(path) && category_id
28
+ end
29
+ end
30
+
31
+ protected
32
+
33
+ def excluded?(path)
34
+ path =~ exclude
35
+ end
36
+
37
+ def extract_category_id(env, path)
38
+ if section = section_for(env, path) and path =~ recognition_pattern(section)
39
+ if category = section.categories.where(:path => $2).first
40
+ path.gsub!("#{$1}#{$2}", '')
41
+ path.replace('/') if path.blank?
42
+ category.id.to_s
43
+ end
44
+ end
45
+ end
46
+
47
+ def recognition_pattern(section)
48
+ paths = section.categories.map(&:path).reject(&:blank?)
49
+ paths = paths.sort { |a, b| b.size <=> a.size }.join('|')
50
+ paths.empty? ? %r(^$) : %r(^.*(/categories/)(#{paths})(?=/|\.|\?|$))
51
+ end
52
+
53
+ def insert_category_path(path, category_id)
54
+ category = Category.find(category_id)
55
+ if path =~ section_pattern
56
+ path.sub!("/#{$1}/#{$2}", "/#{$1}/#{$2}/categories/#{category.path}")
57
+ elsif category.section.root?
58
+ path.sub!(%r(^/), "/categories/#{category.path}")
59
+ end
60
+ end
61
+
62
+ def section_pattern
63
+ types = Section.types.map { |type| type.downcase.pluralize }.join('|')
64
+ %r(/(sections|#{types})/(\d+)(?=/|\.|\?|$))
65
+ end
66
+
67
+ def section_for(env, path)
68
+ if path =~ section_pattern
69
+ Section.find($2)
70
+ elsif path =~ %r(^/categories/\w+) && site = Site.by_host(host(env))
71
+ site.sections.root
72
+ end
73
+ end
74
+
75
+ def host(env)
76
+ host, port = env.values_at('SERVER_NAME', 'SERVER_PORT')
77
+ port == default_port ? host : [host, port].compact.join(':')
78
+ end
79
+ end
80
+ end
81
+
@@ -0,0 +1 @@
1
+ require 'adva/categories'
@@ -0,0 +1,4 @@
1
+ Factory.define :category do |f|
2
+ f.section { Section.first || Factory(:section) }
3
+ f.name 'Category'
4
+ end
@@ -0,0 +1,15 @@
1
+ module Adva::Categories::Paths
2
+ def path_to(page)
3
+ case page
4
+ when /^the admin "([^"]*)" section categories page$/
5
+ site = Site.first
6
+ section = Section.where(:name => $1).first || raise("could not find section named #{$1}")
7
+ polymorphic_path([:admin, site, section, :categories])
8
+ else
9
+ super
10
+ end
11
+ end
12
+ end
13
+
14
+ World(Adva::Categories::Paths)
15
+
@@ -0,0 +1,21 @@
1
+ When /^I drag the category "([^"]*)" below the category "([^"]*)"$/ do |category, target|
2
+ category = Category.find_by_name(category)
3
+ target = Category.find_by_name(target)
4
+ section = Section.first
5
+ put(admin_site_section_path(section.site, section), {
6
+ :section => { :categories_attributes => [{ :id => category.id, :left_id => target.id }] },
7
+ :return_to => @request.url
8
+ })
9
+ follow_redirect!
10
+ end
11
+
12
+ Then /^the ([\w]+) (name|title)d "([^"]+)" should be categorized as "([^"]+)"$/ do |model, attribute, value, category|
13
+ record = model.classify.constantize.where(attribute => value).first
14
+ assert record.categories.map(&:name).include?(category), "expected #{record.inspect} to be categorized as #{category}"
15
+ end
16
+
17
+ Then /^the ([\w]+) (name|title)d "([^"]+)" should not be categorized as "([^"]+)"$/ do |model, attribute, value, category|
18
+ record = model.classify.constantize.where(attribute => value).first
19
+ assert !record.categories.map(&:name).include?(category), "expected #{record.inspect} not to be categorized as #{category}"
20
+ end
21
+
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: adva-categories
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Ingo Weiss
14
+ - Sven Fuchs
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-10-29 00:00:00 +02:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: adva-core
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ description: "[description]"
37
+ email: nobody@adva-cms.org
38
+ executables: []
39
+
40
+ extensions: []
41
+
42
+ extra_rdoc_files: []
43
+
44
+ files:
45
+ - app/controllers/admin/categories_controller.rb
46
+ - app/controllers/base_controller_slice.rb
47
+ - app/helpers/url_helper_slice.rb
48
+ - app/views/admin/categories/index.html.rb
49
+ - app/views/admin/categories/edit.html.rb
50
+ - app/views/admin/categories/new.html.rb
51
+ - app/views/admin/categories/_form.html.rb
52
+ - app/views/admin/categories/_menu.html.rb
53
+ - app/models/content_slice.rb
54
+ - app/models/category.rb
55
+ - app/models/categorization.rb
56
+ - config/redirects.rb
57
+ - config/routes.rb
58
+ - config/locales/en.yml
59
+ - lib/adva-categories.rb
60
+ - lib/adva/categories.rb
61
+ - lib/adva/routing_filters/categories.rb
62
+ - lib/testing/factories.rb
63
+ - lib/testing/paths.rb
64
+ - lib/testing/step_definitions.rb
65
+ has_rdoc: true
66
+ homepage: http://github.com/svenfuchs/adva-cms2
67
+ licenses: []
68
+
69
+ post_install_message:
70
+ rdoc_options: []
71
+
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ hash: 3
80
+ segments:
81
+ - 0
82
+ version: "0"
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ requirements: []
93
+
94
+ rubyforge_project: "[none]"
95
+ rubygems_version: 1.3.7
96
+ signing_key:
97
+ specification_version: 3
98
+ summary: "[summary]"
99
+ test_files: []
100
+