shoulda 2.0.6 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. data/README.rdoc +35 -7
  2. data/Rakefile +5 -3
  3. data/lib/shoulda.rb +7 -15
  4. data/lib/shoulda/action_mailer.rb +1 -1
  5. data/lib/shoulda/action_mailer/assertions.rb +32 -33
  6. data/lib/shoulda/active_record.rb +6 -2
  7. data/lib/shoulda/active_record/assertions.rb +62 -81
  8. data/lib/shoulda/active_record/helpers.rb +40 -0
  9. data/lib/shoulda/active_record/macros.rb +518 -639
  10. data/lib/shoulda/active_record/matchers.rb +42 -0
  11. data/lib/shoulda/active_record/matchers/allow_mass_assignment_of_matcher.rb +83 -0
  12. data/lib/shoulda/active_record/matchers/allow_value_matcher.rb +102 -0
  13. data/lib/shoulda/active_record/matchers/association_matcher.rb +226 -0
  14. data/lib/shoulda/active_record/matchers/ensure_inclusion_of_matcher.rb +87 -0
  15. data/lib/shoulda/active_record/matchers/ensure_length_of_matcher.rb +141 -0
  16. data/lib/shoulda/active_record/matchers/have_db_column_matcher.rb +169 -0
  17. data/lib/shoulda/active_record/matchers/have_index_matcher.rb +105 -0
  18. data/lib/shoulda/active_record/matchers/have_named_scope_matcher.rb +125 -0
  19. data/lib/shoulda/active_record/matchers/have_readonly_attribute_matcher.rb +59 -0
  20. data/lib/shoulda/active_record/matchers/validate_acceptance_of_matcher.rb +41 -0
  21. data/lib/shoulda/active_record/matchers/validate_numericality_of_matcher.rb +39 -0
  22. data/lib/shoulda/active_record/matchers/validate_presence_of_matcher.rb +60 -0
  23. data/lib/shoulda/active_record/matchers/validate_uniqueness_of_matcher.rb +148 -0
  24. data/lib/shoulda/active_record/matchers/validation_matcher.rb +56 -0
  25. data/lib/shoulda/assertions.rb +50 -40
  26. data/lib/shoulda/autoload_macros.rb +46 -0
  27. data/lib/shoulda/context.rb +124 -126
  28. data/lib/shoulda/controller.rb +8 -8
  29. data/lib/shoulda/controller/formats/html.rb +158 -160
  30. data/lib/shoulda/controller/formats/xml.rb +132 -134
  31. data/lib/shoulda/controller/helpers.rb +51 -53
  32. data/lib/shoulda/controller/macros.rb +278 -258
  33. data/lib/shoulda/controller/resource_options.rb +211 -214
  34. data/lib/shoulda/helpers.rb +5 -7
  35. data/lib/shoulda/macros.rb +63 -64
  36. data/lib/shoulda/private_helpers.rb +16 -18
  37. data/lib/shoulda/rails.rb +1 -8
  38. data/lib/shoulda/rspec.rb +5 -0
  39. data/lib/shoulda/tasks/list_tests.rake +6 -1
  40. data/lib/shoulda/test_unit.rb +19 -0
  41. data/rails/init.rb +1 -1
  42. data/test/README +2 -2
  43. data/test/fail_macros.rb +16 -16
  44. data/test/functional/posts_controller_test.rb +5 -2
  45. data/test/matchers/allow_mass_assignment_of_matcher_test.rb +68 -0
  46. data/test/matchers/allow_value_matcher_test.rb +41 -0
  47. data/test/matchers/association_matcher_test.rb +258 -0
  48. data/test/matchers/ensure_inclusion_of_matcher_test.rb +80 -0
  49. data/test/matchers/ensure_length_of_matcher_test.rb +158 -0
  50. data/test/matchers/have_db_column_matcher_test.rb +169 -0
  51. data/test/matchers/have_index_matcher_test.rb +74 -0
  52. data/test/matchers/have_named_scope_matcher_test.rb +65 -0
  53. data/test/matchers/have_readonly_attributes_matcher_test.rb +29 -0
  54. data/test/matchers/validate_acceptance_of_matcher_test.rb +44 -0
  55. data/test/matchers/validate_numericality_of_matcher_test.rb +52 -0
  56. data/test/matchers/validate_presence_of_matcher_test.rb +86 -0
  57. data/test/matchers/validate_uniqueness_of_matcher_test.rb +141 -0
  58. data/test/model_builder.rb +61 -0
  59. data/test/other/autoload_macro_test.rb +18 -0
  60. data/test/other/helpers_test.rb +58 -0
  61. data/test/other/private_helpers_test.rb +1 -1
  62. data/test/other/should_test.rb +16 -16
  63. data/test/rails_root/app/controllers/posts_controller.rb +6 -5
  64. data/test/rails_root/app/models/pets/dog.rb +10 -0
  65. data/test/rails_root/app/models/treat.rb +3 -0
  66. data/test/rails_root/app/models/user.rb +2 -2
  67. data/test/rails_root/app/views/layouts/posts.rhtml +2 -0
  68. data/test/rails_root/config/database.yml +1 -1
  69. data/test/rails_root/config/environments/{sqlite3.rb → test.rb} +0 -0
  70. data/test/rails_root/db/migrate/001_create_users.rb +3 -2
  71. data/test/rails_root/db/migrate/011_create_treats.rb +12 -0
  72. data/test/rails_root/log/test.log +0 -0
  73. data/test/rails_root/test/shoulda_macros/custom_macro.rb +6 -0
  74. data/test/rails_root/vendor/gems/gem_with_macro-0.0.1/shoulda_macros/gem_macro.rb +6 -0
  75. data/test/rails_root/vendor/plugins/plugin_with_macro/shoulda_macros/plugin_macro.rb +6 -0
  76. data/test/test_helper.rb +3 -1
  77. data/test/unit/address_test.rb +1 -1
  78. data/test/unit/dog_test.rb +5 -2
  79. data/test/unit/post_test.rb +7 -3
  80. data/test/unit/product_test.rb +2 -2
  81. data/test/unit/tag_test.rb +2 -1
  82. data/test/unit/user_test.rb +17 -8
  83. metadata +44 -4
  84. data/test/rails_root/app/models/dog.rb +0 -5
