├── .gitignore ├── .travis.yml ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── app └── controllers │ └── chili │ └── application_controller.rb ├── chili.gemspec ├── lib ├── chili.rb ├── chili │ ├── activatable.rb │ ├── base.rb │ ├── bundler.rb │ ├── engine.rb │ ├── engine_extensions.rb │ ├── feature.rb │ ├── overrides.rb │ └── version.rb ├── generators │ └── chili │ │ ├── feature │ │ ├── USAGE │ │ └── feature_generator.rb │ │ └── generator_proxy.rb └── tasks │ └── chili.rake └── spec ├── README.md ├── chili └── activatable_spec.rb ├── dummy ├── app │ ├── app │ │ └── controllers │ │ │ └── application_controller.rb │ ├── config │ │ ├── application.rb │ │ ├── boot.rb │ │ ├── database.yml │ │ ├── environment.rb │ │ └── environments │ │ │ └── test.rb │ └── script │ │ └── rails └── blank_feature │ ├── README.rdoc │ ├── app │ ├── assets │ │ ├── images │ │ │ └── blank_feature │ │ │ │ └── .gitkeep │ │ ├── javascripts │ │ │ └── blank_feature │ │ │ │ └── application.js │ │ └── stylesheets │ │ │ └── blank_feature │ │ │ └── application.css │ ├── controllers │ │ └── blank_feature │ │ │ └── application_controller.rb │ └── overrides │ │ └── layouts │ │ └── application │ │ ├── assets.html.erb.deface │ │ └── example.html.erb.deface │ ├── blank_feature.gemspec │ ├── config │ └── routes.rb │ └── lib │ ├── blank_feature.rb │ ├── blank_feature │ ├── engine.rb │ └── version.rb │ ├── generators │ └── blank_feature_generator.rb │ └── tasks │ └── blank_feature_tasks.rake ├── example_app ├── README.rdoc ├── Rakefile ├── app │ ├── assets │ │ ├── javascripts │ │ │ └── application.js │ │ └── stylesheets │ │ │ ├── application.css │ │ │ ├── posts.css │ │ │ ├── scaffold.css │ │ │ └── users.css │ ├── controllers │ │ ├── application_controller.rb │ │ ├── posts_controller.rb │ │ ├── sessions_controller.rb │ │ └── users_controller.rb │ ├── helpers │ │ ├── application_helper.rb │ │ ├── posts_helper.rb │ │ └── users_helper.rb │ ├── mailers │ │ └── .gitkeep │ ├── models │ │ ├── .gitkeep │ │ ├── post.rb │ │ └── user.rb │ ├── overrides │ │ └── posts │ │ │ └── index │ │ │ └── spree.html.erb.deface │ └── views │ │ ├── layouts │ │ └── application.html.erb │ │ ├── posts │ │ ├── _form.html.erb │ │ ├── _post.html.erb │ │ ├── edit.html.erb │ │ ├── index.html.erb │ │ ├── new.html.erb │ │ └── show.html.erb │ │ ├── sessions │ │ └── new.html.erb │ │ └── users │ │ ├── _form.html.erb │ │ ├── edit.html.erb │ │ ├── index.html.erb │ │ ├── new.html.erb │ │ └── show.html.erb ├── config.ru ├── config │ ├── application.rb │ ├── boot.rb │ ├── database.yml │ ├── environment.rb │ ├── environments │ │ ├── development.rb │ │ ├── production.rb │ │ └── test.rb │ ├── initializers │ │ ├── backtrace_silencers.rb │ │ ├── filter_parameter_logging.rb │ │ ├── inflections.rb │ │ ├── mime_types.rb │ │ ├── secret_token.rb │ │ ├── session_store.rb │ │ └── wrap_parameters.rb │ ├── locales │ │ └── en.yml │ └── routes.rb ├── db │ ├── migrate │ │ ├── 20120513023816_create_posts.rb │ │ ├── 20120513023840_create_users.rb │ │ └── 20120513032032_create_social_feature_likes.rb │ └── schema.rb ├── lib │ ├── assets │ │ └── .gitkeep │ └── chili │ │ ├── invites_feature │ │ ├── .gitignore │ │ ├── app │ │ │ ├── assets │ │ │ │ ├── images │ │ │ │ │ └── invites_feature │ │ │ │ │ │ └── .gitkeep │ │ │ │ ├── javascripts │ │ │ │ │ └── invites_feature │ │ │ │ │ │ └── application.js │ │ │ │ └── stylesheets │ │ │ │ │ └── invites_feature │ │ │ │ │ └── application.css │ │ │ ├── controllers │ │ │ │ └── invites_feature │ │ │ │ │ └── application_controller.rb │ │ │ └── overrides │ │ │ │ └── posts │ │ │ │ └── index │ │ │ │ └── disclaimer.html.erb.deface │ │ ├── config │ │ │ └── routes.rb │ │ └── lib │ │ │ ├── generators │ │ │ └── invites_feature_generator.rb │ │ │ ├── invites_feature.rb │ │ │ └── invites_feature │ │ │ └── engine.rb │ │ └── social_feature │ │ ├── app │ │ ├── assets │ │ │ ├── images │ │ │ │ └── social_feature │ │ │ │ │ └── .gitkeep │ │ │ ├── javascripts │ │ │ │ └── social_feature │ │ │ │ │ └── application.js │ │ │ └── stylesheets │ │ │ │ └── social_feature │ │ │ │ └── application.css.scss │ │ ├── controllers │ │ │ └── social_feature │ │ │ │ ├── application_controller.rb │ │ │ │ └── likes_controller.rb │ │ ├── models │ │ │ └── social_feature │ │ │ │ ├── like.rb │ │ │ │ ├── post.rb │ │ │ │ └── user.rb │ │ ├── overrides │ │ │ ├── layouts │ │ │ │ └── application │ │ │ │ │ └── likes_link.html.erb.deface │ │ │ └── posts │ │ │ │ ├── _post │ │ │ │ └── like_actions.html.erb.deface │ │ │ │ └── index │ │ │ │ ├── disclaimer.html.erb.deface │ │ │ │ └── table_headers.html.erb.deface │ │ └── views │ │ │ └── social_feature │ │ │ └── likes │ │ │ └── index.html.erb │ │ ├── config │ │ └── routes.rb │ │ ├── db │ │ └── migrate │ │ │ └── 20120513031021_create_social_feature_likes.rb │ │ └── lib │ │ ├── generators │ │ └── social_feature_generator.rb │ │ ├── social_feature.rb │ │ └── social_feature │ │ └── engine.rb ├── log │ └── .gitkeep ├── public │ ├── 404.html │ ├── 422.html │ ├── 500.html │ └── favicon.ico ├── script │ └── rails └── spec │ └── support │ └── user_macros.rb ├── features └── social_feature_spec.rb ├── generators └── chili │ ├── feature_generator_spec.rb │ └── generator_proxy_spec.rb ├── spec_helper.rb └── support └── dummy_app.rb /.gitignore: -------------------------------------------------------------------------------- 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/reports 15 | spec/example_app/db/*.sqlite3 16 | spec/example_app/log/*.log 17 | spec/example_app/tmp/ 18 | spec/example_app/.sass-cache 19 | spec/dummy/app/Gemfile 20 | spec/dummy/app/log/ 21 | spec/dummy/app/lib/ 22 | tmp 23 | .DS_Store 24 | .pt 25 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | script: "rake app:db:setup && rake app:db:test:prepare && rake" 3 | rvm: 4 | - 1.9.3 5 | - 2.0.0 6 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in chili.gemspec 4 | gemspec 5 | gem 'rake' 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Jens Balvig 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🌶️ Chili 2 | 3 | Have you ever wanted to test out a new feature on only a subset of users? 4 | Did that implementation end up being lots of if/else statements embedded in the main code? 5 | If so, Chili can help. 6 | 7 | Chili is built on top of Rails Engines and Deface and allows you to conditionally add new/modify existing views, 8 | while leaving the main code untouched. 9 | 10 | ## Tutorial & Examples 11 | 12 | - [Walkthrough of creating and releasing a new feature with Chili](https://balvig.github.io/chili/) 13 | 14 | ## Requirements 15 | 16 | - Rails 4.1+ 17 | - Ruby 1.9.2+ 18 | 19 | ## Installation 20 | 21 | First add Chili to your app's Gemfile: 22 | 23 | ```ruby 24 | gem 'chili' 25 | ``` 26 | 27 | and run `bundle`. 28 | 29 | ## Usage 30 | 31 | Chili features are like mini apps that are created inside your main app's lib/chili directory using using the "chili" generator. 32 | 33 | ### Creating a new chili feature 34 | 35 | As an example, assuming you want to add a beta feature named "social" that shows a new like-button 36 | to a subset of users, first within your main app run: 37 | 38 | ```bash 39 | $ rails g chili:feature social 40 | ``` 41 | 42 | This will: 43 | 44 | 1. Create the directory `lib/chili/social_feature` containing the basic structure for the feature 45 | 2. Add a reference to the feature to the main app gemfile 46 | 47 | Since the feature is mounted as a gem you'll have to restart the app. 48 | 49 | ### Define who can see the feature 50 | 51 | Use the active_if block to control whether new the feature is active for each user. 52 | The context of the active_if block is the application controller so you can use any methods available to that. 53 | 54 | ```ruby 55 | # {feature}/lib/social_feature.rb 56 | module SocialFeature 57 | extend Chili::Base 58 | active_if { logged_in? && current_user.admin? } # Feature is only visible to logged in admin users 59 | end 60 | ``` 61 | 62 | ### Modifying view templates in main app 63 | 64 | Chili uses Deface to dynamically modify existing view templates (see [Deface docs](https://github.com/spree/deface#using-the-deface-dsl-deface-files) for details) 65 | To generate an override to the feature, run the deface generator specifying the name of the feature and path to the template you want to modify. 66 | For example, assuming the main app has the partial `app/views/posts/_post.html.erb` run: 67 | 68 | ```bash 69 | $ rails g social_feature deface:override posts/_post like_button 70 | ``` 71 | 72 | This will create a dummy override at `{feature}/app/overrides/posts/_post/like_button.html.erb.deface` that you can edit: 73 | 74 | ```erb 75 | <% # {feature}/app/overrides/posts/_post/like_button.html.erb.deface %> 76 | 77 | <%= link_to 'Like!', social_feature.likes_path(like: {post_id: post}), method: :post %> 78 | ``` 79 | 80 | ### Adding new resources 81 | 82 | You can run the usual Rails generators for each feature by prepending 83 | the generator with the name of the feature: 84 | 85 | ```bash 86 | $ rails g social_feature scaffold Like 87 | ``` 88 | 89 | The new resource will be namespaced to `SocialFeature::Like` and automounted as an [isolated engine](http://railscasts.com/episodes/277-mountable-engines?view=asciicast) in the main app at `/chili/social_feature/likes`, 90 | but will only be accessible when active_if is true. 91 | 92 | ### Migrations 93 | 94 | To copy and run feature db migrations use the following command: 95 | 96 | ```bash 97 | $ rake social_feature:db:migrate 98 | ``` 99 | 100 | ### Modifying existing models 101 | 102 | Create a model with the same name as the one you want to modify by running: `rails g social_feature model User --migration=false` and edit it to inherit from the original: 103 | 104 | ```ruby 105 | # {feature}/app/models/social_feature/user.rb 106 | module SocialFeature 107 | class User < ::User 108 | has_many :likes 109 | end 110 | end 111 | ``` 112 | 113 | Access in your overrides/feature views through the namespaced model: 114 | 115 | ```erb 116 | <%= SocialFeature::User.first.likes %> 117 | <%= current_user.becomes(SocialFeature::User).likes %> 118 | ``` 119 | 120 | ### Stylesheets/javascripts 121 | 122 | Files added to the feature's `app/assets/social_feature/javascripts|stylesheets` directory are automatically injected into the layout using a pre-generated override: 123 | 124 | ```erb 125 | <% # {feature}/app/overrides/layouts/application/assets.html.erb.deface %> 126 | 127 | <%= stylesheet_link_tag 'social_feature/application' %> 128 | <%= javascript_include_tag 'social_feature/application' %> 129 | ``` 130 | 131 | If you don't need any css/js in your feature, you can remove this file. 132 | 133 | ## Gotchas 134 | 135 | - Chili will not be able to automount if you use a catch-all route in your main app (ie `match '*a', to: 'errors#routing'`), you will have to remove the catch-all or manually add the engine to the main app's routes file. 136 | - Just like normal engines, Chili requires you to prepend path helpers with `main_app` (ie `main_app.root_path` etc) in view templates that are shared with the main app (such as the main app's application layout file). 137 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | 3 | begin 4 | require 'bundler/setup' 5 | rescue LoadError 6 | puts 'You must `gem install bundler` and `bundle install` to run rake tasks' 7 | end 8 | 9 | APP_RAKEFILE = File.expand_path("../spec/example_app/Rakefile", __FILE__) 10 | load 'rails/tasks/engine.rake' 11 | 12 | require 'rspec/core/rake_task' 13 | 14 | RSpec::Core::RakeTask.new(:spec) 15 | task :default => :spec 16 | 17 | Bundler::GemHelper.install_tasks 18 | -------------------------------------------------------------------------------- /app/controllers/chili/application_controller.rb: -------------------------------------------------------------------------------- 1 | module Chili 2 | class ApplicationController < ::ApplicationController 3 | before_filter :activate_feature 4 | 5 | private 6 | 7 | def activate_feature 8 | raise ActionController::RoutingError, 'Feature Disabled' unless self.class.parent.active?(self) 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /chili.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | require File.expand_path('../lib/chili/version', __FILE__) 3 | 4 | Gem::Specification.new do |gem| 5 | gem.authors = ["Jens Balvig"] 6 | gem.email = ["jens@balvig.com"] 7 | gem.description = %q{The spicy feature toggle framework} 8 | gem.summary = %q{The spicy feature toggle framework} 9 | gem.homepage = "http://balvig.github.com/chili/" 10 | 11 | gem.files = `git ls-files`.split($\) 12 | gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } 13 | gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) 14 | gem.name = "chili" 15 | gem.require_paths = ["lib"] 16 | gem.version = Chili::VERSION 17 | 18 | gem.add_dependency "rails", ">= 4.1" 19 | gem.add_dependency "deface", "~> 1.0.0" 20 | 21 | gem.add_development_dependency 'rspec', '~> 2.14.0' 22 | gem.add_development_dependency 'rspec-rails', '~> 2.14.0' 23 | gem.add_development_dependency 'jquery-rails' 24 | gem.add_development_dependency 'capybara', '~> 2.0' 25 | gem.add_development_dependency 'xpath' 26 | gem.add_development_dependency 'sqlite3' 27 | gem.add_development_dependency 'pry' 28 | end 29 | -------------------------------------------------------------------------------- /lib/chili.rb: -------------------------------------------------------------------------------- 1 | require "deface" 2 | require "chili/base" 3 | require "chili/bundler" 4 | require "chili/engine" 5 | require "chili/feature" 6 | require "chili/overrides" 7 | require "chili/version" 8 | require "generators/chili/generator_proxy" 9 | 10 | module Chili 11 | FEATURE_FOLDER = 'lib/chili' 12 | end 13 | -------------------------------------------------------------------------------- /lib/chili/activatable.rb: -------------------------------------------------------------------------------- 1 | module Chili 2 | module Activatable 3 | def self.extended(base) 4 | base.send(:unloadable) if base.respond_to?(:unloadable) 5 | end 6 | 7 | def active_if(&block) 8 | @active_if = block 9 | end 10 | 11 | def active?(controller) 12 | controller.instance_eval(&@active_if) 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/chili/base.rb: -------------------------------------------------------------------------------- 1 | require "chili/activatable" 2 | require "chili/engine_extensions" 3 | 4 | module Chili 5 | module Base 6 | def self.extended(base) 7 | base.extend(Activatable) 8 | base::Engine.extend(EngineExtensions) 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/chili/bundler.rb: -------------------------------------------------------------------------------- 1 | Bundler.require(:chili) 2 | -------------------------------------------------------------------------------- /lib/chili/engine.rb: -------------------------------------------------------------------------------- 1 | module Chili 2 | class Engine < ::Rails::Engine 3 | 4 | initializer "chili.add_autoload_paths", before: :set_autoload_paths do |app| 5 | app.config.autoload_paths += Dir["#{app.config.root}/#{FEATURE_FOLDER}/*/lib"] 6 | end 7 | 8 | initializer 'chili.deface' do |app| 9 | app.config.deface.namespaced = true 10 | end 11 | 12 | initializer 'chili.controller' do |app| 13 | ActiveSupport.on_load(:action_controller) do 14 | include Chili::Overrides 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/chili/engine_extensions.rb: -------------------------------------------------------------------------------- 1 | module Chili 2 | module EngineExtensions 3 | def self.extended(base) 4 | base.rake_tasks do 5 | next if self.is_a?(Rails::Application) 6 | next unless has_migrations? 7 | 8 | namespace railtie_name do 9 | namespace :db do 10 | desc "Copy and migrate migrations from #{railtie_name}" 11 | task :migrate do 12 | Rake::Task["#{railtie_name}:install:migrations"].invoke 13 | Rake::Task["db:migrate"].invoke 14 | end 15 | end 16 | end 17 | end 18 | end 19 | 20 | def automount!(path = nil) 21 | engine = self 22 | path ||= 'chili/' + engine.parent.to_s.underscore 23 | Rails.application.routes.draw do 24 | mount engine => path 25 | end 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/chili/feature.rb: -------------------------------------------------------------------------------- 1 | module Chili 2 | class Feature 3 | def initialize(short_name) 4 | @short_name = short_name 5 | end 6 | 7 | def name 8 | @short_name.to_s.underscore.gsub('_feature','') + '_feature' 9 | end 10 | 11 | def path 12 | "#{FEATURE_FOLDER}/#{name}" 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/chili/overrides.rb: -------------------------------------------------------------------------------- 1 | module Chili 2 | module Overrides 3 | def self.included(base) 4 | base.send(:include, InstanceMethods) 5 | base.before_filter :activate_overrides 6 | end 7 | 8 | module InstanceMethods 9 | def activate_overrides 10 | Deface::Override.all.values.map(&:values).flatten.each do |override| 11 | engine = override.railtie_class.constantize.parent 12 | override.args[:disabled] = !engine.active?(self) if engine.respond_to?(:active?) 13 | end 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/chili/version.rb: -------------------------------------------------------------------------------- 1 | module Chili 2 | VERSION = "4.0.1" 3 | end 4 | -------------------------------------------------------------------------------- /lib/generators/chili/feature/USAGE: -------------------------------------------------------------------------------- 1 | Description: 2 | Generate a new chili feature 3 | 4 | Example: 5 | rails generate chili:feature social 6 | 7 | This will create: 8 | basic chili feature structure in vendor/chili/social_feature 9 | -------------------------------------------------------------------------------- /lib/generators/chili/feature/feature_generator.rb: -------------------------------------------------------------------------------- 1 | module Chili 2 | module Generators 3 | class FeatureGenerator < Rails::Generators::NamedBase 4 | 5 | def run_plugin_generator 6 | ARGV[0] = feature.path 7 | ARGV[1] = '--mountable' 8 | ARGV[2] = '--skip-test-unit' 9 | ARGV[3] = '--skip-bundle' 10 | 11 | require 'rails/generators' 12 | require 'rails/generators/rails/plugin/plugin_generator' 13 | Rails::Generators::PluginGenerator.start 14 | end 15 | 16 | def reset_destination_root 17 | self.destination_root = '' 18 | end 19 | 20 | def edit_gemspec 21 | require File.expand_path('../../../../chili/version', __FILE__) 22 | gemspec = "#{feature.name}.gemspec" 23 | gsub_file gemspec, 'TODO: Your name', `git config user.NAME`.chomp 24 | gsub_file gemspec, 'TODO: Your email', `git config user.email`.chomp 25 | gsub_file gemspec, /TODO(:\s)?/, '' 26 | inject_into_file gemspec, " s.add_dependency 'chili', '~> #{Chili::VERSION.sub(/\.\d+$/,'')}'\n\n", before: ' s.add_development_dependency "sqlite3"' 27 | end 28 | 29 | def add_gem_to_main_gemfile 30 | gemfile = "../../../Gemfile" 31 | group = "group :chili do\n" 32 | append_to_file gemfile, group 33 | append_to_file gemfile, " gem '#{feature.name}', path: '#{feature.path}'\nend", after: group 34 | gsub_file gemfile, 'end gem', ' gem' #nasty cleanup 35 | end 36 | 37 | def remove_unused_files 38 | remove_dir "app/helpers/#{feature.name}" 39 | remove_dir 'app/views/layouts' 40 | remove_dir 'script' 41 | remove_file 'Gemfile' 42 | remove_file 'Rakefile' 43 | remove_file 'MIT-LICENSE' 44 | end 45 | 46 | def remove_jquery_stuff 47 | gsub_file "app/assets/javascripts/#{feature.name}/application.js", "//= require jquery_ujs\n", '' 48 | gsub_file "app/assets/javascripts/#{feature.name}/application.js", "//= require jquery\n", '' 49 | end 50 | 51 | def chilify_application_controller 52 | gsub_file "app/controllers/#{feature.name}/application_controller.rb", "ActionController::Base", 'Chili::ApplicationController' 53 | end 54 | 55 | def clean_up_gitignore 56 | gsub_file ".gitignore", /test\/dummy.*\n/, '' 57 | end 58 | 59 | def automount_engine 60 | prepend_to_file 'config/routes.rb', "#{feature.name.camelcase}::Engine.automount!\n" 61 | end 62 | 63 | def include_chili_libs 64 | prepend_to_file "lib/#{feature.name}.rb", "require \"chili\"\n" 65 | end 66 | 67 | def include_base_and_active_if 68 | inject_into_file "lib/#{feature.name}.rb", after: "module #{feature.name.camelcase}\n" do <<-RUBY 69 | extend Chili::Base 70 | active_if { true } # edit this to activate/deactivate feature at runtime 71 | RUBY 72 | end 73 | end 74 | 75 | def add_dummy_override 76 | example_file_path = "app/overrides/layouts/application/example.html.erb.deface" 77 | create_file example_file_path do <<-RUBY 78 | 79 |
80 | #{feature.name} active - edit/remove this file:
81 | #{feature.path}/#{example_file_path}
82 | <%= link_to 'deface docs', 'https://github.com/spree/deface', target: '_blank' %> 83 |
84 | RUBY 85 | end 86 | end 87 | 88 | def add_assets_override 89 | create_file 'app/overrides/layouts/application/assets.html.erb.deface' do <<-RUBY 90 | 91 | <%= stylesheet_link_tag '#{feature.name}/application' %> 92 | <%= javascript_include_tag '#{feature.name}/application' %> 93 | RUBY 94 | end 95 | end 96 | 97 | def add_generator_proxy 98 | create_file "lib/generators/#{feature.name}_generator.rb" do <<-RUBY 99 | class #{feature.name.camelcase}Generator < Rails::Generators::Base 100 | include Chili::GeneratorProxy 101 | end 102 | RUBY 103 | end 104 | end 105 | 106 | protected 107 | 108 | def feature 109 | @feature ||= Chili::Feature.new(ARGV[0]) 110 | end 111 | end 112 | end 113 | end 114 | -------------------------------------------------------------------------------- /lib/generators/chili/generator_proxy.rb: -------------------------------------------------------------------------------- 1 | module Chili 2 | module GeneratorProxy 3 | def self.included(base) 4 | base.class_eval do 5 | argument :generator, type: :string 6 | argument :generator_options, type: :array, default: [], banner: "GENERATOR_OPTIONS" 7 | 8 | def self.desc 9 | "Generates resources (scaffold, model, migration etc) for #{generator_name}" 10 | end 11 | 12 | def delegate 13 | engine = self.class.generator_name.classify.constantize 14 | Rails::Generators.namespace = engine 15 | Rails::Generators.invoke ARGV.shift, ARGV, destination_root: Feature.new(engine).path, behavior: behavior 16 | end 17 | end 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/tasks/chili.rake: -------------------------------------------------------------------------------- 1 | { spec: 'RSpec::Core::RakeTask', test: 'Rake::TestTask' }.each do |test_lib, rake_task| 2 | if Rake::Task.task_defined?(test_lib) 3 | 4 | Rake::Task[test_lib].clear 5 | chili_specs = "#{Chili::FEATURE_FOLDER}/**/#{test_lib}/**/*_#{test_lib}.rb" 6 | 7 | task = rake_task.constantize.new(test_lib => 'test:prepare') 8 | task.pattern = [task.pattern, chili_specs] 9 | 10 | namespace test_lib do 11 | desc "Run tests for all Chili features" 12 | rake_task.constantize.new(:chili) do |t| 13 | t.pattern = chili_specs 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /spec/README.md: -------------------------------------------------------------------------------- 1 | # Running tests 2 | 3 | ```bash 4 | $ rake app:db:setup 5 | $ rake app:db:test:prepare 6 | $ rake 7 | ``` 8 | 9 | ## Folders 10 | 11 | ```bash 12 | spec/dummy/app # dummy app for generating chili features inside 13 | spec/dummy/blank_feature # blank feature template used to compare output of generators 14 | spec/example_app # rails app containing 2 chili features for integration testing 15 | spec/generators # generator tests 16 | spec/chili # chili unit tests 17 | spec/requests # integration tests 18 | ``` 19 | -------------------------------------------------------------------------------- /spec/chili/activatable_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module Engine 4 | extend Chili::Activatable 5 | end 6 | 7 | class DummyController 8 | def logged_in? ; true end 9 | def admin? ; false end 10 | end 11 | 12 | describe Chili::Activatable do 13 | describe '#active_if & #active?' do 14 | it "evaluates the active_if block within the context of the instance" do 15 | Engine.active_if { logged_in? } 16 | Engine.active?(DummyController.new).should be_true 17 | Engine.active_if { logged_in? && admin? } 18 | Engine.active?(DummyController.new).should be_false 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/dummy/app/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | protect_from_forgery 3 | end 4 | -------------------------------------------------------------------------------- /spec/dummy/app/config/application.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../boot', __FILE__) 2 | 3 | require 'rails/all' 4 | 5 | # Require the gems listed in Gemfile, including any gems 6 | # you've limited to :test, :development, or :production. 7 | Bundler.require(:default, Rails.env) 8 | require "chili" 9 | Dir.glob(File.expand_path('../../lib/chili/*', __FILE__)).each do |dir| 10 | require File.basename(dir) 11 | end 12 | 13 | module Dummy 14 | class Application < Rails::Application 15 | # Settings in config/environments/* take precedence over those specified here. 16 | # Application configuration should go into files in config/initializers 17 | # -- all .rb files in that directory are automatically loaded. 18 | 19 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. 20 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. 21 | # config.time_zone = 'Central Time (US & Canada)' 22 | 23 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. 24 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] 25 | # config.i18n.default_locale = :de 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /spec/dummy/app/config/boot.rb: -------------------------------------------------------------------------------- 1 | # Set up gems listed in the Gemfile. 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../../Gemfile', __FILE__) 3 | 4 | require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) 5 | $:.unshift File.expand_path('../../../../../lib', __FILE__) 6 | $:.unshift File.expand_path('../../lib/chili/blank_feature/lib', __FILE__) 7 | -------------------------------------------------------------------------------- /spec/dummy/app/config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite version 3.x 2 | # gem install sqlite3 3 | # 4 | # Ensure the SQLite 3 gem is defined in your Gemfile 5 | # gem 'sqlite3' 6 | development: 7 | adapter: sqlite3 8 | database: db/development.sqlite3 9 | pool: 5 10 | timeout: 5000 11 | 12 | # Warning: The database defined as "test" will be erased and 13 | # re-generated from your development database when you run "rake". 14 | # Do not set this db to the same as development or production. 15 | test: 16 | adapter: sqlite3 17 | database: db/test.sqlite3 18 | pool: 5 19 | timeout: 5000 20 | 21 | production: 22 | adapter: sqlite3 23 | database: db/production.sqlite3 24 | pool: 5 25 | timeout: 5000 26 | -------------------------------------------------------------------------------- /spec/dummy/app/config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require File.expand_path('../application', __FILE__) 3 | 4 | # Initialize the Rails application. 5 | Dummy::Application.initialize! 6 | -------------------------------------------------------------------------------- /spec/dummy/app/config/environments/test.rb: -------------------------------------------------------------------------------- 1 | Dummy::Application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # The test environment is used exclusively to run your application's 5 | # test suite. You never need to work with it otherwise. Remember that 6 | # your test database is "scratch space" for the test suite and is wiped 7 | # and recreated between test runs. Don't rely on the data there! 8 | config.cache_classes = true 9 | 10 | # Do not eager load code on boot. This avoids loading your whole application 11 | # just for the purpose of running a single test. If you are using a tool that 12 | # preloads Rails for running tests, you may have to set it to true. 13 | config.eager_load = false 14 | 15 | # Configure static asset server for tests with Cache-Control for performance. 16 | config.serve_static_assets = true 17 | config.static_cache_control = "public, max-age=3600" 18 | 19 | # Show full error reports and disable caching. 20 | config.consider_all_requests_local = true 21 | config.action_controller.perform_caching = false 22 | 23 | # Raise exceptions instead of rendering exception templates. 24 | config.action_dispatch.show_exceptions = false 25 | 26 | # Disable request forgery protection in test environment. 27 | config.action_controller.allow_forgery_protection = false 28 | 29 | # Tell Action Mailer not to deliver emails to the real world. 30 | # The :test delivery method accumulates sent emails in the 31 | # ActionMailer::Base.deliveries array. 32 | config.action_mailer.delivery_method = :test 33 | 34 | # Print deprecation notices to the stderr. 35 | config.active_support.deprecation = :stderr 36 | end 37 | -------------------------------------------------------------------------------- /spec/dummy/app/script/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. 3 | 4 | APP_PATH = File.expand_path('../../config/application', __FILE__) 5 | require File.expand_path('../../config/boot', __FILE__) 6 | require 'rails/commands' 7 | -------------------------------------------------------------------------------- /spec/dummy/blank_feature/README.rdoc: -------------------------------------------------------------------------------- 1 | = BlankFeature 2 | 3 | This project rocks and uses MIT-LICENSE. -------------------------------------------------------------------------------- /spec/dummy/blank_feature/app/assets/images/blank_feature/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balvig/chili/3a5e24b1d8b4e731cb1a589a9ae276799549b126/spec/dummy/blank_feature/app/assets/images/blank_feature/.gitkeep -------------------------------------------------------------------------------- /spec/dummy/blank_feature/app/assets/javascripts/blank_feature/application.js: -------------------------------------------------------------------------------- 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 vendor/assets/javascripts of plugins, if any, 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/sstephenson/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require_tree . 14 | -------------------------------------------------------------------------------- /spec/dummy/blank_feature/app/assets/stylesheets/blank_feature/application.css: -------------------------------------------------------------------------------- 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 vendor/assets/stylesheets of plugins, if any, 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 | */ 16 | -------------------------------------------------------------------------------- /spec/dummy/blank_feature/app/controllers/blank_feature/application_controller.rb: -------------------------------------------------------------------------------- 1 | module BlankFeature 2 | class ApplicationController < Chili::ApplicationController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /spec/dummy/blank_feature/app/overrides/layouts/application/assets.html.erb.deface: -------------------------------------------------------------------------------- 1 | 2 | <%= stylesheet_link_tag 'blank_feature/application' %> 3 | <%= javascript_include_tag 'blank_feature/application' %> 4 | -------------------------------------------------------------------------------- /spec/dummy/blank_feature/app/overrides/layouts/application/example.html.erb.deface: -------------------------------------------------------------------------------- 1 | 2 |
3 | blank_feature active - edit/remove this file:
4 | lib/chili/blank_feature/app/overrides/layouts/application/example.html.erb.deface
5 | <%= link_to 'deface docs', 'https://github.com/spree/deface', target: '_blank' %> 6 |
7 | -------------------------------------------------------------------------------- /spec/dummy/blank_feature/blank_feature.gemspec: -------------------------------------------------------------------------------- 1 | $:.push File.expand_path("../lib", __FILE__) 2 | 3 | # Maintain your gem's version: 4 | require "blank_feature/version" 5 | 6 | # Describe your gem and declare its dependencies: 7 | Gem::Specification.new do |s| 8 | s.name = "blank_feature" 9 | s.version = BlankFeature::VERSION 10 | s.authors = ["GIT_AUTHOR"] 11 | s.email = ["GIT_EMAIL"] 12 | s.homepage = "" 13 | s.summary = "Summary of BlankFeature." 14 | s.description = "Description of BlankFeature." 15 | s.license = "MIT" 16 | 17 | s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.rdoc"] 18 | 19 | s.add_dependency "rails", "~> 4.1.6" 20 | 21 | s.add_dependency 'chili', '~> 4.0' 22 | 23 | s.add_development_dependency "sqlite3" 24 | end 25 | -------------------------------------------------------------------------------- /spec/dummy/blank_feature/config/routes.rb: -------------------------------------------------------------------------------- 1 | BlankFeature::Engine.automount! 2 | BlankFeature::Engine.routes.draw do 3 | end 4 | -------------------------------------------------------------------------------- /spec/dummy/blank_feature/lib/blank_feature.rb: -------------------------------------------------------------------------------- 1 | require "chili" 2 | require "blank_feature/engine" 3 | 4 | module BlankFeature 5 | extend Chili::Base 6 | active_if { true } # edit this to activate/deactivate feature at runtime 7 | end 8 | -------------------------------------------------------------------------------- /spec/dummy/blank_feature/lib/blank_feature/engine.rb: -------------------------------------------------------------------------------- 1 | module BlankFeature 2 | class Engine < ::Rails::Engine 3 | isolate_namespace BlankFeature 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/dummy/blank_feature/lib/blank_feature/version.rb: -------------------------------------------------------------------------------- 1 | module BlankFeature 2 | VERSION = "0.0.1" 3 | end 4 | -------------------------------------------------------------------------------- /spec/dummy/blank_feature/lib/generators/blank_feature_generator.rb: -------------------------------------------------------------------------------- 1 | class BlankFeatureGenerator < Rails::Generators::Base 2 | include Chili::GeneratorProxy 3 | end 4 | -------------------------------------------------------------------------------- /spec/dummy/blank_feature/lib/tasks/blank_feature_tasks.rake: -------------------------------------------------------------------------------- 1 | # desc "Explaining what the task does" 2 | # task :blank_feature do 3 | # # Task goes here 4 | # end 5 | -------------------------------------------------------------------------------- /spec/example_app/README.rdoc: -------------------------------------------------------------------------------- 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 | rake doc:app. 29 | -------------------------------------------------------------------------------- /spec/example_app/Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require File.expand_path('../config/application', __FILE__) 5 | 6 | Dummy::Application.load_tasks 7 | -------------------------------------------------------------------------------- /spec/example_app/app/assets/javascripts/application.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balvig/chili/3a5e24b1d8b4e731cb1a589a9ae276799549b126/spec/example_app/app/assets/javascripts/application.js -------------------------------------------------------------------------------- /spec/example_app/app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 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 vendor/assets/stylesheets of plugins, if any, 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 top of the 9 | * compiled file, but it's generally better to create a new file per style scope. 10 | * 11 | *= require_self 12 | *= require_tree . 13 | */ 14 | -------------------------------------------------------------------------------- /spec/example_app/app/assets/stylesheets/posts.css: -------------------------------------------------------------------------------- 1 | /* 2 | Place all the styles related to the matching controller here. 3 | They will automatically be included in application.css. 4 | */ 5 | -------------------------------------------------------------------------------- /spec/example_app/app/assets/stylesheets/scaffold.css: -------------------------------------------------------------------------------- 1 | body { background-color: #fff; color: #333; } 2 | 3 | body, p, ol, ul, td { 4 | font-family: verdana, arial, helvetica, sans-serif; 5 | font-size: 13px; 6 | line-height: 18px; 7 | } 8 | 9 | pre { 10 | background-color: #eee; 11 | padding: 10px; 12 | font-size: 11px; 13 | } 14 | 15 | a { color: #4CAEDD; } 16 | a:visited { color: #4CAEDD; } 17 | a:hover { color: #fff; background-color:#000; } 18 | 19 | div.field, div.actions { 20 | margin-bottom: 10px; 21 | } 22 | 23 | #notice { 24 | color: green; 25 | } 26 | 27 | .field_with_errors { 28 | padding: 2px; 29 | background-color: red; 30 | display: table; 31 | } 32 | 33 | #error_explanation { 34 | width: 450px; 35 | border: 2px solid red; 36 | padding: 7px; 37 | padding-bottom: 0; 38 | margin-bottom: 20px; 39 | background-color: #f0f0f0; 40 | } 41 | 42 | #error_explanation h2 { 43 | text-align: left; 44 | font-weight: bold; 45 | padding: 5px 5px 5px 15px; 46 | font-size: 12px; 47 | margin: -7px; 48 | margin-bottom: 0px; 49 | background-color: #c00; 50 | color: #fff; 51 | } 52 | 53 | #error_explanation ul li { 54 | font-size: 12px; 55 | list-style: square; 56 | } 57 | 58 | header { 59 | background:#DDD; 60 | padding:8px 6px; 61 | } 62 | 63 | header form, header form div { 64 | display: inline; 65 | } 66 | 67 | table { 68 | border:1px solid #CCC; 69 | border-radius:4px; 70 | } 71 | 72 | th { 73 | text-align:left; 74 | border-bottom:3px double #CCC; 75 | } 76 | 77 | th, td { 78 | padding:0.8em 1.1em; 79 | font-size: 1.1em; 80 | } 81 | 82 | .remark { 83 | font-weight:normal; 84 | font-style:italic; 85 | color:#888; 86 | } 87 | 88 | .disclaimer { 89 | background: #FFFF8B; 90 | padding: 9px; 91 | display: inline-block; 92 | } 93 | -------------------------------------------------------------------------------- /spec/example_app/app/assets/stylesheets/users.css: -------------------------------------------------------------------------------- 1 | /* 2 | Place all the styles related to the matching controller here. 3 | They will automatically be included in application.css. 4 | */ 5 | -------------------------------------------------------------------------------- /spec/example_app/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | protect_from_forgery 3 | helper_method :current_user, :logged_in? 4 | 5 | def current_user 6 | User.find_by_id(session[:user_id]) 7 | end 8 | 9 | def logged_in? 10 | current_user 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /spec/example_app/app/controllers/posts_controller.rb: -------------------------------------------------------------------------------- 1 | class PostsController < ApplicationController 2 | # GET /posts 3 | # GET /posts.json 4 | def index 5 | @posts = Post.all 6 | 7 | respond_to do |format| 8 | format.html # index.html.erb 9 | format.json { render json: @posts } 10 | end 11 | end 12 | 13 | # GET /posts/1 14 | # GET /posts/1.json 15 | def show 16 | @post = Post.find(params[:id]) 17 | 18 | respond_to do |format| 19 | format.html # show.html.erb 20 | format.json { render json: @post } 21 | end 22 | end 23 | 24 | # GET /posts/new 25 | # GET /posts/new.json 26 | def new 27 | @post = Post.new 28 | 29 | respond_to do |format| 30 | format.html # new.html.erb 31 | format.json { render json: @post } 32 | end 33 | end 34 | 35 | # GET /posts/1/edit 36 | def edit 37 | @post = Post.find(params[:id]) 38 | end 39 | 40 | # POST /posts 41 | # POST /posts.json 42 | def create 43 | @post = Post.new(post_params) 44 | 45 | respond_to do |format| 46 | if @post.save 47 | format.html { redirect_to @post, notice: 'Post was successfully created.' } 48 | format.json { render json: @post, status: :created, location: @post } 49 | else 50 | format.html { render action: "new" } 51 | format.json { render json: @post.errors, status: :unprocessable_entity } 52 | end 53 | end 54 | end 55 | 56 | # PUT /posts/1 57 | # PUT /posts/1.json 58 | def update 59 | @post = Post.find(params[:id]) 60 | 61 | respond_to do |format| 62 | if @post.update_attributes(post_params) 63 | format.html { redirect_to @post, notice: 'Post was successfully updated.' } 64 | format.json { head :no_content } 65 | else 66 | format.html { render action: "edit" } 67 | format.json { render json: @post.errors, status: :unprocessable_entity } 68 | end 69 | end 70 | end 71 | 72 | # DELETE /posts/1 73 | # DELETE /posts/1.json 74 | def destroy 75 | @post = Post.find(params[:id]) 76 | @post.destroy 77 | 78 | respond_to do |format| 79 | format.html { redirect_to posts_url } 80 | format.json { head :no_content } 81 | end 82 | end 83 | 84 | private 85 | 86 | def post_params 87 | params.require(:post).permit(:title) 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /spec/example_app/app/controllers/sessions_controller.rb: -------------------------------------------------------------------------------- 1 | class SessionsController < ApplicationController 2 | def create 3 | session[:user_id] = User.find_by_name(params[:name]).id 4 | redirect_to root_path 5 | end 6 | 7 | def destroy 8 | session[:user_id] = nil 9 | redirect_to root_path 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /spec/example_app/app/controllers/users_controller.rb: -------------------------------------------------------------------------------- 1 | class UsersController < ApplicationController 2 | # GET /users 3 | # GET /users.json 4 | def index 5 | @users = User.all 6 | 7 | respond_to do |format| 8 | format.html # index.html.erb 9 | format.json { render json: @users } 10 | end 11 | end 12 | 13 | # GET /users/1 14 | # GET /users/1.json 15 | def show 16 | @user = User.find(params[:id]) 17 | 18 | respond_to do |format| 19 | format.html # show.html.erb 20 | format.json { render json: @user } 21 | end 22 | end 23 | 24 | # GET /users/new 25 | # GET /users/new.json 26 | def new 27 | @user = User.new 28 | 29 | respond_to do |format| 30 | format.html # new.html.erb 31 | format.json { render json: @user } 32 | end 33 | end 34 | 35 | # GET /users/1/edit 36 | def edit 37 | @user = User.find(params[:id]) 38 | end 39 | 40 | # POST /users 41 | # POST /users.json 42 | def create 43 | @user = User.new(user_params) 44 | 45 | respond_to do |format| 46 | if @user.save 47 | format.html { redirect_to @user, notice: 'User was successfully created.' } 48 | format.json { render json: @user, status: :created, location: @user } 49 | else 50 | format.html { render action: "new" } 51 | format.json { render json: @user.errors, status: :unprocessable_entity } 52 | end 53 | end 54 | end 55 | 56 | # PUT /users/1 57 | # PUT /users/1.json 58 | def update 59 | @user = User.find(params[:id]) 60 | 61 | respond_to do |format| 62 | if @user.update_attributes(user_params) 63 | format.html { redirect_to @user, notice: 'User was successfully updated.' } 64 | format.json { head :no_content } 65 | else 66 | format.html { render action: "edit" } 67 | format.json { render json: @user.errors, status: :unprocessable_entity } 68 | end 69 | end 70 | end 71 | 72 | # DELETE /users/1 73 | # DELETE /users/1.json 74 | def destroy 75 | @user = User.find(params[:id]) 76 | @user.destroy 77 | 78 | respond_to do |format| 79 | format.html { redirect_to users_url } 80 | format.json { head :no_content } 81 | end 82 | end 83 | 84 | private 85 | 86 | def user_params 87 | params.require(:user).permit(:name) 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /spec/example_app/app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /spec/example_app/app/helpers/posts_helper.rb: -------------------------------------------------------------------------------- 1 | module PostsHelper 2 | end 3 | -------------------------------------------------------------------------------- /spec/example_app/app/helpers/users_helper.rb: -------------------------------------------------------------------------------- 1 | module UsersHelper 2 | end 3 | -------------------------------------------------------------------------------- /spec/example_app/app/mailers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balvig/chili/3a5e24b1d8b4e731cb1a589a9ae276799549b126/spec/example_app/app/mailers/.gitkeep -------------------------------------------------------------------------------- /spec/example_app/app/models/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balvig/chili/3a5e24b1d8b4e731cb1a589a9ae276799549b126/spec/example_app/app/models/.gitkeep -------------------------------------------------------------------------------- /spec/example_app/app/models/post.rb: -------------------------------------------------------------------------------- 1 | class Post < ActiveRecord::Base 2 | end 3 | -------------------------------------------------------------------------------- /spec/example_app/app/models/user.rb: -------------------------------------------------------------------------------- 1 | class User < ActiveRecord::Base 2 | end 3 | -------------------------------------------------------------------------------- /spec/example_app/app/overrides/posts/index/spree.html.erb.deface: -------------------------------------------------------------------------------- 1 | 2 |

