file_share 0.1.9 → 0.1.11

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,16 +1,7 @@
1
1
  source 'http://rubygems.org'
2
-
3
- gem 'rails', '3.0.4'
4
-
5
- gem 'sqlite3'
6
-
7
- gem "formtastic"
8
-
9
2
  group :development, :test do
10
- gem "acts_as_fu"
3
+ gem "formtastic"
11
4
  gem "capybara"
12
- gem "cucumber-rails"
13
- gem "engineer"
14
- gem "rcov"
15
- gem "rspec-rails"
5
+ gem "database_cleaner"
16
6
  end
7
+ gemspec :path => File.expand_path('..', __FILE__)
@@ -1,37 +1,45 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ file_share (0.1.11)
5
+ file_share
6
+ formtastic
7
+ rails (= 3.0.7)
8
+
1
9
  GEM
2
10
  remote: http://rubygems.org/
3
11
  specs:
4
12
  abstract (1.0.0)
5
- actionmailer (3.0.4)
6
- actionpack (= 3.0.4)
13
+ actionmailer (3.0.7)
14
+ actionpack (= 3.0.7)
7
15
  mail (~> 2.2.15)
8
- actionpack (3.0.4)
9
- activemodel (= 3.0.4)
10
- activesupport (= 3.0.4)
16
+ actionpack (3.0.7)
17
+ activemodel (= 3.0.7)
18
+ activesupport (= 3.0.7)
11
19
  builder (~> 2.1.2)
12
20
  erubis (~> 2.6.6)
13
- i18n (~> 0.4)
21
+ i18n (~> 0.5.0)
14
22
  rack (~> 1.2.1)
15
- rack-mount (~> 0.6.13)
23
+ rack-mount (~> 0.6.14)
16
24
  rack-test (~> 0.5.7)
17
25
  tzinfo (~> 0.3.23)
18
- activemodel (3.0.4)
19
- activesupport (= 3.0.4)
26
+ activemodel (3.0.7)
27
+ activesupport (= 3.0.7)
20
28
  builder (~> 2.1.2)
21
- i18n (~> 0.4)
22
- activerecord (3.0.4)
23
- activemodel (= 3.0.4)
24
- activesupport (= 3.0.4)
29
+ i18n (~> 0.5.0)
30
+ activerecord (3.0.7)
31
+ activemodel (= 3.0.7)
32
+ activesupport (= 3.0.7)
25
33
  arel (~> 2.0.2)
26
34
  tzinfo (~> 0.3.23)
27
- activeresource (3.0.4)
28
- activemodel (= 3.0.4)
29
- activesupport (= 3.0.4)
30
- activesupport (3.0.4)
35
+ activeresource (3.0.7)
36
+ activemodel (= 3.0.7)
37
+ activesupport (= 3.0.7)
38
+ activesupport (3.0.7)
31
39
  acts_as_fu (0.0.7.2)
32
40
  activerecord
33
41
  sqlite3-ruby
34
- arel (2.0.8)
42
+ arel (2.0.9)
35
43
  builder (2.1.2)
36
44
  capybara (0.4.1.2)
37
45
  celerity (>= 0.7.9)
@@ -42,40 +50,42 @@ GEM
42
50
  rack-test (>= 0.5.4)
43
51
  selenium-webdriver (>= 0.0.27)
44
52
  xpath (~> 0.1.3)
45
- celerity (0.8.8)
46
- childprocess (0.1.7)
47
- ffi (~> 0.6.3)
48
- cucumber (0.10.0)
53
+ celerity (0.8.9)
54
+ childprocess (0.1.9)
55
+ ffi (~> 1.0.6)
56
+ cucumber (0.10.2)
49
57
  builder (>= 2.1.2)
50
- diff-lcs (~> 1.1.2)
51
- gherkin (~> 2.3.2)
52
- json (~> 1.4.6)
53
- term-ansicolor (~> 1.0.5)
54
- cucumber-rails (0.3.2)
55
- cucumber (>= 0.8.0)
58
+ diff-lcs (>= 1.1.2)
59
+ gherkin (>= 2.3.5)
60
+ json (>= 1.4.6)
61
+ term-ansicolor (>= 1.0.5)
62
+ cucumber-rails (0.4.1)
63
+ cucumber (>= 0.10.1)
64
+ nokogiri (>= 1.4.4)
65
+ rack-test (>= 0.5.7)
56
66
  culerity (0.2.15)
