class Object
Constants
- MissingApplicationController
- MissingApplicationMailer
Public Class Methods
Tests access permissions for a specific action.
Options:
-
controller
is the string name of the controller. If not supplied, the controller is inferred from the class name. -
url_helper
is a string to generate the url. If not supplied, the helper is inferred from the controller and action names. -
fixture_helper
is a string defining the fixture helper to use. If not supplied the controller name will be used. -
fixture_key
is the fixture key to use. Defaults to :one. -
allow_anon
determines if anonymous users should be able to access the action. Default is false. -
allow_any_user
determines if any logged in user should be able to access the action. Default is false. -
allow_groups
determines if a specific set of groups can access the action. Default is nil. -
deny_groups
determines if a specific set of groups should not be able to access the action. Default is nil. -
allow_admin
determines if system admins can access the action. Default is true. -
method
determines the method to process the action with. Default is ‘get’. -
success
determines the result on success. Defaults to :success for ‘get’ requests, otherwise the pluralized controller helper path. -
failure
determines the result on failure for non-anon tests. Defaults to ‘root_url’. -
anon_failure
determines the result on failure for anon tests. Defaults to ‘login_url’.
# File lib/barkest_core/extensions/test_case_extensions.rb, line 188 def self.access_tests_for(action, options = {}) if action.respond_to?(:each) action.each do |act| access_tests_for(act, options.dup) end return end options = { allow_anon: false, allow_any_user: false, allow_groups: nil, allow_admin: true, fixture_key: :one, failure: 'root_url', anon_failure: 'login_url' }.merge(options || {}) action = action.to_sym params = options[:"#{action}_params"] params = nil unless params.is_a?(Hash) if options[:method].blank? options[:method] = if action == :destroy 'delete' elsif action == :update 'patch' elsif action == :create 'post' else 'get' end end if options[:controller].blank? options[:controller] = self.name.underscore.rpartition('_')[0] else options[:controller] = options[:controller].to_s.underscore end if options[:controller][-11..-1] == '_controller' options[:controller] = options[:controller].rpartition('_')[0] end if options[:fixture_helper].blank? options[:fixture_helper] = options[:controller] end options[:method] = options[:method].to_sym if options[:url_helper].blank? fix_val = "#{options[:fixture_helper].pluralize}(#{options[:fixture_key].inspect})" options[:url_helper] = case action when :show, :update, :destroy then "#{options[:controller].singularize}_path(#{fix_val})" when :edit then "edit_#{options[:controller].singularize}_path(#{fix_val})" when :new then "new_#{options[:controller].singularize}_path" else "#{options[:controller].pluralize}_path" end end if options[:success].blank? if options[:method] == :get options[:success] = :success else options[:success] = "#{options[:controller].pluralize}_path" end end method = options[:method] url_helper = options[:url_helper] tests = [ [ 'anonymous', options[:allow_anon], nil, nil, nil, options[:anon_failure] ], [ 'any user', options[:allow_any_user], :basic ], [ 'admin user', options[:allow_admin], :admin ] ] unless options[:allow_groups].blank? if options[:allow_groups].is_a?(String) options[:allow_groups] = options[:allow_groups].gsub(',', ';').split(';').map{|v| v.strip} end options[:allow_groups].each do |group| tests << [ "#{group} member", true, :basic, group ] end end unless options[:deny_groups].blank? if options[:deny_groups].is_a?(String) options[:deny_groups] = options[:deny_groups].gsub(',', ';').split(';').map{|v| v.strip} end options[:deny_groups].each do |group| tests << [ "#{group} member", false, :basic, group ] end end tests.each do |(label, result, user, group, success_override, failure_override)| expected_result = result ? (success_override || options[:success]) : (failure_override || options[:failure]) test_code = "test \"should #{result ? '' : 'not '}allow access to #{action} for #{label}\" do\n" if user test_code += "user = users(#{user.inspect})\n" if group test_code += "group = AccessGroup.get(#{group.inspect}) || AccessGroup.create(name: #{group.inspect})\n" test_code += "user.groups << group\n" end test_code += "log_in_as user\n" end test_code += "path = #{url_helper}\n" if params.blank? test_code += "#{method} path\n" else test_code += "#{method} path, #{params.inspect[1...-1]}\n" end if expected_result.is_a?(Symbol) test_code += "assert_response #{expected_result.inspect}\n" else test_code += "assert_redirected_to #{expected_result}\n" end test_code += "end\n" eval test_code end end
Loads the concerns for the current model.
# File lib/barkest_core/extensions/active_record_extensions.rb, line 77 def self.add_concerns(subdir = nil) klass = self subdir ||= klass.name.underscore Dir.glob(File.expand_path("../../../app/models/concerns/#{subdir}/*.rb", __FILE__)).each do |item| require item mod_name = File.basename(item)[0...-3].camelcase if const_defined? mod_name mod_name = const_get mod_name klass.include mod_name else raise StandardError.new("The #{mod_name} module does not appear to be defined.") end end end
Determines the fixtures that will be loaded first.
Arguments can either be just table names or a hash of table names with indexes. If just table names, then the tables are inserted at the end of the list. If a hash, then the value is the index you want the table to appear in the load list.
BarkestCore
tables are pre-indexed to load before any other tables.
Usage:
ActiveRecord::FixtureSet.load_first :table_1, :table_2 ActiveRecord::FixtureSet.load_first :table_1 => 0, :table_2 => 1
# File lib/barkest_core/extensions/fixture_set_extensions.rb, line 22 def self.load_first(*args) priority_list = %w(access_groups users) @load_first ||= priority_list unless args.blank? args.each do |arg| if arg.is_a?(Hash) arg.each do |fix,order| fix = fix.to_s order += priority_list.length if order >= @load_first.length @load_first << fix unless @load_first.include?(fix) else @load_first.insert(order, fix) unless @load_first.include?(fix) end end else fix = arg.to_s @load_first << fix unless @load_first.include?(fix) end end end @load_first end
Determines the fixtures that will purged first.
Arguments can either be just table names or a hash of table names with indexes. If just table names then the tables are inserted at the beginning of the list. If a hash, then the value is the index you want the table to appear in the purge list.
BarkestCore
tables are pre-indexed to be purged after any other tables added to this list.
Usage:
ActiveRecord::FixtureSet.purge_first :table_1, :table_2 ActiveRecord::FixtureSet.purge_first :table_1 => 0, :table_2 => 1
# File lib/barkest_core/extensions/fixture_set_extensions.rb, line 61 def self.purge_first(*args) priority_list = %w(ldap_access_groups access_group_user_members access_group_group_members user_login_histories users access_groups) @purge_first ||= priority_list unless args.blank? args.reverse.each do |arg| if arg.is_a?(Hash) arg.each do |fix,order| fix = fix.to_s if order <= 0 @purge_first.insert(0, fix) unless @purge_first.include?(fix) elsif order >= @purge_first.length - priority_list.length @purge_first.insert(@purge_first.length - priority_list.length, fix) unless @purge_first.include?(fix) else @purge_first.insert(order, fix) unless @purge_first.include?(fix) end end else fix = arg.to_s @purge_first.insert(0, fix) unless @purge_first.include?(fix) end end end @purge_first end
Parses a time string into UTC time.
Supports either M/D/Y H:M:S or Y-M-D H:M:S format.
If a timezone is provided, it will be taken into account and the UTC equivalent will be returned.
# File lib/barkest_core/extensions/time_extensions.rb, line 16 def self.utc_parse(s) raise ArgumentError, 'expected a time value to be provided' if s.blank? # If it's already a time, return the UTC variant. return s.utc if s.is_a?(Time) # If it can be converted to a time, and is not a string, convert and return the UTC variant. return s.to_time.utc if s.respond_to?(:to_time) && !s.is_a?(String) # If it is not a string, turn it into a string and parse that. return utc_parse(s.to_s) unless s.is_a?(String) dt,tm,tz,ex = s.split(' ') # Time only? if dt.include?(':') ex = tz tz = tm tm = dt dt = '1900-01-01' end yr,mon,day = if dt.include?('/') # M/D/Y _m,_d,_y = dt.split('/') _y ||= Time.now.utc.year [ _y, _m, _d ] elsif dt.include?('-') # Y-M-D dt.split('-') # Because we may be interacting with Spectrum users, accept these formats as well. elsif (/^\d{4}$/).match(dt) # MMDD [ Time.now.utc.year, dt[0...2], dt[2...4] ] elsif (/^\d{6}(\d{2})?$/).match(dt) # MMDDYY(YY) [ dt[4..-1], dt[0...2], dt[2...4] ] elsif (/^\d+(am|pm)?$/i).match(dt) && (0..24).include?(dt.to_i) # a single integer parsing to a valid hour, possibly with an AM/PM specifier ex = tz tz = tm tm = dt [ 1900, 1, 1 ] else # Unsupported format. [] end.map { |i| i.to_i } raise ArgumentError, 'year is missing' unless yr raise ArgumentError, 'month is missing' unless mon raise ArgumentError, 'day is missing' unless day yr += 2000 if yr < 40 yr += 1900 if yr < 100 mon = 1 unless mon day = 1 unless day if tm # allow AM/PM specifier to be attached to time. if %w(AM PM).include?(tm[-2..-1].to_s.upcase) ex = tz tz = tm[-2..-1] end end hr,min,sec = tm ? tm.split(':') : [] hr = hr ? hr.to_i : 0 min = min ? min.to_i : 0 sec = sec ? sec.to_f : 0.0 if %w(AM PM).include?(tz.to_s.upcase) raise ArgumentError, 'hour must be between 1 and 12 for 12-hour formats' unless (1..12).include?(hr) tz = tz.to_s.upcase if tz == 'AM' hr = 0 if hr == 12 # only need to modify midnight. else hr += 12 unless hr == 12 # modify everything except noon. end # grab the next item from the original string. tz = ex end if hr == 24 && min == 0 && sec == 0 tmp_date = Time.utc(yr,mon,day) raise ArgumentError, 'time component overflow' unless tmp_date.year == yr && tmp_date.month == mon && tmp_date.day == day tmp_date = (tmp_date + 1.day).to_time.utc yr = tmp_date.year mon = tmp_date.month day = tmp_date.day hr = 0 end tz = nil if %w(UTC).include?(tz.to_s.upcase) result = if tz bits = (/^([+-])(\d{1,2}):?(\d{2})$/).match(tz) raise ArgumentError, '"+HH:MM" or "-HH:MM" expected for utc_offset' unless bits tz = "#{bits[1]}#{bits[2].rjust(2,'0')}:#{bits[3]}" Time.new(yr, mon, day, hr, min, sec, tz) else Time.utc(yr, mon, day, hr, min, sec) end raise ArgumentError, 'time component overflow' unless result.year == yr && result.month == mon && result.day == day && result.hour == hr && result.min == min && result.sec.to_i == sec.to_i result.utc end
Public Instance Methods
Tests for equality on ID.
# File lib/barkest_core/extensions/active_record_extensions.rb, line 61 def ==(other) if respond_to?(:id) if other.is_a?(Numeric) id == other elsif other.class == self.class id == other.id else false end else self.inspect == other.inspect end end
Gets the company responsible for the application.
This should be overridden in your application.rb
file.
# File lib/barkest_core/extensions/application_extensions.rb, line 38 def app_company 'BarkerEST' end
Gets the application name and version.
This can be overridden in your application.rb
file if you want a different behavior.
# File lib/barkest_core/extensions/application_extensions.rb, line 46 def app_info "#{app_name} v#{app_version}" end
Gets the application name.
This should be overridden in your application.rb
file.
# File lib/barkest_core/extensions/application_extensions.rb, line 22 def app_name 'BarkerEST' end
Gets the application version.
This should be overridden in your application.rb
file.
# File lib/barkest_core/extensions/application_extensions.rb, line 30 def app_version '0.0.1' end
Discards time zone information and makes
The current time zone offset is discarded. For instance, ‘2016-12-19 19:00:00 -05:00’ becomes ‘2016-12-19 19:00:00 +00:00’
# File lib/barkest_core/extensions/time_extensions.rb, line 144 def as_utc Time.utc(year, month, day, hour, min, sec) end
# File lib/barkest_core/extensions/generator_extensions.rb, line 62 def ask_for_bool(question, default = false) return default if options.quiet? print "#{trimq(question)} [#{default ? 'Y/n' : 'y/N'}]? " if options.force? puts default ? 'Y' : 'N' return default end answer = STDIN.gets.strip.upcase[0] return default if answer.blank? answer == 'Y' end
# File lib/barkest_core/extensions/generator_extensions.rb, line 111 def ask_for_int(question, default = 0, valid = nil) return default if options.quiet? loop do print "#{question} [#{default}]? " if options.force? puts default.to_s return default end answer = STDIN.gets.strip return default if answer.blank? answer = answer.to_i if valid && valid.respond_to?(:call) return answer if valid.call(answer) elsif valid && valid.respond_to?(:include?) return answer if valid.include?(answer) else return answer end puts "Entered value (#{answer}) is invalid." unless valid.respond_to?(:call) puts "Valid values are #{valid.inspect}." end end end
# File lib/barkest_core/extensions/generator_extensions.rb, line 143 def ask_for_secret(question, default = '') return default if options.quiet? print "#{question} [enter to keep, . to clear]: " if options.force? puts '' return default end loop do answer1 = STDIN.noecho(&:gets).strip puts '' return '' if answer1 == '.' return default if answer1.blank? print 'Enter again to confirm: ' answer2 = STDIN.noecho(&:gets).strip puts '' return answer1 if answer2 == answer1 puts 'Confirmation does not match!' print 'Please try again: ' end end
# File lib/generators/barkest_core/actions/09_configure_secrets.rb, line 21 def ask_for_secret_key_base(question, default = '') default = default.to_s puts "Current secret key base: #{default[0...20]}..." unless options.quiet? tell 'Changing the secret key base will invalidate encrypted values.', :yellow return default unless ask_for_bool('Do you want to change the secret key base to a new random value?', false) SecureRandom.urlsafe_base64(72) end
# File lib/barkest_core/extensions/generator_extensions.rb, line 79 def ask_for_string(question, default = '', valid = nil) return default if options.quiet? loop do print "#{trimq(question)} [#{default}] (. to clear)? " if options.force? puts default.to_s return default end answer = STDIN.gets.strip return '' if answer == '.' return default if answer.blank? if valid && valid.respond_to?(:call) return answer if valid.call(answer) elsif valid && valid.respond_to?(:include?) return answer if valid.include?(answer) else return answer end puts "Entered value (#{answer}) is invalid." unless valid.respond_to?(:call) puts "Valid values are #{valid.inspect}." end end end
Tests a specific field for maximum length restriction.
model
must respond to attribute and attribute= as well as valid?.
attribute
must provide the name of a valid attribute in the model.
max_length
is the maximum valid length for the field.
message
is optional, but if provided it will be postfixed with the failure reason.
# File lib/barkest_core/extensions/test_case_extensions.rb, line 48 def assert_max_length(model, attribute, max_length, message = nil, options = {}) original_value = model.send(attribute) original_valid = model.valid? setter = :"#{attribute}=" if message.is_a?(Hash) options = message.merge(options || {}) message = nil end pre = options[:start].to_s post = options[:end].to_s len = max_length - pre.length - post.length # try with maximum valid length. value = pre + ('a' * len) + post model.send setter, value assert model.valid?, message ? (message + ": !(#{value.length})") : "Should allow a string of #{value.length} characters." # try with one extra character. value = pre + ('a' * (len + 1)) + post model.send setter, value assert_not model.valid?, message ? (message + ": (#{value.length})") : "Should not allow a string of #{value.length} characters." model.send setter, original_value if original_valid assert model.valid?, message ? (message + ": !(#{original_value.inspect})") : "Should allow #{attribute} to be set back to '#{original_value.inspect}'." end end
Tests a specific field for maximum length restriction.
model
must respond to attribute and attribute= as well as valid?.
attribute
must provide the name of a valid attribute in the model.
max_length
is the maximum valid length for the field.
message
is optional, but if provided it will be postfixed with the failure reason.
# File lib/barkest_core/extensions/test_case_extensions.rb, line 88 def assert_min_length(model, attribute, min_length, message = nil, options = {}) original_value = model.send(attribute) original_valid = model.valid? setter = :"#{attribute}=" if message.is_a?(Hash) options = message.merge(options || {}) message = nil end pre = options[:start].to_s post = options[:end].to_s len = max_length - pre.length - post.length # try with minimum valid length. value = pre + ('a' * len) + post model.send setter, value assert model.valid?, message ? (message + ": !(#{value.length})") : "Should allow a string of #{value.length} characters." # try with one extra character. value = pre + ('a' * (len - 1)) + post model.send setter, value assert_not model.valid?, message ? (message + ": (#{value.length})") : "Should not allow a string of #{value.length} characters." model.send setter, original_value if original_valid assert model.valid?, message ? (message + ": !(#{original_value.inspect})") : "Should allow #{attribute} to be set back to '#{original_value.inspect}'." end end
Tests a specific field for presence validation.
model
must respond to attribute and attribute= as well as valid?.
attribute
must provide the name of a valid attribute in the model.
message
is optional, but if provided it will be postfixed with the failure reason.
# File lib/barkest_core/extensions/test_case_extensions.rb, line 19 def assert_required(model, attribute, message = nil) original_value = model.send(attribute) original_valid = model.valid? is_string = original_value.is_a?(String) setter = :"#{attribute}=" model.send setter, nil assert_not model.valid?, message ? (message + ': (nil)') : "Should not allow #{attribute} to be set to nil." if is_string model.send setter, '' assert_not model.valid?, message ? (message + ": ('')") : "Should not allow #{attribute} to be set to empty string." model.send setter, ' ' assert_not model.valid?, message ? (message + ": (' ')") : "Should not allow #{attribute} to be set to blank string." end model.send setter, original_value if original_valid assert model.valid?, message ? (message + ": !(#{original_value.inspect})") : "Should allow #{attribute} to be set back to '#{original_value.inspect}'." end end
Tests a specific field for uniqueness.
model
must respond to attribute and attribute= as well as valid?. The model will be saved to perform uniqueness testing.
attribute
must provide the name of a valid attribute in the model.
case_sensitive
determines if changing case should change validation.
message
is optional, but if provided it will be postfixed with the failure reason.
alternate_scopes
is also optional. If provided the keys of the hash will be used to set additional attributes on the model. When these attributes are changed to the alternate values, the model should once again be valid.
# File lib/barkest_core/extensions/test_case_extensions.rb, line 133 def assert_uniqueness(model, attribute, case_sensitive = false, message = nil, alternate_scopes = {}) setter = :"#{attribute}=" original_value = model.send(attribute) if case_sensitive.is_a?(Hash) alternate_scopes = case_sensitive.merge(alternate_scopes || {}) case_sensitive = false end if message.is_a?(Hash) alternate_scopes = message.merge(alternate_scopes || {}) message = nil end copy = model.dup model.save! assert_not copy.valid?, message ? (message + ": (#{copy.send(attribute).inspect})") : "Duplicate model with #{attribute}=#{copy.send(attribute).inspect} should not be valid." unless case_sensitive copy.send(setter, original_value.to_s.upcase) assert_not copy.valid?, message ? (message + ": (#{copy.send(attribute).inspect})") : "Duplicate model with #{attribute}=#{copy.send(attribute).inspect} should not be valid." copy.send(setter, original_value.to_s.downcase) assert_not copy.valid?, message ? (message + ": (#{copy.send(attribute).inspect})") : "Duplicate model with #{attribute}=#{copy.send(attribute).inspect} should not be valid." end unless alternate_scopes.blank? copy.send(setter, original_value) assert_not copy.valid?, message ? (message + ": (#{copy.send(attribute).inspect})") : "Duplicate model with #{attribute}=#{copy.send(attribute).inspect} should not be valid." alternate_scopes.each do |k,v| kset = :"#{k}=" vorig = copy.send(k) copy.send(kset, v) assert copy.valid?, message ? (message + ": !#{k}(#{v})") : "Duplicate model with #{k}=#{v.inspect} should be valid with #{attribute}=#{copy.send(attribute).inspect}." copy.send(kset, vorig) assert_not copy.valid?, message ? (message + ": (#{copy.send(attribute).inspect})") : "Duplicate model with #{attribute}=#{copy.send(attribute).inspect} should not be valid." end end end
Installs all known Barkest
routes.
Basically every Barkest
plugin should define a ‘barkest_’ helper in the routing mapper class, so this method simply finds and executes those helpers.
# File lib/barkest_core/extensions/router_extensions.rb, line 10 def barkest(options = {}) self.methods.each do |method| if method.to_s.index('barkest_') == 0 send method, options end end end
Installs the BarkestCore
routes.
# File lib/barkest_core/extensions/router_extensions.rb, line 20 def barkest_core(options = {}) options = { path: options } if options.is_a?(String) options = (options || {}).symbolize_keys path = options[:path].blank? ? '/' : options[:path].to_s path = '/' + path unless path[0] == '/' scope path: path do if Rails.env.test? || Rails.env.development? scope as: :barkest_core do # test routes get 'test_access/allow_anon' get 'test_access/require_user' get 'test_access/require_admin' get 'test_access/require_group_x' get 'test_report' => 'test_report#index' # namespaced tests (these should have the subheader in place). get 'test_sub' => 'barkest_core/testsub#page1', as: :testsub_page1 get 'test_sub/page2' => 'barkest_core/testsub#page2', as: :testsub_page2 get 'test_sub/page3' => 'barkest_core/testsub#page3', as: :testsub_page3 end end # contact form get 'contact' => 'contact#index' post 'contact' => 'contact#create' # login/logout get 'login' => 'sessions#new', as: :login post 'login' => 'sessions#create' delete 'logout' => 'sessions#destroy', as: :logout # user management get 'signup' => 'users#new', as: :signup post 'signup' => 'users#create' resources :users do member do get 'disable', action: :disable_confirm patch 'disable', action: :disable put 'disable', action: :disable patch 'enable', action: :enable put 'enable', action: :enable end end # account activation route. get 'account_activation/:id' => 'account_activations#edit', as: 'edit_account_activation' # password reset routes. resources :password_resets, only: [:new, :create, :edit, :update] # group management resources :access_groups # status paths get 'status/current' => 'status#current' get 'status/first' => 'status#first' get 'status/more' => 'status#more' get 'status/test(/:flag)' => 'status#test', as: :status_test # system update paths get 'system_update/new' get 'system_update' => 'system_update#index', as: :system_update # system configuration paths get 'system_config' => 'system_config#index', as: :system_config post 'system_config/restart' => 'system_config#restart', as: :system_config_restart SystemConfigController.get_config_items.sort.each do |(item_name, attrib)| if attrib[:require_id] get "system_config/#{item_name}/:id" => "system_config#show_#{item_name}", as: attrib[:route_name] post "system_config/#{item_name}/:id" => "system_config#update_#{item_name}" else get "system_config/#{item_name}" => "system_config#show_#{item_name}", as: attrib[:route_name] post "system_config/#{item_name}" => "system_config#update_#{item_name}" end end # log view paths get 'system_log' => 'log_view#index', as: :system_log post 'system_log' => 'log_view#index' end end
Generates a database.yml configuration file.
# File lib/generators/barkest_core/actions/08_configure_database.rb, line 4 def configure_database config_file = 'config/database.yml' attributes = [ ['adapter', :ask_for_string, %w(sqlite3 postgresql sqlserver mysql2), 'database_adapter'], ['pool', :ask_for_int, (1..1000), 'connection_pool_size'], ['timeout', :ask_for_int, (500..300000)], { 'sqlite3' => [ [ 'database', :ask_for_string, nil, 'sqlite_database', 'db/my-db.sqlite3' ] ], 'postgresql' => [ [ 'host', :ask_for_string, nil, 'pg_host' ], [ 'port', :ask_for_int, (1..65535), 'pg_port', 5432 ], [ 'username', :ask_for_string, nil, 'pg_username' ], [ 'password', :ask_for_secret, nil, 'pg_password' ], [ 'database', :ask_for_string, nil, 'pg_database' ] ], 'sqlserver' => [ [ 'host', :ask_for_string, nil, 'sql_host' ], [ 'port', :ask_for_int, (1..65535), 'sql_port', 1433 ], [ 'username', :ask_for_string, nil, 'sql_username' ], [ 'password', :ask_for_secret, nil, 'sql_password' ], [ 'database', :ask_for_string, nil, 'sql_database', 'my_db' ] ], 'mysql2' => [ [ 'host', :ask_for_string, nil, 'mysql_host' ], [ 'port', :ask_for_int, (1..65535), 'mysql_port', 3306 ], [ 'username', :ask_for_string, nil, 'mysql_username' ], [ 'password', :ask_for_secret, nil, 'mysql_password' ], [ 'database', :ask_for_string, nil, 'mysql_database', 'my_db' ] ] } ] default = { 'adapter' => 'sqlite3', 'pool' => 5, 'timeout' => 5000, 'database' => 'db/my-data.sqlite3' } configure_the 'database connection', config_file, attributes, 'adapter', default, 'barkest_core' end
Generates a secrets.yml configuration file.
# File lib/generators/barkest_core/actions/09_configure_secrets.rb, line 5 def configure_secrets config_file = 'config/secrets.yml' attributes = [ [ 'recaptcha_public_key', :ask_for_string ], [ 'recaptcha_private_key', :ask_for_string ], [ 'secret_key_base', :ask_for_secret_key_base ], ] default = {} configure_the 'application secrets', config_file, attributes, nil, default end
# File lib/barkest_core/extensions/generator_extensions.rb, line 171 def configure_the(what, config_file, attributes, hash_key, defaults, *optional_levels) tell '=' * 79 if ask_for_bool("Would you like to configure #{what.pluralize}?", true) current_config = File.exist?(config_file) ? YAML.load_file(config_file) : {} levels = ([''] + (optional_levels || [])).uniq levels.each do |level| if level.blank? || ask_for_bool("Would you like to configure a #{level} #{what.singularize} configuration?", false) current_config[level] ||= {} unless level.blank? env_list = %w(test development production) unless level.blank? level,_,envs = level.partition('[') unless envs.blank? env_list = envs.partition(']').first.strip.split(' ') end end last_env = nil env_list.each do |env| tell "Configure the '#{level.blank? ? '' : (level + ':')}#{env}' environment." tell '-' * 79 cur_env = level.blank? ? env : "#{level}_#{env}" current = (current_config[cur_env] || {}).dup if current.blank? || ask_for_bool("Do you want to make changes to the '#{cur_env}' environment?", false) if last_env if ask_for_bool("Would you like to use the configuration from the '#{last_env}' environment to start?", false) current = (current_config[last_env] || {}).dup end end current = input_attributes(current, attributes, defaults, hash_key) end current_config[cur_env] = current tell '-' * 79 last_env = cur_env end end end perform "> creating '#{config_file}'..." do File.write config_file, current_config.to_yaml end end end
Runs the rake task to install the BarkestCore
migrations.
# File lib/generators/barkest_core/actions/07_copy_migrations.rb, line 4 def copy_migrations tell '=' * 79 if ask_for_bool('Would you like to install the BarkestCore database migrations?', true) tell 'Copying database migrations...' unless options.quiet? ts = Time.now.strftime('%Y%m%d%H%M%S').to_i ext = '.barkest_core.rb' unless Dir.exist?('db/migrate') perform '> creating \'db/migrate\' directory...' do Dir.mkdir 'db/migrate' end end existing = Dir.glob("db/migrate/*#{ext}") find_existing = Proc.new do |file| fn = File.basename(file)[0...-3].partition('_')[2] existing.find do |ex| fn == File.basename(ex)[0...(-ext.length)].partition('_')[2] end end Dir.glob(File.expand_path('../../../../../db/migrate/*.rb', __FILE__)).each do |file| target_file = find_existing.call(file) contents = File.read(file) if target_file cur_contents = File.read(target_file) if cur_contents.strip == contents.strip tell "> '#{target_file}' is good.", :bright_green else perform "> updating '#{target_file}'..." do File.write target_file, contents end end else target_file = "db/migrate/#{ts}_#{File.basename(file)[0...-3].partition('_')[2]}#{ext}" ts += 1 perform "> creating '#{target_file}'..." do File.write target_file, contents end end end end end
Gets the date component of the time.
# File lib/barkest_core/extensions/time_extensions.rb, line 134 def date return utc.date unless utc? Time.utc(year, month, day) end
# File lib/barkest_core/extensions/generator_extensions.rb, line 8 def erb_read(file) ERB.new(File.read(file), 0).result end
# File lib/barkest_core/extensions/generator_extensions.rb, line 227 def input_attributes(target_hash, attribute_list, defaults, hash_key = nil) attribute_list.each do |data| if data.is_a?(Hash) if hash_key && target_hash[hash_key] && data[target_hash[hash_key]].is_a?(Array) target_hash = input_attributes(target_hash, data[target_hash[hash_key]], defaults, hash_key) end elsif data.is_a?(Array) field,asker,valid,label,default_override = data label ||= field def_val = if target_hash[field].nil? if default_override.nil? defaults[field] else default_override end else target_hash[field] end answer = if valid send(asker, label, def_val, valid) else send(asker, label, def_val) end target_hash[field] = answer end end target_hash end
Are we running an integration test?
# File lib/barkest_core/extensions/test_case_extensions.rb, line 342 def integration_test? defined?(post_via_redirect) end
Is a user currently logged in?
# File lib/barkest_core/extensions/test_case_extensions.rb, line 324 def is_logged_in? !session[:user_id].nil? end
Logs in as the specified user.
# File lib/barkest_core/extensions/test_case_extensions.rb, line 330 def log_in_as(user, options = {}) password = options[:password] || 'password' remember_me = options[:remember_me] || '1' if integration_test? post login_path, session: { email: user.email, password: password, remember_me: remember_me } else session[:user_id] = user.id end end
Patches the ApplicationController class to inherit from BarkestCore::ApplicationController.
# File lib/generators/barkest_core/actions/01_patch_application_controller.rb, line 6 def patch_application_controller app_file = 'app/controllers/application_controller.rb' dest_source = '::BarkestCore::ApplicationControllerBase' if File.exist?(app_file) regex = /^(?<NAME>\s*class ApplicationController\s*<\s*)(?<ORIG>\S+)\s*(?<COMMENT>#.*)?$/ found = false changed = false lines = File.read(app_file).split("\n").map do |line| match = regex.match(line) found = true if match if match && match['ORIG'] != dest_source changed = true "#{match['NAME']}#{dest_source} # #{match['ORIG']} #{match['COMMENT']}" else line end end raise MissingApplicationController.new('ApplicationController class not found') unless found if changed if ask_for_bool("Your ApplicationController does not currently inherit from BarkestCore.\nWould you like to change this?", true) perform "> updating '#{app_file}'..." do File.write app_file, lines.join("\n") end else tell "> '#{app_file}' is unchanged.", :bright_green end else tell "> '#{app_file}' is good.", :bright_green end else if ask_for_bool("Your application is missing an ApplicationController.\nWould you like to create one?", true) perform "> creating '#{app_file}'..." do File.write app_file, <<-APPCTRLR class ApplicationController < #{dest_source} # This is your application controller, it inherits functionality from BarkestCore. end APPCTRLR end end end end
Patches the ApplicationMailer class to inherit from BarkestCore::ApplicationMailer.
# File lib/generators/barkest_core/actions/02_patch_application_mailer.rb, line 7 def patch_application_mailer app_file = 'app/mailers/application_mailer.rb' dest_source = '::BarkestCore::ApplicationMailerBase' if File.exist?(app_file) regex = /^(?<NAME>\s*class ApplicationMailer\s*<\s*)(?<ORIG>\S+)\s*(?<COMMENT>#.*)?$/ found = false changed = false lines = File.read(app_file).split("\n").map do |line| match = regex.match(line) found = true if match if match && match['ORIG'] != dest_source changed = true "#{match['NAME']}#{dest_source} # #{match['ORIG']} #{match['COMMENT']}" else line end end raise MissingApplicationMailer.new('ApplicationMailer class not found') unless found if changed if ask_for_bool("Your ApplicationMailer does not currently inherit from BarkestCore.\nWould you like to change this?", true) perform "> updating '#{app_file}'..." do File.write app_file, lines.join("\n") end else tell "> '#{app_file}' is unchanged.", :bright_green end else tell "> '#{app_file}' is good.", :bright_green end else if ask_for_bool("Your application is missing an ApplicationMailer.\nWould you like to create one?", true) perform "> creating '#{app_file}'..." do File.write app_file, <<-APPMLR class ApplicationMailer < #{dest_source} # This is your application mailer, it inherits functionality from BarkestCore. end APPMLR end end end end
Patches application.js and application.css
# File lib/generators/barkest_core/actions/03_patch_assets.rb, line 4 def patch_assets target = 'barkest_core/application' [ [ 'app/assets/javascripts/application.js', '//=', "// Application.js\n//= require_tree .\n" ], [ 'app/assets/stylesheets/application.css', '*=', "/*\n * Application.css\n *= require_tree .\n *= require_self\n */\n" ] ].each do |(path, line_tag, def_contents)| lines = if File.exist?(path) File.read(path) else def_contents end.split("\n") first_tag = -1 first_pass = true loop do lines.each_with_index do |line, index| if line.strip[0...line_tag.length] == line_tag first_tag = index break end end if first_tag < 0 if first_pass lines += def_contents.split("\n") else raise StandardError.new("Failed to locate line starting with '#{line_tag}' in '#{path}'.") end else break end first_pass = false end regex = /^\s*#{line_tag.gsub('*',"\\*")}\s*require\s*['"]?#{target}['"]?\s*$/ tag_index = -1 lines.each_with_index do |line, index| if regex.match(line) tag_index = index break end end if tag_index < 0 if ask_for_bool("Would you like to add a reference to BarkestCore in '#{path}'?", true) lines.insert first_tag, "#{line_tag} require #{target}" perform "> updating '#{path}'..." do File.write path, lines.join("\n") end else tell "> '#{path}' is unchanged.", :bright_green end else tell "> '#{path}' is good.", :bright_green end end end
Patches .gitignore to ignore *.yml configuration files.
# File lib/generators/barkest_core/actions/99_patch_gitignore.rb, line 4 def patch_gitignore file = '.gitignore' dummy = Dir.exist?('test/dummy') if File.exist?(file) lines = File.read(file).split("\n") protect_cfg = false protect_dummy_cfg = false cfg_regex = /^\s*config\/\*.yml\s*$/ dummy_cfg_regex = /^\s*test\/dummy\/config\/\*.yml\s*$/ lines.each do |line| protect_cfg = true if cfg_regex.match(line) protect_dummy_cfg = true if dummy_cfg_regex.match(line) end changed = false unless protect_cfg if ask_for_bool("Your .gitignore does not protect your YAML configuration files.\nWould you like to add a line to protect them?", true) lines << 'config/*.yml' changed = true end end if dummy && !protect_dummy_cfg if ask_for_bool("Your .gitignore does not protect your dummy application's YAML configuration files.\nWould you like to add a line to protect them?", true) lines << 'test/dummy/config/*.yml' changed = true end end if changed perform '> updating \'.gitignore\'...' do File.write file, lines.join("\n") end else tell '> \'.gitignore\' is good.', :bright_green end else if ask_for_bool('Would you like to create a .gitignore that protects your YAML files?', true) perform '> creating \'.gitignore\'...' do contents = %w(.bundle/ .sass-cache/ config/*.yml db/*.sqlite3 db/*.sqlite3-journal doc/ log/*.log pkg/ tmp/ vendor/bundle/) contents += contents.map{|v| "test/dummy/#{v}"} if dummy File.write file, contents.join("\n") end end end end
Patches the default layouts to inherit from the BarkestCore
layouts.
# File lib/generators/barkest_core/actions/04_patch_layouts.rb, line 4 def patch_layouts { 'app/views/layouts/application.html.erb' => 'layouts/barkest_core/application', 'app/views/layouts/mailer.html.erb' => 'layouts/barkest_core/html_mailer', 'app/views/layouts/mailer.text.erb' => 'layouts/barkest_core/text_mailer' }.each do |file,layout| if File.exist?(file) regex = /<%=\s+render[\s\(]+['"]#{layout}['"][\)\s]*%>/ if regex.match(File.read(file)) tell "> '#{file}' is good.", :bright_green else if ask_for_bool("Your '#{file}' layout does not reference the BarkestCore layout.\nWould you like to change it to use the BarkestCore layout?", true) perform "> updating '#{file}'..." do File.write file, "<%= render '#{layout}' %>\n" end else tell "> '#{file}' is unchanged.", :bright_green end end else if ask_for_bool("Your application is missing '#{file}'.\nWould you like to add one?", true) perform "> creating '#{file}'..." do File.write file, "<%= render '#{layout}' %>\n" end else tell "> '#{file}' is missing.", :yellow end end end end
Patches routes.rb to include BarkestCore::Engine
and session management paths.
# File lib/generators/barkest_core/actions/05_patch_routes.rb, line 4 def patch_routes route_file = 'config/routes.rb' unless File.exist?(route_file) if ask_for_bool("Your application is missing a 'routes.rb' configuration file.\nWould you like to create one?", true) perform '> creating \'routes.rb\'...' do File.write route_file, <<-DEFRTS Rails.application.routes.draw do # Enter your routes in this file. end DEFRTS end else tell '> missing \'routes.rb\'.', :yellow return end end lines = File.exist?(route_file) ? File.read(route_file).split("\n") : ['Rails.application.routes.draw do','end'] insert_at = -1 regex = /.*\.routes\.draw\s+do\s*(#.*)?$/ lines.each_with_index do |line, index| if regex.match(line) insert_at = index + 1 break end end raise MissingRoutes.new('routes not found') unless insert_at >= 0 changed = false core_regex = /^\s*barkest_core([\s\(]+(?<OPTIONS>[^\s\)#][^\)#]+)\)?)?\s*(?<COMMENT>#.*)?$/ root_regex = /^\s*root([\s\(]+(?<OPTIONS>[^\s\)#][^\)#]+)\)?)?\s*(?<COMMENT>#.*)?$/ core = nil root = nil lines.each_with_index do |line, index| line = line.strip if (match = core_regex.match(line)) opts = match['OPTIONS'].to_s.strip core = { index: index, path: if (path_offset = opts.index(':path')) opts[path_offset..-1].partition('=>')[2].partition(',')[0].strip[1...-1] elsif (path_offset = opts.index('path:')) opts[path_offset..-1].partition(':')[2].partition(',')[0].strip[1...-1] else opts[1...-1] # strip '...' or "..." to ... end.to_s } elsif (match = root_regex.match(line)) opts = match['OPTIONS'].to_s.strip root = { index: index, path: opts[1...-1].to_s # strip '...' or "..." to ... } end end unless core if ask_for_bool('Would you like to add the \'barkest_core\' routes to your application?', true) path = ask_for_string('What path prefix would you like?', '/') lines.insert insert_at, "\n barkest_core #{path.inspect}" changed = true end end unless root if ask_for_bool("Your application is missing a root route.\nWould you like to add one?", true) path = ask_for_string('What controller#action would you like for your root route?', 'test_access#allow_anon') lines.insert insert_at, "\n root #{path.inspect}" changed = true end end if changed perform '> updating \'routes.rb\'...' do File.write route_file, lines.join("\n") end else tell '> \'routes.rb\' is good.', :bright_green end end
Patches the db/seeds to allow multiple seeding files and includes the seeds necessary for BarkestCore
.
# File lib/generators/barkest_core/actions/06_patch_seeds.rb, line 4 def patch_seeds files = Dir.glob(File.expand_path('../../../../../db/{seeds.rb,seeds/*.rb}', __FILE__)) unless Dir.exists?('db/seeds') if ask_for_bool("Your application does not currently have a 'db/seeds' directory.\nBarkestCore can alter your application to make use of multiple seeding files.\nDo you want to create the 'db/seeds' directory to enable this behavior?", true) perform '> creating \'db/seeds\' directory.' do Dir.mkdir 'db' unless Dir.exists?('db') Dir.mkdir 'db/seeds' end else tell "> 'db/seeds' directory is missing.", :yellow return end end source = files.find{|v| v[-11..-1] == 'db/seeds.rb'} prefix_dir_len = source.length - 11 dest = source[prefix_dir_len..-1] if File.exist?(dest) current_contents = File.read(dest).strip # if 'seeds.rb' defines a 'Seeds' class, then we assuming it to be a seeder. is_seeder = false current_contents.split("\n").each do |line| is_seeder = true if /^\s*class\s+Seeds(\s.*)?$/.match(line) end unless is_seeder if ask_for_bool('Would you like to move your \'db/seeds.rb\' file into the \'db/seeds\' directory?', true) perform "> moving '#{dest}' into 'db/seeds' directory..." do File.rename dest, 'db/seeds/' + File.basename(dest) end else tell "> 'db/seeds.rb' is not being moved.", :yellow end end end files.each do |source| dest = source[prefix_dir_len..-1] contents = File.read(source) if File.exist?(dest) && File.read(dest).strip == contents.strip tell "> '#{dest}' is good.", :bright_green else if !File.exist?(dest) || ask_for_bool("Would you like to update '#{dest}'?", true) perform "> #{File.exist?(dest) ? 'creating' : 'updating'} \'#{dest}\'..." do File.write dest, contents end else tell "> '#{dest}' is unchanged.", :bright_green end end end end
# File lib/barkest_core/extensions/generator_extensions.rb, line 222 def perform(message, &block) tell message + (options.pretend? ? ' [pretend]' : ''), :teal block.call unless options.pretend? end
Is the rails server running?
# File lib/barkest_core/extensions/application_extensions.rb, line 6 def running? path = File.join(Rails.root, 'tmp/pids/server.pid') pid = File.exist?(path) ? File.read(path).to_i : -1 server_running = true begin Process.getpgid pid rescue Errno::ESRCH server_running = false end server_running end
# File lib/barkest_core/extensions/generator_extensions.rb, line 12 def tell(message, color = nil) open = '' close = '' if color open = "\033[0" close = "\033[0m" open += case color.to_sym when :black ';30' when :dark_grey, :dark_gray ';30;1' when :red, :dark_red ';31' when :bright_red ';31;1' when :green, :dark_green ';32' when :bright_green ';32;1' when :gold, :dark_yellow ';33' when :yellow ';33;1' when :dark_blue ';34' when :blue ';34;1' when :dark_magenta, :violet, :purple ';35' when :magenta, :pink ';35;1' when :dark_cyan, :teal ';36' when :cyan, :aqua ';36;1' when :light_gray, :gray, :light_grey, :grey ';37' when :white ';37;1' when :bold ';1' else '' end + 'm' end puts open + message + close unless options.quiet? end
# File lib/barkest_core/extensions/generator_extensions.rb, line 261 def trimq(question) question = question.to_s.strip if question[-1] == '?' || question[-1] == ':' question = question[0...-1] end question end