fixed_model 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/MIT-LICENSE +20 -0
- data/README.md +113 -0
- data/Rakefile +34 -0
- data/lib/fixed_model.rb +12 -0
- data/lib/fixed_model/base.rb +125 -0
- data/lib/fixed_model/loader.rb +41 -0
- data/lib/fixed_model/version.rb +3 -0
- data/lib/tasks/fixed_model_tasks.rake +4 -0
- data/test/compliance_test.rb +9 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/controllers/countries_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/models/country.rb +2 -0
- data/test/dummy/app/views/countries/index.html.erb +6 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +29 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +13 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/custom_directory/countries.yml +4 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +35 -0
- data/test/dummy/config/environments/production.rb +72 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/fixed_models/countries.yml +14 -0
- data/test/dummy/config/fixed_models/test/countries.yml +12 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +43 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/schema.rb +16 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +4 -0
- data/test/dummy/log/test.log +38475 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/-6Aexu4-9zXP7fttMrwdcp6ut5W4svYiwYaN1S11p9U.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/APhcRkuSUag3sAMrv147SiqtfM-n4sIyfNkqkP5p69M.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/AQff0XbTiXjznwSo3fs-LpH7XQV9hwLzDr7Hn6w4RQQ.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/EXAQ6pLNH4aYOxoJcmNdZAmsPZQsxPhQe8rlbRUOeos.cache +2 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/TncLlV4b8r5OvOLRIye-1hdOy8VRPZug5cZ_MA3IsHQ.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/V-KescSabX7T78JV-ihOuiwXQAAaK6TutFbWePxQF1E.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/XZgUSUY6JX5YiIG-pYsSkUr7ydqJlk8XruCemoMycV0.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/ZGNTCr85QzLaZulY-capAFXvkDEEr6N81d3bn6Iz4cA.cache +3 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/cOXTJSqqUSSZiPnW-HtRwyBPMvwE4ha2qZLSbmaxbIw.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/gBGP0GxcODm_c-aOQnAahOusWVfj-YYTkmGUAj-E6JM.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/hHaCdnnepQTM2egBk_nNjx2qtE0nJ9AoCURFgFCimW0.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/o6ueeBxouoMB3i0BojV9csF7Nv7vj-VOG_uQuI50Bsw.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/qU-CZGfXFumxCXsfIRmNyVkxQbynRnZU9MB3VCPUBOI.cache +2 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/sRGS14pPtrh56KyQ_kl9N-zL1uB9ioBkupw2fsFv5Qg.cache +3 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/uQRTceYLrl73R0pgWCxVOnYpJ45bJLISR0_4UDPlJz4.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/ySK7zTiTeC0Yma0kl-Eg7cApzKz-5tN6Y5p6ljvFAV8.cache +1 -0
- data/test/fixed_model/base_test.rb +7 -0
- data/test/fixed_model_test.rb +127 -0
- data/test/integration/navigation_test.rb +14 -0
- data/test/test_helper.rb +18 -0
- metadata +198 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9c9db27f13b391e27b06f3deee776d0cc8b35a5e
|
4
|
+
data.tar.gz: 4e090077c600752a89fd77b46615e8a5b72b7d54
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a86581d29697003d548e319606dadc70a17c42f3fff044209e2c6739a4dceb9301d013d22d42435cfdae83b1e4e877fd43338d03095481b8a84d8a27a2d0290f
|
7
|
+
data.tar.gz: e4079963dfbf17016c01b69c6b49ca99d44ef02e8b7e8f27abf4b4902e30f6500e5e0cf170e3c7651a6113caeb71983bf183d3f23ecf6f79f98d3cc4dcaaf528
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2015 mollerhoj
|
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,113 @@
|
|
1
|
+
Fixed Model
|
2
|
+
==========
|
3
|
+
|
4
|
+
Fixed Models act like ActiveRecord models, but they are immutable and read from data files.
|
5
|
+
|
6
|
+
Sometimes we need static data in our applications. It can often be modeled as models in the MVC pattern. Instead of storing such data in the database, it can be useful to store the data in simple datafiles.
|
7
|
+
|
8
|
+
This has several advantages:
|
9
|
+
|
10
|
+
- It makes it easier for developers to quickly inspect and edit the data.
|
11
|
+
- It is trivial to make sure the data is never modified.
|
12
|
+
- It makes it easier to make assumptions about what records exists.
|
13
|
+
|
14
|
+
Installing
|
15
|
+
-----------
|
16
|
+
Include `gem fixed_model` in your `Gemfile` and run `bundle install`
|
17
|
+
|
18
|
+
Usage
|
19
|
+
-----------
|
20
|
+
|
21
|
+
To use a FixedModel, inherit from `FixedModel::Base`:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
class Country < FixedModel::Base
|
25
|
+
|
26
|
+
end
|
27
|
+
```
|
28
|
+
|
29
|
+
The model will read from `config/fixed_models/countries.yml`, an example of such a file could be:
|
30
|
+
|
31
|
+
```yaml
|
32
|
+
---
|
33
|
+
denmark:
|
34
|
+
name: Denmark
|
35
|
+
capital: Copenhagen
|
36
|
+
|
37
|
+
england:
|
38
|
+
name: England
|
39
|
+
language: English
|
40
|
+
capital: London
|
41
|
+
center:
|
42
|
+
- 53.562925
|
43
|
+
- 1.806361
|
44
|
+
features:
|
45
|
+
- :drive_on_left_side
|
46
|
+
cities:
|
47
|
+
:london:
|
48
|
+
:name: London
|
49
|
+
:status: :capital
|
50
|
+
```
|
51
|
+
|
52
|
+
The outermost keys (in this case `denmark` and `england` will be discarded. They are only used as primary keys for merging multiple data files. (See the section "Merge files from multiple file paths").
|
53
|
+
|
54
|
+
Merge files from multiple file paths
|
55
|
+
------------------------------------
|
56
|
+
|
57
|
+
The file paths can be changed by setting `FixedModel.file_paths`. The default is:
|
58
|
+
|
59
|
+
```
|
60
|
+
FixedModel.file_paths = ['config/fixed_models']
|
61
|
+
```
|
62
|
+
|
63
|
+
The data in latter file paths will override values in the former. This makes it possible to set values specific to different environments. For example, the `countries.yml` file from the previous section might have different names in production. The file `config/fixed_models/production/countries.yml` can specify that:
|
64
|
+
|
65
|
+
```yaml
|
66
|
+
---
|
67
|
+
england:
|
68
|
+
name: ENGLAND
|
69
|
+
```
|
70
|
+
|
71
|
+
In the case of arrays and hashes, the former files will be appended to the latter. So in the example below England would end up with both the `:rail_roads` and the `:drive_on_left_side` features. As well as the cities `:london` and `:manchester`:
|
72
|
+
|
73
|
+
```yaml
|
74
|
+
---
|
75
|
+
england:
|
76
|
+
name: England
|
77
|
+
features:
|
78
|
+
- :rail_roads
|
79
|
+
cities:
|
80
|
+
:manchester:
|
81
|
+
:name: Manchester
|
82
|
+
```
|
83
|
+
|
84
|
+
The default file paths depend on the environment. In the development environment, the data will be read from `config/fixed_models` and `config/fixed_models/development`. To change this behavior, set:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
FixedModel.use_environment_file_paths = false
|
88
|
+
```
|
89
|
+
|
90
|
+
Supported methods
|
91
|
+
-----------------
|
92
|
+
|
93
|
+
Fixed Models support the most common methods used on ActiveRecord models:
|
94
|
+
|
95
|
+
Class methods:
|
96
|
+
```
|
97
|
+
find, first, second, third, fourth, last, all, count, each, attribute_names
|
98
|
+
```
|
99
|
+
|
100
|
+
Dynamic class methods. (here, attribute name is `capital`)
|
101
|
+
```
|
102
|
+
find_by_capital, find_by_capital!
|
103
|
+
```
|
104
|
+
|
105
|
+
Instance methods:
|
106
|
+
```
|
107
|
+
persisted?, new_record?, read_attribute
|
108
|
+
```
|
109
|
+
|
110
|
+
Dynamic instance methods:
|
111
|
+
```
|
112
|
+
capital, capital?, attribute_names
|
113
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'FixedModel'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
Bundler::GemHelper.install_tasks
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'lib'
|
28
|
+
t.libs << 'test'
|
29
|
+
t.pattern = 'test/**/*_test.rb'
|
30
|
+
t.verbose = false
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
task default: :test
|
data/lib/fixed_model.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
module FixedModel
|
2
|
+
autoload :Base, "fixed_model/base"
|
3
|
+
autoload :Loader, "fixed_model/loader"
|
4
|
+
|
5
|
+
cattr_accessor :file_paths
|
6
|
+
cattr_accessor :use_environment_paths
|
7
|
+
|
8
|
+
@@file_paths = ['config/fixed_models']
|
9
|
+
@@use_environment_paths = true
|
10
|
+
|
11
|
+
class RecordNotFound < StandardError; end
|
12
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module FixedModel
|
2
|
+
class Base
|
3
|
+
include ActiveModel::Model
|
4
|
+
include ActiveModel::AttributeMethods
|
5
|
+
|
6
|
+
attribute_method_suffix '?'
|
7
|
+
|
8
|
+
class << self
|
9
|
+
delegate :find, :first, :first!, :last, :second, :second!, :third,
|
10
|
+
:third!, :fourth, :fourth!, :fifth, :fifth!, :forty_two, :forty_two!,
|
11
|
+
:count, to: :all
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(row={})
|
15
|
+
@row = row
|
16
|
+
define_attribute_readers
|
17
|
+
end
|
18
|
+
|
19
|
+
def persisted?
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def new_record?
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
27
|
+
def attributes
|
28
|
+
@row.dup.freeze
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.inherited(subclass)
|
32
|
+
subclass.define_find_by_attributes
|
33
|
+
subclass.define_find_by_attributes!
|
34
|
+
define_attribute_methods(subclass.attribute_names)
|
35
|
+
end
|
36
|
+
|
37
|
+
def attribute?(attr)
|
38
|
+
send(attr.to_sym).present?
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.attribute_names
|
42
|
+
names = []
|
43
|
+
data.each do |row|
|
44
|
+
names.concat(row.keys)
|
45
|
+
end
|
46
|
+
names.uniq.map(&:to_s)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.all
|
50
|
+
data.map { |row| new(row) }
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.each(&block)
|
54
|
+
all.each(&block)
|
55
|
+
end
|
56
|
+
|
57
|
+
def attribute_names
|
58
|
+
@row.keys.map(&:to_s)
|
59
|
+
end
|
60
|
+
|
61
|
+
def read_attribute(attribute)
|
62
|
+
@row[attribute]
|
63
|
+
end
|
64
|
+
|
65
|
+
def ==(other)
|
66
|
+
other.instance_of?(self.class) && other.attributes == attributes
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
# Seems to be called when denmark.language is not defined and called.
|
72
|
+
# Look in rails source for explanation...
|
73
|
+
def attribute(attribute)
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
|
77
|
+
def define_attribute_readers
|
78
|
+
attribute_names.each do |attribute_name|
|
79
|
+
define_singleton_method attribute_name do
|
80
|
+
read_attribute(attribute_name)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.singleton_class
|
86
|
+
class << self
|
87
|
+
self
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.define_find_by_attribute(attribute)
|
92
|
+
singleton_class.send :define_method, "find_by_#{attribute}" do |arg|
|
93
|
+
row = data.find { |i| i[attribute] == arg } # or sym?
|
94
|
+
row ? self.new(row) : nil
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.define_find_by_attribute!(attribute)
|
99
|
+
singleton_class.send :define_method, "find_by_#{attribute}!" do |arg|
|
100
|
+
row = data.find { |i| i[attribute] == arg } # or sym?
|
101
|
+
if row
|
102
|
+
self.new(row)
|
103
|
+
else
|
104
|
+
raise FixedModel::RecordNotFound
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.define_find_by_attributes
|
110
|
+
attribute_names.each do |attribute|
|
111
|
+
define_find_by_attribute(attribute)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.define_find_by_attributes!
|
116
|
+
attribute_names.each do |attribute|
|
117
|
+
define_find_by_attribute!(attribute)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.data
|
122
|
+
@data ||= FixedModel::Loader.new(self).load
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module FixedModel
|
2
|
+
class Loader
|
3
|
+
def initialize(model_name)
|
4
|
+
@model_name = model_name
|
5
|
+
end
|
6
|
+
|
7
|
+
def load
|
8
|
+
data = {}
|
9
|
+
files.each do |file|
|
10
|
+
merge_data(data, YAML.load(File.read(file)))
|
11
|
+
end
|
12
|
+
data.values
|
13
|
+
end
|
14
|
+
|
15
|
+
def merge_data(row, new_row)
|
16
|
+
new_row.each do |key, value|
|
17
|
+
if row[key].is_a?(Hash) && value.is_a?(Hash)
|
18
|
+
merge_data(row[key], value)
|
19
|
+
elsif row[key].is_a?(Array) && value.is_a?(Array)
|
20
|
+
row[key].concat(value)
|
21
|
+
else
|
22
|
+
row[key] = value
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def files
|
28
|
+
plural_model_name = ActiveModel::Naming.plural(@model_name)
|
29
|
+
files = []
|
30
|
+
FixedModel.file_paths.each do |file_path|
|
31
|
+
files << File.join(Rails.root, file_path, "#{plural_model_name}.yml")
|
32
|
+
if FixedModel.use_environment_paths
|
33
|
+
file = File.join(Rails.root, file_path, 'test',"#{plural_model_name}.yml")
|
34
|
+
files << file if File.exists?(file)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
files
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
== README
|
2
|
+
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
4
|
+
application up and running.
|
5
|
+
|
6
|
+
Things you may want to cover:
|
7
|
+
|
8
|
+
* Ruby version
|
9
|
+
|
10
|
+
* System dependencies
|
11
|
+
|
12
|
+
* Configuration
|
13
|
+
|
14
|
+
* Database creation
|
15
|
+
|
16
|
+
* Database initialization
|
17
|
+
|
18
|
+
* How to run the test suite
|
19
|
+
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
21
|
+
|
22
|
+
* Deployment instructions
|
23
|
+
|
24
|
+
* ...
|
25
|
+
|
26
|
+
|
27
|
+
Please feel free to use a different markup language if you do not plan to run
|
28
|
+
<tt>rake doc:app</tt>.
|
data/test/dummy/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require_tree .
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any styles
|
10
|
+
* defined in the other CSS/SCSS files in this directory. It is generally better to create a new
|
11
|
+
* file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|