redmine_extensions 0.3.00 → 0.3.2

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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +16 -40
  3. data/lib/generators/redmine_extensions/entity/entity_generator.rb +77 -24
  4. data/lib/generators/redmine_extensions/entity/templates/_%model_name_underscored%.api.rsb.tt +18 -0
  5. data/lib/generators/redmine_extensions/entity/templates/controller.rb.erb +14 -20
  6. data/lib/generators/redmine_extensions/entity/templates/controller_spec.rb.erb +19 -22
  7. data/lib/generators/redmine_extensions/entity/templates/easy_query.rb.erb +1 -3
  8. data/lib/generators/redmine_extensions/entity/templates/factories.rb.erb +5 -6
  9. data/lib/generators/redmine_extensions/entity/templates/helper.rb.erb +0 -21
  10. data/lib/generators/redmine_extensions/entity/templates/index.api.rsb.erb +2 -4
  11. data/lib/generators/redmine_extensions/entity/templates/migration.rb.erb +4 -3
  12. data/lib/generators/redmine_extensions/entity/templates/model.rb.erb +1 -1
  13. data/lib/generators/redmine_extensions/entity/templates/show.api.rsb.erb +1 -1
  14. data/lib/generators/redmine_extensions/entity/templates/spec/requests/%model_name_underscored%_spec.rb.tt +19 -0
  15. data/lib/redmine_extensions/engine.rb +1 -0
  16. data/lib/redmine_extensions/redmine_patches/models/custom_field_patch.rb +11 -0
  17. data/lib/redmine_extensions/tags/autocomplete_field.rb +1 -1
  18. data/lib/redmine_extensions/version.rb +1 -1
  19. data/spec/factories/easy_settings.rb +5 -4
  20. data/spec/features/autocomplete_spec.rb +1 -3
  21. data/spec/features/jasmine_spec.rb +1 -3
  22. data/spec/init_rails.rb +13 -0
  23. data/spec/models/easy_setting_spec.rb +0 -2
  24. data/spec/presenters/easy_settings/params_wrapper_spec.rb +2 -2
  25. data/spec/spec_helper.rb +2 -69
  26. data/spec/support/plugin_generator.rb +1 -10
  27. metadata +12 -126
  28. data/spec/factories/easy_queries.rb +0 -8
  29. data/spec/factories/issues.rb +0 -96
  30. data/spec/factories/projects.rb +0 -84
  31. data/spec/factories/time_entries.rb +0 -38
  32. data/spec/factories/trackers.rb +0 -15
  33. data/spec/factories/users.rb +0 -23
  34. data/spec/rails_helper.rb +0 -119
@@ -1,12 +1,11 @@
1
1
  FactoryBot.define do
2
2
 
3
3
  factory :<%= model_name_underscored %> do
4
- <%- string_columns.each_key do |c| -%>
5
- sequence(:<%= c %>) { | n | "<%= c %>-#{n}"}
6
- <%- end -%>
7
- <%= 'association :author, factory: :user' if author? %>
8
- <%= 'project' if project? %>
9
-
4
+ <%- string_columns.each_key do |c| -%>
5
+ sequence(:<%= c %>) { | n | "<%= c %>-#{n}"}
6
+ <%- end -%>
7
+ <%= 'association :author, factory: :user' if author? %>
8
+ <%= 'project' if project? %>
10
9
  end
11
10
 
12
11
  end
@@ -1,24 +1,3 @@
1
1
  module <%= controller_class %>Helper
2
2
 