67
+ database_cleaner (0.6.7)
57
68
  diff-lcs (1.1.2)
58
69
  engineer (0.2.3)
59
70
  jeweler (>= 1.4.0)
60
71
  erubis (2.6.6)
61
72
  abstract (>= 1.0.0)
62
- ffi (0.6.3)
63
- rake (>= 0.8.7)
73
+ ffi (1.0.8)
64
74
  formtastic (1.2.3)
65
75
  actionpack (>= 2.3.7)
66
76
  activesupport (>= 2.3.7)
67
77
  i18n (~> 0.4)
68
- gherkin (2.3.3)
69
- json (~> 1.4.6)
78
+ gherkin (2.3.7)
79
+ json (>= 1.4.6)
70
80
  git (1.2.5)
71
81
  i18n (0.5.0)
72
- jeweler (1.5.2)
82
+ jeweler (1.6.0)
73
83
  bundler (~> 1.0.0)
74
84
  git (>= 1.2.5)
75
85
  rake
76
- json (1.4.6)
86
+ json (1.5.1)
77
87
  json_pure (1.5.1)
78
- mail (2.2.15)
88
+ mail (2.2.19)
79
89
  activesupport (>= 2.3.6)
80
90
  i18n (>= 0.4.0)
81
91
  mime-types (~> 1.16)
@@ -83,43 +93,43 @@ GEM
83
93
  mime-types (1.16)
84
94
  nokogiri (1.4.4)
85
95
  polyglot (0.3.1)
86
- rack (1.2.1)
87
- rack-mount (0.6.13)
96
+ rack (1.2.2)
97
+ rack-mount (0.6.14)
88
98
  rack (>= 1.0.0)
89
99
  rack-test (0.5.7)
90
100
  rack (>= 1.0)
91
- rails (3.0.4)
92
- actionmailer (= 3.0.4)
93
- actionpack (= 3.0.4)
94
- activerecord (= 3.0.4)
95
- activeresource (= 3.0.4)
96
- activesupport (= 3.0.4)
101
+ rails (3.0.7)
102
+ actionmailer (= 3.0.7)
103
+ actionpack (= 3.0.7)
104
+ activerecord (= 3.0.7)
105
+ activeresource (= 3.0.7)
106
+ activesupport (= 3.0.7)
97
107
  bundler (~> 1.0)
98
- railties (= 3.0.4)
99
- railties (3.0.4)
100
- actionpack (= 3.0.4)
101
- activesupport (= 3.0.4)
108
+ railties (= 3.0.7)
109
+ railties (3.0.7)
110
+ actionpack (= 3.0.7)
111
+ activesupport (= 3.0.7)
102
112
  rake (>= 0.8.7)
103
113
  thor (~> 0.14.4)
104
114
  rake (0.8.7)
105
115
  rcov (0.9.9)
106
- rspec (2.5.0)
107
- rspec-core (~> 2.5.0)
108
- rspec-expectations (~> 2.5.0)
109
- rspec-mocks (~> 2.5.0)
110
- rspec-core (2.5.1)
111
- rspec-expectations (2.5.0)
116
+ rspec (2.6.0)
117
+ rspec-core (~> 2.6.0)
118
+ rspec-expectations (~> 2.6.0)
119
+ rspec-mocks (~> 2.6.0)
120
+ rspec-core (2.6.0)
121
+ rspec-expectations (2.6.0)
112
122
  diff-lcs (~> 1.1.2)
113
- rspec-mocks (2.5.0)
114
- rspec-rails (2.5.0)
123
+ rspec-mocks (2.6.0)
124
+ rspec-rails (2.6.0)
115
125
  actionpack (~> 3.0)
116
126
  activesupport (~> 3.0)
117
127
  railties (~> 3.0)
118
- rspec (~> 2.5.0)
128
+ rspec (~> 2.6.0)
119
129
  rubyzip (0.9.4)
