contentment 0.4.0 → 0.5.0

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.
data/README.rdoc CHANGED
@@ -2,9 +2,61 @@
2
2
 
3
3
  ===Contentment is a extremely basic Content Management System.
4
4
 
5
+ How often do your clients want to manage / edit some piddly little portion of the site you're building for them?
6
+ Every time? Yeah me too. If what you need is a way for your clients to manage the FAQ or Testimonials, contentment is for you.
7
+ It's blindingly simple to use and it will save you time.
8
+
5
9
  The primary advantage it offers over a roll-your-own CMS is consistency.
6
10
  Use Contentment whenever you need a basic CMS and you can stop re-inventing the wheel and start pumping code.
7
11
 
12
+ ==Get Contentment
13
+ Add it to your gemfile
14
+ gem 'contentment'
15
+ and run
16
+ bundle install
17
+
18
+ ==Use Contentment
19
+ rails g contentment
20
+ rake db:migrate
21
+ This will create the Content model and a migration to add the contents table to your database, if it doesn't already exist.
22
+ It will also create contents_controller.rb for you with all the CRUD already done.
23
+ rails g contentment_views
24
+ Will create the views to manage your Content.
25
+
26
+ Fire up the server and you're ready to go.
27
+
28
+ ==Details
29
+ title and body are pretty self explanatory, perfect for question and answer, or header and paragraph.
30
+ tipe is not type to get around rails polymorphic associations stuff and exists because then you can
31
+ do things like Content.for_FAQ or Content.for_navigation.
32
+ dom_id is rarely used, but sometimes you need to manipulate Content programmatically and this is there for that.
33
+ position, because clients love ordering stuff around.
34
+ visible, because clients like to hide things from their users.
35
+
36
+ ==Live Preview of Content on Edit
37
+
38
+ Slap this in your application.js to get live preview of the title attribute of content
39
+ $('.edit_content').keyup(function(){
40
+ var bob = $('#content_title').val();
41
+ $('.content_preview_title').html(bob);
42
+ })
43
+ I'm using TinyMCE Hammer to get TinyMCE in my projects, and if you install it too you can have live preview of the body of your content pretty easily.
44
+ (I'm working on getting TinyMCE included in this gem)
45
+ TinyMCE is nice because your clients probably want the ability to add line breaks and other styling without having to learn HTML.
46
+ So. Install the TinyMCE Hammer plugin https://github.com/trevorrowe/tinymce_hammer or http://tinymcehammer.lanalot.com/ , I don't know which is canonical.
47
+ Then add
48
+ <%= yield :scripts %>
49
+ to the <head> section of whatever layout (probably application.html.erb) is rendered around the contents/edit.html.erb file.
50
+ Donezo. You should now see the changes made to the title and body of your content on the edit view live and in real time in the preview area.
51
+ Clients love that.
52
+
53
+ ==That's It!
54
+ If we did anything else it wouldn't be simple anymore.
55
+
56
+ Questions, Thoughts, Comments to larrick@gmail.com
57
+
58
+
59
+
8
60
 
9
61
  ==Thanks
10
62
 
@@ -1,36 +1,34 @@
1
1
  <%= link_to 'New content', new_content_path, :class => 'button', :id => "add-content" %>
2
2
  <%= link_to "Back to Content List", contents_path, :class => 'button', :id => 'back-to-contents' %>
3
3
  <div class="panel clearfix">
4
- <h3>Edit content</h3>
5
- <% form_for(@content) do |f| %>
6
- <div class="tools">
7
- <%= link_to 'Back', contents_path %>
8
- <%= f.submit 'Update' %>
9
- </div>
10
- <div class="main">
11
- <%= f.text_field :title, :placeholder => "Content Title", :class => 'title' %>
12
- <%= f.label :body %>
13
- <%= f.text_area :body %>
14
- </div>
15
- <div class="side">
16
- <p>
17
- <%= f.label :type %>
18
- <%= f.select :tipe, content_tipe_options %>
19
- </p>
20
- <p>
21
- <%= f.label "DOM id" %>
22
- <%= f.text_field :dom_id %>
23
- </p>
24
-
25
- <p>
26
- <%= f.label :position %>
27
- <%= f.text_field :position %>
28
- </p>
29
- <p>
30
- <%= f.label :visible %>
31
- <%= f.check_box :visible%>
32
- </p>
33
- </div>
34
- <% end %>
4
+ <h3>Edit content</h3>
5
+ <% form_for(@content) do |f| %>
6
+ <p>
7
+ <%= f.text_field :title, :placeholder => "Content Title", :class => 'title' %>
8
+ </p>
9
+ <p>
10
+ <%= f.label :body %>
11
+ <%= f.text_area :body %>
12
+ </p>
13
+ <p>
14
+ <%= f.label :type %>
15
+ <%= f.select :tipe, content_tipe_options %>
16
+ </p>
17
+ <p>
18
+ <%= f.label "DOM id" %>
19
+ <%= f.text_field :dom_id %>
20
+ </p>
21
+ <p>
22
+ <%= f.label :position %>
23
+ <%= f.text_field :position %>
24
+ </p>
25
+ <p>
26
+ <%= f.label :visible %>
27
+ <%= f.check_box :visible%>
28
+ </p>
29
+ <%= link_to 'Back', contents_path %>
30
+ <%= f.submit 'Update' %>
31
+
32
+ <% end %>
35
33
  </div>
36
34
  <%= render :partial => "preview", :locals => { :form => '.edit_content', :content => @content } %>
@@ -1,37 +1,34 @@
1
1
  <div class="panel clearfix">
2
- <h3>New content</h3>
3
- <% form_for(@content) do |f| %>
4
- <div class="tools">
5
- <%= link_to 'Cancel', contents_path %>
6
- <%= f.submit 'Create' %>
7
- </div>
8
2
 
9
- <div class="main">
10
- <%= f.text_field :title, :placeholder => "Content Title", :class => 'title' %>
11
3
 
12
- <%= f.label :body %>
13
- <%= f.text_area :body %>
14
-
15
- </div>
16
- <div class="side">
17
- <p>
18
- <%= f.label :type %>
19
- <%= f.select :tipe, content_tipe_options %>
20
- </p>
21
- <p>
22
- <%= f.label "DOM id" %>
23
- <%= f.text_field :dom_id %>
24
- </p>
25
-
26
- <p>
27
- <%= f.label :position %>
28
- <%= f.text_field :position %>
29
- </p>
30
- <p>
31
- <%= f.label :visible %>
32
- <%= f.check_box :visible%>
33
- </p>
34
- </div>
35
- <% end %>
4
+ <h3>New content</h3>
5
+ <% form_for(@content) do |f| %>
6
+ <p>
7
+ <%= f.text_field :title, :placeholder => "Content Title", :class => 'title' %>
8
+ </p>
9
+ <p>
10
+ <%= f.label :body %>
11
+ <%= f.text_area :body %>
12
+ </p>
13
+ <p>
14
+ <%= f.label :type %>
15
+ <%= f.select :tipe, content_tipe_options %>
16
+ </p>
17
+ <p>
18
+ <%= f.label "DOM id" %>
19
+ <%= f.text_field :dom_id %>
20
+ </p>
21
+ <p>
22
+ <%= f.label :position %>
23
+ <%= f.text_field :position %>
24
+ </p>
25
+ <p>
26
+ <%= f.label :visible %>
27
+ <%= f.check_box :visible%>
28
+ </p>
29
+ <%= link_to 'Cancel', contents_path %>
30
+ <%= f.submit 'Create' %>
31
+
32
+ <% end %>
36
33
  </div>
37
34
  <%= render :partial => "preview", :locals => { :form => '.new_content', :content => @content } %>
@@ -1,4 +1,7 @@
1
1
  module ContentsHelper
2
+
3
+ # Is a helper really necessary? Apparently I thought so at some point. <%= f.select :tipe, content_tipe_options %>
4
+ # When the helper is longer than what it replaces you've got a problem.
2
5
  def content_tipe_options
3
6
  Content.tipes
4
7
  end
@@ -1,10 +1,12 @@
1
1
  class Content < ActiveRecord::Base
2
2
 
3
- # ADJUST_POSTIONS DOES NOT WORK RIGHT NOW
4
- # before_save :adjust_positions
3
+ before_save :adjust_positions
4
+
5
5
 
6
6
  class << self; attr_accessor :tipes; end
7
7
 
8
+ # Put all the different kinds of content you will have in here to get a select helper and some named scopes
9
+ # generated for you.
8
10
  @tipes = [
9
11
  # "Billboard",
10
12
  # "What You Learn",
@@ -16,23 +18,27 @@ class Content < ActiveRecord::Base
16
18
  # "Navigation",
17
19
  ]
18
20
 
21
+ # Pretty much always want to only find content of one tipe at a time, so generate scopes for all tipes.
19
22
  @tipes.each do |thing|
20
23
  scope "for_#{thing.downcase.gsub(' ', '_')}".intern, where("tipe = ?", thing)
21
24
  end
22
25
 
26
+ # It's pretty common to want the ability to hide some content. Use the visible scope liberally.
23
27
  scope :visible, lambda {|x| where(:visible => x)}
24
28
 
25
-
29
+ # Returns all Content with like tipe.
26
30
  def brothers
27
31
  Content.where("tipe = ?", self.tipe).where("id NOT in (#{self.id})")
28
32
  end
29
33
 
30
34
  private
35
+ # It's a pain with ordered content to have to manually update each piece of content when rearranging them.
36
+ # adjust_positions will make sure when you change the position of one content, all other content of that tipe
37
+ # has position changed to keep a reasonable order.
31
38
  def adjust_positions
32
39
  return true unless changed.include?('position')
33
40
  return true unless brothers.map{|x| x.position}.include?(self.position)
34
41
 
35
- brothers.where("position < ?", self.position).update_all("position = (position - 1)")
36
42
  brothers.where("position >= ?", self.position).update_all("position = (position + 1)")
37
43
  end
38
44
 
@@ -1,16 +1,34 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class ContentTest < ActiveSupport::TestCase
4
+
5
+ def setup
6
+ @a = Content.create(:app_id => 1, :position => 1, :title => 'a', :tipe => 'test')
7
+ @b = Content.create(:app_id => 1, :position => 2, :title => 'b', :tipe => 'test')
8
+ @c = Content.create(:app_id => 1, :position => 3, :title => 'c', :tipe => 'test')
9
+ end
4
10
  # Replace this with your real tests.
5
- test "content should fix position on save" do
6
- a = Content.create(:position => 1, :title => 'a', :tipe => 'test')
7
- b = Content.create(:position => 2, :title => 'b', :tipe => 'test')
8
- c = Content.create(:position => 3, :title => 'c', :tipe => 'test')
9
- c.position = 1
10
- c.save
11
+ test "content should fix position of other content with similar tipe on save" do
12
+ @c.position = 1
13
+ @c.save
11
14
 
12
- assert(c.reload.position == 1)
13
- assert(a.reload.position == 2)
14
- assert(b.reload.position == 3)
15
+ assert(@c.reload.position == 1)
16
+ assert(@a.reload.position == 2)
17
+ assert(@b.reload.position == 3)
15
18
  end
19
+
20
+ test "saving multiple pieces of content things kind of escalate out of control ... " do
21
+ @a.position = 3
22
+ @a.save
23
+ assert(3 == @a.reload.position)
24
+ assert(2 == @b.reload.position)
25
+ assert(4 == @c.reload.position)
26
+ @b.position = 3
27
+ @b.save
28
+ assert(3 == @b.reload.position)
29
+ assert(5 == @c.reload.position)
30
+ assert(4 == @a.reload.position)
31
+
32
+ end
33
+
16
34
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 4
7
+ - 5
8
8
  - 0
9
- version: 0.4.0
9
+ version: 0.5.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Bob Larrick
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-01-12 00:00:00 -05:00
17
+ date: 2011-01-14 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies: []
20
20