kitestrings 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +38 -0
  7. data/Rakefile +10 -0
  8. data/kitestrings.gemspec +28 -0
  9. data/lib/array_validator.rb +22 -0
  10. data/lib/async.rb +26 -0
  11. data/lib/form_object.rb +96 -0
  12. data/lib/generators/kitestrings/install_generator.rb +41 -0
  13. data/lib/generators/kitestrings/messages_generator.rb +11 -0
  14. data/lib/generators/kitestrings/templates/message.rb.erb +56 -0
  15. data/lib/generators/templates/deploy.rb +136 -0
  16. data/lib/generators/templates/deploy/integ.rb +21 -0
  17. data/lib/generators/templates/deploy/production.rb +26 -0
  18. data/lib/generators/templates/deploy/uat.rb +23 -0
  19. data/lib/generators/templates/haml/scaffold/_form.html.haml +17 -0
  20. data/lib/generators/templates/haml/scaffold/edit.html.haml +6 -0
  21. data/lib/generators/templates/haml/scaffold/index.html.haml +27 -0
  22. data/lib/generators/templates/haml/scaffold/new.html.haml +6 -0
  23. data/lib/generators/templates/haml/scaffold/show.html.haml +10 -0
  24. data/lib/generators/templates/rails/scaffold_controller/controller.rb +62 -0
  25. data/lib/generators/templates/rspec/helper/helper_spec.rb +17 -0
  26. data/lib/generators/templates/rspec/integration/request.rb +4 -0
  27. data/lib/generators/templates/rspec/model/model_spec.rb +14 -0
  28. data/lib/generators/templates/rspec/scaffold/controller_spec.rb +131 -0
  29. data/lib/generators/templates/rspec/scaffold/routing_spec.rb +18 -0
  30. data/lib/generators/templates/spec_ext/my_ip_spec.rb +7 -0
  31. data/lib/generators/templates/spec_ext/spec_helper_ext.rb +37 -0
  32. data/lib/generators/templates/views/application/_navigation.html.haml +0 -0
  33. data/lib/generators/templates/views/layouts/application.html.haml +23 -0
  34. data/lib/kitestrings.rb +6 -0
  35. data/lib/kitestrings/railtie.rb +15 -0
  36. data/lib/kitestrings/version.rb +3 -0
  37. data/lib/page_and_sort_helper.rb +99 -0
  38. data/lib/size_validator.rb +22 -0
  39. data/lib/tasks/test_prepare_after_migrate.rake +11 -0
  40. data/lib/uniqueness_without_deleted_validator.rb +7 -0
  41. data/spec/lib/array_validator_spec.rb +40 -0
  42. data/spec/lib/async_spec.rb +49 -0
  43. data/spec/lib/generators/kitestrings/install_generator_spec.rb +53 -0
  44. data/spec/lib/generators/kitestrings/messages_generator_spec.rb +19 -0
  45. data/spec/lib/page_and_sort_helper_spec.rb +96 -0
  46. data/spec/lib/size_validator_spec.rb +40 -0
  47. data/spec/spec_helper.rb +17 -0
  48. metadata +181 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c0cfbc92932ce23470326d07836d6ef8ba8d24f6