3
- def render_api_<%= model_name_underscored %>(api, <%= model_name_underscored %>)
4
- api.<%= model_name_underscored %> do
5
- api.id <%= model_name_underscored %>.id
6
- <%- db_columns.keys.each do |column_name| -%>
7
- api.<%= column_name %> <%= model_name_underscored %>.<%= column_name %>
8
- <%- end -%>
9
- <%- if acts_as_customizable? -%>
10
- render_api_custom_values <%= model_name_underscored %>.visible_custom_field_values, api
11
- <%- end -%>
12
- <%- if acts_as_attachable? -%>
13
- api.array :attachments do
14
- <%= model_name_underscored %>.attachments.each do |attachment|
15
- render_api_attachment(attachment, api)
16
- end
17
- end if include_in_api_response?('attachments')
18
- <%- end -%>
19
-
20
- call_hook(:helper_render_api_<%= model_name_underscored %>, {api: api, <%= model_name_underscored %>: <%= model_name_underscored %>})
21
- end
22
- end
23
-
24
3
  end
@@ -1,5 +1,3 @@
1
1
  api.array :<%= model_name_pluralize_underscored %>, api_meta(total_count: @entity_count, offset: @offset, limit: @limit) do
2
- @entities.each do |<%= model_name_underscored %>|
3
- render_api_<%= model_name_underscored %>(api, <%= model_name_underscored %>)
4
- end
5
- end
2
+ render(@entities, {api: api})
3
+ end
@@ -1,11 +1,12 @@
1
- class Create<%= model_name_pluralize_underscored.camelize %> < ActiveRecord::Migration
1
+ class Create<%= model_name_pluralize_underscored.camelize %> < ActiveRecord::Migration[<%= ActiveRecord::Migration::Current.current_version %>]
2
2
  def change
3
- create_table :<%= model_name_pluralize_underscored %>, force: true do |t|
3
+ create_table :<%= model_name_pluralize_underscored %> do |t|
4
4
  <%- columns = db_columns.reject{|k| k.in?(["created_at", "updated_at"])} -%>
5
5
  <%- columns.each do |column_name, column_attrs| -%>
6
6
  t.<%= column_attrs[:type] %> :<%= column_name %>, null: <%= column_attrs[:null] %>
7
7
  <%- end -%>
8
- t.timestamps null: false
8
+
9
+ t.timestamps
9
10
  end
10
11
  end
11
12
  end
@@ -59,7 +59,7 @@ class <%= model_name %> < ActiveRecord::Base
59
59
  after_update :send_update_notification
60
60
  <%- end -%>
61
61
 
62
- def self.visible_condition(user, options={})
62
+ def self.visible_condition(user, options = {})
63
63
  <%- if project? -%>
64
64
  Project.allowed_to_condition(user, :<%= view_permission %>, options)
65
65
  <%- else -%>
@@ -1 +1 @@
1
- render_api_<%= model_name_underscored %>(api, @<%= model_name_underscored %>)
1
+ render(@<%= model_name_underscored %>, { api: api })
@@ -0,0 +1,19 @@
1
+ RSpec.describe "<%= model_name_pluralize_underscored %>", type: :request do
2
+ describe "API" do
3
+ context "logged", logged: true do
4
+ before(:each) do
5
+ role = Role.non_member
6
+ role.add_permission! :view_<%= model_name_pluralize_underscored %>
7
+ end
8
+
9
+ it "list" do
10
+ FactoryBot.create_list :<%= model_name_underscored %>, 2
11
+ get <%= model_name_pluralize_underscored %>_path(format: "json")
12
+ expect(response).to have_http_status :success
13
+ expect(response.body).to include "limit", "offset"
14
+ expect(response.body).to match /total_count.{,2}:2/
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -2,6 +2,7 @@ require 'active_support/dependencies'
2
2
  require_relative './patch_manager'
3
3
  require_relative './redmine_patches/controllers/application_controller_patch'
4
4
  require_relative './redmine_patches/models/project_patch'
5
+ require_relative './redmine_patches/models/custom_field_patch'
5
6
 
6
7
  require_relative './query_output'
7
8
 
@@ -0,0 +1,11 @@
1
+ module RedmineExtensions
2
+ module CustomFieldPatch
3
+
4
+ def translated_name
5
+ self.name
6
+ end
7
+
8
+ end
9
+ end
10
+
11
+ RedmineExtensions::PatchManager.register_model_patch 'CustomField', 'RedmineExtensions::CustomFieldPatch', if: -> { !Redmine::Plugin.installed?(:easy_extensions) }
@@ -18,7 +18,7 @@ module RedmineExtensions
18
18
 