Permanent spree override

3 | -------------------------------------------------------------------------------- /spec/example_app/app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dummy 5 | <%= stylesheet_link_tag "application", :media => "all" %> 6 | <%= javascript_include_tag "application", '//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js', 'https://raw.github.com/rails/jquery-ujs/master/src/rails.js' %> 7 | <%= csrf_meta_tags %> 8 | 9 | 10 | 11 |
12 | <% if logged_in? %> 13 | Hi <%= current_user.name %>. <%= button_to 'Log out', main_app.session_path, method: 'delete' %> 14 | <% else %> 15 | <%= link_to "Log in", main_app.new_session_path %> 16 | <% end %> 17 |
18 | 19 |
20 | <%= yield %> 21 |
22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /spec/example_app/app/views/posts/_form.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for(@post) do |f| %> 2 | <% if @post.errors.any? %> 3 |
4 |

<%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:

5 | 6 | 11 |
12 | <% end %> 13 | 14 |
15 | <%= f.label :title %>
16 | <%= f.text_field :title %> 17 |
18 |
19 | <%= f.submit %> 20 |
21 | <% end %> 22 | -------------------------------------------------------------------------------- /spec/example_app/app/views/posts/_post.html.erb: -------------------------------------------------------------------------------- 1 | 2 | <%= post.title %> 3 | 4 | -------------------------------------------------------------------------------- /spec/example_app/app/views/posts/edit.html.erb: -------------------------------------------------------------------------------- 1 |

