rafters 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/.rspec +2 -0
- data/.rvmrc +53 -0
- data/Gemfile +18 -0
- data/MIT-LICENSE +20 -0
- data/README.md +168 -0
- data/Rakefile +32 -0
- data/lib/generators/rafters/component/component_generator.rb +33 -0
- data/lib/generators/rafters/component/templates/assets/javascripts/component.js.erb +0 -0
- data/lib/generators/rafters/component/templates/assets/stylesheets/component.scss.erb +0 -0
- data/lib/generators/rafters/component/templates/component.rb.erb +4 -0
- data/lib/generators/rafters/component/templates/views/component.html.erb +0 -0
- data/lib/generators/rafters/install/install_generator.rb +23 -0
- data/lib/generators/rafters/install/templates/initializer.rb +2 -0
- data/lib/rafters/component.rb +70 -0
- data/lib/rafters/component_context.rb +19 -0
- data/lib/rafters/component_renderer.rb +20 -0
- data/lib/rafters/directive_processor.rb +9 -0
- data/lib/rafters/engine.rb +33 -0
- data/lib/rafters/version.rb +3 -0
- data/lib/rafters.rb +27 -0
- data/lib/tasks/rafters_tasks.rake +4 -0
- data/rafters.gemspec +28 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +16 -0
- data/spec/dummy/app/assets/javascripts/foos.js +2 -0
- data/spec/dummy/app/assets/stylesheets/application.css +14 -0
- data/spec/dummy/app/assets/stylesheets/foos.css +4 -0
- data/spec/dummy/app/components/heading/assets/javascripts/heading_component.js +0 -0
- data/spec/dummy/app/components/heading/assets/stylesheets/heading_component.css +0 -0
- data/spec/dummy/app/components/heading/heading_component.rb +13 -0
- data/spec/dummy/app/components/heading/views/heading_component.html.erb +1 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/controllers/foos_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/helpers/foos_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/views/foos/index.html.erb +1 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +59 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +70 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/rafters.rb +2 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +5 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/rafters/component_spec.rb +153 -0
- data/spec/spec_helper.rb +13 -0
- metadata +241 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 20c5adf484fe6dee7a436bf120a01abc45262768
|
4
|
+
data.tar.gz: 492d4021eb8760ea3d0a1da556c31a0b9bd3c2ef
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d55783f2ff80d38f75990f1a82b3a04d48d8a18f1c0026cb7dbd5adcded1afdc7c4218dd58a936a5aac9ab0cf0e2d033a865eab6071eba75549930ecdada9cd3
|
7
|
+
data.tar.gz: 16d62a56843a39b954b94438b7e6c29d0cc7c051b932d55507468daea22442440a743fbb5f0d8644b5d2befb8b9b3e4c0e6c4123729e7986498ce80049a13ee6
|
data/.gitignore
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/dummy/.sass-cache
|
15
|
+
spec/dummy/db/*.sqlite3
|
16
|
+
spec/dummy/db/*.sqlite3-journal
|
17
|
+
spec/dummy/log/*.log
|
18
|
+
spec/dummy/tmp/
|
19
|
+
spec/reports
|
20
|
+
tmp
|
data/.rspec
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
# This is an RVM Project .rvmrc file, used to automatically load the ruby
|
4
|
+
# development environment upon cd'ing into the directory
|
5
|
+
|
6
|
+
# First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
|
7
|
+
# Only full ruby name is supported here, for short names use:
|
8
|
+
# echo "rvm use 2.0.0" > .rvmrc
|
9
|
+
environment_id="ruby-2.0.0-p0@rafters"
|
10
|
+
|
11
|
+
# Uncomment the following lines if you want to verify rvm version per project
|
12
|
+
# rvmrc_rvm_version="1.19.1 (master)" # 1.10.1 seams as a safe start
|
13
|
+
# eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
|
14
|
+
# echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
|
15
|
+
# return 1
|
16
|
+
# }
|
17
|
+
|
18
|
+
# First we attempt to load the desired environment directly from the environment
|
19
|
+
# file. This is very fast and efficient compared to running through the entire
|
20
|
+
# CLI and selector. If you want feedback on which environment was used then
|
21
|
+
# insert the word 'use' after --create as this triggers verbose mode.
|
22
|
+
if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
|
23
|
+
&& -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
|
24
|
+
then
|
25
|
+
\. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
|
26
|
+
for __hook in "${rvm_path:-$HOME/.rvm}/hooks/after_use"*
|
27
|
+
do
|
28
|
+
if [[ -f "${__hook}" && -x "${__hook}" && -s "${__hook}" ]]
|
29
|
+
then \. "${__hook}" || true
|
30
|
+
fi
|
31
|
+
done
|
32
|
+
unset __hook
|
33
|
+
else
|
34
|
+
# If the environment file has not yet been created, use the RVM CLI to select.
|
35
|
+
rvm --create "$environment_id" || {
|
36
|
+
echo "Failed to create RVM environment '${environment_id}'."
|
37
|
+
return 1
|
38
|
+
}
|
39
|
+
fi
|
40
|
+
|
41
|
+
# If you use bundler, this might be useful to you:
|
42
|
+
# if [[ -s Gemfile ]] && {
|
43
|
+
# ! builtin command -v bundle >/dev/null ||
|
44
|
+
# builtin command -v bundle | GREP_OPTIONS= \grep $rvm_path/bin/bundle >/dev/null
|
45
|
+
# }
|
46
|
+
# then
|
47
|
+
# printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
|
48
|
+
# gem install bundler
|
49
|
+
# fi
|
50
|
+
# if [[ -s Gemfile ]] && builtin command -v bundle >/dev/null
|
51
|
+
# then
|
52
|
+
# bundle install | GREP_OPTIONS= \grep -vE '^Using|Your bundle is complete'
|
53
|
+
# fi
|
data/Gemfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
# Declare your gem's dependencies in rafters.gemspec.
|
4
|
+
# Bundler will treat runtime dependencies like base dependencies, and
|
5
|
+
# development dependencies will be added by default to the :development group.
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
# jquery-rails is used by the dummy application
|
9
|
+
gem "jquery-rails"
|
10
|
+
gem "sqlite3"
|
11
|
+
|
12
|
+
# Declare any dependencies that are still in development here instead of in
|
13
|
+
# your gemspec. These might include edge Rails or gems from your path or
|
14
|
+
# Git. Remember to move these dependencies to your gemspec before releasing
|
15
|
+
# your gem to rubygems.org.
|
16
|
+
|
17
|
+
# To use debugger
|
18
|
+
# gem 'debugger'
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2013 Andrew Hite
|
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.md
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
# Rafters
|
2
|
+
|
3
|
+
!!! STILL UNDER ACTIVE DEVELOPMENT. USE AT YOUR OWN RISK !!!
|
4
|
+
|
5
|
+
Rafters lets you think about each page of your application as a collection of small pieces instead of monolithic, difficult to maintain
|
6
|
+
views.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'rafters'
|
14
|
+
```
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
```sh
|
19
|
+
$ bundle
|
20
|
+
```
|
21
|
+
|
22
|
+
Or install it yourself as:
|
23
|
+
|
24
|
+
```sh
|
25
|
+
$ gem install rafters
|
26
|
+
```
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
After you install the Rafters gem, you need to run the following generator:
|
31
|
+
|
32
|
+
```sh
|
33
|
+
$ rails generate rafters:install
|
34
|
+
```
|
35
|
+
|
36
|
+
This generator will create an `app/rafters` directory in your application, a `config/initializers/rafters.rb` initializer with some basic configuration, and add the `require_components` directive to your application.css and application.js files.
|
37
|
+
|
38
|
+
### Creating a component
|
39
|
+
|
40
|
+
When you build out a page using Rafters you're effectively breaking it down into small, easy to digest chunks of code / markup that can optimally be configured and re-used on other pages as well. These bite-sized "views" are called Components, and you can think of them as partials on steroids (with their own "controllers" and templates).
|
41
|
+
|
42
|
+
To begin creating a new component, run the following generator:
|
43
|
+
|
44
|
+
```sh
|
45
|
+
$ rails generate rafters:component [name]
|
46
|
+
```
|
47
|
+
|
48
|
+
This generator will create the following files:
|
49
|
+
|
50
|
+
```
|
51
|
+
app/rafters/[name]
|
52
|
+
app/rafters/[name]/[name]_component.rb
|
53
|
+
app/rafters/[name]/assets/stylesheets/[name]_component.scss
|
54
|
+
app/rafters/[name]/assets/javascripts/[name]_component.js.coffee
|
55
|
+
app/rafters/[name]/views/[name]_component.html.erb
|
56
|
+
```
|
57
|
+
|
58
|
+
The two most important files generated above are `app/rafters/[name]/[name]_component.rb` and `app/rafters/[name]/views/[name]_component.html.erb`, which are (respectively) our component controller and view.
|
59
|
+
|
60
|
+
### Rendering a component
|
61
|
+
|
62
|
+
You can render components anywhere - in your view, in your controller, in another component, etc. - but the most common place will (obviously) be in your views. To render a component, call `render_component [symbolized, underscored name]` in one of your app views. For example:
|
63
|
+
|
64
|
+
```erb
|
65
|
+
...
|
66
|
+
<div class="main">
|
67
|
+
<%= render_component :heading %>
|
68
|
+
</div>
|
69
|
+
...
|
70
|
+
```
|
71
|
+
|
72
|
+
### Adding an attribute to a component
|
73
|
+
|
74
|
+
Each component exposes attributes to it's view using `Rafters::Component#attributes`, which are available in the view under the local variable `attributes`. The `attributes` are simply a collection of methods that you explicitly declare as such in your component, using the `Rafters::Component.attribute` method.
|
75
|
+
|
76
|
+
For instance, let's say we have a HeadingComponent that exposes a title attribute:
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
class HeadingComponent
|
80
|
+
include Rafters::Component
|
81
|
+
|
82
|
+
attribute :title
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def title
|
87
|
+
"Lorem Ipsum"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
92
|
+
Since we won't be accessing the `HeadingComponent#title` method directly from within our view, it's recommended to make it a private method. The interface that our component exposes is taken care of behind the scenes.
|
93
|
+
|
94
|
+
You can access the attribute in your component view using the `attributes` object:
|
95
|
+
|
96
|
+
```erb
|
97
|
+
<div class="heading">
|
98
|
+
<h1><%= attributes.title %></h1>
|
99
|
+
</div>
|
100
|
+
```
|
101
|
+
|
102
|
+
### Adding a setting to a component
|
103
|
+
|
104
|
+
In order to build components in a way that allows for re-use, you'll want to define settings that allow individual instances of the component to be configured. These settings will likely be used throughout your component view and controller for any number of purposes, like values in query conditions, section titles, turning on or off specific features of a component, etc.
|
105
|
+
|
106
|
+
Adding a setting is very similar to adding an attribute, except they don't point at methods:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
class PostsComponent
|
110
|
+
include Rafters::Component
|
111
|
+
|
112
|
+
setting :published
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
116
|
+
Setting values are specified when rendering a component:
|
117
|
+
|
118
|
+
```erb
|
119
|
+
...
|
120
|
+
<div class="main">
|
121
|
+
<%= render_component :posts, published: true %>
|
122
|
+
</div>
|
123
|
+
...
|
124
|
+
```
|
125
|
+
|
126
|
+
And can be accessed via the `settings` object in your component view:
|
127
|
+
|
128
|
+
```erb
|
129
|
+
<div class="posts">
|
130
|
+
<% if settings.published? %>
|
131
|
+
...
|
132
|
+
<% else %>
|
133
|
+
...
|
134
|
+
<% end %>
|
135
|
+
</div>
|
136
|
+
```
|
137
|
+
|
138
|
+
Or your component controller:
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
class PostsComponent
|
142
|
+
...
|
143
|
+
|
144
|
+
def posts
|
145
|
+
Post.where(published: settings.published)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
```
|
149
|
+
|
150
|
+
Default values can be provided for settings using the `default` option:
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
setting :type, default: "Comment"
|
154
|
+
```
|
155
|
+
|
156
|
+
Required settings can be specified using the `required` option:
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
setting :user_id, required: true
|
160
|
+
```
|
161
|
+
|
162
|
+
## Contributing
|
163
|
+
|
164
|
+
1. Fork it
|
165
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
166
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
167
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
168
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
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
|
+
|
8
|
+
begin
|
9
|
+
require 'rdoc/task'
|
10
|
+
rescue LoadError
|
11
|
+
require 'rdoc/rdoc'
|
12
|
+
require 'rake/rdoctask'
|
13
|
+
RDoc::Task = Rake::RDocTask
|
14
|
+
end
|
15
|
+
|
16
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = 'Rafters'
|
19
|
+
rdoc.options << '--line-numbers'
|
20
|
+
rdoc.rdoc_files.include('README.rdoc')
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
end
|
23
|
+
|
24
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
25
|
+
load 'rails/tasks/engine.rake'
|
26
|
+
|
27
|
+
Bundler::GemHelper.install_tasks
|
28
|
+
|
29
|
+
require 'rspec/core/rake_task'
|
30
|
+
RSpec::Core::RakeTask.new('spec')
|
31
|
+
|
32
|
+
task :default => :spec
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class Rafters::ComponentGenerator < Rails::Generators::NamedBase
|
2
|
+
source_root File.expand_path("../templates", __FILE__)
|
3
|
+
|
4
|
+
def create_directories
|
5
|
+
empty_directory "#{base_directory}"
|
6
|
+
empty_directory "#{base_directory}/assets"
|
7
|
+
empty_directory "#{base_directory}/assets/javascripts"
|
8
|
+
empty_directory "#{base_directory}/assets/stylesheets"
|
9
|
+
empty_directory "#{base_directory}/assets/images"
|
10
|
+
empty_directory "#{base_directory}/views"
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_gitkeeps
|
14
|
+
create_file "#{base_directory}/assets/images/.gitkeep"
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_files
|
18
|
+
template "component.rb.erb", "#{base_directory}/#{file_name}_component.rb"
|
19
|
+
template "assets/javascripts/component.js.erb", "#{base_directory}/assets/javascripts/#{file_name}_component.js"
|
20
|
+
template "assets/stylesheets/component.scss.erb", "#{base_directory}/assets/stylesheets/#{file_name}_component.scss"
|
21
|
+
template "views/component.html.erb", "#{base_directory}/views/#{file_name}_component.html.erb"
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def app_root
|
27
|
+
Rails.root
|
28
|
+
end
|
29
|
+
|
30
|
+
def base_directory
|
31
|
+
"app/components/#{file_name}"
|
32
|
+
end
|
33
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Rafters::InstallGenerator < Rails::Generators::Base
|
2
|
+
source_root File.expand_path("../templates", __FILE__)
|
3
|
+
|
4
|
+
def create_initializer
|
5
|
+
copy_file "initializer.rb", "config/initializers/rafters.rb"
|
6
|
+
end
|
7
|
+
|
8
|
+
def create_directories
|
9
|
+
empty_directory "app/components"
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_asset_requires
|
13
|
+
inject_into_file "app/assets/stylesheets/application.css", after: "*= require_tree .\n" do <<-'RUBY'
|
14
|
+
*= require_components`
|
15
|
+
RUBY
|
16
|
+
end
|
17
|
+
|
18
|
+
inject_into_file "app/assets/javascripts/application.js", after: "//= require_tree .\n" do <<-'RUBY'
|
19
|
+
//= require_components
|
20
|
+
RUBY
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Rafters::Component
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
attr_writer :controller
|
5
|
+
|
6
|
+
def initialize(settings = {})
|
7
|
+
@settings = settings
|
8
|
+
end
|
9
|
+
|
10
|
+
def template_name
|
11
|
+
return @_template_name if @_template_name
|
12
|
+
|
13
|
+
_template_name = self.class._template_name
|
14
|
+
_underscored_name = self.class.name.underscore
|
15
|
+
|
16
|
+
if _template_name.is_a?(Proc)
|
17
|
+
_template_name = _template_name.call(self)
|
18
|
+
end
|
19
|
+
|
20
|
+
@_template_name = (_template_name || _underscored_name)
|
21
|
+
end
|
22
|
+
|
23
|
+
def attributes
|
24
|
+
@_attributes ||= Hashie::Mash.new.tap do |_attributes|
|
25
|
+
self.class._attributes.each do |name, options|
|
26
|
+
_attributes[name] = send(name)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def settings
|
32
|
+
@_settings ||= Hashie::Mash.new.tap do |_settings|
|
33
|
+
self.class._settings.each do |name, options|
|
34
|
+
_settings[name] = (@settings[name] || options[:default] || nil)
|
35
|
+
raise SettingRequired if options[:required] && _settings[name].nil?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def current(variable_or_method_name)
|
41
|
+
if @controller.instance_variable_defined?("@#{variable_or_method_name}")
|
42
|
+
@controller.instance_variable_get("@#{variable_or_method_name}")
|
43
|
+
elsif @controller.respond_to?(variable_or_method_name)
|
44
|
+
@controller.send(variable_or_method_name)
|
45
|
+
else
|
46
|
+
raise CurrentVariableOrMethodNameMissing
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
module ClassMethods
|
51
|
+
attr_accessor :_attributes, :_settings, :_template_name
|
52
|
+
|
53
|
+
def attribute(name, options = {})
|
54
|
+
self._attributes ||= {}
|
55
|
+
self._attributes[name.to_sym] = options
|
56
|
+
end
|
57
|
+
|
58
|
+
def setting(name, options = {})
|
59
|
+
self._settings ||= {}
|
60
|
+
self._settings[name.to_sym] = options
|
61
|
+
end
|
62
|
+
|
63
|
+
def template_name(name)
|
64
|
+
self._template_name = name.to_s
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class CurrentVariableOrMethodNameMissing < StandardError; end
|
69
|
+
class SettingRequired < StandardError; end
|
70
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Rafters::ComponentContext
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
helper_method :render_component
|
6
|
+
end
|
7
|
+
|
8
|
+
def render_component(name, settings = {}, template_name = nil)
|
9
|
+
component_klass = "#{name}_component".classify.constantize
|
10
|
+
component = component_klass.new(settings)
|
11
|
+
component_renderer.render(component, template_name)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def component_renderer
|
17
|
+
@_component_renderer ||= Rafters::ComponentRenderer.new(self)
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Rafters::ComponentRenderer
|
2
|
+
def initialize(controller)
|
3
|
+
@controller = controller
|
4
|
+
|
5
|
+
Rafters.view_paths.each do |view_path|
|
6
|
+
@controller.prepend_view_path(view_path)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def render(component, template_name = nil)
|
11
|
+
component.controller = @controller
|
12
|
+
|
13
|
+
template_name = (template_name || component.template_name)
|
14
|
+
|
15
|
+
@controller.view_context.render(file: "/#{template_name}", locals: {
|
16
|
+
settings: component.settings,
|
17
|
+
attributes: component.attributes
|
18
|
+
})
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class Rafters::DirectiveProcessor < Sprockets::DirectiveProcessor
|
2
|
+
def process_require_components_directive
|
3
|
+
Rafters.asset_paths.sort.each do |asset_path|
|
4
|
+
each_entry(asset_path) do |pathname|
|
5
|
+
context.require_asset(pathname) if context.asset_requirable?(pathname)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class Rafters::Engine < Rails::Engine
|
2
|
+
isolate_namespace Rafters
|
3
|
+
|
4
|
+
config.generators do |g|
|
5
|
+
g.test_framework :rspec
|
6
|
+
g.assets false
|
7
|
+
g.helper false
|
8
|
+
end
|
9
|
+
|
10
|
+
initializer "rafters.load_view_paths" do |app|
|
11
|
+
Rafters.view_paths = Dir[app.root.join("app", "components", "*", "views")]
|
12
|
+
end
|
13
|
+
|
14
|
+
initializer "rafters.load_asset_paths" do |app|
|
15
|
+
Rafters.asset_paths = Dir[app.root.join("app", "components", "*", "assets", "*")]
|
16
|
+
end
|
17
|
+
|
18
|
+
initializer "rafters.set_asset_paths", :after => "rafters.load_asset_paths" do |app|
|
19
|
+
app.config.assets.paths += Rafters.asset_paths
|
20
|
+
end
|
21
|
+
|
22
|
+
initializer "rafters.set_autoload_paths", :before => :set_autoload_paths do |app|
|
23
|
+
app.config.autoload_paths += Dir[app.root.join("app", "components", "*/")]
|
24
|
+
end
|
25
|
+
|
26
|
+
config.after_initialize do |app|
|
27
|
+
app.assets.unregister_preprocessor('text/css', Sprockets::DirectiveProcessor)
|
28
|
+
app.assets.register_preprocessor('text/css', Rafters::DirectiveProcessor)
|
29
|
+
|
30
|
+
app.assets.unregister_preprocessor('application/javascript', Sprockets::DirectiveProcessor)
|
31
|
+
app.assets.register_preprocessor('application/javascript', Rafters::DirectiveProcessor)
|
32
|
+
end
|
33
|
+
end
|
data/lib/rafters.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'hashie'
|
3
|
+
|
4
|
+
require 'rafters/engine'
|
5
|
+
|
6
|
+
module Rafters
|
7
|
+
extend ActiveSupport::Autoload
|
8
|
+
|
9
|
+
eager_autoload do
|
10
|
+
autoload :Component
|
11
|
+
autoload :ComponentContext
|
12
|
+
autoload :ComponentRenderer
|
13
|
+
autoload :DirectiveProcessor
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.setup
|
17
|
+
yield self
|
18
|
+
end
|
19
|
+
|
20
|
+
mattr_accessor :view_paths
|
21
|
+
@@view_paths = nil
|
22
|
+
|
23
|
+
mattr_accessor :asset_paths
|
24
|
+
@@asset_paths = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
ActionController::Base.send(:include, Rafters::ComponentContext)
|
data/rafters.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rafters/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "rafters"
|
8
|
+
spec.version = Rafters::VERSION
|
9
|
+
spec.authors = ["Andrew Hite"]
|
10
|
+
spec.email = ["andrew@andrew-hite.com"]
|
11
|
+
spec.description = %q{Rafters lets you think about each page of your application as a collection of small pieces instead of monolithic, difficult to maintain views.}
|
12
|
+
spec.summary = %q{Rafters lets you think about each page of your application as a collection of small pieces instead of monolithic, difficult to maintain views.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "debugger", "~> 1.6"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.1"
|
24
|
+
spec.add_development_dependency "rspec-rails", "~> 2.14"
|
25
|
+
|
26
|
+
spec.add_dependency "rails", "~> 4.0.0"
|
27
|
+
spec.add_dependency "hashie", "~> 2.0.5"
|
28
|
+
end
|