19
19
  def render
20
20
  options = @options.stringify_keys
21
- options["value"] = options.fetch("value") { value_before_type_cast(object) }
21
+ options["value"] = options.fetch("value") { value_before_type_cast }
22
22
  add_default_name_and_id(options)
23
23
  @template_object.autocomplete_field_tag(options.delete('name'), @choices, options.delete('value'), options.symbolize_keys)
24
24
  end
@@ -1,3 +1,3 @@
1
1
  module RedmineExtensions
2
- VERSION = '0.3.00'
2
+ VERSION = '0.3.2'
3
3
  end
@@ -1,13 +1,14 @@
1
1
  FactoryBot.define do
2
+
2
3
  factory :easy_setting do
3
4
 
4
- name 'my_setting'
5
- value 'my_value'
5
+ name { 'my_setting' }
6
+ value { 'my_value' }
6
7
  project
7
8
 
8
9
  trait :global do
9
- value 'my_global_value'
10
- project nil
10
+ value { 'my_global_value' }
11
+ project { n il}
11
12
  end
12
13
  end
13
14
 
@@ -1,6 +1,4 @@
1
- require 'rails_helper'
2
-
3
- RSpec.describe 'autocomplete', type: :feature, js: true do
1
+ RSpec.describe 'autocomplete', type: :feature, js: true, logged: :admin do
4
2
 
5
3
  describe 'render' do
6
4
  it 'generate default autocomplete' do
@@ -1,6 +1,4 @@
1
- require 'rails_helper'
2
-
3
- RSpec.describe 'jasmine', type: :feature, js: true do
1
+ RSpec.describe 'jasmine', type: :feature, js: true, logged: :admin do
4
2
 
5
3
  it 'run tests' do
6
4
  visit "/dummy_entities?jasmine=true"
@@ -0,0 +1,13 @@
1
+ possible_app_dirs = [
2
+ ENV['DUMMY_PATH'],
3
+ File.join(Dir.pwd, 'test/dummy'),
4
+ Bundler.root.join('test/dummy'),
5
+ ]
6
+
7
+ possible_app_dirs.each do |dir|
8
+ next if !dir
9
+ next if !Dir.exist?(dir)
10
+
11
+ require File.join(dir, 'plugins/easyproject/easy_plugins/easy_extensions/test/spec/rails_helper')
12
+ break
13
+ end
@@ -1,5 +1,3 @@
1
- require 'rails_helper'
2
-
3
1
  RSpec.describe EasySetting, type: :model do
4
2
 
5
3
  let(:project) { FactoryBot.create(:project, name: 'My project') }
@@ -1,5 +1,3 @@
1
- require 'rails_helper'
2
-
3
1
  module EasySettings
4
2
  RSpec.describe ParamsWrapper, clear_cache: true do
5
3
 
@@ -14,6 +12,8 @@ module EasySettings
14
12
  end
15
13
 
16
14
  it 'create project setting' do
15
+ EasySetting.where(name: ['key', 'key2']).destroy_all
16
+
17
17
  presenter = EasySettings::ParamsWrapper.from_params({'key' => 'value', 'key2' => 'value2'}, project: project)
18
18
  expect{ presenter.save }.to change(EasySetting, :count).by(2)
19
19
  expect( EasySetting.where(project_id: project.id).count ).to eq(2)