Editing post

2 | 3 | <%= render 'form' %> 4 | 5 | <%= link_to 'Show', @post %> | 6 | <%= link_to 'Back', posts_path %> 7 | -------------------------------------------------------------------------------- /spec/example_app/app/views/posts/index.html.erb: -------------------------------------------------------------------------------- 1 |

Listing posts

2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= render @posts %> 9 |
Title
10 | 11 |
12 | 13 | <%= link_to 'New Post', new_post_path %> 14 | -------------------------------------------------------------------------------- /spec/example_app/app/views/posts/new.html.erb: -------------------------------------------------------------------------------- 1 |

New post

2 | 3 | <%= render 'form' %> 4 | 5 | <%= link_to 'Back', posts_path %> 6 | -------------------------------------------------------------------------------- /spec/example_app/app/views/posts/show.html.erb: -------------------------------------------------------------------------------- 1 |

<%= notice %>

2 | 3 |

4 | Title: 5 | <%= @post.title %> 6 |

7 | 8 | 9 | <%= link_to 'Edit', edit_post_path(@post) %> | 10 | <%= link_to 'Back', posts_path %> 11 | -------------------------------------------------------------------------------- /spec/example_app/app/views/sessions/new.html.erb: -------------------------------------------------------------------------------- 1 |

Input name

