rhyhann-merb_stathyc_slice 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/LICENSE +21 -0
  2. data/README.markdown +106 -0
  3. data/Rakefile +55 -0
  4. data/TODO +5 -0
  5. data/app/controllers/application.rb +3 -0
  6. data/app/controllers/pages.rb +62 -0
  7. data/app/helpers/application_helper.rb +136 -0
  8. data/app/helpers/pages_helper.rb +49 -0
  9. data/app/models/page.rb +49 -0
  10. data/app/views/layout/static_slice.html.haml +27 -0
  11. data/app/views/pages/_cud.html.haml +11 -0
  12. data/app/views/pages/_sidebar.html.haml +2 -0
  13. data/app/views/pages/delete.html.haml +2 -0
  14. data/app/views/pages/edit.html.haml +6 -0
  15. data/app/views/pages/index.html.haml +5 -0
  16. data/app/views/pages/new.html.haml +6 -0
  17. data/app/views/pages/show.html.haml +5 -0
  18. data/lib/static_slice.rb +85 -0
  19. data/lib/static_slice/merbtasks.rb +103 -0
  20. data/lib/static_slice/slicetasks.rb +18 -0
  21. data/lib/static_slice/spectasks.rb +65 -0
  22. data/public/images/css/banner_mountains.jpg +0 -0
  23. data/public/images/css/bg.png +0 -0
  24. data/public/images/css/bg02-blue-left.png +0 -0
  25. data/public/images/css/bg02-blue-right.png +0 -0
  26. data/public/images/css/bg02-left.png +0 -0
  27. data/public/images/css/bg02-right.png +0 -0
  28. data/public/images/css/bg02-white-left.png +0 -0
  29. data/public/images/css/bg02-white-right.png +0 -0
  30. data/public/images/css/logo.png +0 -0
  31. data/public/images/css/menu.png +0 -0
  32. data/public/images/css/menuleft.png +0 -0
  33. data/public/images/css/menuright.png +0 -0
  34. data/public/stylesheets/master.css +138 -0
  35. data/spec/models/page_spec.rb +7 -0
  36. data/spec/requests/pages_spec.rb +110 -0
  37. data/spec/spec_helper.rb +43 -0
  38. data/spec/static_slice_spec.rb +19 -0
  39. data/stubs/app/controllers/application.rb +2 -0
  40. data/stubs/app/controllers/main.rb +2 -0
  41. metadata +118 -0
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ (The MIT/X11 License)
2
+
3
+ Copyright (c) <2008> <Othmane Benkirane>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,106 @@
1
+ /!\ My version numbers mean that they are stable when they are pair (2,4,6,8…) and
2
+ nearly bugfree when they finish with a 0 (10,20,30) so if you see version 1, just know
3
+ that it's not meant for production now!
4
+
5
+ StaticSlice
6
+ ===========
7
+
8
+ A slice for the Merb framework that provides the core static pages functionnalities.
9
+ Just see the views for edit.
10
+
11
+ To see all available tasks for StaticSlice run:
12
+ rake -T slices:static_slice
13
+
14
+ CUD Customization
15
+ -----------------
16
+
17
+ If you want to protect the CUD actions, you must know that: ALL of them are located in
18
+ a content named *for_cud*. simple.
19
+ If you want to change the look of the CUD operations, it's stored in a partial named *_cud*.
20
+ But _please see the default one first_.
21
+
22
+ Sidebar
23
+ -------
24
+
25
+ A partial called *_sidebar* may help you with Sidebar customization.
26
+
27
+ Installation
28
+ ============
29
+
30
+ * dependency (config/init.rb)
31
+
32
+ \# add the slice as a regular dependency
33
+ dependency 'static_slice'
34
+
35
+ * router
36
+
37
+ \# example: /static_slice/:controller/:action/:id
38
+ add_slice(:StaticSlice)
39
+ \# example: /foo/:controller/:action/:id
40
+ add_slice(:StaticSlice, 'foo') # same as :path => 'foo'
41
+ \# example: /:lang/:controller/:action/:id
42
+ add_slice(:StaticSlice, :path => ':lang')
43
+ \# example: /:controller/:action/:id
44
+ slice(:StaticSlice)
45
+
46
+ * rake
47
+
48
+ rake slices:static_slice:install
49
+
50
+ Uses
51
+ ====
52
+
53
+ You can put your overrides here:
54
+ host-app/slices/static_slice/app - controllers, models, views ...
55
+
56
+ Templates are located in this order:
57
+ 1. host-app/slices/static_slice/app/views/*
58
+ 2. gems/static_slice/app/views/*
59
+ 3. host-app/app/views/*
60
+
61
+ You can use the host application's layout by configuring the
62
+ static_slice slice in a before_app_loads block:
63
+
64
+ Merb::Slices.config[:static_slice] = { :layout => :application }
65
+
66
+ By default :static_slice is used. If you need to override
67
+ stylesheets or javascripts, just specify your own files in your layout
68
+ instead/in addition to the ones supplied (if any) in
69
+ host-app/public/slices/static_slice.
70
+
71
+ In any case don't edit those files directly as they may be clobbered any time
72
+ rake static_slice:install is run.
73
+
74
+ About Slices
75
+ ============
76
+
77
+ Merb-Slices is a Merb plugin for using and creating application 'slices' which
78
+ help you modularize your application. Usually these are reuseable extractions
79
+ from your main app. In effect, a Slice is just like a regular Merb MVC
80
+ application, both in functionality as well as in structure.
81
+
82
+ When you generate a Slice stub structure, a module is setup to serve as a
83
+ namespace for your controller, models, helpers etc. This ensures maximum
84
+ encapsulation. You could say a Slice is a mixture between a Merb plugin (a
85
+ Gem) and a Merb application, reaping the benefits of both.
86
+
87
+ A host application can 'mount' a Slice inside the router, which means you have
88
+ full over control how it integrates. By default a Slice's routes are prefixed
89
+ by its name (a router :namespace), but you can easily provide your own prefix
90
+ or leave it out, mounting it at the root of your url-schema. You can even
91
+ mount a Slice multiple times and give extra parameters to customize an
92
+ instance's behaviour.
93
+
94
+ A Slice's Application controller uses controller_for_slice to setup slice
95
+ specific behaviour, which mainly affects cascaded view handling. Additionaly,
96
+ this method is available to any kind of controller, so it can be used for
97
+ Merb Mailer too for example.
98
+
99
+ There are many ways which let you customize a Slice's functionality and
100
+ appearance without ever touching the Gem-level code itself. It's not only easy
101
+ to add template/layout overrides, you can also add/modify controllers, models
102
+ and other runtime code from within the host application.
103
+
104
+ To create your own Slice run this (somewhere outside of your merb app):
105
+
106
+ merb-gen slice <your-lowercase-slice-name>
data/Rakefile ADDED
@@ -0,0 +1,55 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+
4
+ require 'merb-core'
5
+ require 'merb-core/tasks/merb'
6
+
7
+ GEM_NAME = "merb_stathyc_slice"
8
+ AUTHOR = "Othmane Benkirane (rhyhann)"
9
+ EMAIL = "eo-in-rhyhann-net"
10
+ HOMEPAGE = "http://github.com/rhyhann/merb-stathyc_slice"
11
+ SUMMARY = "Merb Slice that provides core static pages functionnalities"
12
+ GEM_VERSION = "0.1"
13
+
14
+ spec = Gem::Specification.new do |s|
15
+ s.rubyforge_project = 'merb'
16
+ s.name = GEM_NAME
17
+ s.version = GEM_VERSION
18
+ s.platform = Gem::Platform::RUBY
19
+ s.has_rdoc = true
20
+ s.extra_rdoc_files = ["README.markdown", "LICENSE", 'TODO']
21
+ s.summary = SUMMARY
22
+ s.description = s.summary
23
+ s.author = AUTHOR
24
+ s.email = EMAIL
25
+ s.homepage = HOMEPAGE
26
+ s.add_dependency('merb-slices', '>= 1.0')
27
+ s.require_path = 'lib'
28
+ s.files = %w(LICENSE README.markdown Rakefile TODO) + Dir.glob("{lib,spec,app,public,stubs}/**/*")
29
+ end
30
+
31
+ Rake::GemPackageTask.new(spec) do |pkg|
32
+ pkg.gem_spec = spec
33
+ end
34
+
35
+ desc "Install the gem"
36
+ task :install do
37
+ Merb::RakeHelper.install(GEM_NAME, :version => GEM_VERSION)
38
+ end
39
+
40
+ desc "Uninstall the gem"
41
+ task :uninstall do
42
+ Merb::RakeHelper.uninstall(GEM_NAME, :version => GEM_VERSION)
43
+ end
44
+
45
+ desc "Create a gemspec file"
46
+ task :gemspec do
47
+ File.open("#{GEM_NAME}.gemspec", "w") do |file|
48
+ file.puts spec.to_ruby
49
+ end
50
+ end
51
+
52
+ require 'spec/rake/spectask'
53
+ require 'merb-core/test/tasks/spectasks'
54
+ desc 'Default: run spec examples'
55
+ task :default => 'spec'
data/TODO ADDED
@@ -0,0 +1,5 @@
1
+ TODO:
2
+
3
+ - Specs
4
+ - CUD partial
5
+
@@ -0,0 +1,3 @@
1
+ class StaticSlice::Application < Merb::Controller
2
+ controller_for_slice
3
+ end
@@ -0,0 +1,62 @@
1
+ class StaticSlice::Pages < StaticSlice::Application
2
+ # provides :xml, :yaml, :js
3
+ def index
4
+ @pages = Page.all
5
+ display @pages
6
+ end
7
+
8
+ def show(id)
9
+ @page = Page.get(id)
10
+ raise NotFound unless @page
11
+ display @page
12
+ end
13
+
14
+ def new
15
+ only_provides :html
16
+ @page = Page.new
17
+ display @page
18
+ end
19
+
20
+ def edit(id)
21
+ only_provides :html
22
+ @page = Page.get(id)
23
+ raise NotFound unless @page
24
+ display @page
25
+ end
26
+
27
+ def create(page)
28
+ @page = Page.new(page)
29
+ if @page.save
30
+ redirect resource(@page), :message => {:notice => "Page was successfully created"}
31
+ else
32
+ message[:error] = "Page failed to be created"
33
+ render :new
34
+ end
35
+ end
36
+
37
+ def update(id, page)
38
+ @page = Page.get(id)
39
+ raise NotFound unless @page
40
+ if @page.update_attributes(page)
41
+ redirect resource(@page)
42
+ else
43
+ display @page, :edit
44
+ end
45
+ end
46
+
47
+ def delete(id)
48
+ @page = Page.get(id)
49
+ raise NotFound unless @page
50
+ display @page
51
+ end
52
+ def destroy(id)
53
+ @page = Page.get(id)
54
+ raise NotFound unless @page
55
+ if @page.destroy
56
+ redirect resource(:pages)
57
+ else
58
+ raise InternalServerError
59
+ end
60
+ end
61
+
62
+ end # Pages
@@ -0,0 +1,136 @@
1
+ module Merb
2
+ module StaticSlice
3
+ module ApplicationHelper
4
+
5
+ # @param *segments<Array[#to_s]> Path segments to append.
6
+ #
7
+ # @return <String>
8
+ # A path relative to the public directory, with added segments.
9
+ def image_path(*segments)
10
+ public_path_for(:image, *segments)
11
+ end
12
+
13
+ # @param *segments<Array[#to_s]> Path segments to append.
14
+ #
15
+ # @return <String>
16
+ # A path relative to the public directory, with added segments.
17
+ def javascript_path(*segments)
18
+ public_path_for(:javascript, *segments)
19
+ end
20
+
21
+ # @param *segments<Array[#to_s]> Path segments to append.
22
+ #
23
+ # @return <String>
24
+ # A path relative to the public directory, with added segments.
25
+ def stylesheet_path(*segments)
26
+ public_path_for(:stylesheet, *segments)
27
+ end
28
+
29
+ # Construct a path relative to the public directory
30
+ #
31
+ # @param <Symbol> The type of component.
32
+ # @param *segments<Array[#to_s]> Path segments to append.
33
+ #
34
+ # @return <String>
35
+ # A path relative to the public directory, with added segments.
36
+ def public_path_for(type, *segments)
37
+ ::StaticSlice.public_path_for(type, *segments)
38
+ end
39
+
40
+ # Construct an app-level path.
41
+ #
42
+ # @param <Symbol> The type of component.
43
+ # @param *segments<Array[#to_s]> Path segments to append.
44
+ #
45
+ # @return <String>
46
+ # A path within the host application, with added segments.
47
+ def app_path_for(type, *segments)
48
+ ::StaticSlice.app_path_for(type, *segments)
49
+ end
50
+
51
+ # Construct a slice-level path.
52
+ #
53
+ # @param <Symbol> The type of component.
54
+ # @param *segments<Array[#to_s]> Path segments to append.
55
+ #
56
+ # @return <String>
57
+ # A path within the slice source (Gem), with added segments.
58
+ def slice_path_for(type, *segments)
59
+ ::StaticSlice.slice_path_for(type, *segments)
60
+ end
61
+
62
+
63
+
64
+ # This function takes the Model.sexhy hash and guesses the untyped variables, sorts it
65
+ # and then returns the incredible formù!
66
+ def sexify(object, f_d = {:properties => {}})
67
+ f = ''
68
+ f_d = object_labels(object, object_types(object))
69
+ f_d[:properties].delete_if {|k,v| [:id,:created_at,:updated_at].include?(k)}
70
+ f_d[:properties].to_a.sort_by {|a|a[1][:order]}.each do |element|
71
+ type, options = element[0], element[1]
72
+ # TODO: default hashes
73
+ html = object.class.sexhy[:html]
74
+ f << nl(open_tag(:div))
75
+ f << nl(html[:label][:tag],
76
+ options[:label],
77
+ html[:label][:attributes].merge(
78
+ {:for => "#{object.class.to_s.downcase}_#{type.to_s}"}
79
+ )
80
+ )
81
+ eval "f << nl(html[:input][:tag],
82
+ (#{options[:input]}(:#{type})).to_s,
83
+ html[:input][:attributes]
84
+ )"
85
+ f << nl(close_tag(:div))
86
+ end
87
+ f
88
+ end
89
+ def order(hash)
90
+ n = 0
91
+ hash[:properties].each do |k,v|
92
+ n+=1
93
+ hash[:properties][k][:order] = n if hash[:properties][k][:order].nil?
94
+ end
95
+ hash
96
+ end
97
+ # This function returns the list of the inputs.
98
+ # It will first try to merge it to the given hash, then to the model's hash
99
+ # then to nothing.
100
+ def object_types(o, c_d = {:properties => {}})
101
+ c_d = o.class.sexhy if c_d == {:properties => {}} && o.class.methods.include?('sexhy')
102
+ c_d = order c_d
103
+ properties = {}
104
+ o.class.properties.each do |pr|
105
+ t = DataMapper::Types
106
+ properties[pr.name] = {}
107
+ properties[pr.name][:input] = if pr.type.is_a?(t::Boolean) ||
108
+ pr.type.is_a?(TrueClass); 'check_box'
109
+ elsif [String, Float, Fixnum,
110
+ Integer, BigDecimal,
111
+ ].include?(pr.type); 'text_field'
112
+ elsif pr.type == t::Text; 'text_area'
113
+ elsif pr.type.is_a?(Date); 'date'
114
+ end
115
+ end
116
+ c_d[:properties].each {|k,v|
117
+ properties[k].merge!(v)}
118
+ {:properties => properties}
119
+ end
120
+ def object_labels(o, c_d = {:properties => {}})
121
+ c_d = o.class.sexhy if c_d == {} && o.class.methods.include?('sexhy')
122
+ properties = {}
123
+ o.class.properties.each do |pr|
124
+ properties[pr.name] = {}
125
+ properties[pr.name][:label] = pr.name.to_s.capitalize
126
+ end
127
+ c_d[:properties].each {|k,v| properties[k].merge!(v)}
128
+ {:properties => properties}
129
+ end
130
+ # This function returns its arguments with new lines
131
+ def nl(*arg)
132
+ arg[0].is_a?(Symbol) ? nl(tag(*arg)) : " \n #{arg[0]}"
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,49 @@
1
+ module Merb
2
+ module PagesHelper
3
+ def sexify(object, form_definition = {})
4
+ f = "\n"
5
+ object.class.properties.each do |pr|
6
+ t = DataMapper::Types
7
+ if pr.type.is_a?(t::Boolean) || pr.type.is_a?(TrueClass)
8
+ f << nl(label(:"#{pr.name}"))
9
+ f << nl(check_box(:"#{pr.name}"))
10
+ elsif [String, Float, Fixnum, Integer, BigDecimal].include?(pr.type)
11
+ f << nl(label(:"#{pr.name}"))
12
+ f << nl(text_field(:"#{pr.name}"))
13
+ elsif pr.type == t::Text
14
+ f << nl(label( :"#{pr.name}" ))
15
+ f << nl(text_area(:"#{pr.name}"))
16
+ elsif pr.type.is_a?(Date)
17
+ dater = "\n"
18
+ f << tag(:label, :class => :date) do
19
+ yearc = (Time.now.year-100..Time.now.year)
20
+ dater << select(:"#{pr.name}_month", :collection => (1..12).to_a); dater << " / "
21
+ dater << select(:"#{pr.name}_day" , :collection => (1..31).to_a); dater << " / "
22
+ dater << select(:"#{pr.name}_year" , :collection => (yearc).to_a); dater << " / "
23
+ dater
24
+ end
25
+ end
26
+ end
27
+ f
28
+ end
29
+ def hy_guess_type(object)
30
+ object.class.properties.each do |pr|
31
+ t = DataMapper::Types
32
+ inputs = {}
33
+ inputs[:"#{pr.name}"] = if pr.type.is_a?(t::Boolean) ||
34
+ pr.type.is_a?(TrueClass); :check_box
35
+ elsif [String, Float, Fixnum,
36
+ Integer, BigDecimal,
37
+ ].include?(pr.type); :text_field
38
+ elsif pr.type == t::Text; :text_area
39
+ elsif pr.type.is_a?(Date); :date
40
+ end
41
+ inputs
42
+ end
43
+ end
44
+ # This function returns its arguments with new lines
45
+ def nl(arg)
46
+ tag(:div, "\n #{arg}\n")
47
+ end
48
+ end
49
+ end # Merb