120
- selenium-webdriver (0.1.3)
121
- childprocess (~> 0.1.5)
122
- ffi (~> 0.6.3)
130
+ selenium-webdriver (0.2.0)
131
+ childprocess (>= 0.1.7)
132
+ ffi (>= 1.0.7)
123
133
  json_pure
124
134
  rubyzip
125
135
  sqlite3 (1.3.3)
@@ -129,8 +139,8 @@ GEM
129
139
  thor (0.14.6)
130
140
  treetop (1.4.9)
131
141
  polyglot (>= 0.3.1)
132
- tzinfo (0.3.24)
133
- xpath (0.1.3)
142
+ tzinfo (0.3.27)
143
+ xpath (0.1.4)
134
144
  nokogiri (~> 1.3)
135
145
 
136
146
  PLATFORMS
@@ -140,9 +150,11 @@ DEPENDENCIES
140
150
  acts_as_fu
141
151
  capybara
142
152
  cucumber-rails
153
+ database_cleaner
143
154
  engineer
155
+ file_share!
144
156
  formtastic
145
- rails (= 3.0.4)
157
+ jeweler
146
158
  rcov
147
159
  rspec-rails
148
160
  sqlite3
data/Rakefile CHANGED
@@ -8,7 +8,7 @@ FileShare::Application.load_tasks
8
8
 
9
9
  excluded_files = %w(config/database.yml public/files)
10
10
 
11
- Engineer::Tasks.new do |gem|
11
+ Jeweler::Tasks.new do |gem|
12
12
  gem.name = "file_share"
13
13
  gem.summary = %Q{Provides basic file management features.}
14
14
  gem.description = %Q{Simple versioned event management for Rails 3.}
@@ -22,17 +22,17 @@ Engineer::Tasks.new do |gem|
22
22
  "db/**/*.rb"
23
23
  ]
24
24
  excluded_files.each{|f| gem.files.exclude(f)}
25
-
26
- # Include Bundler dependencies
27
- Bundler.definition.dependencies.each do |dependency|
28
- next if dependency.name == "engineer"
29
25
 
30
- if (dependency.groups & [:default, :production]).any?
31
- gem.add_dependency dependency.name, *dependency.requirement.as_list
32
- else
33
- gem.add_development_dependency dependency.name, *dependency.requirement.as_list
34
- end
35
- end
26
+ gem.add_dependency 'rails', '3.0.7'
27
+ gem.add_dependency 'formtastic'
28
+
29
+ gem.add_development_dependency 'jeweler'
30
+ gem.add_development_dependency "acts_as_fu"
31
+ gem.add_development_dependency "capybara"
32
+ gem.add_development_dependency "cucumber-rails"
33
+ gem.add_development_dependency "rcov"
34
+ gem.add_development_dependency "rspec-rails"
35
+ gem.add_development_dependency 'sqlite3'
36
36
 
37
37
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
38
38
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.9
1
+ 0.1.11
@@ -18,7 +18,9 @@ class FileAttachment < ActiveRecord::Base
18
18
  belongs_to :attachable, :polymorphic => true
19
19
 
20
20
  before_validation :autofill_blank_name, :on => :create
21
- before_validation :save_to_folder_path, :on => :create
21
+ #before_validation :save_to_folder_path, :on => :create
22
+ before_validation :build_filepath
23
+ after_save :save_to_folder_path, :if => Proc.new{|file| file.uploaded_file.present?}
22
24
  before_save :normalize_attachable_fields
23
25
  before_destroy :move_file_to_trash_folder!
24
26
 
@@ -28,6 +30,13 @@ class FileAttachment < ActiveRecord::Base
28
30
  scope :attached, where('attachable_id IS NOT NULL')
29
31
 
30
32
  private
33
+ def attachable_folder
34
+ if attachable_type.blank? or attachable_id.blank?
35
+ "general"
36
+ else
37
+ File.join attachable_type.underscore.downcase, attachable_id.to_s
38
+ end
39
+ end
31
40
  def normalize_attachable_fields
32
41
  if attachable_type.blank? || attachable_id.blank?
33
42
  self.attachable_type = nil