2 | <%= form_tag session_path do %> 3 | <%= text_field_tag :name %> 4 | <%= submit_tag 'Log in' %> 5 | <% end %> 6 | -------------------------------------------------------------------------------- /spec/example_app/app/views/users/_form.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for(@user) do |f| %> 2 | <% if @user.errors.any? %> 3 |
4 |

<%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:

5 | 6 | 11 |
12 | <% end %> 13 | 14 |
15 | <%= f.label :name %>
16 | <%= f.text_field :name %> 17 |
18 |
19 | <%= f.submit %> 20 |
21 | <% end %> 22 | -------------------------------------------------------------------------------- /spec/example_app/app/views/users/edit.html.erb: -------------------------------------------------------------------------------- 1 |

Editing user

2 | 3 | <%= render 'form' %> 4 | 5 | <%= link_to 'Show', @user %> | 6 | <%= link_to 'Back', users_path %> 7 | -------------------------------------------------------------------------------- /spec/example_app/app/views/users/index.html.erb: -------------------------------------------------------------------------------- 1 |

Listing users

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | <% @users.each do |user| %> 12 | 13 | 14 | 15 | 16 | 17 | 18 | <% end %> 19 |
Name
<%= user.name %><%= link_to 'Show', user %><%= link_to 'Edit', edit_user_path(user) %><%= link_to 'Destroy', user, confirm: 'Are you sure?', method: :delete %>
20 | 21 |
22 | 23 | <%= link_to 'New User', new_user_path %> 24 | -------------------------------------------------------------------------------- /spec/example_app/app/views/users/new.html.erb: -------------------------------------------------------------------------------- 1 |