@@ -1,74 +1,73 @@
1
1
  require 'shoulda/private_helpers'
2
2
 
3
- module ThoughtBot # :nodoc:
4
- module Shoulda # :nodoc:
5
- module Macros
6
- # Macro that creates a test asserting a change between the return value
7
- # of an expression that is run before and after the current setup block
8
- # is run. This is similar to Active Support's <tt>assert_difference</tt>
9
- # assertion, but supports more than just numeric values. See also
10
- # should_not_change.
11
- #
12
- # Example:
13
- #
14
- # context "Creating a post" do
15
- # setup { Post.create }
16
- # should_change "Post.count", :by => 1
17
- # end
18
- #
19
- # As shown in this example, the <tt>:by</tt> option expects a numeric
20
- # difference between the before and after values of the expression. You
21
- # may also specify <tt>:from</tt> and <tt>:to</tt> options:
22
- #
23
- # should_change "Post.count", :from => 0, :to => 1
24
- # should_change "@post.title", :from => "old", :to => "new"
25
- #
26
- # Combinations of <tt>:by</tt>, <tt>:from</tt>, and <tt>:to</tt> are allowed:
27
- #
28
- # should_change "@post.title" # => assert the value changed in some way
29
- # should_change "@post.title", :from => "old" # => assert the value changed to anything other than "old"
30
- # should_change "@post.title", :to => "new" # => assert the value changed from anything other than "new"
31
- def should_change(expression, options = {})
32
- by, from, to = get_options!([options], :by, :from, :to)
33
- stmt = "change #{expression.inspect}"
34
- stmt << " from #{from.inspect}" if from
35
- stmt << " to #{to.inspect}" if to
36
- stmt << " by #{by.inspect}" if by
3
+ module Shoulda # :nodoc:
4
+ module Macros
5
+ # Macro that creates a test asserting a change between the return value
6
+ # of an expression that is run before and after the current setup block
7
+ # is run. This is similar to Active Support's <tt>assert_difference</tt>
8
+ # assertion, but supports more than just numeric values. See also
9
+ # should_not_change.
10
+ #
11
+ # Example:
12
+ #
13
+ # context "Creating a post" do
14
+ # setup { Post.create }
15
+ # should_change "Post.count", :by => 1
16
+ # end
17
+ #
18
+ # As shown in this example, the <tt>:by</tt> option expects a numeric
19
+ # difference between the before and after values of the expression. You
20
+ # may also specify <tt>:from</tt> and <tt>:to</tt> options:
21
+ #
22
+ # should_change "Post.count", :from => 0, :to => 1
23
+ # should_change "@post.title", :from => "old", :to => "new"
24
+ #
25
+ # Combinations of <tt>:by</tt>, <tt>:from</tt>, and <tt>:to</tt> are allowed:
26
+ #
27
+ # should_change "@post.title" # => assert the value changed in some way
28
+ # should_change "@post.title", :from => "old" # => assert the value changed to anything other than "old"
29
+ # should_change "@post.title", :to => "new" # => assert the value changed from anything other than "new"
30
+ def should_change(expression, options = {})
31
+ by, from, to = get_options!([options], :by, :from, :to)
32
+ stmt = "change #{expression.inspect}"
33
+ stmt << " from #{from.inspect}" if from
34
+ stmt << " to #{to.inspect}" if to
35
+ stmt << " by #{by.inspect}" if by
37
36
 