@@ -1,69 +1,2 @@
1
- # This file was generated by the `rails generate rspec:install` command. Conventionally, all
2
- # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
- # The generated `.rspec` file contains `--require spec_helper` which will cause
4
- # this file to always be loaded, without a need to explicitly require it in any
5
- # files.
6
- #
7
- # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
8
- RSpec.configure do |config|
9
- # rspec-expectations config goes here. You can use an alternate
10
- # assertion/expectation library such as wrong or the stdlib/minitest
11
- # assertions if you prefer.
12
- config.expect_with :rspec do |expectations|
13
- expectations.include_chain_clauses_in_custom_matcher_descriptions = true
14
- end
15
-
16
- # rspec-mocks config goes here. You can use an alternate test double
17
- # library (such as bogus or mocha) by changing the `mock_with` option here.
18
- config.mock_with :rspec do |mocks|
19
- # Prevents you from mocking or stubbing a method that does not exist on
20
- # a real object. This is generally recommended, and will default to
21
- # `true` in RSpec 4.
22
- mocks.verify_partial_doubles = true
23
- end
24
-
25
- # The settings below are suggested to provide a good initial experience
26
- # with RSpec, but feel free to customize to your heart's content.
27
- =begin
28
- # These two settings work together to allow you to limit a spec run
29
- # to individual examples or groups you care about by tagging them with
30
- # `:focus` metadata. When nothing is tagged with `:focus`, all examples
31
- # get run.
32
- config.filter_run :focus
33
- config.run_all_when_everything_filtered = true
34
-
35
- # Limits the available syntax to the non-monkey patched syntax that is
36
- # recommended. For more details, see:
37
- # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
38
- # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
39
- # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
40
- config.disable_monkey_patching!
41
-
42
- # Many RSpec users commonly either run the entire suite or an individual
43
- # file, and it's useful to allow more verbose output when running an
44
- # individual spec file.
45
- if config.files_to_run.one?
46
- # Use the documentation formatter for detailed output,
47
- # unless a formatter has already been configured
48
- # (e.g. via a command-line flag).
49
- config.default_formatter = 'doc'
50
- end
51
-
52
- # Print the 10 slowest examples and example groups at the
53
- # end of the spec run, to help surface which specs are running
54
- # particularly slow.
55
- config.profile_examples = 10
56
-
57
- # Run specs in random order to surface order dependencies. If you find an
58
- # order dependency and want to debug it, you can fix the order by providing
59
- # the seed, which is printed after each run.
60
- # --seed 1234
61
- config.order = :random
62
-
63
- # Seed global randomization in this process using the `--seed` CLI option.
64
- # Setting this allows you to use `--seed` to deterministically reproduce
65
- # test failures related to randomization by passing the same `--seed` value
66
- # as the one that triggered the failure.
67
- Kernel.srand config.seed
68
- =end
69
- end
1
+ require_relative 'init_rails'
2
+ require Rails.root.join('plugins/easyproject/easy_plugins/easy_extensions/test/spec/spec_helper')
@@ -4,13 +4,6 @@ module PluginGenerator
4
4
  def self.generate_test_plugin!
5
5
  Rails::Generators.invoke 'redmine_extensions:plugin', ['DummyPlugin'], behavior: :revoke, destination_root: Rails.root
6
6
  Rails::Generators.invoke 'redmine_extensions:plugin', ['DummyPlugin'], behavior: :invoke, destination_root: Rails.root
7
- # if Rails::VERSION::MAJOR >= 5
8
- # Rails.application.reloader.reload!
9
- # else
10
- # ActionDispatch::Reloader.cleanup!
11
- # ActionDispatch::Reloader.prepare!
12
- # end
13
-
14
7
  generate_autocomplete!
15
8
  end
16
9
 
@@ -25,7 +18,7 @@ module PluginGenerator
25
18
  def self.generate_dummy_entity!
26
19
  File.open( Rails.root.join('plugins', 'dummy_plugin', 'db', 'migrate', '20162010160230_create_dummy_entities.rb'), 'w' ) do |file|
27
20
  file.write( <<-END_RUBY )
28
- class CreateDummyEntities < ActiveRecord::Migration
21
+ class CreateDummyEntities < ActiveRecord::Migration[4.2]
29
22
  def change
30
23
  create_table :dummy_entities do |t|
31
24
  t.string :name
@@ -47,8 +40,6 @@ module PluginGenerator
47
40
  'project_id',
48
41
  'array_of_dummies'
49
42
 
50
- attr_protected :id
51
-
52
43
  serialize :array_of_dummies, Array