New user

2 | 3 | <%= render 'form' %> 4 | 5 | <%= link_to 'Back', users_path %> 6 | -------------------------------------------------------------------------------- /spec/example_app/app/views/users/show.html.erb: -------------------------------------------------------------------------------- 1 |

<%= notice %>

2 | 3 |

4 | Name: 5 | <%= @user.name %> 6 |

7 | 8 | 9 | <%= link_to 'Edit', edit_user_path(@user) %> | 10 | <%= link_to 'Back', users_path %> 11 | -------------------------------------------------------------------------------- /spec/example_app/config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require ::File.expand_path('../config/environment', __FILE__) 4 | run Dummy::Application 5 | -------------------------------------------------------------------------------- /spec/example_app/config/application.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../boot', __FILE__) 2 | 3 | require 'rails/all' 4 | 5 | # Require the gems listed in Gemfile, including any gems 6 | # you've limited to :test, :development, or :production. 7 | Bundler.require(:default, Rails.env) 8 | require "chili" 9 | require "social_feature" 10 | require "invites_feature" 11 | 12 | module Dummy 13 | class Application < Rails::Application 14 | # Settings in config/environments/* take precedence over those specified here. 15 | # Application configuration should go into files in config/initializers 16 | # -- all .rb files in that directory are automatically loaded. 17 | 18 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. 19 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. 20 | # config.time_zone = 'Central Time (US & Canada)' 21 | 22 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. 23 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] 24 | # config.i18n.default_locale = :de 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /spec/example_app/config/boot.rb: -------------------------------------------------------------------------------- 1 | # Set up gems listed in the Gemfile. 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../../Gemfile', __FILE__) 3 | 4 | require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) 5 | $:.unshift File.expand_path('../../../../../lib', __FILE__) 6 | $:.unshift File.expand_path('../../lib/chili/social_feature/lib', __FILE__) 7 | $:.unshift File.expand_path('../../lib/chili/invites_feature/lib', __FILE__) 8 | -------------------------------------------------------------------------------- /spec/example_app/config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite version 3.x 2 | # gem install sqlite3 3 | # 4 | # Ensure the SQLite 3 gem is defined in your Gemfile 5 | # gem 'sqlite3' 6 | development: 7 | adapter: sqlite3 8 | database: db/development.sqlite3 9 | pool: 5 10 | timeout: 5000 11 | 12 | # Warning: The database defined as "test" will be erased and 13 | # re-generated from your development database when you run "rake". 14 | # Do not set this db to the same as development or production. 15 | test: 16 | adapter: sqlite3 17 | database: db/test.sqlite3 18 | pool: 5 19 | timeout: 5000 20 | 21 | production: 22 | adapter: sqlite3 23 | database: db/production.sqlite3 24 | pool: 5 25 | timeout: 5000 26 | -------------------------------------------------------------------------------- /spec/example_app/config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require File.expand_path('../application', __FILE__) 3 | 4 | # Initialize the Rails application. 5 | Dummy::Application.initialize! 6 | -------------------------------------------------------------------------------- /spec/example_app/config/environments/development.rb: -------------------------------------------------------------------------------- 1 | Dummy::Application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # In the development environment your application's code is reloaded on 5 | # every request. This slows down response time but is perfect for development 6 | # since you don't have to restart the web server when you make code changes. 7 | config.cache_classes = false 8 | 9 | # Do not eager load code on boot. 10 | config.eager_load = false 11 | 12 | # Show full error reports and disable caching. 13 | config.consider_all_requests_local = true 14 | config.action_controller.perform_caching = false 15 | 16 | # Don't care if the mailer can't send. 17 | config.action_mailer.raise_delivery_errors = false 18 | 19 | # Print deprecation notices to the Rails logger. 20 | config.active_support.deprecation = :log 21 | 22 | # Raise an error on page load if there are pending migrations 23 | config.active_record.migration_error = :page_load 24 | 25 | # Debug mode disables concatenation and preprocessing of assets. 26 | # This option may cause significant delays in view rendering with a large 27 | # number of complex assets. 28 | config.assets.debug = true 29 | end 30 | -------------------------------------------------------------------------------- /spec/example_app/config/environments/production.rb: -------------------------------------------------------------------------------- 1 | Dummy::Application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # Code is not reloaded between requests. 5 | config.cache_classes = true 6 | 7 | # Eager load code on boot. This eager loads most of Rails and 8 | # your application in memory, allowing both thread web servers 9 | # and those relying on copy on write to perform better. 10 | # Rake tasks automatically ignore this option for performance. 11 | config.eager_load = true 12 | 13 | # Full error reports are disabled and caching is turned on. 14 | config.consider_all_requests_local = false 15 | config.action_controller.perform_caching = true 16 | 17 | # Enable Rack::Cache to put a simple HTTP cache in front of your application 18 | # Add `rack-cache` to your Gemfile before enabling this. 19 | # For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid. 20 | # config.action_dispatch.rack_cache = true 21 | 22 | # Disable Rails's static asset server (Apache or nginx will already do this). 23 | config.serve_static_assets = false 24 | 25 | # Compress JavaScripts and CSS. 26 | config.assets.js_compressor = :uglifier 27 | # config.assets.css_compressor = :sass 28 | 29 | # Do not fallback to assets pipeline if a precompiled asset is missed. 30 | config.assets.compile = false 31 | 32 | # Generate digests for assets URLs. 33 | config.assets.digest = true 34 | 35 | # Version of your assets, change this if you want to expire all your assets. 36 | config.assets.version = '1.0' 37 | 38 | # Specifies the header that your server uses for sending files. 39 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache 40 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx 41 | 42 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 43 | # config.force_ssl = true 44 | 45 | # Set to :debug to see everything in the log. 46 | config.log_level = :info 47 | 48 | # Prepend all log lines with the following tags. 49 | # config.log_tags = [ :subdomain, :uuid ] 50 | 51 | # Use a different logger for distributed setups. 52 | # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) 53 | 54 | # Use a different cache store in production. 55 | # config.cache_store = :mem_cache_store 56 | 57 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 58 | # config.action_controller.asset_host = "http://assets.example.com" 59 | 60 | # Precompile additional assets. 61 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. 62 | # config.assets.precompile += %w( search.js ) 63 | 64 | # Ignore bad email addresses and do not raise email delivery errors. 65 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 66 | # config.action_mailer.raise_delivery_errors = false 67 | 68 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 69 | # the I18n.default_locale when a translation can not be found). 70 | config.i18n.fallbacks = true 71 | 72 | # Send deprecation notices to registered listeners. 73 | config.active_support.deprecation = :notify 74 | 75 | # Disable automatic flushing of the log to improve performance. 76 | # config.autoflush_log = false 77 | 78 | # Use default logging formatter so that PID and timestamp are not suppressed. 79 | config.log_formatter = ::Logger::Formatter.new 80 | end 81 | -------------------------------------------------------------------------------- /spec/example_app/config/environments/test.rb: -------------------------------------------------------------------------------- 1 | Dummy::Application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # The test environment is used exclusively to run your application's 5 | # test suite. You never need to work with it otherwise. Remember that 6 | # your test database is "scratch space" for the test suite and is wiped 7 | # and recreated between test runs. Don't rely on the data there! 8 | config.cache_classes = true 9 | 10 | # Do not eager load code on boot. This avoids loading your whole application 11 | # just for the purpose of running a single test. If you are using a tool that 12 | # preloads Rails for running tests, you may have to set it to true. 13 | config.eager_load = false 14 | 15 | # Configure static asset server for tests with Cache-Control for performance. 16 | config.serve_static_assets = true 17 | config.static_cache_control = "public, max-age=3600" 18 | 19 | # Show full error reports and disable caching. 20 | config.consider_all_requests_local = true 21 | config.action_controller.perform_caching = false 22 | 23 | # Raise exceptions instead of rendering exception templates. 24 | config.action_dispatch.show_exceptions = false 25 | 26 | # Disable request forgery protection in test environment. 27 | config.action_controller.allow_forgery_protection = false 28 | 29 | # Tell Action Mailer not to deliver emails to the real world. 30 | # The :test delivery method accumulates sent emails in the 31 | # ActionMailer::Base.deliveries array. 32 | config.action_mailer.delivery_method = :test 33 | 34 | # Print deprecation notices to the stderr. 35 | config.active_support.deprecation = :stderr 36 | end 37 | -------------------------------------------------------------------------------- /spec/example_app/config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /spec/example_app/config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /spec/example_app/config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /spec/example_app/config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | # Mime::Type.register_alias "text/html", :iphone 6 | -------------------------------------------------------------------------------- /spec/example_app/config/initializers/secret_token.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Your secret key is used for verifying the integrity of signed cookies. 4 | # If you change this key, all old signed cookies will become invalid! 5 | 6 | # Make sure the secret is at least 30 characters and all random, 7 | # no regular words or you'll be exposed to dictionary attacks. 8 | # You can use `rake secret` to generate a secure secret key. 9 | 10 | # Make sure your secret_key_base is kept private 11 | # if you're sharing your code publicly. 12 | Dummy::Application.config.secret_key_base = '2a0617151da19d2aabb8ffe843d6c90ad2d4d9482f4291ec42ae5e60cd01210defd77db787cc47cc4d5997da47b3f40156fcc298b7b4caabd076b63e3e0aa26c' 13 | -------------------------------------------------------------------------------- /spec/example_app/config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Dummy::Application.config.session_store :cookie_store, key: '_dummy_session' 4 | -------------------------------------------------------------------------------- /spec/example_app/config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] if respond_to?(:wrap_parameters) 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /spec/example_app/config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # To learn more, please read the Rails Internationalization guide 20 | # available at http://guides.rubyonrails.org/i18n.html. 21 | 22 | en: 23 | hello: "Hello world" 24 | -------------------------------------------------------------------------------- /spec/example_app/config/routes.rb: -------------------------------------------------------------------------------- 1 | Dummy::Application.routes.draw do 2 | resources :users, :posts 3 | resource :session 4 | root to: 'posts#index' 5 | end 6 | -------------------------------------------------------------------------------- /spec/example_app/db/migrate/20120513023816_create_posts.rb: -------------------------------------------------------------------------------- 1 | class CreatePosts < ActiveRecord::Migration 2 | def change 3 | create_table :posts do |t| 4 | t.string :title 5 | 6 | t.timestamps 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/example_app/db/migrate/20120513023840_create_users.rb: -------------------------------------------------------------------------------- 1 | class CreateUsers < ActiveRecord::Migration 2 | def change 3 | create_table :users do |t| 4 | t.string :name, default: 'Bob' 5 | t.boolean :admin 6 | t.timestamps 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/example_app/db/migrate/20120513032032_create_social_feature_likes.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from social_feature (originally 20120513031021) 2 | class CreateSocialFeatureLikes < ActiveRecord::Migration 3 | def change 4 | create_table :social_feature_likes do |t| 5 | t.integer :post_id 6 | t.integer :user_id 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /spec/example_app/db/schema.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | # This file is auto-generated from the current state of the database. Instead 3 | # of editing this file, please use the migrations feature of Active Record to 4 | # incrementally modify your database, and then regenerate this schema definition. 5 | # 6 | # Note that this schema.rb definition is the authoritative source for your 7 | # database schema. If you need to create the application database on another 8 | # system, you should be using db:schema:load, not running all the migrations 9 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations 10 | # you'll amass, the slower it'll run and the greater likelihood for issues). 11 | # 12 | # It's strongly recommended to check this file into your version control system. 13 | 14 | ActiveRecord::Schema.define(:version => 20120513032032) do 15 | 16 | create_table "posts", :force => true do |t| 17 | t.string "title" 18 | t.datetime "created_at", :null => false 19 | t.datetime "updated_at", :null => false 20 | end 21 | 22 | create_table "social_feature_likes", :force => true do |t| 23 | t.integer "post_id" 24 | t.integer "user_id" 25 | t.datetime "created_at", :null => false 26 | t.datetime "updated_at", :null => false 27 | end 28 | 29 | create_table "users", :force => true do |t| 30 | t.string "name", :default => "Bob" 31 | t.boolean "admin" 32 | t.datetime "created_at", :null => false 33 | t.datetime "updated_at", :null => false 34 | end 35 | 36 | end 37 | -------------------------------------------------------------------------------- /spec/example_app/lib/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balvig/chili/3a5e24b1d8b4e731cb1a589a9ae276799549b126/spec/example_app/lib/assets/.gitkeep -------------------------------------------------------------------------------- /spec/example_app/lib/chili/invites_feature/.gitignore: -------------------------------------------------------------------------------- 1 | .bundle/ 2 | log/*.log 3 | pkg/ 4 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/invites_feature/app/assets/images/invites_feature/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balvig/chili/3a5e24b1d8b4e731cb1a589a9ae276799549b126/spec/example_app/lib/chili/invites_feature/app/assets/images/invites_feature/.gitkeep -------------------------------------------------------------------------------- /spec/example_app/lib/chili/invites_feature/app/assets/javascripts/invites_feature/application.js: -------------------------------------------------------------------------------- 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 vendor/assets/javascripts of plugins, if any, 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 | // the compiled file. 9 | // 10 | // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD 11 | // GO AFTER THE REQUIRES BELOW. 12 | // 13 | //= require_tree . 14 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/invites_feature/app/assets/stylesheets/invites_feature/application.css: -------------------------------------------------------------------------------- 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 vendor/assets/stylesheets of plugins, if any, 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 top of the 9 | * compiled file, but it's generally better to create a new file per style scope. 10 | * 11 | *= require_self 12 | *= require_tree . 13 | */ 14 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/invites_feature/app/controllers/invites_feature/application_controller.rb: -------------------------------------------------------------------------------- 1 | module InvitesFeature 2 | class ApplicationController < Chili::ApplicationController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/invites_feature/app/overrides/posts/index/disclaimer.html.erb.deface: -------------------------------------------------------------------------------- 1 | 2 |