@@ -35,25 +44,27 @@ class FileAttachment < ActiveRecord::Base
35
44
  end
36
45
  end
37
46
  def move_file_to_trash_folder!
38
- ensure_folder_path_exists(TRASH_FOLDER)
39
- trash_filename = generate_unique_filename(TRASH_FOLDER)
47
+ trash_folder = File.join FOLDER_PATH, attachable_folder, 'trash'
48
+ ensure_folder_path_exists(trash_folder)
49
+ trash_filename = generate_unique_filename(trash_folder)
40
50
 
41
- FileUtils.mv(full_path, File.join(TRASH_FOLDER, trash_filename))
51
+ FileUtils.mv(full_path, File.join(trash_folder, trash_filename))
42
52
 
43
- unless File.exists?(File.join(TRASH_FOLDER, trash_filename))
44
- raise Errno::ENOENT("The file at #{File.join(FOLDER_ROOT, filepath)} should be in the trash at #{File.join(TRASH_FOLDER, trash_filename)}")
53
+ unless File.exists?(File.join(trash_folder, trash_filename))
54
+ raise Errno::ENOENT("The file at #{File.join(FOLDER_ROOT, filepath)} should be in the trash at #{File.join(trash_folder, trash_filename)}")
45
55
  end
46
- logger.info("Moved File Attachment to Trash: #{File.join(TRASH_FOLDER, trash_filename)}")
56
+ logger.info("Moved File Attachment to Trash: #{File.join(trash_folder, trash_filename)}")
47
57
  end
48
58
  def save_to_folder_path
49
59
  ensure_folder_path_exists
50
60
  build_filepath
51
61
  File.open(full_path, "wb") { |f| f.write(uploaded_file.read) }
52
62
  return true if file_saved?
53
- errors.add_to_base("The file could not be saved. Please try again or contact someone and make a note of how many files, what kind, etc.")
63
+ errors.add(:base, "The file could not be saved. Please try again or contact someone and make a note of how many files, what kind, etc.")
54
64
  false
55
65
  end
56
- def generate_unique_filename(dest_path=FOLDER_PATH)
66
+ def generate_unique_filename(dest_path=nil)
67
+ dest_path ||= File.join FOLDER_PATH, attachable_folder
57
68
  base_filename = File.basename(uploaded_file && uploaded_file.original_filename || filepath)
58
69
  new_filename = base_filename
59
70
  path = File.join dest_path, new_filename
@@ -62,14 +73,16 @@ class FileAttachment < ActiveRecord::Base
62
73
  count += 1
63
74
  new_filename = base_filename.gsub File.extname(base_filename), "-#{count}#{File.extname(base_filename)}"
64
75
  path = File.join dest_path, new_filename
76
+ raise "Unable to generate a unique filename for #{base_filename}; tried #{count} times." if count > 99
65
77
  end
66
78
  new_filename
67
79
  end
68
- def ensure_folder_path_exists(dest_path=FOLDER_PATH)
80
+ def ensure_folder_path_exists(dest_path=nil)
81
+ dest_path ||= File.join FOLDER_PATH, attachable_folder
69
82
  FileUtils.mkdir_p dest_path
70
83
  end
71
84
  def build_filepath
72
- self.filepath = File.join FOLDER, generate_unique_filename
85
+ self.filepath = File.join FOLDER, attachable_folder, generate_unique_filename
73
86
  end
74
87
  def autofill_blank_name
75
88
  if name.blank?
@@ -79,7 +92,7 @@ class FileAttachment < ActiveRecord::Base
79
92
  protected
80
93
  public
81
94
  def full_path
82
- "#{FOLDER_ROOT}/#{filepath}"
95
+ File.join FOLDER_ROOT, filepath
83
96
  end
84
97
  def file_saved?
85
98
  return true if File.exists?(full_path) && File.basename(full_path) != FOLDER
@@ -94,4 +107,19 @@ class FileAttachment < ActiveRecord::Base
94
107
  self.attachable_type = p[0].blank? ? nil : p[0]
95
108
  self.attachable_id = p[1].blank? ? nil : p[1]
96
109
  end