38
- expression_eval = lambda { eval(expression) }
39
- before = lambda { @_before_should_change = expression_eval.bind(self).call }
40
- should stmt, :before => before do
41
- old_value = @_before_should_change
42
- new_value = expression_eval.bind(self).call
43
- assert_operator from, :===, old_value, "#{expression.inspect} did not originally match #{from.inspect}" if from
44
- assert_not_equal old_value, new_value, "#{expression.inspect} did not change" unless by == 0
45
- assert_operator to, :===, new_value, "#{expression.inspect} was not changed to match #{to.inspect}" if to
46
- assert_equal old_value + by, new_value if by
47
- end
37
+ expression_eval = lambda { eval(expression) }
38
+ before = lambda { @_before_should_change = expression_eval.bind(self).call }
39
+ should stmt, :before => before do
40
+ old_value = @_before_should_change
41
+ new_value = expression_eval.bind(self).call
42
+ assert_operator from, :===, old_value, "#{expression.inspect} did not originally match #{from.inspect}" if from
43
+ assert_not_equal old_value, new_value, "#{expression.inspect} did not change" unless by == 0
44
+ assert_operator to, :===, new_value, "#{expression.inspect} was not changed to match #{to.inspect}" if to
45
+ assert_equal old_value + by, new_value if by
48
46
  end
47
+ end
49
48
 
50
- # Macro that creates a test asserting no change between the return value
51
- # of an expression that is run before and after the current setup block
52
- # is run. This is the logical opposite of should_change.
53
- #
54
- # Example:
55
- #
56
- # context "Updating a post" do
57
- # setup { @post.update_attributes(:title => "new") }
58
- # should_not_change "Post.count"
59
- # end
60
- def should_not_change(expression)
61
- expression_eval = lambda { eval(expression) }
62
- before = lambda { @_before_should_not_change = expression_eval.bind(self).call }
63
- should "not change #{expression.inspect}", :before => before do
64
- new_value = expression_eval.bind(self).call
65
- assert_equal @_before_should_not_change, new_value, "#{expression.inspect} changed"
66
- end
49
+ # Macro that creates a test asserting no change between the return value
50
+ # of an expression that is run before and after the current setup block
51
+ # is run. This is the logical opposite of should_change.
52
+ #
53
+ # Example:
54
+ #
55
+ # context "Updating a post" do
56
+ # setup { @post.update_attributes(:title => "new") }
57
+ # should_not_change "Post.count"
58
+ # end
59
+ def should_not_change(expression)
60
+ expression_eval = lambda { eval(expression) }
61
+ before = lambda { @_before_should_not_change = expression_eval.bind(self).call }
62
+ should "not change #{expression.inspect}", :before => before do
63
+ new_value = expression_eval.bind(self).call
64
+ assert_equal @_before_should_not_change, new_value, "#{expression.inspect} changed"
67
65
  end
66
+ end
68
67
 
69
- private
68
+ private
70
69
 
71
- include ThoughtBot::Shoulda::Private
72
- end
70
+ include Shoulda::Private
73
71
  end