53
44
  end
54
45
  END_RUBY
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redmine_extensions
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.00
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Easy Software Ltd
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-11 00:00:00.000000000 Z
11
+ date: 2019-07-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -30,110 +30,6 @@ dependencies:
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '6'
33
- - !ruby/object:Gem::Dependency
34
- name: actionpack
35
- requirement: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- version: '4.2'
40
- - - "<"
41
- - !ruby/object:Gem::Version
42
- version: '6'
43
- type: :runtime
44
- prerelease: false
45
- version_requirements: !ruby/object:Gem::Requirement
46
- requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: '4.2'
50
- - - "<"
51
- - !ruby/object:Gem::Version
52
- version: '6'
53
- - !ruby/object:Gem::Dependency
54
- name: sqlite3
55
- requirement: !ruby/object:Gem::Requirement
56
- requirements:
57
- - - "~>"
58
- - !ruby/object:Gem::Version
59
- version: '1.3'
60
- type: :development
61
- prerelease: false
62
- version_requirements: !ruby/object:Gem::Requirement
63
- requirements:
64
- - - "~>"
65
- - !ruby/object:Gem::Version
66
- version: '1.3'
67
- - !ruby/object:Gem::Dependency
68
- name: rspec-rails
69
- requirement: !ruby/object:Gem::Requirement
70
- requirements:
71
- - - "~>"
72
- - !ruby/object:Gem::Version
73
- version: '3.4'
74
- type: :development
75
- prerelease: false
76
- version_requirements: !ruby/object:Gem::Requirement
77
- requirements:
78
- - - "~>"
79
- - !ruby/object:Gem::Version
80
- version: '3.4'
81
- - !ruby/object:Gem::Dependency
82
- name: capybara
83
- requirement: !ruby/object:Gem::Requirement
84
- requirements:
85
- - - "~>"
86
- - !ruby/object:Gem::Version
87
- version: 3.3.1
88
- type: :development
89
- prerelease: false
90
- version_requirements: !ruby/object:Gem::Requirement
91
- requirements:
92
- - - "~>"
93
- - !ruby/object:Gem::Version
94
- version: 3.3.1
95
- - !ruby/object:Gem::Dependency
96
- name: factory_bot_rails
97
- requirement: !ruby/object:Gem::Requirement
98
- requirements:
99
- - - "~>"
100
- - !ruby/object:Gem::Version
101
- version: '4.6'
102
- type: :development
103
- prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
105
- requirements:
106
- - - "~>"
107
- - !ruby/object:Gem::Version
108
- version: '4.6'
109
- - !ruby/object:Gem::Dependency
110
- name: poltergeist
111
- requirement: !ruby/object:Gem::Requirement
112
- requirements:
113
- - - "~>"
114
- - !ruby/object:Gem::Version
115
- version: '1.10'
116
- type: :development
117
- prerelease: false
118
- version_requirements: !ruby/object:Gem::Requirement
119
- requirements:
120
- - - "~>"
121
- - !ruby/object:Gem::Version
122
- version: '1.10'
123
- - !ruby/object:Gem::Dependency
124
- name: database_cleaner
125
- requirement: !ruby/object:Gem::Requirement
126
- requirements:
127
- - - "~>"
128
- - !ruby/object:Gem::Version
129
- version: '1.5'
130
- type: :development
131
- prerelease: false
132
- version_requirements: !ruby/object:Gem::Requirement
133
- requirements:
134
- - - "~>"
135
- - !ruby/object:Gem::Version
136
- version: '1.5'
137
33
  description: Redmine Extensions provide many extended functionalities for Redmine
138
34
  project.
139
35
  email:
@@ -199,6 +95,7 @@ files:
199
95
  - db/migrate/20190206121100_remove_foreign_key_from_easy_settings.rb
200
96
  - lib/generators/redmine_extensions/entity/USAGE
201
97
  - lib/generators/redmine_extensions/entity/entity_generator.rb
