honey-cms 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/cms.rb ADDED
@@ -0,0 +1,13 @@
1
+ module CMS
2
+ autoload :Routes, 'cms/routes'
3
+ autoload :Configuration, 'cms/configuration'
4
+ autoload :Type, 'cms/type'
5
+ autoload :Attribute, 'cms/attribute'
6
+ autoload :Helper, 'cms/helper'
7
+ autoload :Orderable, 'cms/orderable'
8
+ autoload :Uploader, 'cms/Uploader'
9
+ autoload :ViewTags, 'cms/view_tags'
10
+ autoload :FormBuilder, 'cms/form_builder'
11
+ end
12
+
13
+ Cms = CMS
@@ -0,0 +1,86 @@
1
+ class CMS::Attribute
2
+ attr_accessor :name, :format, :options
3
+
4
+ def initialize name, format, options
5
+ @name = name
6
+ @format = format
7
+ @options = options
8
+ @attr_options = {
9
+ # null: false
10
+ }
11
+ end
12
+
13
+ def format
14
+ @format_enquirer ||= ActiveSupport::StringInquirer.new(@format)
15
+ end
16
+
17
+ def reference? ; format.reference? end
18
+ def orderable? ; format.orderable? end
19
+ def file? ; format.file? end
20
+
21
+ def has_index?
22
+ false
23
+ end
24
+
25
+ def has_uniq_index?
26
+ false
27
+ end
28
+
29
+ def index_name
30
+ format.reference? ? "#{name}_id" : name
31
+ end
32
+
33
+ def migration_type
34
+ if format.reference?
35
+ 'belongs_to'
36
+ elsif format.orderable?
37
+ 'integer'
38
+ elsif format.file?
39
+ 'string'
40
+ elsif format.html?
41
+ 'text'
42
+ else
43
+ format
44
+ end
45
+ end
46
+
47
+ def form_type
48
+ if format.orderable? || format.reference?
49
+ 'select'
50
+ elsif format.text? or format.html?
51
+ 'text_area'
52
+ elsif format.file?
53
+ 'file_field'
54
+ elsif format.boolean?
55
+ 'check_box'
56
+ else
57
+ 'text_field'
58
+ end
59
+ end
60
+
61
+ def field_name
62
+ if reference?
63
+ name + '_id'
64
+ else
65
+ name
66
+ end
67
+ end
68
+
69
+ def inject_options
70
+ "".tap { |s| @attr_options.each { |k,v| s << ", :#{k} => #{v.inspect}" } }
71
+ end
72
+
73
+ def inject_index_options
74
+ has_uniq_index? ? ", :unique => true" : ''
75
+ end
76
+
77
+ def reference_to
78
+ if reference?
79
+ @reference_to ||= CMS::Configuration.types.find{|t| t.name == @options['reference_to']}
80
+ end
81
+ end
82
+
83
+ def to_s
84
+ name
85
+ end
86
+ end
@@ -0,0 +1,40 @@
1
+ module CMS::Configuration
2
+ def data
3
+ @data = YAML.load(File.read(Rails.root.join 'config/cms.yml'))
4
+ end
5
+
6
+ def scoped_types options
7
+ if options[:only]
8
+ [types.find{|t| options[:only] == t.name}]
9
+ else
10
+ types.reject{|t| options[:except].include?(t.name)}
11
+ end
12
+ end
13
+
14
+ def types
15
+ if defined?(@types) then return @types end
16
+
17
+ @types = data['content_types'].map do |name, config|
18
+ CMS::Type.new(name, config.delete('attributes'), config)
19
+ end
20
+
21
+ @types.each do |type|
22
+ type.attributes = attributes(type.attributes, type)
23
+ end
24
+
25
+ @types
26
+ end
27
+
28
+ def attributes attributes, type
29
+ attributes.map do |args|
30
+ options = args.extract_options!
31
+ name = args.shift
32
+ format = args.pop || options.delete('format')
33
+ attribute = CMS::Attribute.new(name, format, options)
34
+ attribute.reference_to.references << type if attribute.reference?
35
+ attribute
36
+ end
37
+ end
38
+
39
+ extend self
40
+ end
@@ -0,0 +1,3 @@
1
+ class CMS::ControllerStub
2
+
3
+ end
data/lib/cms/engine.rb ADDED
@@ -0,0 +1,5 @@
1
+ module CMS
2
+ class Engine < ::Rails::Engine
3
+ # stubbed for assets.. ?
4
+ end
5
+ end
@@ -0,0 +1,276 @@
1
+ class CMS::FormBuilder < ActionView::Helpers::FormBuilder ; end
2
+
3
+ ActionView::Base.field_error_proc = Proc.new do |html, instance|
4
+ if html =~ /<label/
5
+ html
6
+ else
7
+ message = instance.error_message.map{|m| "#{instance.method_name.humanize} #{m}"}.join(', ')
8
+ "#{html}<div class=\"help-inline\">#{message}</div>".html_safe
9
+ end
10
+ end
11
+
12
+ module CMS::FormBuilder::Fields
13
+ def radio name, *args
14
+ args = _apply_field_defaults(args)
15
+ options = args.extract_options!
16
+ values = args
17
+ field_wrapper :radio, name do
18
+ out = ''.html_safe
19
+ out.concat label(name) if options[:label]
20
+
21
+ value_div = @template.content_tag(:span, class: 'values') do
22
+ values.map do |value|
23
+ @template.content_tag :span, class: 'value' do
24
+ if value.is_a? Array
25
+ radio_button(name, value[1]) + label(name, value[0], value: value[1])
26
+ else
27
+ radio_button(name, value) + label(name, value, value: value)
28
+ end
29
+ end
30
+ end.join("\n").html_safe
31
+ end
32
+ out.concat value_div
33
+ end
34
+ end
35
+
36
+ def location name, options
37
+ autocomplete name, options.merge(prepend: @template.content_tag(:div, '', class: 'geolocate'))
38
+ end
39
+
40
+ def autocomplete name, *args
41
+ args = _apply_field_defaults(args)
42
+ options = args.extract_options!
43
+ options.reverse_merge!(waiting: 'Searching...')
44
+
45
+ option_text = '<div class="options"><div class="inner">'.html_safe
46
+ option_text.concat @template.content_tag(:div, options[:waiting], class: 'waiting')
47
+ option_text.concat '<div class="results"></div>'.html_safe
48
+ option_text.concat '</div></div>'.html_safe
49
+
50
+ field_wrapper(:autocomplete, name) do
51
+ out = ''.html_safe
52
+ if options[:label] == true
53
+ out.concat label(name)
54
+ elsif options[:label]
55
+ out.concat label(name, options[:label])
56
+ end
57
+ out.concat @template.link_to 'learn more', '#', class: 'tipsy', title: send("#{name}_help_text") if options[:help_text]
58
+ options[:help_text] = false
59
+ out.concat string(name, options.merge(autocomplete: false, label: false, append: option_text))
60
+ end
61
+ end
62
+
63
+ def text_with_counter name, *args
64
+ args = _apply_field_defaults(args)
65
+ options = args.extract_options!
66
+
67
+ unless options[:length].blank?
68
+ counter = "<div class=\"counter\"><span class=\"count\">0</span>/<span class=\"maximum\">#{options[:length]}</span></div>".html_safe
69
+ end
70
+
71
+ text(name, options.merge(label: options[:label], append: counter))
72
+ end
73
+
74
+ def boolean *args
75
+ field :boolean, *_apply_default_options(args, label_first: false)
76
+ end
77
+
78
+ def string *args
79
+ field :string, *args
80
+ end
81
+
82
+ def search *args
83
+ field :search, *args
84
+ end
85
+
86
+ def text *args
87
+ field :text, *args
88
+ end
89
+
90
+ def email *args
91
+ field :email, *args
92
+ end
93
+
94
+ def password *args
95
+ field :password, *args
96
+ end
97
+
98
+ def hidden *args
99
+ field :hidden, *_apply_default_options(args, label: false, wrap_field: false)
100
+ end
101
+
102
+ # slider is weird enough that we will not use the default field helper.
103
+ # instead, we will construct our own field that looks like a regular field.
104
+ def slider name, *args
105
+ args = _apply_field_defaults(args)
106
+ options = args.extract_options!
107
+ out = ''.html_safe
108
+
109
+ field_wrapper :slider, name do
110
+ out.concat label(name, options[:label]) if options[:label]
111
+ out.concat @template.content_tag :div, '', class: 'slider-edit'
112
+ out.concat hidden(name)
113
+ end
114
+ end
115
+
116
+ def toggle name, *args
117
+ args = _apply_field_defaults(args)
118
+ options = args.extract_options!
119
+ out = ''.html_safe
120
+
121
+ field_wrapper :toggle, name, :'data-default' => options[:default] do
122
+ out.concat label(name) if options[:label]
123
+ out.concat(@template.content_tag(:div, class: (object.send(name) ? 'visible' : 'hidden')) do
124
+ check_box(name) << @template.label_tag(object.send(name) ? 'visible' : 'hidden')
125
+ end)
126
+ end
127
+ end
128
+
129
+ def actions options = {}
130
+ options.reverse_merge! save: 'Save', saving: 'Saving...', class: 'form-actions'
131
+ @template.content_tag(:div, class: options.delete(:class)) do
132
+ actions = ''.html_safe
133
+ actions << submit(options[:save], disable_with: options[:saving], class: 'btn btn-primary')
134
+ actions << status
135
+ end
136
+ end
137
+
138
+ def modal_actions options = {}
139
+ options.reverse_merge! save: 'Save', saving: 'Saving...', class: 'modal-footer'
140
+ @template.content_tag(:div, class: options.delete(:class)) do
141
+ actions = ''.html_safe
142
+ actions << @template.link_to('Close', '#close', class: 'btn', data: {dismiss: 'modal'})
143
+ actions << submit(options[:save], disable_with: options[:saving], class: 'btn btn-primary')
144
+ end
145
+ end
146
+
147
+ def status options = {}
148
+ options.reverse_merge! success: 'Saved!', error: 'Failed!'
149
+ out = @template.content_tag(:div, class: 'status') do
150
+ status = ''.html_safe
151
+ status << @template.content_tag(:div, '', class: 'spinner')
152
+ # status << @template.content_tag(:div, options[:success], class: 'success')
153
+ # status << @template.content_tag(:div, options[:error], class: 'error')
154
+ end
155
+ end
156
+
157
+ def field_wrapper type, name, options = {}
158
+ classes = "field #{type} #{name.to_s.dasherize} control-group"
159
+ classes << options[:classes] if options[:classes]
160
+ classes << ' error' if object.errors.include? name
161
+ options.merge! class: classes
162
+ @template.content_tag :div, options do
163
+ yield
164
+ end
165
+ end
166
+
167
+ # def _input_options options
168
+ # [:autocomplete, :placeholder]
169
+ # end
170
+
171
+ def field *args, &block
172
+ type, name, options = _extract_field_args(args)
173
+ out = ''.html_safe
174
+
175
+ input_options = {}
176
+
177
+ unless options[:autocomplete].nil?
178
+ options.delete(:autocomplete)
179
+ input_options[:autocomplete] = 'off'
180
+ end
181
+
182
+ unless options[:placeholder].nil?
183
+ input_options[:placeholder] = options.delete(:placeholder)
184
+ end
185
+
186
+ unless options[:hidden].nil?
187
+ input_options[:class] = 'hidden' if options[:hidden] == true
188
+ end
189
+
190
+ unless options[:required].nil?
191
+ input_options[:required] = 'required' if options[:required] == true
192
+ end
193
+
194
+ out.concat options[:prepend] if options[:prepend]
195
+
196
+
197
+ label_html = label(name, options[:label], class: 'control-label')
198
+
199
+ out.concat label_html if options[:label] && options[:label_first]
200
+
201
+ if options[:help_text]
202
+ help_text = send("#{name}_help_text")
203
+ help_html = "<a class=\"tipsy\" title=\"#{help_text}\" href=\"#\">learn more</a>".html_safe
204
+ out.concat help_html
205
+ end
206
+
207
+ out.concat(@template.content_tag(:div, class: 'controls') do
208
+ controls = send(_field_types(type), name, input_options)
209
+ controls.concat @template.content_tag(:div, options[:help_block], class: 'help-block') if options[:help_block].present?
210
+ controls
211
+ end)
212
+
213
+ out.concat label_html if options[:label] && !options[:label_first]
214
+
215
+ out.concat options[:append] if options[:append]
216
+ out.concat yield if block_given?
217
+
218
+ if options[:wrap_field]
219
+ field_wrapper(type, name) { out }
220
+ else
221
+ out
222
+ end
223
+ end
224
+
225
+ # simple helper method for extracting and applying default options.
226
+ def _apply_default_options args, defaults
227
+ options = args.extract_options!
228
+ args << options.reverse_merge!(defaults)
229
+ end
230
+
231
+ # apply the default options for all fields.
232
+ def _apply_field_defaults args
233
+ _apply_default_options args, label: true, wrap_field: true, label_first: true
234
+ end
235
+
236
+ # single use method for parsing options provided by the +field+ helper
237
+ def _extract_field_args args
238
+ args = _apply_field_defaults(args)
239
+ options = args.extract_options!
240
+ name = args.pop
241
+ type = args.pop
242
+ options[:label] = name.to_s.humanize if options[:label].is_a? TrueClass
243
+ [type, name, options]
244
+ end
245
+
246
+ def _field_types(type)
247
+ case type
248
+ when :string, :location
249
+ :text_field
250
+ when :search
251
+ :search_field
252
+ when :text
253
+ :text_area
254
+ when :email
255
+ :email_field
256
+ when :password
257
+ :password_field
258
+ when :hidden, :slider
259
+ :hidden_field
260
+ when :boolean, :radio
261
+ :radio_button
262
+ when :boolean, :check
263
+ :check_box
264
+ end
265
+ end
266
+
267
+ def error_messages
268
+ if object.errors.any?
269
+ @template.render partial: 'shared/form/error_messages', object: object.errors
270
+ end
271
+ end
272
+ end
273
+
274
+ class CMS::FormBuilder
275
+ include CMS::FormBuilder::Fields
276
+ end
data/lib/cms/helper.rb ADDED
@@ -0,0 +1,65 @@
1
+ module CMS::Helper
2
+ def cms_file name, size = false
3
+ if file = CMS::FileUpload.find_by_name(name) then return file end
4
+ opts = {name: name}
5
+ opts[:description] = (size.sub('x', ' by ') << ' pixels')
6
+ CMS::FileUpload.create(opts, without_protection: true)
7
+ end
8
+
9
+ def cms_image name, size = false, width = '', height = ''
10
+ width, height = size.split('x') if size
11
+ image = cms_file(name, size)
12
+
13
+ if image.file?
14
+ image_tag image.file.url, class: 'cms-image', style: "width: #{width}px ; height: #{height}px"
15
+ else
16
+ if current_user && current_user.role.admin?
17
+ link_to(name, edit_cms_file_upload_path(image), class: 'cms-image missing-cms-image', style: "width: #{width}px ; height: #{height}px ")
18
+ else
19
+ content_tag :div, name, class: 'cms-image missing-cms-image', style: "width: #{width}px ; height: #{height}px"
20
+ end
21
+ end
22
+ end
23
+
24
+ def cms_page_area name, &block
25
+ page_area = if area = CMS::PageArea.find_by_name(name) then area else CMS::PageArea.new({name: name}, without_protection: true) end
26
+
27
+ content_tag :div, role: 'html-editor' do
28
+ out = content_tag(:div, class: 'cms-page-area', role: 'display') do
29
+ if page_area.content.present? && !page_area.default
30
+ content = page_area.content
31
+ elsif block_given?
32
+ content = capture(&block)
33
+ page_area.content = ''.concat(content)
34
+ page_area.save!
35
+ end
36
+
37
+ display = ''.html_safe
38
+ display << cms_page_area_edit_link if admin?
39
+ display << content_tag(:div, class: 'content') do
40
+ cms_content_parse(content) if content.present?
41
+ end
42
+ end
43
+
44
+ out << content_tag(:div, role: 'editor') do
45
+ form_for([:cms, page_area], format: 'json', remote: true) do |f|
46
+ form = f.hidden_field(:name)
47
+ form << f.hidden_field(:content, class: 'content')
48
+ form << f.actions(save: 'done')
49
+ end
50
+ end
51
+ end
52
+ rescue Exception => e
53
+ if Rails.env.production? then '' else raise e end
54
+ end
55
+
56
+ def cms_page_area_edit_link
57
+ content_tag :div, class: 'cms-edit-link' do
58
+ link_to('Edit', '#edit')
59
+ end
60
+ end
61
+
62
+ def cms_content_parse content
63
+ CMS::ViewTags.instance.parse content, context: self
64
+ end
65
+ end
@@ -0,0 +1,24 @@
1
+ module CMS::Orderable
2
+ extend ActiveSupport::Concern
3
+
4
+ def order_scope
5
+ self.class
6
+ end
7
+
8
+ module ClassMethods
9
+ def orderable name
10
+ default_scope order(name)
11
+ after_save :"order_#{name}"
12
+
13
+ define_method :"order_#{name}" do
14
+ order_scope.where("#{name} >= #{send(name)}").where("id != #{id}").select(:id).select(name).inject(send(name)) do |i, record|
15
+ record.update_column name, (i += 1) ; i
16
+ end
17
+
18
+ order_scope.all.inject(1) do |i, record|
19
+ record.update_column name, i ; i + 1
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
data/lib/cms/routes.rb ADDED
@@ -0,0 +1,14 @@
1
+ class CMS::Routes < SimpleDelegator
2
+ def draw
3
+ namespace :cms do
4
+ get 'description' => 'root#description'
5
+ get '' => 'root#index'
6
+
7
+ CMS::Configuration.types.each do |type|
8
+ resources type.model_name.route_key
9
+ end
10
+
11
+ resources :topic_datas, :community_maps, :downtowns
12
+ end
13
+ end
14
+ end
data/lib/cms/type.rb ADDED
@@ -0,0 +1,44 @@
1
+ class CMS::Type
2
+ attr_accessor :name, :attributes, :options, :references
3
+ include ActiveModel::Naming # using include instead of extend on purpose
4
+ def parents ; [] end # quacks like a Module
5
+
6
+ def initialize name, attributes, options = {}
7
+ @name = name
8
+ @attributes = attributes
9
+ @options = options.symbolize_keys.merge(timestamps: true, indexes: true)
10
+ @references = []
11
+ end
12
+
13
+ def accessible_attributes
14
+ attributes
15
+ end
16
+
17
+ def attributes_with_index
18
+ attributes.select { |a| a.has_index? || (a.reference? && options[:indexes]) }
19
+ end
20
+
21
+ def orderable_attributes
22
+ attributes.select(&:orderable?)
23
+ end
24
+
25
+ def file_attributes
26
+ attributes.select(&:file?)
27
+ end
28
+
29
+ def orderable?
30
+ !!order_attribute
31
+ end
32
+
33
+ def order_attribute
34
+ orderable_attributes.first
35
+ end
36
+
37
+ def to_s
38
+ name
39
+ end
40
+
41
+ def subject
42
+ options[:subject] || name
43
+ end
44
+ end
@@ -0,0 +1,7 @@
1
+ class CMS::Uploader < CarrierWave::Uploader::Base
2
+ def store_dir
3
+ base = File.join('cms-uploads', model.class.model_name.collection.gsub('_', '-'), model.id.try(:to_s))
4
+ base = File.join('uploads', base) if storage.is_a? CarrierWave::Storage::File
5
+ base
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ class CMS::ViewTags
2
+ attr_accessor :context, :controller
3
+ delegate :current_user, :config, to: :context
4
+
5
+ include Singleton
6
+ include ApplicationHelper
7
+ include ActionView::Helpers::TextHelper
8
+ include ActionView::Helpers::UrlHelper
9
+ include ActionView::Helpers::AssetTagHelper
10
+ include ApplicationHelper
11
+ include CMS::Helper
12
+ include Rails.application.routes.url_helpers
13
+
14
+ def setup opts
15
+ @context = @controller = opts[:context]
16
+ end
17
+
18
+ def parse content, opts = {}
19
+ setup(opts)
20
+ content.gsub(/\{\{image [^}}]+\}\}/) do |tag|
21
+ str, name, size = tag.match(/\{\{image (\w+) (\w+)\}\}/).to_a
22
+ cms_image(name, size)
23
+ end.html_safe
24
+ end
25
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Explain the generator
3
+
4
+ Example:
5
+ rails generate cms Thing
6
+
7
+ This will create:
8
+ what/will/it/create
@@ -0,0 +1,44 @@
1
+ require 'rails/generators/active_record/migration'
2
+
3
+ class CmsGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../templates', __FILE__)
5
+ include Rails::Generators::Migration
6
+ extend ActiveRecord::Generators::Migration
7
+
8
+ class_option :except, type: :array, default: [],
9
+ desc: 'skip certain types.'
10
+
11
+ class_option :only, type: :string, default: false,
12
+ desc: 'run a specific type generator.'
13
+
14
+ class_option :migrate, type: :boolean, default: false,
15
+ desc: 'generate the migration'
16
+
17
+ class_option :controller, type: :boolean, default: false,
18
+ desc: 'generate the controller'
19
+
20
+ def create_migration_file
21
+ if options[:only].present?
22
+ migration_template 'migration.rb', "db/migrate/create_#{options[:only].underscore.pluralize}" if options[:migrate]
23
+ else
24
+ migration_template 'migration.rb', 'db/migrate/create_cms' if options[:migrate]
25
+ end
26
+ end
27
+
28
+ def copy_controller_file
29
+ template 'cms_base_controller.rb', 'app/controllers/cms/base_controller.rb' if options[:controller]
30
+
31
+ empty_directory 'app/controllers/cms'
32
+ empty_directory 'app/models/cms'
33
+
34
+ CMS::Configuration.scoped_types(options).each do |type|
35
+ @name = (@type = type).model_name
36
+ template 'type_controller.rb', "app/controllers/cms/#{@name.collection}_controller.rb"
37
+ template 'type_model.rb', "app/models/cms/#{@name.element}.rb"
38
+
39
+ %w(index new show edit).each do |view|
40
+ template "views/#{view}.html.haml", "app/views/cms/#{@name.collection}/#{view}.html.haml"
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,78 @@
1
+ class CMS::BaseController < ApplicationController
2
+ before_filter :admin!
3
+ before_filter :set_active
4
+ layout 'cms'
5
+
6
+ before_filter :find_record, only: [:show, :edit, :update, :destroy]
7
+ before_filter :set_element_variable, only: [:show, :edit, :update, :destroy]
8
+ respond_to :html, :json
9
+
10
+ def index
11
+ @records = if params[:search].blank?
12
+ subject.order('id asc') .page(params[:page]).per(100)
13
+ else
14
+ subject.search(params[:search]).page(params[:page]).per(100)
15
+ end
16
+
17
+ set_collection_variable
18
+ respond_with(@records)
19
+ end
20
+
21
+ def new
22
+ @record = subject.new
23
+ set_element_variable
24
+ respond_with(@record)
25
+ end
26
+
27
+ def create
28
+ @record = subject.create(params[subject.model_name.element])
29
+ set_element_variable
30
+ respond_with @record
31
+ end
32
+
33
+ def show
34
+ respond_with @record
35
+ end
36
+
37
+ def edit
38
+ respond_with @record
39
+ end
40
+
41
+ def update
42
+ @record.update_attributes params[subject.model_name.element]
43
+ respond_with @record
44
+ end
45
+
46
+ def destroy
47
+ @record.destroy
48
+ respond_with @record
49
+ end
50
+
51
+ protected
52
+
53
+ def respond_with object
54
+ super [:cms, object]
55
+ end
56
+
57
+ def find_record
58
+ @record = subject.find(params[:id])
59
+ end
60
+
61
+ def set_collection_variable
62
+ instance_variable_set :"@#{subject.model_name.collection}", @records
63
+ end
64
+
65
+ def set_element_variable
66
+ instance_variable_set :"@#{subject.model_name.element}", @record
67
+ end
68
+
69
+ def admin!
70
+ unless signed_in? && current_user.role.admin?
71
+ auth_failed
72
+ end
73
+ end
74
+
75
+ def set_active
76
+ @active_page = /cms/
77
+ end
78
+ end
@@ -0,0 +1,3 @@
1
+ class CMS::Model < ActiveRecord::Base
2
+
3
+ end
@@ -0,0 +1,19 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration
2
+ def change
3
+ <% CMS::Configuration.scoped_types(options).each do |type| -%>
4
+ create_table :<%= type.model_name.collection %> do |t|
5
+ <% type.attributes.each do |attribute| -%>
6
+ t.<%= attribute.migration_type %> :<%= attribute.name %><%= attribute.inject_options %>
7
+ <% end -%>
8
+ <% if type.options[:timestamps] -%>
9
+ t.timestamps
10
+ <% end -%>
11
+ end
12
+
13
+ <% type.attributes_with_index.each do |attribute| -%>
14
+ add_index :<%= type.model_name.collection %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
15
+ <% end -%>
16
+ <% end -%>
17
+
18
+ end
19
+ end
@@ -0,0 +1,9 @@
1
+ class CMS::<%= @name.pluralize %>Controller < CMS::BaseController
2
+ helper_method :subject
3
+
4
+ protected
5
+
6
+ def subject
7
+ CMS::<%= @name %>
8
+ end
9
+ end
@@ -0,0 +1,23 @@
1
+ class CMS::<%= @name %> < ActiveRecord::Base
2
+ self.table_name = '<%= @name.collection %>'
3
+ <% @type.attributes.select {|attr| attr.reference? }.each do |attribute| -%>
4
+ belongs_to :<%= attribute.name %>, class_name: 'CMS::<%= attribute.reference_to %>'
5
+ <% end -%>
6
+ <% if @type.references.any? -%>
7
+ <% @type.references.each do |type| -%>
8
+ has_many :<%= type.model_name.collection %>, class_name: 'CMS::<%= type %>'
9
+ <% end -%>
10
+ <% end -%>
11
+ attr_accessible <%= @type.accessible_attributes.map {|a| ":#{a.field_name}" }.sort.join(', ') %>
12
+ <% if @type.orderable? -%>
13
+ include CMS::Orderable
14
+ orderable(:<%= @type.order_attribute.name %>)
15
+ <% end -%>
16
+ <% @type.file_attributes.each do |attribute| -%>
17
+ mount_uploader :<%= attribute.name %>, CMS::Uploader
18
+ <% end -%>
19
+
20
+ def self.name
21
+ '<%= @name %>'
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ %h2 Edit <%= @name.human.downcase %>
2
+
3
+ = form_for @<%= @name.element %>, url: cms_<%= @name.element %>_path(@<%= @name.element %>), html: {class: 'form-horizontal'} do |f|
4
+ <% @type.attributes.each do |attribute| -%>
5
+ .control-group
6
+ = f.label :<%= attribute.field_name %>, class: 'control-label'
7
+ <% if attribute.orderable? -%>
8
+ .controls
9
+ = f.<%= attribute.form_type %> :<%= attribute.name %>, 1.upto(CMS::<%= @name %>.count).to_a
10
+ <% elsif attribute.reference? -%>
11
+ .controls
12
+ = f.<%= attribute.form_type %> :<%= attribute.field_name %>, CMS::<%= attribute.reference_to %>.all.collect {|r| [ r.<%= attribute.options['reference_label'] %>, r.id ] }
13
+ <% else -%>
14
+ .controls
15
+ = f.<%= attribute.form_type %> :<%= attribute.name %>
16
+ <% end -%>
17
+ <% end -%>
18
+ .form-actions
19
+ = f.submit 'Save', class: 'btn btn-primary', :'data-disable-with' => 'Saving...'
@@ -0,0 +1,34 @@
1
+ %h2 <%= @name.human.pluralize %>
2
+
3
+ = link_to 'New <%= @name.human.downcase %>', new_cms_<%= @name.element %>_path
4
+
5
+ %table.table
6
+ %thead
7
+ %tr
8
+ %th Id
9
+ <% @type.attributes.each do |attribute| -%>
10
+ %th <%= attribute.name.humanize %>
11
+ <% end -%>
12
+ %th
13
+
14
+ %tbody
15
+ - @<%= @name.collection %>.each do |<%= @name.element %>|
16
+ %tr
17
+ %td= <%= @name.element %>.id
18
+ <% @type.attributes.each do |attribute| -%>
19
+ <% if attribute.reference? -%>
20
+ %td
21
+ - if <%= @name.element %>.<%= attribute.name %>.present?
22
+ = link_to <%= @name.element %>.<%= attribute.name %>.<%= attribute.options['reference_label'] %>, cms_<%= attribute.reference_to.model_name.element %>_path(<%= @name.element %>.<%= attribute.name %>)
23
+ <% elsif attribute.format.file? -%>
24
+ %td
25
+ %img{src: <%= @name.element %>.<%= attribute.name %>}
26
+ <% else -%>
27
+ %td= <%= @name.element %>.<%= attribute.name %>
28
+ <% end -%>
29
+ <% end -%>
30
+ %td
31
+ = link_to 'Edit', edit_cms_<%= @name.element %>_path(<%= @name.element %>)
32
+ = link_to 'Destroy', cms_<%= @name.element %>_path(<%= @name.element %>), confirm: 'are you sure?', method: 'delete'
33
+
34
+ = paginate @<%= @name.collection %>
@@ -0,0 +1,19 @@
1
+ %h2 New <%= @name.human.downcase %>
2
+
3
+ = form_for @<%= @name.element %>, url: cms_<%= @name.collection %>_path, html: {class: 'form-horizontal'} do |f|
4
+ <% @type.attributes.each do |attribute| -%>
5
+ .control-group
6
+ = f.label :<%= attribute.field_name %>, class: 'control-label'
7
+ <% if attribute.orderable? -%>
8
+ .controls
9
+ = f.<%= attribute.form_type %> :<%= attribute.name %>, 1.upto(CMS::<%= @name %>.count + 1).to_a
10
+ <% elsif attribute.reference? -%>
11
+ .controls
12
+ = f.<%= attribute.form_type %> :<%= attribute.field_name %>, CMS::<%= attribute.reference_to %>.all.collect {|r| [ r.<%= attribute.options['reference_label'] %>, r.id ] }
13
+ <% else -%>
14
+ .controls
15
+ = f.<%= attribute.form_type %> :<%= attribute.name %>
16
+ <% end -%>
17
+ <% end -%>
18
+ .form-actions
19
+ = f.submit 'Save', class: 'btn btn-primary', :'data-disable-with' => 'Saving...'
@@ -0,0 +1,13 @@
1
+ %h2== Showing <%= @name.human.downcase %> ##{@<%= @name.element %>.id}
2
+
3
+ %dl
4
+ <% @type.attributes.each do |attribute| -%>
5
+ %dt <%= attribute.name.humanize %>
6
+ <% if attribute.reference? -%>
7
+ %dd= @<%= @name.element %>.<%= attribute.name %>.try(:<%= attribute.options['reference_label'] %>)
8
+ <% elsif attribute.format.text? -%>
9
+ %dd= markdown @<%= @name.element %>.<%= attribute.name %>
10
+ <% else -%>
11
+ %dd= @<%= @name.element %>.<%= attribute.name %>
12
+ <% end -%>
13
+ <% end -%>
data/lib/honey-cms.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'cms'
2
+ require 'cms/engine'
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: honey-cms
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Quinn Shanahan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-16 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Some CMS functionality
15
+ email: quinn@tastehoneyco.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/cms/attribute.rb
21
+ - lib/cms/configuration.rb
22
+ - lib/cms/controller_stub.rb
23
+ - lib/cms/engine.rb
24
+ - lib/cms/form_builder.rb
25
+ - lib/cms/helper.rb
26
+ - lib/cms/orderable.rb
27
+ - lib/cms/routes.rb
28
+ - lib/cms/type.rb
29
+ - lib/cms/uploader.rb
30
+ - lib/cms/view_tags.rb
31
+ - lib/cms.rb
32
+ - lib/generators/cms/cms_generator.rb
33
+ - lib/generators/cms/templates/cms_base_controller.rb
34
+ - lib/generators/cms/templates/cms_model.rb
35
+ - lib/generators/cms/templates/migration.rb
36
+ - lib/generators/cms/templates/type_controller.rb
37
+ - lib/generators/cms/templates/type_model.rb
38
+ - lib/generators/cms/templates/views/edit.html.haml
39
+ - lib/generators/cms/templates/views/index.html.haml
40
+ - lib/generators/cms/templates/views/new.html.haml
41
+ - lib/generators/cms/templates/views/show.html.haml
42
+ - lib/generators/cms/USAGE
43
+ - lib/honey-cms.rb
44
+ homepage: https://github.com/honeyco/honey-cms
45
+ licenses: []
46
+ post_install_message:
47
+ rdoc_options: []
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubyforge_project:
64
+ rubygems_version: 1.8.11
65
+ signing_key:
66
+ specification_version: 3
67
+ summary: CMS
68
+ test_files: []