Project

General

Profile

« Previous | Next » 

Revision 76607ed5

Added by Ohad Levy almost 13 years ago

  • ID 76607ed5fc692646c4b31791eea9c71a903e8f17

fixes #100 - Setting is now a ActiveRecord object

This allows users to manage foreman settings via the UI.

the UI is a bit ugly, but works :)

View differences:

app/controllers/hosts_controller.rb
end
def errors
params[:search]="last_report > \"#{SETTINGS[:puppet_interval] + 5} minutes ago\" and (status.failed > 0 or status.failed_restarts > 0)"
params[:search]="last_report > \"#{Setting[:puppet_interval] + 5} minutes ago\" and (status.failed > 0 or status.failed_restarts > 0)"
index "Hosts with errors"
end
def active
params[:search]="last_report > \"#{SETTINGS[:puppet_interval] + 5} minutes ago\" and (status.applied > 0 or status.restarted > 0)"
params[:search]="last_report > \"#{Setting[:puppet_interval] + 5} minutes ago\" and (status.applied > 0 or status.restarted > 0)"
index "Active Hosts"
end
def out_of_sync
params[:search]="last_report < \"#{SETTINGS[:puppet_interval]} minutes ago\" and status.enabled = true"
index "Hosts which didn't run puppet in the last #{SETTINGS[:puppet_interval]} minutes"
params[:search]="last_report < \"#{Setting[:puppet_interval]} minutes ago\" and status.enabled = true"
index "Hosts which didn't run puppet in the last #{Setting[:puppet_interval]} minutes"
end
def disabled
app/controllers/settings_controller.rb
class SettingsController < ApplicationController
include Foreman::Controller::AutoCompleteSearch
def index
values = Setting.search_for(params[:search], :order => params[:order])
respond_to do |format|
format.html do
@settings = values.paginate(:page => params[:page])
end
format.json { render :json => values.all}
end
end
def edit
@setting = Setting.find(params[:id])
end
def update
@setting = Setting.find(params[:id])
if @setting.update_attributes(params[:setting])
process_success
else
process_error
end
end
end
app/helpers/dashboard_helper.rb
module DashboardHelper
def count_reports()
interval = SETTINGS[:puppet_interval] / 10
interval = Setting[:puppet_interval] / 10
counter = []
labels = []
start =Time.now.utc - SETTINGS[:puppet_interval].minutes
(1..(SETTINGS[:puppet_interval] / interval)).each do
start =Time.now.utc - Setting[:puppet_interval].minutes
(1..(Setting[:puppet_interval] / interval)).each do
now = start + interval.minutes
counter << [ Report.count(:all, :conditions => {:reported_at => start..(now-1.second)})]
labels << [ "'#{time_ago_in_words(start.getlocal)}'" ]
......
enabled: false,
},
title: {
text: 'Run Distribution in the last #{SETTINGS[:puppet_interval]} minutes'
text: 'Run Distribution in the last #{Setting[:puppet_interval]} minutes'
},
xAxis: {
categories: [ #{data[:labels].join(' ,')} ] ,
app/helpers/settings_helper.rb
module SettingsHelper
def value f
case f.object.settings_type
when "boolean"
f.select :value, options_for_select(["true", "false"]), :value => f.object.value.to_s
else
f.text_field :value, :value => f.object.value
end
end
end
app/models/environment.rb
unless Rails.env == "test"
# reread puppet configuration
Puppet.clear
Puppet[:config] = SETTINGS[:puppetconfdir] || "/etc/puppet/puppet.conf"
Puppet[:config] = SETTINGS[:puppetconfdir]
end
Puppet.parse_config # Check that puppet.conf has not been edited since the rack application was started
conf = Puppet.settings.instance_variable_get(:@values)
......
end
if env.values.compact.size == 0
# fall back to defaults - we probably don't use environments
env[:production] = conf[:main][:modulepath] || conf[:puppetmasterd][:modulepath] || SETTINGS[:modulepath] || Puppet[:modulepath] || "/etc/puppet/modules"
env[:production] = conf[:main][:modulepath] || conf[:puppetmasterd][:modulepath] || Setting[:modulepath]
end
return env
end
app/models/host.rb
:params, :hostgroup, :domain, :ip, :mac
end
named_scope :recent, lambda { |*args| {:conditions => ["last_report > ?", (args.first || (SETTINGS[:run_interval] + 5.minutes).ago)]} }
named_scope :out_of_sync, lambda { |*args| {:conditions => ["last_report < ? and enabled != ?", (args.first || (SETTINGS[:run_interval] + 5.minutes).ago), false]} }
named_scope :recent, lambda { |*args| {:conditions => ["last_report > ?", (args.first || (Setting[:puppet_interval] + 5).minutes.ago)]} }
named_scope :out_of_sync, lambda { |*args| {:conditions => ["last_report < ? and enabled != ?", (args.first || (Setting[:puppet_interval] + 5).minutes.ago), false]} }
named_scope :with_fact, lambda { |fact,value|
unless fact.nil? or value.nil?
......
end
def no_report
last_report.nil? or last_report < Time.now - (SETTINGS[:run_interval] + 3.minutes) and enabled?
last_report.nil? or last_report < Time.now - (Setting[:puppet_interval] + 3).minutes and enabled?
end
def disabled?
......
# maybe these should be moved to the common parameters, leaving them in for now
param["puppetmaster"] = puppetmaster.to_s
param["domainname"] = domain.fullname unless domain.nil? or domain.fullname.nil?
if SETTINGS[:ignore_puppet_facts_for_provisioning]
if Setting[:ignore_puppet_facts_for_provisioning]
param["ip"] = ip
param["mac"] = mac
end
......
end
def populateFieldsFromFacts
unless SETTINGS[:ignore_puppet_facts_for_provisioning]
unless Setting[:ignore_puppet_facts_for_provisioning]
self.mac = fv(:macaddress).downcase unless fv(:macaddress).blank?
self.ip = fv(:ipaddress) if ip.nil?
end
......
self.arch=Architecture.find_or_create_by_name myarch unless myarch.empty?
end
# by default, puppet doesnt store an env name in the database
env=fv(:environment) || SETTINGS[:default_puppet_environment] || "production"
env=fv(:environment) || Setting[:default_puppet_environment]
self.environment ||= Environment.find_or_create_by_name env
os_name = fv(:operatingsystem)
app/models/host_common.rb
if puppetca?
SmartProxy.find(read_attribute(:puppetproxy_id))
else
read_attribute(:puppetmaster_name) || SETTINGS[:puppet_server] || "puppet"
read_attribute(:puppetmaster_name) || Setting[:puppet_server]
end
end
......
if puppetca?
write_attribute(:puppetproxy_id, pm.id)
else
write_attribute(:puppetmaster_name, pm == (SETTINGS[:puppet_server] || "puppet") ? nil : pm)
write_attribute(:puppetmaster_name, pm == (Setting[:puppet_server]) ? nil : pm)
end
end
# no need to store anything in the db if the password is our default
def root_pass
read_attribute(:root_pass) || SETTINGS[:root_pass] || "!*!*!*!*!"
read_attribute(:root_pass) || Setting[:root_pass]
end
# If the host/hostgroup has a medium then use the path from there
app/models/host_mailer.rb
# options our host list if required
filter = []
if (body[:url] = SETTINGS[:foreman_url]).empty?
if (body[:url] = Setting[:foreman_url]).empty?
raise ":foreman_url: entry in Foreman configuration file, see http://theforeman.org/projects/foreman/wiki/Mail_Notifications"
end
......
# we didnt define a filter, use all hosts instead
hosts=Host
end
email = options[:email] || SETTINGS[:administrator] || User.all(:select => :mail).map(&:mail)
email = options[:email] || Setting[:administrator]
raise "unable to find recipients" if email.empty?
recipients email
from "Foreman-noreply@" + Facter.domain
......
def error_state(report)
host = report.host
email = host.owner.recipients if SETTINGS[:login] and not host.owner.nil?
email = SETTINGS[:administrator] if email.empty?
email = Setting[:administrator] if email.empty?
raise "unable to find recipients" if email.empty?
recipients email
from "Foreman-noreply@" + Facter.domain
app/models/puppetclass.rb
relocated = root != "/" # This is true if the prepare phase copied the modules tree
# Retrieve an optional http server's DocumentRoot from the settings.yaml file, and prepare it for writing
doc_root = Pathname.new(SETTINGS[:document_root] || RAILS_ROOT + "/public") + "puppet/rdoc"
doc_root = Pathname.new(Setting[:document_root])
doc_root.mkpath
unless doc_root.directory? and doc_root.writable?
puts "Unable to write html to #{doc_root}"
app/models/report.rb
r.import_log_messages report
# if we are using storeconfigs then we already have the facts
# so we can refresh foreman internal fields accordingly
host.populateFieldsFromFacts if SETTINGS[:using_storeconfigs]
host.populateFieldsFromFacts if Setting[:using_storeconfigs]
r.inspect_report
return r
rescue Exception => e
......
logger.warn "#{report.host} is disabled - skipping." and return if host.disabled?
logger.debug "error detected, checking if we need to send an email alert"
HostMailer.deliver_error_state(self) if SETTINGS[:failed_report_email_notification]
HostMailer.deliver_error_state(self) if Setting[:failed_report_email_notification]
# add here more actions - e.g. snmp alert etc
end
rescue => e
app/models/setting.rb
class Setting < ActiveRecord::Base
attr_accessible :name, :value, :description, :category, :settings_type, :default
TYPES= %w{ integer boolean hash array }
FROZEN_ATTRS = %w{ name default description category settings_type }
validates_presence_of :name, :description
validates_uniqueness_of :name
validates_numericality_of :value, :if => Proc.new {|s| s.settings_type == "integer"}
validates_inclusion_of :value, :in => [true,false], :if => Proc.new {|s| s.settings_type == "boolean"}
validates_inclusion_of :settings_type, :in => TYPES, :allow_nil => true, :allow_blank => true
serialize :value
serialize :default
before_validation :fix_booleans, :strip_unneeded_value
before_save :save_as_settings_type
validate :validate_attributes
scoped_search :on => :name, :complete_value => :true
scoped_search :on => :category, :complete_value => :true
scoped_search :on => :description, :complete_value => :true
def self.[](name)
if record = first(:conditions => {:name => name.to_s})
record.value
end
end
def self.[]=(name, value)
record = find_or_create_by_name name.to_s
record.value = value
record.save
end
def self.method_missing(method, *args)
super(method, *args)
rescue NoMethodError
method_name = method.to_s
#setter method
if method_name =~ /=$/
self[method_name.chomp("=")] = args.first
#getter
else
self[method_name]
end
end
def value
v = (super.blank? ? default : super)
case settings_type
when "integer"
v = v.to_i
when "boolean"
v = ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(v)
end
v
end
private
def save_as_settings_type
t = default.class.to_s.downcase
if TYPES.include?(t)
self.settings_type = t
else
self.settings_type = "integer" if default.is_a?(Integer)
self.settings_type = "boolean" if default.is_a?(TrueClass) or default.is_a?(FalseClass)
end
end
def fix_booleans
if settings_type = "boolean"
self.value = true if value == "true"
self.value = false if value == "false"
end
end
def strip_unneeded_value
self.value = nil if value == default
end
def self.create_default_settings
domain = Facter.domain
[
set('administrator', "The Default administrator email address", "root@#{domain}"),
set('foreman_url', "The URL where your foreman instance is running on", "http://foreman.#{domain}"),
].each { |s| create s.update(:category => "General")}
[
set('root_pass', "Default ecrypted root password on provisioned hosts default is 123123", "xybxa6JUkz63w"),
set('safemode_render', "Enable safe mode config templates rendinging(recommended)", true),
set('ssl_certificate', "SSL Certificate path that foreman would use to communicate with its proxies", Puppet.settings[:hostcert]),
set('ssl_ca_file', "SSL CA file that foreman would use to communicate with its proxies", Puppet.settings[:localcacert]),
set('ssl_priv_key', "SSL Private Key file that foreman would use to communicate with its proxies", Puppet.settings[:hostprivkey]),
set('ignore_puppet_facts_for_provisioning', "Does not update ipaddress and MAC values from puppet facts", false)
].each { |s| create s.update(:category => "Provisioning")}
[
set('puppet_interval', "Puppet interval in minutes", 30 ),
set('default_puppet_environment',"The Puppet environment foreman would default to in case it can't auto detect it", "production"),
set('modulepath',"The Puppet default module path in case that Foreman can't auto detect it", "/etc/puppet/modules"),
set('document_root', "Document root where puppetdoc files should be created", "#{RAILS_ROOT}/public/puppet/rdoc"),
set('puppetrun', "Enables Puppetrun Support", false),
set('puppet_server', "Default Puppet Server hostname", "puppet"),
set('failed_report_email_notification', "Enable Email Alerts per each failed puppet report", false),
set('using_storeconfigs', "Foreman is sharing its database with Puppet Store configs", (!Puppet.settings.instance_variable_get(:@values)[:master][:dbadapter].empty? rescue false))
].compact.each { |s| create s.update(:category => "Puppet")}
end
def self.set name, description, default, value = nil
value ||= SETTINGS[name.to_sym]
{:name => name, :value => value, :description => description, :default => default}
end
def validate_attributes
return true if new_record?
changed_attributes.keys.each do |c|
if FROZEN_ATTRS.include?(c.to_s)
errors.add(c, "is not allowed to change")
return false
end
end
true
end
end
app/models/user.rb
end
def self.create_admin
email = SETTINGS[:administrator] || "root@" + Facter.domain
email = Setting[:administrator]
user = User.create(:login => "admin", :firstname => "Admin", :lastname => "User",
:mail => email, :auth_source => AuthSourceInternal.first, :password => "changeme")
user.update_attribute :admin, true
app/views/dashboard/index.html.erb
<th>Data</th>
</tr>
<tr class="even">
<td>Good Host Reports in the last <%= SETTINGS[:puppet_interval] %> minutes</td>
<td>Good Host Reports in the last <%= Setting[:puppet_interval] %> minutes</td>
<td> <%= "#{@report[:good_hosts]} / #{@report[:total_hosts]}" %> hosts (<%= @report[:percentage] %>%)</td>
</tr>
<tr class="odd">
app/views/home/_settings.html.erb
['Bookmarks', bookmarks_url],
['Domains', domains_url],
['Environments', environments_url],
['Foreman Settings', settings_url],
['Global Parameters', common_parameters_url],
['Hardware Models', models_url],
['Host Groups', hostgroups_url],
app/views/hosts/show.html.erb
<%= link_to_if_authorized "Cancel Build", hash_for_cancelBuild_host_path(:id => @host).merge(:enable_link => !@host.can_be_build?),
:title => "Cancel build request for this host" %>
<% end -%>
<%= link_to_if_authorized "Run puppet", hash_for_puppetrun_host_path(:id => @host).merge(:auth_action => :edit, :enable_link => SETTINGS[:puppetrun]),
<%= link_to_if_authorized "Run puppet", hash_for_puppetrun_host_path(:id => @host).merge(:auth_action => :edit, :enable_link => Setting[:puppetrun]),
:title => "Trigger a puppetrun on a node; requires that puppet run is enabled" %>
<%= link_to_if_authorized "All Puppet Classes", hash_for_storeconfig_klasses_host_path(:id => @host).merge(:auth_action => :read, :enable_link => @host.resources.count > 0),
:title => "Show all host puppet classes, requires storeconfigs" %>
app/views/settings/edit.html.erb
<% title "Edit Setting" %>
<% form_for @setting do |f| %>
<div class="span-24 last">
<%= f.error_messages %>
<span class="span-8">
<%= f.object %>
</span>
<span class="span-8">
<%= f.label :value %>
<%= value(f) %>
</span>
<span class="span-8 last">
<%= f.object.description %>
</span>
</div>
<div class="span-24 last"><%= f.submit %></div>
<% end %>
app/views/settings/index.html.erb
<% title "Foreman Settings" %>
<table class="list">
<tr>
<th><%= sort :name %></th>
<th>Value</th>
<th>Description</th>
<th><%= sort :category %></th>
<th></th>
</tr>
<% for setting in @settings %>
<tr class="<%= cycle("even", "odd") -%>">
<td><%=h setting.name %></td>
<td><%=h setting.value %></td>
<td><%=h setting.description %></td>
<td><%=h setting.category %></td>
<td><%= link_to "Edit", edit_setting_path(setting) %></td>
</tr>
<% end %>
</table>
<%= page_entries_info @settings %>
<%= will_paginate @settings %>
config/initializers/foreman.rb
SETTINGS= YAML.load_file("#{RAILS_ROOT}/config/settings.yaml")
SETTINGS[:version] = "0.3"
# fallback to a 30 minutes run interval if its not defined
SETTINGS[:puppet_interval] ||= 30
SETTINGS[:run_interval] = SETTINGS[:puppet_interval].minutes
SETTINGS[:unattended] = SETTINGS[:unattended].nil? || SETTINGS[:unattended]
Puppet[:config] = SETTINGS[:puppetconfdir] || "/etc/puppet/puppet.conf"
Puppet.parse_config
$puppet = Puppet.settings.instance_variable_get(:@values) if Rails.env == "test"
# Are we sharing the database with Storeconfigs?
#
begin
SETTINGS[:using_storeconfigs] = !Puppet.settings.instance_variable_get(:@values)[:master][:dbadapter].empty?
rescue
# we can't tell if we share the db or not if we are not running on the same host as the puppetmaster
# therefore the user should set this explicitly it the settings file
end
SETTINGS[:login] ||= SETTINGS[:ldap]
begin
config/routes.rb
:member => {:power => :put}, :requirements => { :id => /[^\.][\w\.-]+/ }
end if SETTINGS[:libvirt]
map.resources :bookmarks, :except => [:show], :requirements => { :id => /[^\/]+/ }
map.resources :settings, :only => [:index, :edit, :update]
map.connect 'unattended/template/:id/:hostgroup', :controller => "unattended", :action => "template"
map.connect '/status', :controller => "home", :action => "status"
db/migrate/20110628115422_create_settings.rb
class CreateSettings < ActiveRecord::Migration
def self.up
create_table :settings do |t|
t.string :name
t.text :value
t.text :description
t.string :category
t.string :settings_type
t.text :default, :null => false
t.timestamps
end
add_index :settings, :name, :unique => true
Setting.create_default_settings
end
def self.down
drop_table :settings
end
end
lib/foreman/renderer.rb
module Renderer
def render_safe template, allowed_methods = [], allowed_vars = {}
if SETTINGS[:safemode_render]
if Setting[:safemode_render]
box = Safemode::Box.new self, allowed_methods
box.eval(ERB.new(template, nil, '-').src, allowed_vars)
else
......
def unattended_render template
allowed_helpers = [ :foreman_url, :grub_pass, :snippet, :snippets, :ks_console, :root_pass ]
allowed_variables = ({:arch => @arch, :host => @host, :osver => @osver, :mediapath => @mediapath, :static => @static,
:yumrepo => @yumrepo, :dynamic => @dynamic, :epel => @epel,
:yumrepo => @yumrepo, :dynamic => @dynamic, :epel => @epel, :kernel => @kernel, :initrd => @initrd,
:preseed_server => @preseed_server, :preseed_path => @preseed_path })
render_safe template, allowed_helpers, allowed_variables
end
lib/proxy_api.rb
# We authenticate only if we are using SSL
if url.match(/^https/i)
cert = SETTINGS[:ssl_certificate] || Puppet.settings[:hostcert]
ca_cert = SETTINGS[:ssl_ca_file] || Puppet.settings[:localcacert]
hostprivkey = SETTINGS[:ssl_private_key] || Puppet.settings[:hostprivkey]
cert = Setting[:ssl_certificate]
ca_cert = Setting[:ssl_ca_file]
hostprivkey = Setting[:ssl_private_key]
# Use update rather than merge! as this is not rails dependent
connect_params.update(
test/fixtures/settings.yml
attributes1:
name: administrator
category: General
default: root@some.host.fqdn
description: The Default administrator email address
attributes2:
name: foreman_url
category: General
default: http://foreman.some.host.fqdn
attributes3:
name: root_pass
category: Provisioning
default: xybxa6JUkz63w
description: Default root password on provisioned hosts default is 123123
attributes4:
name: safemode_render
category: Provisioning
default: t
description: Enable safe mode config templates rendinging(recommended)
attributes5:
name: ssl_certificate
category: Provisioning
default: /var/lib/puppet/ssl/certs/some.host.fqdn
description: SSL Certificate path that foreman would use to communicate with its proxies
attributes6:
name: ssl_ca_file
category: Provisioning
default: /var/lib/puppet/ssl/certs/ca.pem
description: SSL CA file that foreman would use to communicate with its proxies
attributes7:
name: ssl_priv_key
category: Provisioning
default: /var/lib/puppet/ssl/private_keys/super.some.host.fqdn.pem
description: SSL Private Key file that foreman would use to communicate with its proxies
attributes8:
name: puppet_interval
settings_type: integer
category: Puppet
default: "30"
description: Puppet interval in minutes
attributes9:
name: default_puppet_environment
category: Puppet
default: production
description: "The Puppet environment foreman would default to in case it can't auto detect it"
attributes10:
name: modulepath
category: Puppet
default: /etc/puppet/modules
description: "The Puppet default module path in case that Foreman can't auto detect it"
attributes11:
name: document_root
category: Puppet
default: /home/olevy/git/foreman/public/puppet/rdoc
description: Document root where puppetdoc files should be created
attributes12:
name: puppet_server
category: Puppet
default: puppet
description: Default Puppet Server hostname
attributes13:
name: failed_report_email_notification
category: Puppet
default: false
description: Enable Email Alerts per each failed puppet report
test/functional/settings_controller_test.rb
require 'test_helper'
class SettingsControllerTest < ActionController::TestCase
def test_index
get :index
assert_template 'index'
end
def test_edit
get :edit, :id => Setting.first
assert_template 'edit'
end
def test_update_invalid
Setting.any_instance.stubs(:valid?).returns(false)
put :update, :id => Setting.first
assert_template 'edit'
end
def test_update_valid
Setting.any_instance.stubs(:valid?).returns(true)
put :update, :id => Setting.first
assert_redirected_to settings_url
end
end
test/test_helper.rb
# -- they do not yet inherit this setting
fixtures :all
# Add more helper methods to be used by all tests here...
def logger
RAILS_DEFAULT_LOGGER
end
test/unit/host_mailer_test.rb
@env.save
end
User.current = User.find_by_login "admin"
SETTINGS[:foreman_url] = "http://localhost:3000/hosts/:id"
Setting[:foreman_url] = "http://localhost:3000/hosts/:id"
@options = {}
@options[:env] = @env
......
test "mail should have admin as recipient if email is not defined" do
@options[:email] = nil
SETTINGS[:administrator] = "admin@vurbia.com"
Setting[:administrator] = "admin@vurbia.com"
assert HostMailer.deliver_summary(@options).to.include?("admin@vurbia.com")
end
test "mail should have any recipient if email or admin are not defined" do
user = User.create :mail => "chuck.norris@vurbia.com", :login => "Chuck_Norris", :auth_source => auth_sources(:one)
assert user.valid?
@options[:email] = nil
SETTINGS[:administrator] = nil
assert HostMailer.deliver_summary(@options).to.include?("chuck.norris@vurbia.com")
end
test "mail should have a subject" do
assert !HostMailer.deliver_summary(@options).subject.empty?
end
test/unit/report_test.rb
def setup_for_email_reporting
# Email recepient
SETTINGS[:administrator] = "admin@example.com"
SETTINGS[:failed_report_email_notification] = true
Setting[:administrator] = "admin@example.com"
Setting[:failed_report_email_notification] = true
end
test "when notification fails, if report has an error a mail to admin should be sent" do
......
test "when notification doesn't fails, if report has an error, no mail should be sent" do
setup_for_email_reporting
SETTINGS[:failed_report_email_notification] = false
Setting[:failed_report_email_notification] = false
assert_no_difference 'ActionMailer::Base.deliveries.size' do
Report.import File.read(File.expand_path(File.dirname(__FILE__) + "/../fixtures/report-errors.yaml"))
end
test/unit/setting_test.rb
require 'test_helper'
class SettingTest < ActiveSupport::TestCase
def test_settings_should_save_complex_types
assert (Setting.create(:name => "foo", :value => [1,2,3,'b'], :default => ['b',"b"], :description => "test foo" ))
s = Setting.find_by_name "foo"
assert_equal [1,2,3,'b'], s.value
assert_equal ['b',"b"], s.default
assert_equal "array", s.settings_type
end
def test_should_not_find_a_value_if_doesnt_exists
assert_nil Setting["no_such_thing"]
end
def test_should_provide_default_if_no_value_defined
assert Setting.create(:name => "foo", :default => 5, :description => "test foo")
assert_equal 5, Setting["foo"]
end
def test_should_find_setting_via_method_missing_too
assert Setting.create(:name => "bar", :value => "baz", :default => "x", :description => "test bar")
assert_equal Setting["bar"], Setting.bar
assert_equal "baz", Setting.bar
end
def test_settings_with_the_same_value_as_default_should_save_the_value
assert Setting.create(:name => "foo", :value => "bar", :default => "bar", :description => "x")
s = Setting.find_by_name "foo"
assert_nil s.read_attribute(:value)
assert_equal "bar", Setting.foo
end
def test_should_save_settings_type
assert Setting.create(:name => "foo", :default => 5, :description => "test foo")
assert_equal "integer", Setting.find_by_name("foo").try(:settings_type)
end
def test_should_not_allowed_to_change_frozen_attributes
assert Setting.create(:name => "foo", :default => 5, :description => "test foo")
s = Setting.find_by_name "foo"
s.name = "boo"
assert !s.save
assert_equal s.errors[:name], "is not allowed to change"
end
def test_name_could_be_a_symbol_or_a_string
assert Setting.create(:name => "foo", :default => 5, :description => "test foo")
assert_equal Setting["foo"], Setting[:foo]
Setting[:foo] = 3
assert_equal 3,Setting["foo"]
end
def test_boolean_values_should_have_setting_type_for_false
assert Setting.create(:name => "oo", :default => false, :description => "test foo")
assert_equal "boolean", Setting.find_by_name("oo").settings_type
assert_equal false, Setting["oo"]
end
def test_boolean_values_should_have_setting_type_for_true
assert Setting.create(:name => "oo", :default => true, :description => "test foo")
assert_equal "boolean", Setting.find_by_name("oo").settings_type
assert_equal true, Setting["oo"]
end
end

Also available in: Unified diff