74
72
  end
73
+
@@ -1,22 +1,20 @@
1
- module ThoughtBot # :nodoc:
2
- module Shoulda # :nodoc:
3
- module Private # :nodoc:
4
- # Returns the values for the entries in the args hash who's keys are listed in the wanted array.
5
- # Will raise if there are keys in the args hash that aren't listed.
6
- def get_options!(args, *wanted)
7
- ret = []
8
- opts = (args.last.is_a?(Hash) ? args.pop : {})
9
- wanted.each {|w| ret << opts.delete(w)}
10
- raise ArgumentError, "Unsupported options given: #{opts.keys.join(', ')}" unless opts.keys.empty?
11
- return *ret
12
- end
1
+ module Shoulda # :nodoc:
2
+ module Private # :nodoc:
3
+ # Returns the values for the entries in the args hash who's keys are listed in the wanted array.
4
+ # Will raise if there are keys in the args hash that aren't listed.
5
+ def get_options!(args, *wanted)
6
+ ret = []
7
+ opts = (args.last.is_a?(Hash) ? args.pop : {})
8
+ wanted.each {|w| ret << opts.delete(w)}
9
+ raise ArgumentError, "Unsupported options given: #{opts.keys.join(', ')}" unless opts.keys.empty?
10
+ return *ret
11
+ end
13
12
 
14
- # Returns the model class constant, as determined by the test class name.
15
- #
16
- # class TestUser; model_class; end => User
17
- def model_class
18
- self.name.gsub(/Test$/, '').constantize
19
- end
13
+ # Returns the model class constant, as determined by the test class name.
14
+ #
15
+ # class TestUser; model_class; end => User
16
+ def model_class
17
+ self.name.gsub(/Test$/, '').constantize
20
18
  end
21
19
  end
22
20
  end
data/lib/shoulda/rails.rb CHANGED
@@ -8,12 +8,5 @@ require 'shoulda/action_mailer' if defined? ActionMailer::Base
8
8
 
9
9
  if defined?(RAILS_ROOT)
10
10
  # load in the 3rd party macros from vendorized plugins and gems
11
- Dir[File.join(RAILS_ROOT, "vendor", "{plugins,gems}", "*", "shoulda_macros", "*.rb")].each do |macro_file_path|
12
- require macro_file_path
13
- end
14
-
15
- # load in the local application specific macros
16
- Dir[File.join(RAILS_ROOT, "test", "shoulda_macros", "*.rb")].each do |macro_file_path|
17
- require macro_file_path
18
- end
11
+ Shoulda.autoload_macros RAILS_ROOT, File.join("vendor", "{plugins,gems}", "*")
19
12
  end
@@ -0,0 +1,5 @@
1
+ require 'shoulda/active_record/matchers'
2
+
3
+ Spec::Runner.configure do |config|
4
+ config.include Shoulda::ActiveRecord::Matchers, :type => :model
5
+ end
@@ -13,7 +13,12 @@ namespace :shoulda do
13
13
  test_files = Dir.glob(File.join('test', '**', '*_test.rb'))
14
14
  test_files.each do |file|
15
15
  load file
16
- klass = File.basename(file, '.rb').classify.constantize
16
+ klass = File.basename(file, '.rb').classify
17
+ unless Object.const_defined?(klass.to_s)
18
+ puts "Skipping #{klass} because it doesn't map to a Class"
19
+ next
20
+ end
21
+ klass = klass.constantize
17
22
 
18
23
  puts klass.name.gsub('Test', '')
19
24
 
@@ -0,0 +1,19 @@
1
+ require 'shoulda/context'
2
+ require 'shoulda/proc_extensions'
3
+ require 'shoulda/assertions'
4
+ require 'shoulda/macros'
5
+ require 'shoulda/helpers'
6
+ require 'shoulda/autoload_macros'
7
+ require 'shoulda/rails' if defined? RAILS_ROOT
8
+
9
+ module Test # :nodoc: all
10
+ module Unit
11
+ class TestCase
12
+ extend Shoulda::ClassMethods
13
+ include Shoulda::Assertions
14
+ extend Shoulda::Macros
15
+ include Shoulda::Helpers
16
+ end
17
+ end
18
+ end
19
+
data/rails/init.rb CHANGED
@@ -1 +1 @@
1
- require 'shoulda/rails'
1
+ require 'shoulda/rails' if RAILS_ENV == 'test'
data/test/README CHANGED
@@ -6,7 +6,7 @@ The test directory contains the following files and subdirectories:
6
6
 