Invite functionality is also in beta

3 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/invites_feature/config/routes.rb: -------------------------------------------------------------------------------- 1 | InvitesFeature::Engine.automount! 2 | InvitesFeature::Engine.routes.draw do 3 | end 4 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/invites_feature/lib/generators/invites_feature_generator.rb: -------------------------------------------------------------------------------- 1 | class InvitesFeatureGenerator < Rails::Generators::Base 2 | include Chili::GeneratorProxy 3 | end 4 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/invites_feature/lib/invites_feature.rb: -------------------------------------------------------------------------------- 1 | require "chili" 2 | require "invites_feature/engine" 3 | 4 | module InvitesFeature 5 | extend Chili::Base 6 | active_if { logged_in? } 7 | end 8 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/invites_feature/lib/invites_feature/engine.rb: -------------------------------------------------------------------------------- 1 | module InvitesFeature 2 | class Engine < ::Rails::Engine 3 | isolate_namespace InvitesFeature 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/social_feature/app/assets/images/social_feature/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balvig/chili/3a5e24b1d8b4e731cb1a589a9ae276799549b126/spec/example_app/lib/chili/social_feature/app/assets/images/social_feature/.gitkeep -------------------------------------------------------------------------------- /spec/example_app/lib/chili/social_feature/app/assets/javascripts/social_feature/application.js: -------------------------------------------------------------------------------- 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 vendor/assets/javascripts of plugins, if any, 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 | // the compiled file. 9 | // 10 | // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD 11 | // GO AFTER THE REQUIRES BELOW. 12 | // 13 | //= require_tree . 14 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/social_feature/app/assets/stylesheets/social_feature/application.css.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balvig/chili/3a5e24b1d8b4e731cb1a589a9ae276799549b126/spec/example_app/lib/chili/social_feature/app/assets/stylesheets/social_feature/application.css.scss -------------------------------------------------------------------------------- /spec/example_app/lib/chili/social_feature/app/controllers/social_feature/application_controller.rb: -------------------------------------------------------------------------------- 1 | module SocialFeature 2 | class ApplicationController < Chili::ApplicationController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/social_feature/app/controllers/social_feature/likes_controller.rb: -------------------------------------------------------------------------------- 1 | module SocialFeature 2 | class LikesController < ApplicationController 3 | 4 | def index 5 | @likes = current_user.likes 6 | end 7 | 8 | def create 9 | @like = current_user.likes.create!(params[:like]) 10 | redirect_to :back, notice: 'Post liked!' 11 | end 12 | 13 | private 14 | 15 | def current_user 16 | super.becomes(SocialFeature::User) 17 | end 18 | 19 | def like_params 20 | params.require(:like).permit(:post_id) 21 | end 22 | 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/social_feature/app/models/social_feature/like.rb: -------------------------------------------------------------------------------- 1 | module SocialFeature 2 | class Like < ActiveRecord::Base 3 | belongs_to :post 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/social_feature/app/models/social_feature/post.rb: -------------------------------------------------------------------------------- 1 | module SocialFeature 2 | class Post < ::Post 3 | has_many :likes 4 | 5 | def well_liked? 6 | likes.size >= 3 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/social_feature/app/models/social_feature/user.rb: -------------------------------------------------------------------------------- 1 | module SocialFeature 2 | class User < ::User 3 | has_many :likes 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/social_feature/app/overrides/layouts/application/likes_link.html.erb.deface: -------------------------------------------------------------------------------- 1 | 2 | <%= link_to 'See Your Likes', social_feature.likes_path %> 3 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/social_feature/app/overrides/posts/_post/like_actions.html.erb.deface: -------------------------------------------------------------------------------- 1 | 2 | <% post.becomes(SocialFeature::Post).tap do |post| %> 3 | <%= link_to 'Like!', social_feature.likes_path(like: {post_id: post}), method: :post %> 4 | <%= pluralize post.likes.size, 'like' %> 5 | <%= post.well_liked? ? 'This post is well liked!' : 'This post is boring...' %> 6 | <% end %> 7 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/social_feature/app/overrides/posts/index/disclaimer.html.erb.deface: -------------------------------------------------------------------------------- 1 | 2 |