98
+ - lib/generators/redmine_extensions/entity/templates/_%model_name_underscored%.api.rsb.tt
202
99
  - lib/generators/redmine_extensions/entity/templates/_form.html.erb.erb
203
100
  - lib/generators/redmine_extensions/entity/templates/_sidebar.html.erb.erb
204
101
  - lib/generators/redmine_extensions/entity/templates/context_menu.html.erb.erb
@@ -230,6 +127,7 @@ files:
230
127
  - lib/generators/redmine_extensions/entity/templates/show.api.rsb.erb
231
128
  - lib/generators/redmine_extensions/entity/templates/show.html.erb.erb
232
129
  - lib/generators/redmine_extensions/entity/templates/show.js.erb.erb
130
+ - lib/generators/redmine_extensions/entity/templates/spec/requests/%model_name_underscored%_spec.rb.tt
233
131
  - lib/generators/redmine_extensions/plugin/USAGE
234
132
  - lib/generators/redmine_extensions/plugin/plugin_generator.rb
235
133
  - lib/generators/redmine_extensions/plugin/templates/Gemfile.erb
@@ -276,22 +174,17 @@ files:
276
174
  - lib/redmine_extensions/rails_patches/form_builder_patch.rb
277
175
  - lib/redmine_extensions/rails_patches/route_set_generator_patch.rb
278
176
  - lib/redmine_extensions/redmine_patches/controllers/application_controller_patch.rb
177
+ - lib/redmine_extensions/redmine_patches/models/custom_field_patch.rb
279
178
  - lib/redmine_extensions/redmine_patches/models/project_patch.rb
280
179
  - lib/redmine_extensions/tags/autocomplete_field.rb
281
180
  - lib/redmine_extensions/version.rb
282
181
  - lib/tasks/redmine_extensions_tasks.rake
283
- - spec/factories/easy_queries.rb
284
182
  - spec/factories/easy_settings.rb
285
- - spec/factories/issues.rb
286
- - spec/factories/projects.rb
287
- - spec/factories/time_entries.rb
288
- - spec/factories/trackers.rb
289
- - spec/factories/users.rb
290
183
  - spec/features/autocomplete_spec.rb
291
184
  - spec/features/jasmine_spec.rb
185
+ - spec/init_rails.rb
292
186
  - spec/models/easy_setting_spec.rb
293
187
  - spec/presenters/easy_settings/params_wrapper_spec.rb
294
- - spec/rails_helper.rb
295
188
  - spec/spec_helper.rb
296
189
  - spec/support/plugin_generator.rb
297
190
  homepage: https://www.easyredmine.com
@@ -313,24 +206,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
313
206
  - !ruby/object:Gem::Version
314
207
  version: '0'
315
208
  requirements: []
316
- rubyforge_project:
317
- rubygems_version: 2.7.7
209
+ rubygems_version: 3.0.3
318
210
  signing_key:
319
211
  specification_version: 4
320
212
  summary: Redmine Extensions is set of usefull features for Redmine. Main focus is
321
213
  on development helpers, but many users can find it helpfull
322
214
  test_files:
323
- - spec/rails_helper.rb
324
- - spec/factories/easy_queries.rb
325
- - spec/factories/trackers.rb
326
- - spec/factories/users.rb
327
- - spec/factories/easy_settings.rb
328
- - spec/factories/time_entries.rb
329
- - spec/factories/issues.rb
330
- - spec/factories/projects.rb
215
+ - spec/presenters/easy_settings/params_wrapper_spec.rb
331
216
  - spec/support/plugin_generator.rb
217
+ - spec/init_rails.rb
332
218
  - spec/models/easy_setting_spec.rb
333
- - spec/spec_helper.rb
334
- - spec/presenters/easy_settings/params_wrapper_spec.rb
335
- - spec/features/autocomplete_spec.rb
336
219
  - spec/features/jasmine_spec.rb
220
+ - spec/features/autocomplete_spec.rb
221
+ - spec/factories/easy_settings.rb
222
+ - spec/spec_helper.rb