7
7
  * rails_root - contains the stripped down rails application that the tests run against. The rails root contains:
8
8
  ** the models, controllers, and views defined under app/
9
- ** the sqlite3.rb environment file
9
+ ** the test.rb environment file
10
10
  ** a migration file for each model
11
11
  ** a shoulda initializer that simulates loading the plugin but without relying on vendor/plugins
12
12
  * fixtures - contain the sample DB data for each model
@@ -14,7 +14,7 @@ The test directory contains the following files and subdirectories:
14
14
  * unit - model tests for each of the models under rails_root/app
15
15
  * other - tests for the shoulda contexts, should statements, and assertions
16
16
  * test_helper.rb - responsible for initializing the test environment
17
- ** sets the rails_env to sqlite3
17
+ ** sets the rails_env to test
18
18
  ** sets the rails_root
19
19
  ** runs all the migrations against the in-memory sqlite3 db
20
20
  ** adds some magic to load the right fixture files
data/test/fail_macros.rb CHANGED
@@ -1,15 +1,15 @@
1
- module Thoughtbot
2
- module Shoulda
3
- class << self
4
- attr_accessor :expected_exceptions
5
- end
1
+ module Shoulda
2
+ class << self
3
+ attr_accessor :expected_exceptions
4
+ end
6
5
 
6
+ module ClassMethods
7
7
  # Enables the core shoulda test suite to test for failure scenarios. For
8
8
  # example, to ensure that a set of test macros should fail, do this:
9
9
  #
10
10
  # should_fail do
11
- # should_require_attributes :comments
12
- # should_protect_attributes :name
11
+ # should_validate_presence_of :comments
12
+ # should_not_allow_mass_assignment_of :name
13
13
  # end
14
14
  def should_fail(&block)
15
15
  context "should fail when trying to run:" do
@@ -18,17 +18,17 @@ module Thoughtbot
18
18
  Shoulda.expected_exceptions = nil
19
19
  end
20
20
  end
21
+ end
21
22
 
22
- class Context
23
- # alias_method_chain hack to allow the should_fail macro to work
24
- def should_with_failure_scenario(name, options = {}, &block)
25
- if Shoulda.expected_exceptions
26
- expected_exceptions = Shoulda.expected_exceptions
27
- failure_block = lambda { assert_raise(*expected_exceptions, &block.bind(self)) }
28
- end
29
- should_without_failure_scenario(name, options, &(failure_block || block))
23
+ class Context
24
+ # alias_method_chain hack to allow the should_fail macro to work
25
+ def should_with_failure_scenario(name, options = {}, &block)
26
+ if Shoulda.expected_exceptions
27
+ expected_exceptions = Shoulda.expected_exceptions
28
+ failure_block = lambda { assert_raise(*expected_exceptions, &block.bind(self)) }
30
29
  end
31
- alias_method_chain :should, :failure_scenario
30
+ should_without_failure_scenario(name, options, &(failure_block || block))
32
31
  end
32
+ alias_method_chain :should, :failure_scenario
33
33
  end
34
34
  end
@@ -13,7 +13,7 @@ class PostsControllerTest < Test::Unit::TestCase
13
13
  @response = ActionController::TestResponse.new
14
14
  @post = Post.find(:first)
15
15
  end
16
-
16
+
17
17
  # autodetects the :controller
18
18
  should_route :get, '/posts', :action => :index
19
19
  # explicitly specify :controller
@@ -24,7 +24,7 @@ class PostsControllerTest < Test::Unit::TestCase
24
24
  should_route :put, '/posts/1', :action => :update, :id => "1"
25
25
  should_route :delete, '/posts/1', :action => :destroy, :id => 1
26
26
  should_route :get, '/posts/new', :action => :new
27
-
27
+
28
28
  # Test the nested routes
29
29
  should_route :get, '/users/5/posts', :action => :index, :user_id => 5
30
30
  should_route :post, '/users/5/posts', :action => :create, :user_id => 5