110
+
111
+ # update fs & db filepaths with updated values (eg after dev changes)
112
+ def update_filepath
113
+ old_path = full_path.dup
114
+ build_filepath
115
+ FileUtils.mv(old_path, full_path)
116
+ unless file_saved?
117
+ msg = "Error updating filepath for #{name}"
118
+ logger.error(msg)
119
+ errors.add(:base, msg)
120
+ false
121
+ else
122
+ self.save
123
+ end
124
+ end
97
125
  end
@@ -1,7 +1,7 @@
1
1
  <%
2
2
  rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
3
3
  rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
4
- std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} --strict --tags ~@wip"
4
+ std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags ~@wip"
5
5
  %>
6
6
  default: <%= std_opts %> features
7
7
  wip: --tags @wip:3 --wip features
@@ -1,3 +1,3 @@
1
1
  module FileShare
2
- require "file_share/engine" if defined?(Rails)
2
+ require "file_share/engine"
3
3
  end
@@ -1,22 +1,6 @@
1
- require "file_share"
2
- require "rails"
3
-
4
1
  module FileShare
5
2
  class Engine < Rails::Engine
6
3
  ASSET_PREFIX = "file_share"
7
- ENGINEER_VERSION = "0.2.3"
8
-
9
- initializer "file_share.require_dependencies" do
10
- require 'bundler'
11
- gemfile = Bundler::Definition.build(root.join('Gemfile'), root.join('Gemfile.lock'), {})
12
- specs = gemfile.dependencies.select do |d|
13
- d.name != 'engineer' and (d.groups & [:default, :production]).any?
14
- end
15
-
16
- specs.collect { |s| s.autorequire || [s.name] }.flatten.each do |r|
17
- require r
18
- end
19
- end
20
4
 
21
5
  initializer "file_share.asset_path" do |app|
22
6
  app.config.middleware.use ::ActionDispatch::Static, "#{root}/public"
@@ -43,6 +43,10 @@ begin
43
43
  task :features => :cucumber do
44
44
  STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
45
45
  end
46
+
47
+ # In case we don't have ActiveRecord, append a no-op task that we can depend upon.
48
+ task 'db:test:prepare' do
49
+ end
46
50
  rescue LoadError
47
51
  desc 'cucumber rake task not available (cucumber not installed)'
48
52
  task :cucumber do
@@ -1,57 +1,101 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe FileAttachment do
4
-
4
+
5
5
  include ActionDispatch::TestProcess # for fixture_file_upload
6
-
6
+
7
7
  before(:each) do
8
- @path = File.join(Rails.root.to_s, 'public', 'files')
8
+ File.stub(:open)
9
+ @path = File.join(Rails.root.to_s, 'public', 'files', 'general')
9
10
  @full_path = File.join(@path, 'somefile.txt')
10
11
  @trash_path = File.join(@path, 'trash', 'somefile.txt')
