jbarnette (owner)

Revisions

gist: 67040 Download_button fork
public
Public Clone URL: git://gist.github.com/67040.git
Embed All Files: show embed
config/initializers/model_templates.rb #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
module ModelTemplates
  @@cache = {}
  def self.cache; @@cache end
 
  def self.included target
    target.extend ClassMethods
  end
 
  def assign_model_template_attributes model, attributes
    model.send :attributes=, attributes, false
    model
  end
 
  def valid_model_template_attributes klass, extras = {}
    defaults, block = ModelTemplates.cache[klass]
    lazy = block && instance_eval(&block)
    sources = [defaults, lazy, extras].compact
    sources.inject { |t, s| t.merge s }
  end
 
  def valid_model_template_attributes_without klass, excluded
    valid_model_template_attributes(klass).delete_if do |k, v|
      excluded.include? k
    end
  end
 
  module ClassMethods
    def model_template_for klass, defaults = {}, &block
      if defaults.empty? && !block
        raise "default attributes or lazy block required"
      end
 
      ModelTemplates.cache[klass] = [defaults, block]
 
      klass = klass.name
      model = klass.underscore
 
      module_eval <<-END, __FILE__, __LINE__ + 1
def valid_#{model}_attributes extras = {}
valid_model_template_attributes #{klass}, extras
end
 
def valid_#{model}_attributes_without *excluded
valid_model_template_attributes_without #{klass}, excluded
end
 
def new_#{model} extras = {}
assign_model_template_attributes #{klass}.new,
valid_model_template_attributes(#{klass}, extras)
end
 
def new_#{model}_without *excluded
assign_model_template_attributes #{klass}.new,
valid_model_template_attributes_without(#{klass}, excluded)
end
 
def create_#{model} extras = {}
(m = new_#{model}(extras)).save; m
end
 
def create_#{model}! extras = {}
(m = new_#{model}(extras)).save!; m
end
 
def create_#{model}_without *excluded
(m = new_#{model}_without(*excluded)).save; m
end
 
def create_#{model}_without! *excluded
(m = new_#{model}_without(*excluded)).save!; m
end
END
 
      file, line = caller.first.split ":"
 
      eval <<-END, nil, file, line.to_i - 2
class ::ModelTemplateFor#{klass}Test < ActiveSupport::TestCase
def test_model_template_for_#{model} # hence the - 2 above
assert (m = new_#{model}).valid?,
"#{klass} template is invalid: " +
m.errors.full_messages.to_sentence
end
end
END
    end
  end
end
 
test/test_helper.rb #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Test::Unit::TestCase
  include ModelTemplates
 
  # Model templates can be specified as a simple hash,
 
  model_template_for User, :name => "Horace Angrypants"
 
  # or as a lazily-evaluated block (which is useful if you want to use
  # fixtures or other model templates).
 
  model_template_for User do
    { :name => "Horace Angrypants", :address => addresses(:default) }
  end
 
  # Either of these invocations will create a bunch of instance methods:
  #
  # def valid_user_attributes(extras = {})
  # def valid_user_attributes_without(*excluded)
  # def new_user(extras = {})
  # def new_user_without(*excluded)
  # def create_user(extras = {})
  # def create_user!(extras = {})
  # def create_user_without(*excluded)
  # def create_user_without!(*excluded)
  #
  # It'll also dynamically generate a test case to make sure the
  # template you sepecified creates a valid user:
  #
  # class ::ModelTemplateForUserTest < Test::Unit::TestCase
  # def test_model_template_for_user
  # assert (m = new_user).valid?,
  # "User template is invalid: " +
  # m.errors.full_messages.to_sentence
  # end
  # end
end
 
test/unit/user_test.rb #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
require 'test_helper'
 
class UserTest < ActiveSupport::TestCase
  def test_requires_a_skin
    assert_invalid(create_user_without(:skin), :skin)
  end
  
  def test_requires_an_address
    assert_invalid(create_user_without(:address), :address)
  end
  
  def test_requires_a_name
    assert_invalid(create_user_without(:name), :name)
  end
  
  def _test_requires_a_company_less_than_255_chars_if_specified
    assert_invalid(create_user(:company => 'xx' * 255), :company)
  end
  
  def test_requires_a_name_between_2_and_255_chars
    assert_invalid(create_user(:name => 'x'), :name)
    assert_invalid(create_user(:name => 'xx' * 255), :name)
  end
  
  def test_requires_an_email
    assert_invalid(create_user_without(:email), :email)
  end
  
  def test_requires_an_email_between_6_and_255_chars
    assert_invalid(create_user(:email => 'xxx'), :email)
    assert_invalid(create_user(:email => 'xxx' * 255), :email)
  end
  
  def test_emails_are_unique_per_skin
    assert_valid(create_user(:email => users(:other).email))
    assert_invalid(create_user(:email => users(:default).email), :email)
  end
  
  def test_requires_a_password
    assert_invalid(create_user_without(:password), :password)
  end
 
  def test_requires_a_password_confirmation
    assert_invalid(create_user_without(:password_confirmation), :password_confirmation)
  end
  
  def test_requires_password_and_confirmation_to_match
    assert_invalid(create_user(:password_confirmation => "bluh"), :password)
  end
  
  def test_initially_has_an_empty_hashed_password
    assert_nil(User.new.hashed_password)
  end
  
  def test_password_is_not_a_persistent_attribute
    assert_nil(users(:default).password)
  end
  
  def test_password_is_hashed_and_salted_on_save
    user = create_user
    assert_not_nil(user.hashed_password)
    assert_not_nil(user.password_salt)
  end
  
  def test_password_is_not_required_when_saving_changes
    user = users(:default)
    user.name = "Petronius the Arbiter"
    assert_valid(user)
  end
  
  def test_isnt_admin_by_default
    assert(!create_user.admin?, "shouldn't be admin")
  end
end