Like functionality is in beta

3 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/social_feature/app/overrides/posts/index/table_headers.html.erb.deface: -------------------------------------------------------------------------------- 1 | 2 | Popularity (beta) 3 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/social_feature/app/views/social_feature/likes/index.html.erb: -------------------------------------------------------------------------------- 1 |

Your Likes

2 | 3 | 8 | 9 | <%= link_to 'Go Back', main_app.posts_path %> 10 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/social_feature/config/routes.rb: -------------------------------------------------------------------------------- 1 | SocialFeature::Engine.automount! 2 | SocialFeature::Engine.routes.draw do 3 | resources :likes 4 | end 5 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/social_feature/db/migrate/20120513031021_create_social_feature_likes.rb: -------------------------------------------------------------------------------- 1 | class CreateSocialFeatureLikes < ActiveRecord::Migration 2 | def change 3 | create_table :social_feature_likes do |t| 4 | t.integer :post_id 5 | t.integer :user_id 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/social_feature/lib/generators/social_feature_generator.rb: -------------------------------------------------------------------------------- 1 | class SocialFeatureGenerator < Rails::Generators::Base 2 | include Chili::GeneratorProxy 3 | end 4 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/social_feature/lib/social_feature.rb: -------------------------------------------------------------------------------- 1 | require "chili" 2 | require "social_feature/engine" 3 | 4 | module SocialFeature 5 | extend Chili::Base 6 | active_if { logged_in? && current_user.admin? } 7 | end 8 | -------------------------------------------------------------------------------- /spec/example_app/lib/chili/social_feature/lib/social_feature/engine.rb: -------------------------------------------------------------------------------- 1 | module SocialFeature 2 | class Engine < ::Rails::Engine 3 | isolate_namespace SocialFeature 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/example_app/log/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balvig/chili/3a5e24b1d8b4e731cb1a589a9ae276799549b126/spec/example_app/log/.gitkeep -------------------------------------------------------------------------------- /spec/example_app/public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 17 | 18 | 19 | 20 | 21 |
22 |