11
-
12
- raise "Please back up and clean out public/files before running this spec" if File.exists?(@full_path) || File.exists?(File.join(@path, 'somefile-1.txt'))
13
-
14
- @file_attachment = FileAttachment.create!({
12
+
13
+ @file_attachment = FileAttachment.new({
15
14
  :description => 'unique description',
16
15
  :uploaded_file => fixture_file_upload(File.join(Rails.root.to_s, 'spec', 'fixtures', 'somefile.txt'), 'text/plain')
17
16
  })
17
+ @file_attachment.valid? # force build_filepath
18
18
  end
19
-
20
- after(:each) do
21
- if File.exists?(@full_path)
22
- File.delete(@full_path)
23
- end
24
- if File.exists?(@trash_path)
25
- File.delete(@trash_path)
26
- end
27
- end
28
-
19
+
29
20
  it "should generate a unique name" do
30
- FileUtils.mkdir_p @path
31
-
32
- new_file = FileAttachment.create!({
21
+ File.stub(:open)
22
+ File.stub(:exists?).with("#{@path}/somefile.txt"){ true }
23
+ File.stub(:exists?).with("#{@path}/somefile-1.txt"){ false }
24
+ File.should_receive(:open).with("#{@path}/somefile-1.txt", "wb").at_least(:once)
25
+ new_file = FileAttachment.create({
33
26
  :description => 'other description',
34
27
  :uploaded_file => fixture_file_upload(File.join(Rails.root.to_s, 'spec', 'fixtures', 'somefile.txt'), 'text/plain')
35
28
  })
36
-
37
- new_file.filepath.should_not == 'files/somefile.txt'
38
- new_file.filepath.should == 'files/somefile-1.txt'
39
- File.exists?(@full_path).should be_true
40
-
41
- File.delete(File.join(@path, 'somefile-1.txt'))
42
29
  end
43
30
 
44
31
  it "should know whether its file actually exists" do
32
+ File.stub(:exists?).with("#{@path}/somefile.txt"){ true }
45
33
  @file_attachment.file_saved?.should be_true
46
- File.exists?(@full_path).should be_true
47
- File.delete(@full_path)
34
+ File.stub(:exists?).with("#{@path}/somefile.txt"){ false }
48
35
  @file_attachment.file_saved?.should be_false
49
36
  end
50
37
 
51
38
  it "should move its file to the trash when destroyed" do
52
- File.exists?(@full_path).should be_true
39
+ @file_attachment.should_receive(:move_file_to_trash_folder!)
53
40
  @file_attachment.destroy
54
- File.exists?(@full_path).should be_false
55
- File.exists?(@trash_path).should be_true
41
+ end
42
+
43
+ it "should know how to throw files into the trash" do
44
+ @file_attachment.stub(:generate_unique_filename){ "somefile.txt" }
45
+ File.stub(:exists?){ true }
46
+ FileUtils.should_receive(:mv).with(@full_path, @trash_path)
47
+ @file_attachment.send(:move_file_to_trash_folder!)
48
+ end
49
+
50
+ it "should be able to create a folder name that mirrors the attachable_type and attachable_id" do
51
+ @file_attachment.send(:attachable_folder).should eq "general"
52
+ module Blog; class Post; extend ActiveModel::Naming; def self.base_class; Blog::Post; end end end
53
+ blog_post = mock_model(Blog::Post)
54
+ @file_attachment.attachable = blog_post
55
+ @file_attachment.send(:attachable_folder).should eq "blog/post/#{blog_post.id}"
56
+
57
+ class Event; extend ActiveModel::Naming; def self.base_class; Event; end end
58
+ event = mock_model(Event)
59
+ @file_attachment.attachable = event
60
+ @file_attachment.send(:attachable_folder).should eq "event/#{event.id}"
61
+ end
62
+
63
+ it "should ensure that the destination folder exists" do
64
+ FileUtils.should_receive(:mkdir_p).with(@path)
65
+ @file_attachment.send(:ensure_folder_path_exists)
66
+ end
67
+
68
+ context "should be able to update filepath in db & fs" do
69
+ before(:each) do
70
+ @old_path = File.join "files", "somefile.txt"
71
+ @file_attachment.filepath = @old_path
72
+ FileUtils.stub(:mv).with("#{Rails.root}/public/#{@old_path}", @full_path)
73
+ end
74
+ it "update the fs" do
75
+ FileUtils.should_receive(:mv).with("#{Rails.root}/public/#{@old_path}", @full_path)
76
+ @file_attachment.update_filepath
77
+ end
78
+ context "fs update succeeds :)" do
79
+ it "update the db" do
80
+ p "stubbing obj under test"
81
+ @file_attachment.stub(:file_saved?){ true }
82
+ @file_attachment.should_receive(:save)
83
+ @file_attachment.update_filepath
84
+ end
85
+ end
86
+ context "fs update fails :(" do
87
+ before(:each) do
88
+ @file_attachment.stub(:file_saved?){ false }
89
+ end
90
+ it "add error to base" do
91
+ p "stubbing obj under test"
92
+ @file_attachment.errors.should_receive(:add).with(:base, "Error updating filepath for #{@file_attachment.name}")
93
+ @file_attachment.update_filepath
94
+ end
95
+ it "return false" do
96
+ p "stubbing obj under test"
97
+ @file_attachment.update_filepath.should be_false
98
+ end
99
+ end
56
100
  end
57
101
  end