active_scaffold 3.4.10 → 3.4.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 26af65dba6ac3fe50f666f71c4ed02abb0adda89
4
- data.tar.gz: 619b8200bc93ba0f81d123119723ab24c12fbec5
3
+ metadata.gz: e19f95fd4ac370c29a8d8774e4b3c94083e6df2a
4
+ data.tar.gz: 419230d149a695aebf92be0aa1d6c1455868ddac
5
5
  SHA512:
6
- metadata.gz: ce3969fced5fe06b11f6ac32735ae382f0f494a5087d0a7664eb11b1a15d6952fcf64832f2f585d0408363f10cecab1a8c6617ed90519b04b18d73fbd98cde92
7
- data.tar.gz: be56ceb6696c945eb66872fa482166b430d417de66d26f861e6c66d9f68e03ecb1e1c06050d28a1095c7dbbd2071ae3f9b4ee29e3c455533991e54663e7d44a5
6
+ metadata.gz: d763e9f014fc3b43cfa5f81218d50a5f4f276d56f97522c1631c7771ad9ae6793318ee9b112dc691d73f80541b4a39ab73b8ba6e6f7413fcab4b15510c66c66b
7
+ data.tar.gz: 77add87ef5f5ce6260296e9272fdae39de94407ff9071fdd3250f5f7219262660a2485889dc6f498ad043cf8da39a696d07095c69d662f56f694b30017f1675c
data/CHANGELOG CHANGED
@@ -1,3 +1,10 @@
1
+ = 3.4.11
2
+ - Fix refresh-link on main form (not subform)
3
+ - Workaround for counter_cache bug on rails4 (https://github.com/rails/rails/pull/14849)
4
+ - Support create form on nested scaffolds on through association, if through reflection association is included in create form
5
+ - Remove ruby 1.8 support
6
+ - Fix :index member route (list one item), broken on 3.4.9
7
+
1
8
  = 3.4.10
2
9
  - singular associations on subform are always created, in other case it's not possible to enable a checkbox without filling text fields.
3
10
  - process_action_link_action checks security for crud_type and action now
data/README.md CHANGED
@@ -2,7 +2,7 @@ Overview
2
2
  ========
3
3
  [![travis tests](https://travis-ci.org/activescaffold/active_scaffold.png)](https://travis-ci.org/activescaffold/active_scaffold)
4
4
 
5
- ActiveScaffold provides a quick and powerful user interfaces for CRUD (create, read, update, delete) operations for Rails applications. It offers additonal features including searching, pagination & layout control. Rails 3.2 and 4.x are supported. For rails 4 is recommended >= 4.0.5.
5
+ ActiveScaffold provides a quick and powerful user interfaces for CRUD (create, read, update, delete) operations for Rails applications. It offers additonal features including searching, pagination & layout control. Rails 3.2 and 4.x are supported, ruby >= 1.9 required. For rails 4 is recommended >= 4.0.5.
6
6
 
7
7
  Branch Details
8
8
  --------------
@@ -133,7 +133,11 @@ module ActiveScaffold::Actions
133
133
  end
134
134
 
135
135
  def create_authorized?
136
- !(nested? && (nested.readonly? || nested.readonly_through_association?)) && authorized_for?(:crud_type => :create)
136
+ if nested?
137
+ nested_authorized = !nested.readonly? && !nested.readonly_through_association?(active_scaffold_config.create.columns)
138
+ return false unless nested_authorized
139
+ end
140
+ authorized_for?(:crud_type => :create)
137
141
  end
138
142
  private
139
143
  def create_authorized_filter
@@ -32,6 +32,36 @@ module ActiveScaffold
32
32
  # }
33
33
  module AttributeParams
34
34
  protected
35
+ # workaround to update counters when belongs_to changes on persisted record on Rails 3
36
+ # TODO remove when rails3 support is removed
37
+ def rails3_counter_cache_hack(parent_record, column, value)
38
+ association = parent_record.association(column.name)
39
+ if association.send(:has_cached_counter?)
40
+ counter_attr = association.send(:cached_counter_attribute_name)
41
+ difference = value.select(&:persisted?).size - parent_record.send(counter_attr)
42
+
43
+ if parent_record.new_record?
44
+ parent_record.send "#{counter_attr}=", difference
45
+ else
46
+ # don't decrement counter for deleted records, on destroy they will update counter
47
+ difference += (parent_record.send(column.name) - value).size
48
+ association.send :update_counter, difference unless difference == 0
49
+ end
50
+
51
+ # update counters on old parents if belongs_to is changed
52
+ value.select(&:persisted?).each do |record|
53
+ key = record.send(column.association.foreign_key)
54
+ parent_record.class.decrement_counter counter_attr, key if key != parent_record.id
55
+ end
56
+ end
57
+ end
58
+
59
+ # workaround for updating counters twice bug on rails4 (https://github.com/rails/rails/pull/14849)
60
+ # TODO remove when pull request is merged and no version with bug is supported
61
+ def counter_cache_hack?(column, value)
62
+ Rails.version >= '4.0' && column.association.try(:belongs_to?) && column.association.options[:counter_cache] && !value.is_a?(Hash)
63
+ end
64
+
35
65
  # Takes attributes (as from params[:record]) and applies them to the parent_record. Also looks for
36
66
  # association attributes and attempts to instantiate them as associated objects.
37
67
  #
@@ -62,8 +92,12 @@ module ActiveScaffold
62
92
  value = column_value_from_param_value(parent_record, column, attributes[column.name], avoid_changes)
63
93
  if avoid_changes && column.plural_association?
64
94
  parent_record.association(column.name).target = value
95
+ elsif counter_cache_hack?(column, attributes[column.name])
96
+ parent_record.send "#{column.association.foreign_key}=", value.try(:id)
97
+ parent_record.association(column.name).target = value
65
98
  else
66
99
  begin
100
+ rails3_counter_cache_hack(parent_record, column, value) if Rails.version < '4.0' && column.plural_association?
67
101
  parent_record.send "#{column.name}=", value
68
102
  rescue ActiveRecord::RecordNotSaved
69
103
  parent_record.errors.add column.name, :invalid
@@ -150,7 +184,6 @@ module ActiveScaffold
150
184
  if column.singular_association?
151
185
  manage_nested_record_from_params(parent_record, column, value, avoid_changes)
152
186
  elsif column.plural_association?
153
- value = value.sort if RUBY_VERSION < '1.9'
154
187
  # HACK to be able to delete all associated records, hash will include "0" => ""
155
188
  value.collect {|key, value| manage_nested_record_from_params(parent_record, column, value, avoid_changes) unless value == ""}.compact
156
189
  else
@@ -14,7 +14,7 @@ module ActiveScaffold::DataStructures
14
14
  link = if action.is_a?(ActiveScaffold::DataStructures::ActionLink) || action.is_a?(ActiveScaffold::DataStructures::ActionLinks)
15
15
  action
16
16
  else
17
- options[:type] ||= default_type
17
+ options[:type] ||= default_type if default_type
18
18
  ActiveScaffold::DataStructures::ActionLink.new(action, options)
19
19
  end
20
20
  # NOTE: this duplicate check should be done by defining the comparison operator for an Action data structure
@@ -54,7 +54,7 @@ module ActiveScaffold::DataStructures
54
54
  has_many? || habtm?
55
55
  end
56
56
 
57
- def readonly_through_association?
57
+ def readonly_through_association?(columns)
58
58
  false
59
59
  end
60
60
 
@@ -101,9 +101,13 @@ module ActiveScaffold::DataStructures
101
101
  end
102
102
 
103
103
  # A through association with has_one or has_many as source association
104
- # create cannot be called in such through association
105
- def readonly_through_association?
106
- association.options[:through] && association.source_reflection.macro != :belongs_to
104
+ # create cannot be called in such through association, unless create columns include through reflection of reverse association
105
+ # e.g. customer -> networks -> firewall, reverse is firewall -> network -> customer,
106
+ # firewall can be created if create columns include network
107
+ def readonly_through_association?(columns)
108
+ through_association? && association.source_reflection.macro != :belongs_to && (
109
+ !child_association || !columns.include?(child_association.through_reflection.name)
110
+ )
107
111
  end
108
112
 
109
113
  def through_association?
@@ -23,6 +23,7 @@ module ActionDispatch
23
23
  end
24
24
 
25
25
  def as_routes(opts = {:association => true})
26
+ resource = parent_resource
26
27
  resource_scope(:resource, ActiveScaffold.new(parent_resource.name, parent_resource.options)) do
27
28
  collection do
28
29
  ActionDispatch::Routing::ACTIVE_SCAFFOLD_CORE_ROUTING[:collection].each do |name, type|
@@ -33,7 +34,7 @@ module ActionDispatch
33
34
  ActionDispatch::Routing::ACTIVE_SCAFFOLD_CORE_ROUTING[:member].each do |name, type|
34
35
  match(name, :via => type) if parent_resource.actions.include? name
35
36
  end
36
- get 'list', :action => :index if parent_resource.actions.include? :index
37
+ get 'list', :action => :index if resource.actions.include? :index
37
38
  end
38
39
  end
39
40
  as_association_routes if opts[:association]
@@ -376,7 +376,7 @@ module ActiveScaffold
376
376
 
377
377
  # Converts count to an integer if ActiveRecord returned an OrderedHash
378
378
  # that happens when find_options contains a :group key
379
- count = count.length if count.is_a?(Hash) || count.is_a?(ActiveSupport::OrderedHash) # TODO remove OrderedHash check when ruby 1.8 or rails3 support is removed
379
+ count = count.length if count.is_a?(Hash)
380
380
  count
381
381
  end
382
382
 
@@ -59,7 +59,15 @@ module ActiveScaffold
59
59
  end
60
60
 
61
61
  def association_klass_scoped(association, klass, record)
62
- klass
62
+ if nested? && nested.through_association? && nested.child_association.try(:through_reflection) == association
63
+ if nested.association.through_reflection.collection?
64
+ nested_parent_record.send(nested.association.through_reflection.name)
65
+ else
66
+ klass.where(association.association_primary_key => nested_parent_record.send(nested.association.through_reflection.name).try(:id))
67
+ end
68
+ else
69
+ klass
70
+ end
63
71
  end
64
72
 
65
73
  # Sorts the options for select
@@ -277,7 +277,7 @@ module ActiveScaffold
277
277
  link_options['data-update_send_form_selector'] = html_options['data-update_send_form_selector']
278
278
  else
279
279
  scope = html_options[:name].scan(/^record((\[[^\]]*\])*)\[#{column.name}\]/)[0].try(:first) if html_options[:name]
280
- link_options = update_columns_options(column, scope, link_options, true)
280
+ link_options = update_columns_options(column, scope.presence, link_options, true)
281
281
  end
282
282
  link_options[:class] = 'refresh-link'
283
283
  link_to(as_(:refresh), link_options.delete('data-update_url') || html_options['data-update_url'], link_options)
@@ -10,7 +10,6 @@ module ActiveScaffold
10
10
  if performed?
11
11
  # Either pull out a redirect or the request body
12
12
  script = if response.headers['Location']
13
- #TODO: erase_redirect_results is missing in rails 3.0
14
13
  "document.location.href = '#{self.class.helpers.escape_javascript location.to_s}'"
15
14
  else
16
15
  response.body || ''
@@ -2,7 +2,7 @@ module ActiveScaffold
2
2
  module Version
3
3
  MAJOR = 3
4
4
  MINOR = 4
5
- PATCH = 10
5
+ PATCH = 11
6
6
 
7
7
  STRING = [MAJOR, MINOR, PATCH].compact.join('.')
8
8
  end
@@ -4,6 +4,7 @@ class RoutingMapperTest < ActionController::TestCase
4
4
  test 'rails routes' do
5
5
  assert_routing 'addresses', :controller => 'addresses', :action => 'index'
6
6
  assert_routing 'addresses/1', :controller => 'addresses', :action => 'show', :id => '1'
7
+ assert_routing 'addresses/1/list', :controller => 'addresses', :action => 'index', :id => '1'
7
8
  assert_routing 'addresses/1/edit', :controller => 'addresses', :action => 'edit', :id => '1'
8
9
  assert_routing({:method => :put, :path => 'addresses/1'}, {:controller => 'addresses', :action => 'update', :id => '1'})
9
10
  assert_routing({:method => :delete, :path => 'addresses/1'}, {:controller => 'addresses', :action => 'destroy', :id => '1'})
@@ -13,7 +13,6 @@ class AttributeParamsTest < MiniTest::Test
13
13
  assert model.save
14
14
 
15
15
  model.buildings.create(:name => '1st building')
16
- model.reload
17
16
  model = update_record_from_params(model, :update, :first_name, :last_name, :first_name => 'Name', :last_name => 'Last')
18
17
  assert_equal 'Name', model.first_name
19
18
  assert_equal 'Last', model.last_name
@@ -69,7 +68,7 @@ class AttributeParamsTest < MiniTest::Test
69
68
  assert_equal 0, model.reload.buildings_count
70
69
  end
71
70
 
72
- def test_saving_belongs_to_select
71
+ def test_saving_belongs_to_select_for_has_one_reverse
73
72
  person = Person.create
74
73
  assert person.persisted?
75
74
  assert_equal 0, person.floors_count
@@ -87,8 +86,44 @@ class AttributeParamsTest < MiniTest::Test
87
86
  assert_nil model.tenant, 'tenant should be cleared'
88
87
  assert_equal person.id, Floor.find(model.id).tenant_id, 'floor should not be saved yet'
89
88
  assert model.save
90
- assert_nil Floor.find(model.id).tenant_id, 'floor should not be saved'
89
+ assert_nil Floor.find(model.id).tenant_id, 'floor should be saved'
91
90
  assert_equal 0, person.reload.floors_count
91
+
92
+ model = update_record_from_params(model, :create, :number, :tenant, :number => '1', :tenant => person.id.to_s)
93
+ assert_equal 1, model.number
94
+ assert_equal person.id, model.tenant_id
95
+ assert_equal person, model.tenant
96
+ assert model.save
97
+ assert_equal 1, person.reload.floors_count
98
+ end
99
+
100
+ def test_saving_belongs_to_select_for_has_many_reverse
101
+ person = Person.create
102
+ assert person.persisted?
103
+ assert_equal 0, person.buildings_count
104
+
105
+ model = update_record_from_params(Building.new, :create, :name, :owner, :name => 'Tower', :owner => person.id.to_s)
106
+ assert_equal 'Tower', model.name
107
+ assert_equal person.id, model.owner_id
108
+ assert_equal person, model.owner
109
+ assert model.save
110
+ assert_equal 1, person.reload.buildings_count
111
+
112
+ model = update_record_from_params(model, :update, :name, :owner, :name => 'Tower', :owner => '')
113
+ assert_equal 'Tower', model.name
114
+ assert_nil model.owner_id, 'owner should be cleared'
115
+ assert_nil model.owner, 'owner should be cleared'
116
+ assert_equal person.id, Building.find(model.id).owner_id, 'building should not be saved yet'
117
+ assert model.save
118
+ assert_nil Building.find(model.id).owner_id, 'building should be saved'
119
+ assert_equal 0, person.reload.buildings_count
120
+
121
+ model = update_record_from_params(model, :create, :name, :owner, :name => 'Tower', :owner => person.id.to_s)
122
+ assert_equal 'Tower', model.name
123
+ assert_equal person.id, model.owner_id
124
+ assert_equal person, model.owner
125
+ assert model.save
126
+ assert_equal 1, person.reload.buildings_count
92
127
  end
93
128
 
94
129
  def test_saving_has_one_select
@@ -183,7 +218,7 @@ class AttributeParamsTest < MiniTest::Test
183
218
  floor = Floor.create
184
219
  people = 2.times.map { Person.create }
185
220
  key = Time.now.to_i.to_s
186
- floors = {'0' => '', '1' => {:number => '1', :tenant => '', :id => floor.id.to_s}, key => {:number => '2', 'tenant' => people.first.id.to_s}, key.succ => {:number => '4', 'tenant' => people.last.id.to_s}}
221
+ floors = {'0' => '', floor.id.to_s => {:number => '1', :tenant => '', :id => floor.id.to_s}, key => {:number => '2', 'tenant' => people.first.id.to_s}, key.succ => {:number => '4', 'tenant' => people.last.id.to_s}}
187
222
  model = update_record_from_params(Building.new, :create, :name, :floors, :name => 'First', :floors => floors)
188
223
  assert_equal 'First', model.name
189
224
  assert_equal 3, model.floors.size
@@ -191,11 +226,33 @@ class AttributeParamsTest < MiniTest::Test
191
226
  assert_equal [nil, *people.map(&:id)], model.floors.map(&:tenant_id)
192
227
  assert model.save
193
228
  assert_equal [1, 1], people.map(&:reload).map(&:floors_count)
229
+ assert_equal 3, model.reload.floors_count
230
+
231
+ last_floor = model.floors.last
232
+ floors = {'0' => '', floor.id.to_s => {:number => '1', :tenant => '', :id => floor.id.to_s}, last_floor.id.to_s => {:number => '4', 'tenant' => people.last.id.to_s, :id => last_floor.id.to_s}}
233
+ model = update_record_from_params(model, :create, :name, :floors, :name => 'First', :floors => floors)
234
+ assert_equal 'First', model.name
235
+ assert_equal 2, model.floors.size
236
+ assert_equal floor.id, model.floors.first.id
237
+ assert_equal [nil, last_floor.tenant_id], model.floors.map(&:tenant_id)
238
+ assert model.save
239
+ assert_equal 2, model.reload.floors_count
240
+
241
+ floors = {'0' => '', floor.id.to_s => {:number => '1', :tenant => '', :id => floor.id.to_s}}
242
+ new_model = update_record_from_params(Building.create, :create, :name, :floors, :name => 'Last', :floors => floors)
243
+ assert_equal 'Last', new_model.name
244
+ assert_equal 1, new_model.floors.size
245
+ assert_equal floor.id, new_model.floors.first.id
246
+ assert_equal [nil], new_model.floors.map(&:tenant_id)
247
+ assert new_model.save
248
+ assert_equal 1, new_model.reload.floors_count
249
+ assert_equal 1, model.reload.floors_count
194
250
 
195
251
  model = update_record_from_params(model, :update, :name, :floors, :name => 'Tower', :floors => {'0' => ''})
196
252
  assert_equal 'Tower', model.name
197
253
  assert model.floors.blank?, 'floors should be cleared'
198
254
  assert model.save
255
+ assert_equal 0, model.reload.floors_count
199
256
  end
200
257
 
201
258
  def test_saving_belongs_to_crud
@@ -292,6 +349,7 @@ class AttributeParamsTest < MiniTest::Test
292
349
  params = columns.extract_options!.with_indifferent_access
293
350
  new_record = nil
294
351
  record.class.transaction do
352
+ record = record.class.find(record.id) if record.persisted?
295
353
  new_record = @controller.update_record_from_params(record, build_action_columns(record, action, columns), params)
296
354
  MODELS.each { |model| model.any_instance.unstub(:save) }
297
355
  yield if block_given?
@@ -1,17 +1,8 @@
1
1
  class Building < ActiveRecord::Base
2
- belongs_to :owner, :class_name => 'Person', :counter_cache => true
3
- has_many :floors, :dependent => :delete_all
2
+ belongs_to :owner, :class_name => 'Person', :counter_cache => true, :inverse_of => :building
3
+ has_many :floors, :dependent => :destroy, :inverse_of => :building
4
4
 
5
5
  has_one :address, :as => :addressable
6
6
 
7
7
  has_many :tenants, :through => :floors, :class_name => 'Person'
8
-
9
- if Rails.version < '4.1'
10
- after_update :update_buildings_count, :if => :owner_id_changed?
11
-
12
- def update_buildings_count
13
- Person.decrement_counter(:buildings_count, owner_id_was) if owner_id_was
14
- Person.increment_counter(:buildings_count, owner_id) if owner_id
15
- end
16
- end
17
8
  end
@@ -1,6 +1,6 @@
1
1
  class Floor < ActiveRecord::Base
2
- belongs_to :building
3
- belongs_to :tenant, :class_name => 'Person', :counter_cache => true
2
+ belongs_to :building, :counter_cache => true, :inverse_of => :floors
3
+ belongs_to :tenant, :class_name => 'Person', :counter_cache => true, :inverse_of => :floor
4
4
  has_one :address, :through => :building
5
5
 
6
6
  attr_accessor :number_required
@@ -1,6 +1,6 @@
1
1
  class Person < ActiveRecord::Base
2
- has_many :buildings, :foreign_key => :owner_id
3
- has_one :floor, :foreign_key => :tenant_id
2
+ has_many :buildings, :foreign_key => :owner_id, :inverse_of => :owner
3
+ has_one :floor, :foreign_key => :tenant_id, :inverse_of => :tenant
4
4
  has_one :address, :through => :floor
5
5
  has_one :home, :through => :floor, :source => :building, :class_name => 'Building'
6
6
 
@@ -30,4 +30,5 @@ RailsApp::Application.configure do
30
30
 
31
31
  # Print deprecation notices to the stderr
32
32
  config.active_support.deprecation = :stderr
33
+ config.active_support.test_order = :sorted
33
34
  end
@@ -11,6 +11,7 @@ ActiveRecord::Schema.define do
11
11
  create_table 'buildings' do |t|
12
12
  t.string 'name'
13
13
  t.integer 'owner_id'
14
+ t.integer 'floors_count', :null => false, :default => 0
14
15
  t.datetime "created_at"
15
16
  t.datetime "updated_at"
16
17
  end
@@ -1,7 +1,5 @@
1
- if RUBY_VERSION >= '1.9' && RUBY_ENGINE == 'ruby' # remove RUBY_ENGINE test when rubinius-coverage fix is released
2
- require 'simplecov'
3
- SimpleCov.start { add_filter 'test' }
4
- end
1
+ require 'simplecov'
2
+ SimpleCov.start { add_filter 'test' }
5
3
 
6
4
  ENV['RAILS_ENV'] = 'test'
7
5
  require "mock_app/config/environment"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_scaffold
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.4.10
4
+ version: 3.4.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Many, see README
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-21 00:00:00.000000000 Z
11
+ date: 2014-12-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: shoulda
@@ -427,7 +427,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
427
427
  requirements:
428
428
  - - '>='
429
429
  - !ruby/object:Gem::Version
430
- version: '0'
430
+ version: '1.9'
431
431
  required_rubygems_version: !ruby/object:Gem::Requirement
432
432
  requirements:
433
433
  - - '>='
@@ -435,7 +435,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
435
435
  version: '0'
436
436
  requirements: []
437
437
  rubyforge_project:
438
- rubygems_version: 2.0.3
438
+ rubygems_version: 2.1.11
439
439
  signing_key:
440
440
  specification_version: 4
441
441
  summary: Rails 3.2 and 4.0 version of activescaffold supporting prototype and jquery