ecm_links2 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +52 -0
- data/Rakefile +25 -0
- data/app/controllers/ecm/links/categories_controller.rb +11 -0
- data/app/decorators/ecm/links/category_decorator.rb +17 -0
- data/app/helpers/ecm/links/categories_helper.rb +5 -0
- data/app/helpers/ecm/links/links_helper.rb +5 -0
- data/app/helpers/ecm/links_helper.rb +7 -0
- data/app/models/ecm/links/category.rb +102 -0
- data/app/models/ecm/links/link.rb +63 -0
- data/app/views/ecm/links/_link_footer.html.erb +14 -0
- data/app/views/ecm/links/categories/_category.html.erb +22 -0
- data/app/views/ecm/links/categories/_category_in_index.html.erb +5 -0
- data/app/views/ecm/links/categories/index.html.erb +5 -0
- data/app/views/ecm/links/categories/show.html.erb +9 -0
- data/app/views/ecm/links/links/_link.html.erb +1 -0
- data/app/views/ecm/links/links/_link_in_table.html.erb +5 -0
- data/app/views/ecm/links/links/_table.html.erb +7 -0
- data/config/locales/ecm.links.category.de.yml +26 -0
- data/config/locales/ecm.links.category.en.yml +26 -0
- data/config/locales/ecm.links.de.yml +9 -0
- data/config/locales/ecm.links.en.yml +9 -0
- data/config/locales/ecm.links.link.de.yml +18 -0
- data/config/locales/ecm.links.link.en.yml +18 -0
- data/db/migrate/001_create_ecm_links_categories.rb +26 -0
- data/db/migrate/002_create_ecm_links_links.rb +19 -0
- data/lib/ecm/links/active_admin/ecm_links_categories.rb +121 -0
- data/lib/ecm/links/active_admin/ecm_links_links.rb +56 -0
- data/lib/ecm/links/configuration.rb +33 -0
- data/lib/ecm/links/engine.rb +12 -0
- data/lib/ecm/links/routing.rb +36 -0
- data/lib/ecm/links/version.rb +5 -0
- data/lib/ecm_links2.rb +21 -0
- data/lib/generators/ecm/links/install/install_generator.rb +15 -0
- data/lib/generators/ecm/links/install/templates/ecm_links.rb +29 -0
- data/lib/generators/ecm/links/locales/locales_generator.rb +20 -0
- data/lib/tasks/ecm_links_tasks.rake +50 -0
- metadata +479 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cfd985fcb7b31ba7399eb4616e057f5d7c2f5f6f
|
4
|
+
data.tar.gz: 9b533ddd5f8370e4730f4c35ea5bc3d09ae58901
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 397e94f04d56add60388721b9fce4fc98666b06d967000b906a6f60b4835d05f2deb67a5fa122cd844dd0df599994690c06b2bf165e8f313bddf19e664335959
|
7
|
+
data.tar.gz: 72ade06e8be6d457996f46b3c0a5f09b4a7cad5b96c5265658aeed5be252d8c36f838a8013d05d131f4652f60f6d6476529ef9c3341dc65c244703e34dd73995
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2015 Roberto Vasquez Angel
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
= ECM Links 2
|
2
|
+
|
3
|
+
= Installation
|
4
|
+
|
5
|
+
|
6
|
+
Add it to your gemfile:
|
7
|
+
|
8
|
+
# Gemfile
|
9
|
+
gem 'ecm_links2'
|
10
|
+
|
11
|
+
Install your bundle:
|
12
|
+
|
13
|
+
> bundle install
|
14
|
+
|
15
|
+
Generate initializer:
|
16
|
+
|
17
|
+
> rails generate ecm:links:install
|
18
|
+
|
19
|
+
Generatre the migrations:
|
20
|
+
|
21
|
+
> rake ecm_links_engine:install:migrations
|
22
|
+
|
23
|
+
Migrate:
|
24
|
+
|
25
|
+
> rake db:migrate
|
26
|
+
|
27
|
+
|
28
|
+
== Optional: Generate locale files
|
29
|
+
|
30
|
+
You may want to copy the locales to your app:
|
31
|
+
|
32
|
+
> rails generate ecm:links:locales
|
33
|
+
|
34
|
+
= Usage
|
35
|
+
|
36
|
+
Use the helper to display the link footer:
|
37
|
+
|
38
|
+
# i.e. app/views/layouts/application.html.erb
|
39
|
+
<%= render_link_footer %>
|
40
|
+
|
41
|
+
== Optional: Display a link tree
|
42
|
+
|
43
|
+
To display a link tree, you have to add the routes:
|
44
|
+
|
45
|
+
# config/routes.rb
|
46
|
+
Ecm::Links::Routing.routes(self)
|
47
|
+
|
48
|
+
This will give you a route to /ecm_links_categories
|
49
|
+
|
50
|
+
= License
|
51
|
+
|
52
|
+
This project rocks and uses MIT-LICENSE.
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'ECM Links 2'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
Bundler::GemHelper.install_tasks
|
24
|
+
|
25
|
+
require 'rails/dummy/tasks'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Ecm::Links
|
2
|
+
class CategoriesController < ApplicationController
|
3
|
+
def index
|
4
|
+
@categories = Category.includes(:ecm_links_links).all.decorate
|
5
|
+
end
|
6
|
+
|
7
|
+
def show
|
8
|
+
@category = Category.includes(:ecm_links_links).find(params[:id]).decorate
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Ecm::Links
|
2
|
+
class CategoryDecorator < Draper::Decorator
|
3
|
+
delegate_all
|
4
|
+
|
5
|
+
def ecm_links_links_count_label
|
6
|
+
h.content_tag(:span, ecm_links_links_count, class: 'badge')
|
7
|
+
end
|
8
|
+
|
9
|
+
def locale_label
|
10
|
+
h.content_tag(:span, locale, class: 'label label-info')
|
11
|
+
end
|
12
|
+
|
13
|
+
def tree_name
|
14
|
+
name
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
module Ecm::LinksHelper
|
2
|
+
def render_link_footer(categories = nil, options = {})
|
3
|
+
categories = Ecm::Links::Category.for_link_footer.all if categories.nil?
|
4
|
+
grouped_categories = categories.group_by(&:link_footer_column)
|
5
|
+
render(:partial => 'ecm/links/link_footer', :locals => { :categories => grouped_categories })
|
6
|
+
end
|
7
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require_dependency 'redcloth'
|
2
|
+
|
3
|
+
module Ecm::Links
|
4
|
+
class Category < ActiveRecord::Base
|
5
|
+
# associations
|
6
|
+
has_many :ecm_links_links, -> { order(:position) },
|
7
|
+
:class_name => Ecm::Links::Link,
|
8
|
+
:dependent => :destroy,
|
9
|
+
:foreign_key => :ecm_links_category_id
|
10
|
+
|
11
|
+
|
12
|
+
# attributes
|
13
|
+
attr_accessible :depth,
|
14
|
+
:ecm_links_links_attributes,
|
15
|
+
:lft,
|
16
|
+
:link_footer_column,
|
17
|
+
:locale,
|
18
|
+
:long_description,
|
19
|
+
:markup_language,
|
20
|
+
:name,
|
21
|
+
:parent_id,
|
22
|
+
:rgt,
|
23
|
+
:short_description,
|
24
|
+
:slug if respond_to? :attr_accessible
|
25
|
+
accepts_nested_attributes_for :ecm_links_links, :allow_destroy => true
|
26
|
+
|
27
|
+
# awesome nested set
|
28
|
+
acts_as_nested_set
|
29
|
+
default_scope { order('lft ASC') }
|
30
|
+
|
31
|
+
# callbacks
|
32
|
+
after_initialize :set_defaults
|
33
|
+
|
34
|
+
# friendly id
|
35
|
+
extend FriendlyId
|
36
|
+
friendly_id :name, :use => [:slugged, :finders]
|
37
|
+
|
38
|
+
# validations
|
39
|
+
validates :locale, :presence => true, :if => Proc.new { |c| c.parent.nil? }
|
40
|
+
validates :locale, :absence => true, :if => Proc.new { |c| !c.parent.nil? }
|
41
|
+
validates :name, :presence => true,
|
42
|
+
:uniqueness => { :scope => [ :parent_id ] }
|
43
|
+
validates :markup_language, :presence => true,
|
44
|
+
:inclusion => Configuration.markup_languages.map(&:to_s)
|
45
|
+
|
46
|
+
def human
|
47
|
+
name
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_s
|
51
|
+
human
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.for_actual_locale
|
55
|
+
where(:locale => I18n.locale)
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.for_link_footer
|
59
|
+
where(self.arel_table['link_footer_column'].not_eq(nil)).for_actual_locale
|
60
|
+
end
|
61
|
+
|
62
|
+
def long_description(options = {})
|
63
|
+
options.reverse_merge!(:as => :plain)
|
64
|
+
case options[:as]
|
65
|
+
when :html
|
66
|
+
markup(self[:long_description])
|
67
|
+
else
|
68
|
+
self[:long_description]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def short_description(options = {})
|
73
|
+
options.reverse_merge!(:as => :plain)
|
74
|
+
case options[:as]
|
75
|
+
when :html
|
76
|
+
markup(self[:short_description])
|
77
|
+
else
|
78
|
+
self[:short_description]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def markup(text)
|
85
|
+
case markup_language.to_sym
|
86
|
+
when :textile
|
87
|
+
return unless text
|
88
|
+
RedCloth.new(text).to_html
|
89
|
+
when :none
|
90
|
+
text
|
91
|
+
else
|
92
|
+
raise "Unsupported markup language #{markup_language}"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def set_defaults
|
97
|
+
if self.new_record?
|
98
|
+
self.markup_language ||= Configuration.default_markup_language.to_s
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require_dependency 'redcloth'
|
2
|
+
|
3
|
+
class Ecm::Links::Link < ActiveRecord::Base
|
4
|
+
# acts as list
|
5
|
+
acts_as_list :scope => :ecm_links_category
|
6
|
+
|
7
|
+
# associations
|
8
|
+
belongs_to :ecm_links_category,
|
9
|
+
:class_name => Ecm::Links::Category,
|
10
|
+
:counter_cache => :ecm_links_links_count
|
11
|
+
|
12
|
+
# attributes
|
13
|
+
attr_accessible :description,
|
14
|
+
:ecm_links_category_id,
|
15
|
+
:markup_language,
|
16
|
+
:name,
|
17
|
+
:position,
|
18
|
+
:url if respond_to? :attr_accessible
|
19
|
+
|
20
|
+
# callbacks
|
21
|
+
after_initialize :set_defaults
|
22
|
+
|
23
|
+
# constants
|
24
|
+
MARKUP_LANGUAGES = %w(markdown textile rdoc)
|
25
|
+
|
26
|
+
# validations
|
27
|
+
validates :name, :presence => true # , :uniqueness => { :scope => [ :ecm_links_category_id ] }
|
28
|
+
validates :url, :presence => true # , :uniqueness => { :scope => [ :ecm_links_category_id ] }
|
29
|
+
validates :markup_language, :presence => true,
|
30
|
+
:inclusion => MARKUP_LANGUAGES
|
31
|
+
|
32
|
+
|
33
|
+
def description(options = {})
|
34
|
+
options.reverse_merge!(:as => :plain)
|
35
|
+
case options[:as]
|
36
|
+
when :html
|
37
|
+
markup(self[:description])
|
38
|
+
else
|
39
|
+
self[:description]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
|
46
|
+
def markup(text)
|
47
|
+
case markup_language.to_sym
|
48
|
+
when :textile
|
49
|
+
return unless text
|
50
|
+
RedCloth.new(text).to_html
|
51
|
+
when :none
|
52
|
+
text
|
53
|
+
else
|
54
|
+
raise "Unsupported markup language #{markup_language}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def set_defaults
|
59
|
+
if self.new_record?
|
60
|
+
self.markup_language ||= 'textile'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<div class="row link-footer">
|
2
|
+
<% Ecm::Links::Configuration.link_footer_columns.times do |column| %>
|
3
|
+
<div class="column-<%= column + 1 %> <%= Ecm::Links::Configuration.link_footer_column_css_classes.join(' ') %>">
|
4
|
+
<% categories[column + 1].each do |c| %>
|
5
|
+
<h4><%= c.name %></h4>
|
6
|
+
|
7
|
+
<% c.ecm_links_links.each do |l| %>
|
8
|
+
<p><%= render partial: 'ecm/links/links/link', locals: { link: l } %></p>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<% end if categories.has_key?(column + 1) %>
|
12
|
+
</div>
|
13
|
+
<% end %>
|
14
|
+
</div>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<div class="link_category category" id="link_category-<%= category.id %>">
|
2
|
+
<h1><%= category.name %></h1>
|
3
|
+
|
4
|
+
<% unless category.long_description.blank? %>
|
5
|
+
<div class="link_categories-description">
|
6
|
+
<p><%= category.long_description %></p>
|
7
|
+
</div>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<div class="list-group">
|
11
|
+
<%= render partial: 'category_in_index', collection: Ecm::Links::CategoryDecorator.decorate_collection(category.descendants), as: :category %>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div class="download_category-downloads item_list">
|
15
|
+
<h2><%= Ecm::Links::Category.human_attribute_name(:ecm_links_links) %></h2>
|
16
|
+
<% if category.ecm_links_links.count == 0 %>
|
17
|
+
<p><%= t('ecm.links.category.messages.no_links_available') %></p>
|
18
|
+
<% else %>
|
19
|
+
<%= render partial: 'ecm/links/links/table', locals: { links: category.ecm_links_links } %>
|
20
|
+
<% end %>
|
21
|
+
</div>
|
22
|
+
</div>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<%= render @category %>
|
2
|
+
|
3
|
+
<div class="well">
|
4
|
+
<% if @category.root? %>
|
5
|
+
<%= link_to(t('ecm.links.category.actions.back_to_index'), ecm_links_categories_path, class: 'btn btn-default') if respond_to?(:ecm_links_categories_path) %>
|
6
|
+
<% else %>
|
7
|
+
<%= link_to(Ecm::Links::Category.human_attribute_name(:parent), @category.parent, class: 'btn btn-default') %>
|
8
|
+
<% end %>
|
9
|
+
</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= link_to link.name, link.url, { title: link.description } %>
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<tr class="<%= link.class.name.underscore.gsub('/', ' ') %>" id="<%= "#{link.class.name.underscore.gsub('/', '-')}-#{link.to_param}" %>">
|
2
|
+
<td><%= link_to link.name, link.url %></td>
|
3
|
+
<td><%= link_to link.ecm_links_category.human, link.ecm_links_category %></td>
|
4
|
+
<td><%= link.description(as: :html).html_safe %></td>
|
5
|
+
</tr>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
---
|
2
|
+
de:
|
3
|
+
activerecord:
|
4
|
+
models:
|
5
|
+
ecm/links/category:
|
6
|
+
one: Link Kategorie
|
7
|
+
other: Link Kategorien
|
8
|
+
attributes:
|
9
|
+
ecm/links/category:
|
10
|
+
name: Name
|
11
|
+
ecm_links_links: Links
|
12
|
+
ecm_links_links_count: Links
|
13
|
+
slug: Freundliche ID
|
14
|
+
created_at: Erstellt am
|
15
|
+
short_description: Kurzbeschreibung
|
16
|
+
updated_at: Aktualisiert am
|
17
|
+
depth: Tiefe
|
18
|
+
lft: Links
|
19
|
+
long_description: Langbeschreibung
|
20
|
+
markup_language: Markup Sprache
|
21
|
+
parent_id: Über Kategorie
|
22
|
+
locale: Sprache
|
23
|
+
rgt: Rechts
|
24
|
+
link_footer_column: Link Footer Spalte
|
25
|
+
children: Unterkategorien
|
26
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
---
|
2
|
+
en:
|
3
|
+
activerecord:
|
4
|
+
models:
|
5
|
+
ecm/links/category:
|
6
|
+
one: link category
|
7
|
+
other: link categories
|
8
|
+
attributes:
|
9
|
+
ecm/links/category:
|
10
|
+
name: name
|
11
|
+
ecm_links_links: links
|
12
|
+
ecm_links_links_count: links
|
13
|
+
slug: friendly id
|
14
|
+
created_at: created at
|
15
|
+
short_description: short description
|
16
|
+
updated_at: updated at
|
17
|
+
depth: depth
|
18
|
+
lft: left
|
19
|
+
long_description: long description
|
20
|
+
markup_language: markup language
|
21
|
+
parent_id: parent category
|
22
|
+
locale: language
|
23
|
+
rgt: right
|
24
|
+
link_footer_column: link footer column
|
25
|
+
children: Subcategories
|
26
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
---
|
2
|
+
de:
|
3
|
+
activerecord:
|
4
|
+
models:
|
5
|
+
ecm/links/link:
|
6
|
+
one: Link
|
7
|
+
other: Links
|
8
|
+
attributes:
|
9
|
+
ecm/links/link:
|
10
|
+
position: Position
|
11
|
+
name: Name
|
12
|
+
created_at: Erstellt am
|
13
|
+
updated_at: Aktualisiert am
|
14
|
+
url: URL
|
15
|
+
ecm_links_category: Link Kategorie
|
16
|
+
ecm_links_category_id: Link Kategorie
|
17
|
+
markup_language: Markup Sprache
|
18
|
+
description: Beschreibung
|
@@ -0,0 +1,18 @@
|
|
1
|
+
---
|
2
|
+
en:
|
3
|
+
activerecord:
|
4
|
+
models:
|
5
|
+
ecm/links/link:
|
6
|
+
one: link
|
7
|
+
other: links
|
8
|
+
attributes:
|
9
|
+
ecm/links/link:
|
10
|
+
position: position
|
11
|
+
name: name
|
12
|
+
created_at: created at
|
13
|
+
updated_at: updated at
|
14
|
+
url: url
|
15
|
+
ecm_links_category: link category
|
16
|
+
ecm_links_category_id: link category
|
17
|
+
markup_language: markup language
|
18
|
+
description: description
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class CreateEcmLinksCategories < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :ecm_links_categories do |t|
|
4
|
+
t.string :locale
|
5
|
+
t.string :name
|
6
|
+
t.text :short_description
|
7
|
+
t.text :long_description
|
8
|
+
t.string :markup_language
|
9
|
+
t.integer :link_footer_column
|
10
|
+
|
11
|
+
# associations
|
12
|
+
t.integer :ecm_links_links_count, :default => 0, :null => false
|
13
|
+
|
14
|
+
# awesome nested set
|
15
|
+
t.integer :lft
|
16
|
+
t.integer :rgt
|
17
|
+
t.integer :parent_id
|
18
|
+
t.integer :depth
|
19
|
+
|
20
|
+
# friendly id
|
21
|
+
t.string :slug
|
22
|
+
|
23
|
+
t.timestamps
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class CreateEcmLinksLinks < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :ecm_links_links do |t|
|
4
|
+
t.string :name
|
5
|
+
t.string :url
|
6
|
+
t.text :description
|
7
|
+
t.string :markup_language
|
8
|
+
|
9
|
+
# associations
|
10
|
+
t.references :ecm_links_category
|
11
|
+
|
12
|
+
# acts as list
|
13
|
+
t.integer :position
|
14
|
+
|
15
|
+
t.timestamps
|
16
|
+
end
|
17
|
+
add_index :ecm_links_links, :ecm_links_category_id
|
18
|
+
end
|
19
|
+
end
|