active_scaffold 3.4.10 → 3.4.11

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.
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