@@ -73,6 +73,8 @@ class PostsControllerTest < Test::Unit::TestCase
73
73
  end
74
74
  should_assign_to :posts
75
75
  should_not_assign_to :foo, :bar
76
+ should_render_page_with_metadata :description => /Posts/, :title => /index/
77
+ should_render_page_with_metadata :keywords => "posts"
76
78
  end
77
79
 
78
80
  context "viewing posts for a user with rss format" do
@@ -94,6 +96,7 @@ class PostsControllerTest < Test::Unit::TestCase
94
96
  setup { get :show, :user_id => users(:first), :id => posts(:first) }
95
97
  should_render_with_layout 'wide'
96
98
  should_render_with_layout :wide
99
+ should_assign_to :false_flag
97
100
  end
98
101
 
99
102
  context "on GET to #new" do
@@ -0,0 +1,68 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
+
3
+ class AllowMassAssignmentOfMatcherTest < Test::Unit::TestCase # :nodoc:
4
+
5
+ context "an attribute that is blacklisted from mass-assignment" do
6
+ setup do
7
+ define_model :example, :attr => :string do
8
+ attr_protected :attr
9
+ end
10
+ @model = Example.new
11
+ end
12
+
13
+ should "reject being mass-assignable" do
14
+ assert_rejects allow_mass_assignment_of(:attr), @model
15
+ end
16
+ end
17
+
18
+ context "an attribute that is not whitelisted for mass-assignment" do
19
+ setup do
20
+ define_model :example, :attr => :string, :other => :string do
21
+ attr_accessible :other
22
+ end
23
+ @model = Example.new
24
+ end
25
+
26
+ should "reject being mass-assignable" do
27
+ assert_rejects allow_mass_assignment_of(:attr), @model
28
+ end
29
+ end
30
+
31
+ context "an attribute that is whitelisted for mass-assignment" do
32
+ setup do
33
+ define_model :example, :attr => :string do
34
+ attr_accessible :attr
35
+ end
36
+ @model = Example.new
37
+ end
38
+
39
+ should "accept being mass-assignable" do
40
+ assert_accepts allow_mass_assignment_of(:attr), @model
41
+ end
42
+ end
43
+
44
+ context "an attribute not included in the mass-assignment blacklist" do
45
+ setup do
46
+ define_model :example, :attr => :string, :other => :string do
47
+ attr_protected :other
48
+ end
49
+ @model = Example.new
50
+ end
51
+
52
+ should "accept being mass-assignable" do
53
+ assert_accepts allow_mass_assignment_of(:attr), @model
54
+ end
55
+ end
56
+
57
+ context "an attribute on a class with no protected attributes" do
58
+ setup do
59
+ define_model :example, :attr => :string
60
+ @model = Example.new
61
+ end
62
+
63
+ should "accept being mass-assignable" do
64
+ assert_accepts allow_mass_assignment_of(:attr), @model
65
+ end
66
+ end
67
+
68
+ end
@@ -0,0 +1,41 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
+
3
+ class AllowValueMatcherTest < Test::Unit::TestCase # :nodoc:
4
+
5
+ context "an attribute with a format validation" do
6
+ setup do
7
+ define_model :example, :attr => :string do
8
+ validates_format_of :attr, :with => /abc/
9
+ end
10
+ @model = Example.new
11
+ end
12
+
13
+ should "allow a good value" do
14
+ assert_accepts allow_value("abcde").for(:attr), @model
15
+ end
16
+
17
+ should "not allow a bad value" do
18
+ assert_rejects allow_value("xyz").for(:attr), @model
19
+ end
20
+ end
21
+
22
+ context "an attribute with a format validation and a custom message" do
23
+ setup do
24
+ define_model :example, :attr => :string do
25
+ validates_format_of :attr, :with => /abc/, :message => 'bad value'
26
+ end
27
+ @model = Example.new
28
+ end
29
+
30
+ should "allow a good value" do
31
+ assert_accepts allow_value('abcde').for(:attr).with_message(/bad/),
32
+ @model
33
+ end
34
+
35
+ should "not allow a bad value" do
36
+ assert_rejects allow_value('xyz').for(:attr).with_message(/bad/),
37
+ @model
38
+ end
39
+ end
40
+
41
+ end