The page you were looking for doesn't exist.

23 |

You may have mistyped the address or the page may have moved.

24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /spec/example_app/public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 17 | 18 | 19 | 20 | 21 |
22 |

The change you wanted was rejected.

23 |

Maybe you tried to change something you didn't have access to.

24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /spec/example_app/public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 17 | 18 | 19 | 20 | 21 |
22 |

We're sorry, but something went wrong.

23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /spec/example_app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balvig/chili/3a5e24b1d8b4e731cb1a589a9ae276799549b126/spec/example_app/public/favicon.ico -------------------------------------------------------------------------------- /spec/example_app/script/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. 3 | 4 | APP_PATH = File.expand_path('../../config/application', __FILE__) 5 | require File.expand_path('../../config/boot', __FILE__) 6 | require 'rails/commands' 7 | -------------------------------------------------------------------------------- /spec/example_app/spec/support/user_macros.rb: -------------------------------------------------------------------------------- 1 | module UserMacros 2 | def login(user) 3 | visit new_session_path 4 | fill_in 'name', with: user.name 5 | click_button 'Log in' 6 | end 7 | end 8 | RSpec.configure { |config| config.include(UserMacros) } 9 | -------------------------------------------------------------------------------- /spec/features/social_feature_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | feature 'View overrides' do 4 | scenario 'when user is not admin active_if toggles overrides off' do 5 | login User.create!(admin: false) 6 | visit '/posts' 7 | page.should_not have_content('See Your Likes') 8 | page.should_not have_content('Like functionality is in beta') 9 | end 10 | 11 | scenario 'when admin active_if toggles overrides on' do 12 | login User.create!(admin: true) 13 | visit '/posts' 14 | page.should have_content('See Your Likes') 15 | end 16 | end 17 | 18 | feature 'Togglable controllers' do 19 | scenario 'when user is not admin active_if hides controllers in feature' do 20 | login User.create!(admin: false) 21 | visit '/chili/social_feature/likes' 22 | #expect { visit('/chili/social_feature/likes') }.to raise_error(ActionController::RoutingError) 23 | end 24 | 25 | scenario 'when admin active_if makes controllers available' do 26 | login User.create!(admin: true) 27 | visit '/chili/social_feature/likes' 28 | page.should have_content('Your Likes') 29 | end 30 | end 31 | 32 | feature 'Multiple chili features' do 33 | scenario 'multiple overrides do not redefine each other' do 34 | login User.create!(admin: true) 35 | visit '/posts' 36 | page.should have_content('Like functionality is in beta') 37 | page.should have_content('Invite functionality is also in beta') 38 | end 39 | 40 | scenario 'Chili works alongside permanent spree overrides' do 41 | visit '/posts' 42 | page.should have_content('Permanent spree override') 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /spec/generators/chili/feature_generator_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'FeatureGenerator' do 4 | describe 'rails g chili:feature NAME' do 5 | let(:app) { DummyApp.new } 6 | let(:template_path) { File.expand_path("../../../dummy/blank_feature", __FILE__) } 7 | 8 | before { app.setup! } 9 | 10 | it 'creates a new feature with a correct file structure and appends it to the gemfile' do 11 | puts `cd #{app.path} && rails g chili:feature blank` 12 | 13 | Dir.glob(File.join(template_path, "**/*")).reject { |f| File.directory?(f) }.each do |template| 14 | result = File.join(app.path, 'lib/chili/blank_feature', template.sub(template_path, '')) 15 | result_text = File.open(result, 'rb').read 16 | template_text = File.open(template, 'rb').read 17 | template_text.sub!('GIT_AUTHOR',`git config user.name`.chomp) # Git author is different on each machine 18 | template_text.sub!('GIT_EMAIL',`git config user.email`.chomp) # Git email is different on each machine 19 | result_text.should == template_text 20 | end 21 | end 22 | 23 | it "appends new features to the chili group within the gemfile" do 24 | puts `cd #{app.path} && rails g chili:feature blank` 25 | File.open(app.gemfile, 'rb').read.should include <<-RUBY.chomp 26 | group :chili do 27 | gem 'blank_feature', path: 'lib/chili/blank_feature' 28 | end 29 | RUBY 30 | 31 | puts `cd #{app.path} && rails g chili:feature another_blank` 32 | File.open(app.gemfile, 'rb').read.should include <<-RUBY.chomp 33 | group :chili do 34 | gem 'another_blank_feature', path: 'lib/chili/another_blank_feature' 35 | gem 'blank_feature', path: 'lib/chili/blank_feature' 36 | end 37 | RUBY 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /spec/generators/chili/generator_proxy_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Chili::GeneratorProxy do 4 | let(:app) { DummyApp.new } 5 | 6 | before do 7 | app.setup! 8 | puts `cd #{app.path} && rails g chili:feature blank` 9 | end 10 | 11 | 12 | context 'running generator from a newly created feature' do 13 | it "generates resources properly" do 14 | puts `cd #{app.path} && rails g blank_feature scaffold post` 15 | File.exist?(File.join(app.path, 'lib/chili/blank_feature/app/controllers/blank_feature/posts_controller.rb')).should be_true 16 | File.exist?(File.join(app.path, 'lib/chili/blank_feature/app/assets/stylesheets/blank_feature/posts.css')).should be_true 17 | end 18 | end 19 | 20 | context 'running deface override generator' do 21 | it "generates namespaced override properly" do 22 | puts `cd #{app.path} && rails g blank_feature deface:override posts/index add_links` 23 | File.exist?(File.join(app.path, 'lib/chili/blank_feature/app/overrides/posts/index/add_links.html.erb.deface')).should be_true 24 | end 25 | end 26 | 27 | context 'passing in options' do 28 | it "passes options on to rails generator" do 29 | puts `cd #{app.path} && rails g blank_feature scaffold post --stylesheets=false` 30 | File.exist?(File.join(app.path, 'lib/chili/blank_feature/app/controllers/blank_feature/posts_controller.rb')).should be_true 31 | File.exist?(File.join(app.path, 'lib/chili/blank_feature/app/assets/stylesheets/blank_feature/posts.css')).should be_false 32 | end 33 | end 34 | 35 | end 36 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # This file is copied to spec/ when you run 'rails generate rspec:install' 2 | ENV["RAILS_ENV"] ||= 'test' 3 | require File.expand_path("../example_app/config/environment", __FILE__) 4 | require 'rspec/rails' 5 | 6 | # Requires supporting ruby files with custom matchers and macros, etc, 7 | # in spec/support/ and its subdirectories. 8 | Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} 9 | Dir[File.join(File.dirname(__FILE__),'support', '**', '*.rb')].each {|f| require f} 10 | 11 | RSpec.configure do |config| 12 | # == Mock Framework 13 | # 14 | # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: 15 | # 16 | # config.mock_with :mocha 17 | # config.mock_with :flexmock 18 | # config.mock_with :rr 19 | 20 | # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures 21 | config.fixture_path = "#{::Rails.root}/spec/fixtures" 22 | 23 | # If you're not using ActiveRecord, or you'd prefer not to run each of your 24 | # examples within a transaction, remove the following line or assign false 25 | # instead of true. 26 | config.use_transactional_fixtures = true 27 | end 28 | -------------------------------------------------------------------------------- /spec/support/dummy_app.rb: -------------------------------------------------------------------------------- 1 | class DummyApp 2 | def path 3 | File.expand_path("../../dummy/app", __FILE__) 4 | end 5 | 6 | def gemfile 7 | File.join(path, 'Gemfile') 8 | end 9 | 10 | def setup! 11 | FileUtils.rm_rf File.join(path, 'lib') 12 | FileUtils.rm_rf gemfile 13 | File.open(gemfile, 'w') do |f| 14 | f.write <<-RUBY 15 | group :development do 16 | gem 'somegem' 17 | end 18 | RUBY 19 | end 20 | end 21 | end 22 | --------------------------------------------------------------------------------