4
+ data.tar.gz: a2c6b9b841e88fd63910f46bd36f80b7a25a3c3e
5
+ SHA512:
6
+ metadata.gz: afa6ba0918b66edd5d24c2ab9457f0548f95cb842049473cc1413b9d18780be556782a5b0d0c3ca2659a85b1bf74adf6b79af830bcfb044b2f94edf0cfd47237
7
+ data.tar.gz: b4e6825be0f105315cb4108b2259fcc02b2adafc753be9c859ed0445094269185767cd8c1cd0d757625ce729ce9efce0128b523cc3d3bf5eeffc44f5f8ed8cf0
@@ -0,0 +1,23 @@
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
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+ .idea
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in kitestrings.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 ridget
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.
@@ -0,0 +1,38 @@
1
+ # Kitestrings
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'kitestrings'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install kitestrings
18
+
19
+ Once installed run
20
+
21
+ rails g kitestrings:install
22
+
23
+ If installed using our template file, this will already be done for you.
24
+
25
+ ## Contains
26
+
27
+ Our scaffold templates (views, controlller)
28
+
29
+ A rake task which will run `db:test:prepare` after you run a migration and `db:fixtures:load` so your selections are properly
30
+ loaded in the test db.
31
+
32
+ ## Contributing
33
+
34
+ 1. Fork it ( https://github.com/[my-github-username]/kitestrings/fork )
35
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
36
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
37
+ 4. Push to the branch (`git push origin my-new-feature`)
38
+ 5. Create a new Pull Request
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ desc "Run the specs."
6
+ RSpec::Core::RakeTask.new do |t|
7
+ t.pattern = "spec/**/*_spec.rb"
8
+ end
9
+
10
+ task :default => [:spec]
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'kitestrings/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "kitestrings"
8
+ spec.version = Kitestrings::VERSION
9
+ spec.authors = ["ridget"]
10
+ spec.email = ["tom.ridge@tworedkites.com"]
11
+ spec.summary = %q{For all the 2rk goodness}
12
+ spec.description = %q{}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency "rails", ">= 3.2"
22
+ spec.add_runtime_dependency "activemodel", ">= 3.2"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.6"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rspec", "~> 2.14"
27
+ spec.add_development_dependency 'generator_spec'
28
+ end
@@ -0,0 +1,22 @@
1
+ # A validator to validate the length of an array. Only works on values that are arrays. (Not relationships in Rails 4)
2
+ class ArrayValidator < ActiveModel::EachValidator
3
+ # Validate the value is an Array and optionally that the number of items in it is at least a minimum or at most a
4
+ # maximum.
5
+ #
6
+ # Example:
7
+ # validates :address_states, array: {min: 1, min_message: "must have at least 1 State selected"},
8
+ #
9
+ def validate_each(record, attribute, value)
10
+ if value.is_a? Array
11
+ if options[:min].present? && value.size < options[:min]
12
+ record.errors.add attribute, options[:min_message] || "must have at least #{options[:min]} #{'item'.pluralize(options[:min])}"
13
+ end
14
+
15
+ if options[:max].present? && value.size > options[:max]
16
+ record.errors.add attribute, options[:max_message] || "must have at most #{options[:max]} #{'item'.pluralize(options[:max])}"
17
+ end
18
+ else
19
+ record.errors.add attribute, "must be an array"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,26 @@
1
+ require 'active_support'
2
+
3
+ # a module for executing code asynchronously in another thread. This is disabled
4
+ module Async
5
+ mattr_accessor :enabled
6
+
7
+ # Execute the given block in another thread, but only in production. During development, the block executes
8
+ # on the current thread
9
+ # @return [Thread]
10
+ def async
11
+ raise "A block must be provided" unless block_given?
12
+ if Async.enabled
13
+ Thread.new do
14
+ # ensure that this thread uses a new connection to the database and returns it to the pool when done.
15
+ ActiveRecord::Base.connection_pool.with_connection do
16
+ yield
17
+ end
18
+ end
19
+ else
20
+ yield
21
+ Thread.current
22
+ end
23
+ end
24
+ end
25
+
26
+ Async.enabled = false
@@ -0,0 +1,96 @@
1
+ # This module is to help with using Form Objects that are backed by ActiveRecord resources. The goal
2
+ # is to make a from object act like the underlying model class, but with its own set of validations.
3
+ #
4
+ # Note that saving the form object requires validations in the form object to pass *AND* the validations
5
+ # in the underlying model object. Validation errors in the underlying model object will be included in
6
+ # the errors of the form object.
7
+ module FormObject
8
+ extend ActiveSupport::Concern
9
+ include ActiveModel::Model
10
+ include ActiveRecord::AttributeAssignment
11
+ include ActiveRecord::Persistence
12
+
13
+ module ClassMethods
14
+ # Set up the Form Object class to be a form object for a given model.
15
+ #
16
+ # Example:
17
+ #
18
+ # class NewWorkflow
19
+ # include FormObject
20
+ # form_object_for :workflow, :fields => [:name], :class => MyOtherClass
21
+ # ...
22
+ #
23
+ # This creates a :workflow attr method and delegates methods to it for use with form_for.
24
+ def form_object_for(resource_name, options={})
25
+ # create an attribute for the underlying resource name, (eg :workflow) and make an alias method "resource"
26
+ # for the attr reader
27
+ attr resource_name
28
+ alias_method :resource, resource_name
29
+
30
+ # create a class attribute with the model name of the underlying model name so that polymorphic_url will
31
+ # see the form object as if it were an instance of the underlying model object.
32
+ class_attribute :model_name
33
+ klass = options[:class] || resource_name.to_s
34
+ klass = klass.camelize.constantize unless klass.is_a?(Class)
35
+ self.model_name = klass.model_name
36
+
37
+ # delegate the following methods to the underlying model object, also helps polymorphic_url do the right thing
38
+ # for `form_for @form_object`
39
+ methods_to_delegate = [:id, :persisted?, :to_param]
40
+ if options[:fields]
41
+ options[:fields].each do |field|
42
+ methods_to_delegate << "#{field}".to_sym
43
+ methods_to_delegate << "#{field}=".to_sym
44
+ end
45
+ end
46
+ delegate *methods_to_delegate, :to => resource_name
47
+ include DelegateEverything if options[:delegate_everything]
48
+
49
+ # create a default initializer which will set the resource when a single parameter is passed in.
50
+ define_method :initialize do |object=nil|
51
+ instance_variable_set("@#{resource_name}", object)
52
+ end
53
+ end
54
+ end
55
+
56
+ # Validate the form object and if it's valid, call save on the underlying model object. If there are multiple models
57
+ # that need to be saved you will need to reimplement this method.
58
+ def save(*args)
59
+ if valid?
60
+ resource.save
61
+ end
62
+ end
63
+
64
+ # The form object is valid when its validations pass *AND* the underlying model validations pass. If there
65
+ # are errors in the underlying resource, those errors are copied into the errors object for this form object
66
+ # so that they exist in a single place (easy for the form to work with)
67
+ def valid?
68
+ result = [super, resource.valid?].all?
69
+
70
+ # include any errors in the resource object in the +errors+ for this form object. This is useful
71
+ # for uniqueness validation or existing validations in the model class so that they don't need
72
+ # to be duplicated in the form object. (And especially uniqueness validators can only be run in
73
+ # the ActiveRecord::Base model class.
74
+ unless result
75
+ resource.errors.each do |attr, error|
76
+ errors[attr] << error unless errors[attr].include?(error)
77
+ end
78
+ end
79
+
80
+ result
81
+ end
82
+
83
+ module DelegateEverything
84
+ def method_missing(method, *args, &block)
85
+ if resource.respond_to?(method)
86
+ resource.send(method, *args, &block)
87
+ else
88
+ super
89
+ end
90
+ end
91
+
92
+ def respond_to_missing?(method, include_all)
93
+ resource.respond_to?(method, include_all) || super
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,41 @@
1
+ require 'rails'
2
+ require 'rails/generators'
3
+
4
+ module Kitestrings
5
+ module Generators
6
+ class InstallGenerator < ::Rails::Generators::Base
7
+ source_root File.expand_path("../../templates", __FILE__)
8
+
9
+ desc "Copies 2rk relevant templates to the relevant directory"
10
+
11
+ def copy_deploy
12
+ copy_file "deploy.rb", "config/deploy.rb"
13
+ end
14
+
15
+ def copy_deploy_files
16
+ directory "deploy", "config/deploy"
17
+ end
18
+
19
+ def copy_haml_files
20
+ directory "haml", "lib/templates/haml"
21
+ end
22
+
23
+ def copy_scaffold_files
24
+ directory "rails", "lib/templates/rails"
25
+ end
26
+
27
+ def copy_rspec_files
28
+ directory "rspec", "lib/templates/rspec"
29
+ end
30
+
31
+ def copy_spec_ext
32
+ directory "spec_ext", "spec_ext"
33
+ end
34
+
35
+ def copy_app_view_files
36
+ copy_file "views/application/_navigation.html.haml", "app/views/application/_navigation.html.haml"
37
+ copy_file "views/layouts/application.html.haml", "app/views/layouts/application.html.haml"
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,11 @@
1
+ module Kitestrings
2
+ module Generators
3
+ class MessagesGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../templates", __FILE__)
5
+
6
+ def setup_messages_model
7
+ template "message.rb.erb", "app/models/message.rb"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,56 @@
1
+ class Message < ActiveRecord::Base
2
+ include Async
3
+
4
+ DELIVERY_TIMEOUT = 5
5
+
6
+ <%- if Rails.version =~ /^3/ %>
7
+ attr_accessible :clicked_at, :link, :sent_at, :template, :user_id, :user, :options, :context, :subject
8
+
9
+ <% end %>
10
+ serialize :options
11
+
12
+ include Rails.application.routes_url_helpers
13
+
14
+ after_create :send_email
15
+
16
+ ## RELATIONSHIPS
17
+
18
+ belongs_to :context, polymorphic: true
19
+ belongs_to :user
20
+
21
+ ## VALIDATIONS
22
+
23
+ validates :user, presence: true
24
+
25
+ ## SCOPES
26
+
27
+ scope :latest, -> { order('created_at DESC') }
28
+
29
+ ## METHODS
30
+
31
+ def send_email
32
+ async do
33
+ Timeout.timeout DELIVERY_TIMEOUT do
34
+ mail.deliver
35
+
36
+ # always update the sent at, even if the email address is not on the whitelist to simulate what would happen
37
+ self.update_column(:sent_at, Time.now)
38
+ end
39
+ end
40
+ end
41
+
42
+ # prepare a mail object ready for delivery by email or display on the screen
43
+ def mail
44
+ @mail ||= MessageMailer.prepare_message(self, context)
45
+ end
46
+
47
+ # The "view" link. This is the link to the messages controller that marks the message
48
+ # as "clicked" and redirects to the actual link stored in the message record.
49
+ def view_link
50
+ message_url(self, :only_path => false)
51
+ end
52
+
53
+ def name
54
+ "Message ID: #{id}"
55
+ end
56
+ end
@@ -0,0 +1,136 @@
1
+ require 'bundler/capistrano'
2
+ require 'rvm/capistrano'
3
+ require 'capistrano/ext/multistage'
4
+ require 'airbrake/capistrano'
5
+
6
+ set :stages, %w(integ, uat, production)
7
+ set :default_stage, "integ"
8
+ set :application, 'pwi'
9
+ set :user, 'pwi'
10
+ set (:deploy_to) { "/home/#{user}/apps/#{rails_env}" }
11
+ set :deploy_via, :remote_cache
12
+ set :use_sudo, false
13
+ set :scm, 'git'
14
+ #set :repository, 'git@github.com:2rk/pwi.git'
15
+
16
+ set :ssl, false
17
+ # set :ssl_certificates_path, '/home/amt/ssl'
18
+ # set :ssl_certificates_name, 'amt'
19
+
20
+ set :mysql_password, YAML::load_file("config/database.yml.server")["production"]["password"]
21
+ set :bundle_flags, "--deployment"
22
+
23
+ namespace :deploy do
24
+
25
+ task :airbrake_test do
26
+ run "cd #{current_path}; RAILS_ENV=#{stage} bin/rake airbrake:test; true"
27
+ end
28
+
29
+ task :nginx_conf do
30
+ set :nginx_conf_file, "/opt/nginx/conf/servers/#{application}_#{stage}.conf"
31
+
32
+ ssl_conf = <<ssl_conf
33
+ ssl on;
34
+ ssl_certificate #{ssl_certificates_path}/#{ssl_certificates_name}.crt;
35
+ ssl_certificate_key #{ssl_certificates_path}/#{ssl_certificates_name}.key;
36
+
37
+ passenger_set_cgi_param HTTPS on;
38
+ passenger_set_cgi_param SSL_CLIENT_S_DN $ssl_client_s_dn;
39
+ passenger_set_cgi_param SSL_CLIENT_VERIFY $ssl_client_verify;
40
+
41
+ passenger_set_cgi_param HTTP_X_FORWARDED_PROTO https;
42
+ }
43
+
44
+ server {
45
+ listen 80;
46
+ server_name #{hostnames};
47
+ rewrite ^ https://#{hostnames}$request_uri? permanent;
48
+ ssl_conf
49
+
50
+ conf = <<conf
51
+ server {
52
+ listen #{ssl ? 443 : 80};
53
+ server_name #{user}.#{stage}.tworedkites.com #{hostnames};
54
+ root /home/#{user}/apps/#{stage}/current/public;
55
+ passenger_enabled on;
56
+ passenger_ruby /usr/local/rvm/bin/#{application}_ruby;
57
+ rack_env production;
58
+ client_max_body_size 10m;
59
+
60
+ #{ssl_conf}
61
+ }
62
+ conf
63
+
64
+ put(conf, nginx_conf_file)
65
+
66
+ run "sudo service nginx reload"
67
+ end
68
+
69
+
70
+ task :github_ssh_key do
71
+ run "ssh-keygen -t rsa -f ~/.ssh/id_rsa -P ''; ssh -oStrictHostKeyChecking=no git@github.com; cat .ssh/id_rsa.pub"
72
+ end
73
+
74
+ task :symlink_config do
75
+ run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
76
+ end
77
+ before "deploy:assets:precompile", "deploy:symlink_config"
78
+
79
+ task :create_shared_database_config do
80
+ run "mkdir -p #{shared_path}/config"
81
+ top.upload File.expand_path('../database.yml.server', __FILE__), "#{shared_path}/config/database.yml"
82
+ end
83
+
84
+
85
+ task :create_shared_rvmrc do
86
+ run "cp #{release_path}/.rvmrc.#{rails_env}.example #{release_path}/.rvmrc"
87
+ end
88
+
89
+ after "deploy:finalize_update", "deploy:create_shared_rvmrc"
90
+
91
+ task :create_database do
92
+ set :mysql_pass_arg, mysql_password.blank? ? '' : "-p#{mysql_password}"
93
+ run "mysql --user=root #{mysql_pass_arg} -e \"CREATE DATABASE IF NOT EXISTS #{application}_#{stage}\""
94
+ end
95
+
96
+ task :restart, :roles => :app, :except => { :no_release => true } do
97
+ run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
98
+ end
99
+ end
100
+
101
+ namespace :ruby_make do
102
+ desc "Run a task on a remote server."
103
+ # run like: cap staging rake:invoke task=a_certain_task
104
+ task :invoke do
105
+ run("cd #{deploy_to}/current; /usr/bin/env rake #{ENV['task']} RAILS_ENV=#{rails_env}")
106
+ end
107
+ end
108
+
109
+ # if you want to clean up old releases on each deploy uncomment this:
110
+ # after "deploy:restart", "deploy:cleanup"
111
+
112
+ # if you're still using the script/reaper helper you will need
113
+ # these http://github.com/rails/irs_process_scripts
114
+
115
+ # If you are using Passenger mod_rails uncomment this:
116
+ namespace :deploy do
117
+ task :start do ; end
118
+ task :stop do ; end
119
+ task :restart, :roles => :app, :except => { :no_release => true } do
120
+ run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
121
+ end
122
+ desc "reload the database with seed data"
123
+ task :seed do
124
+ run "cd #{current_path}; bundle exec rake db:seed RAILS_ENV=#{rails_env}"
125
+ end
126
+ end
127
+
128
+ namespace :rvm do
129
+ task :trust_rvmrc do
130
+ run "rvm rvmrc trust #{release_path}"
131
+ end
132
+ end
133
+
134
+ after "deploy", "rvm:trust_rvmrc"
135
+ after 'deploy:setup', 'deploy:create_database', 'deploy:github_ssh_key', 'deploy:nginx_conf', 'deploy:create_shared_database_config'
136
+ after 'deploy:cold', 'deploy:airbrake_test'