openstax_utilities 1.1.0 → 1.2.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.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Yzc2ZjE5YTExNmU0YjkzYWRmMTgwYzQyYjJjOWYzMDE5Nzk2OWI4ZQ==
5
+ data.tar.gz: !binary |-
6
+ NDdhMjA5NDJiOWM4YmM3MzNiNWE2NWE3Nzk5ZmRlYzJiY2FlOTZhOA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MzI4MzM2MDBlN2U2MmNiYzU1ODk3NTA5NmExOWJlZTkyOTdhOGQ0OGQxNWMx
10
+ Nzg5Y2UxNDNhOTc5NWFkYzIwMDkzZDI5YjRjNzcwMWNiOWRlYWY2YjExMDE5
11
+ YTViOWUzZTY5NDRiZDFmODJjZGY5MjllOGMxZmY4ZDJhNmM0NmY=
12
+ data.tar.gz: !binary |-
13
+ N2NjNWY2MTQzMDNmZjRiMTYxM2U0MzQ4NTQxMzQ5Y2Q2MDdiYWQ4YzA4OTc4
14
+ ZGEzODA2YTdiYmY5ZTlhNGE0MDhmNjk1NjFjNDVmYTkzOGU5MDRlMjQ3NzFi
15
+ ZjRjMWFiNGUwZDg5Y2RmMDhlNGFjZTk3MWQwNWMwMDQ5ZTg2MzI=
@@ -3,6 +3,7 @@ module OpenStax::Utilities
3
3
 
4
4
  def osu
5
5
  @@osu_class ||= Class.new(ClassyHelper) do
6
+ include OpenStax::Utilities::Helpers::Misc
6
7
  include OpenStax::Utilities::Helpers::Blocks
7
8
  include OpenStax::Utilities::Helpers::Partials
8
9
  include OpenStax::Utilities::Helpers::ActionList
@@ -0,0 +1,14 @@
1
+ module ActiveRecord
2
+ class Base
3
+
4
+ def self.find_in_specified_order(ids)
5
+ items = find(ids)
6
+
7
+ order_hash = {}
8
+ ids.each_with_index {|id, index| order_hash[id.to_i]=index}
9
+
10
+ items.sort_by!{|item| order_hash[item.id]}
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,218 @@
1
+ # Copyright 2011-2012 Rice University. Licensed under the Affero General Public
2
+ # License version 3 or later. See the COPYRIGHT file for details.
3
+
4
+ module OpenStax
5
+ module Utilities
6
+
7
+ module ActsAsNumberable
8
+
9
+ # Adds code to an ActiveRecord object so that it can be sorted.
10
+ # @example Model is ordered globally using a 'number' field
11
+ # class MyModel < ActiveRecord::Base
12
+ # acts_as_numberable
13
+ # @example Model is ordered globally using a 'position' field
14
+ # class MyModel < ActiveRecord::Base
15
+ # acts_as_numberable :number_field => :position
16
+ # @example Model is ordered within a container class using a position field
17
+ # class MyModel < ActiveRecord::Base
18
+ # belongs_to :other_model
19
+ # acts_as_numberable :container => :other_model,
20
+ # :number_field => :position
21
+ # @param :container The relationship that contains this model in an order.
22
+ # Note that this code assumes the foreign key for this container is found
23
+ # by appending "_id" onto the container name, which might not always be the
24
+ # case.
25
+ # @param :number_field The column to use as the sorting number, given either
26
+ # as a string or a symbol. The default is 'number'
27
+ # @param :table_class By default this code assumes that the database table
28
+ # name to use for this model can be derived from the model's class name; in
29
+ # some cases (e.g. STI) this is not the case and this parameter can be used
30
+ # to manually specify the class from which to derive the database table name.
31
+ #
32
+ def acts_as_numberable(options={})
33
+ configuration = {}
34
+ configuration.update(options) if options.is_a?(Hash)
35
+
36
+ container_column = nil
37
+ container_column_symbol = nil
38
+
39
+ # When calling assign_number below, you normally want to run a query against
40
+ # self.class to figure out what the next available number is; however, if the
41
+ # class acting as numberable is using STI, self.class will return the child class
42
+ # which is likely not what we want. In these cases, we can specify the base
43
+ # class here (the class that has the same name as the DB table) so that it is used
44
+ # instead.
45
+ table_class = configuration[:table_class]
46
+
47
+ number_field = (configuration[:number_field] || 'number').to_s
48
+
49
+ if !configuration[:container].nil?
50
+ container_column = configuration[:container].to_s + "_id"
51
+ container_column_symbol = configuration[:container].to_sym
52
+ end
53
+
54
+ uniqueness_scope_string = container_column.nil? ? "" : ":scope => :#{container_column},"
55
+
56
+ class_eval <<-EOV
57
+ include ActsAsNumberable::BasicInstanceMethods
58
+
59
+ before_validation :assign_number, :on => :create
60
+
61
+ validates :#{number_field}, :uniqueness => { #{uniqueness_scope_string}
62
+ :allow_nil => true},
63
+ :numericality => { :only_integer => true,
64
+ :greater_than_or_equal_to => 0,
65
+ :allow_nil => true }
66
+
67
+
68
+ after_destroy :mark_as_destroyed
69
+
70
+ attr_accessor :destroyed
71
+ attr_accessor :changed_sets
72
+
73
+ attr_protected :#{number_field}
74
+
75
+ scope :ordered, order('#{number_field} ASC')
76
+ scope :reverse_ordered, order('#{number_field} DESC')
77
+
78
+ def self.sort!(sorted_ids)
79
+ return if sorted_ids.blank?
80
+ items = []
81
+ ActiveRecord::Base.transaction do
82
+ items = find_in_specified_order(sorted_ids)
83
+
84
+ items.each do |item|
85
+ item.send('#{number_field}=', nil)
86
+ item.save!
87
+ end
88
+
89
+ items.each_with_index do |item, ii|
90
+ item.send('#{number_field}=', ii)
91
+ item.save!
92
+ end
93
+ end
94
+ items
95
+ end
96
+
97
+ def table_class
98
+ #{table_class}
99
+ end
100
+
101
+ def number_field
102
+ '#{number_field}'
103
+ end
104
+ EOV
105
+
106
+
107
+ if !configuration[:container].nil?
108
+ class_eval <<-EOV
109
+ include ActsAsNumberable::ContainerInstanceMethods
110
+
111
+ # When we had nested acts_as_numberables, there were cases where the
112
+ # objects were having their numbers changed (as their peers were being
113
+ # removed from the container), but then when it came time to delete those
114
+ # objects they still had their old number. So just reload before
115
+ # destroy.
116
+ before_destroy(prepend: true) {self.reload}
117
+
118
+ after_destroy :remove_from_container!
119
+
120
+ def container_column
121
+ '#{container_column}'
122
+ end
123
+
124
+ def container
125
+ '#{configuration[:container]}'
126
+ end
127
+
128
+ def table_class
129
+ #{table_class}
130
+ end
131
+
132
+ EOV
133
+
134
+ end
135
+
136
+ end
137
+
138
+ module BasicInstanceMethods
139
+ protected
140
+
141
+ def my_class
142
+ table_class || self.class
143
+ end
144
+
145
+ def assign_number
146
+ self.send("#{number_field}=", my_class.count) if self.send("#{number_field}").nil?
147
+ end
148
+
149
+ def mark_as_destroyed
150
+ destroyed = true
151
+ end
152
+
153
+ def me_and_peers
154
+ my_class.scoped
155
+ end
156
+ end
157
+
158
+ module ContainerInstanceMethods
159
+ def move_to_container!(new_container)
160
+ return if new_container.id == self.send(container_column)
161
+ ActiveRecord::Base.transaction do
162
+ remove_from_container!
163
+
164
+ self.send container + "=", new_container
165
+
166
+ self.assign_number
167
+ self.save!
168
+ self.changed_sets = true
169
+ end
170
+ end
171
+
172
+ def remove_from_container!
173
+ later_items = my_class.where(container_column => self.send(container_column))
174
+ .where("#{number_field} > ?", self.send(number_field))
175
+
176
+ if !self.destroyed
177
+ self.send "#{number_field}=", nil
178
+ self.send container_column + '=', nil
179
+ self.save!
180
+ end
181
+
182
+ # Do this to make sure that the reordering below doesn't
183
+ # cause a number to be duplicated temporarily (which would
184
+ # cause a validation error)
185
+ later_items.sort_by!{|item| item.send(number_field)}
186
+
187
+ later_items.each do |later|
188
+ later.send("#{number_field}=", later.send(number_field)-1)
189
+ later.save!
190
+ end
191
+ end
192
+
193
+ def my_class
194
+ table_class || self.class
195
+ end
196
+
197
+ def me_and_peers
198
+ my_class.where(container_column => self.send(container_column))
199
+ end
200
+
201
+ protected
202
+
203
+ def assign_number
204
+ if self.send(number_field).nil?
205
+ self.send("#{number_field}=",
206
+ my_class
207
+ .where(container_column => self.send(container_column))
208
+ .count)
209
+ end
210
+ end
211
+ end
212
+
213
+ end
214
+
215
+ end
216
+ end
217
+
218
+ ActiveRecord::Base.extend OpenStax::Utilities::ActsAsNumberable
@@ -0,0 +1,51 @@
1
+ # Copyright 2011-2012 Rice University. Licensed under the Affero General Public
2
+ # License version 3 or later. See the COPYRIGHT file for details.
3
+
4
+ module OpenStax
5
+ module Utilities
6
+
7
+ module DelegateAccessControl
8
+
9
+ # Adds code to an ActiveRecord object to delegate its access control methods to
10
+ # another object.
11
+ # @example Model is ordered globally using a 'number' field
12
+ # class MyModel < ActiveRecord::Base
13
+ # belongs_to :another
14
+ # delegate_access_control to: :another
15
+ # @param :to The relationship to which the access control methods should
16
+ # be delegated.
17
+ # @param :include_sort If true, a "can_be_sorted_by?" method will be included
18
+ # (Default: false)
19
+ #
20
+ def delegate_access_control(options={})
21
+ configuration = {include_sort: false}
22
+ configuration.update(options) if options.is_a?(Hash)
23
+
24
+ raise IllegalArgument, "A :to option must be provided" if configuration[:to].blank?
25
+
26
+ configuration[:to] = configuration[:to].to_s
27
+
28
+ class_eval <<-EOV
29
+ delegate :can_be_read_by?,
30
+ :can_be_updated_by?,
31
+ to: :#{configuration[:to]}
32
+
33
+ # Delegating creation and destroying of this contained object means you can
34
+ # update the containing object
35
+
36
+ alias_method :can_be_created_by?, :can_be_updated_by?
37
+ alias_method :can_be_destroyed_by?, :can_be_updated_by?
38
+
39
+ if #{configuration[:include_sort]}
40
+ alias_method :can_be_sorted_by?, :can_be_updated_by?
41
+ end
42
+ EOV
43
+
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+ end
50
+
51
+ ActiveRecord::Base.extend OpenStax::Utilities::DelegateAccessControl
@@ -0,0 +1,9 @@
1
+ module OpenStax::Utilities::Helpers
2
+ module Misc
3
+
4
+ def tf_to_yn(bool, options={})
5
+ bool ? "Yes" : "No"
6
+ end
7
+
8
+ end
9
+ end
@@ -1,5 +1,5 @@
1
1
  module OpenStax
2
2
  module Utilities
3
- VERSION = "1.1.0"
3
+ VERSION = "1.2.0"
4
4
  end
5
5
  end
@@ -8,6 +8,7 @@ OSU = OpenStax::Utilities
8
8
  require "openstax/utilities/engine"
9
9
  require "openstax/utilities/version"
10
10
  require "openstax/utilities/exceptions"
11
+ require "openstax/utilities/active_record_extensions"
11
12
  require "openstax/utilities/settings"
12
13
  require "openstax/utilities/access"
13
14
  require "openstax/utilities/enum"
@@ -15,8 +16,11 @@ require "openstax/utilities/ruby"
15
16
  require "openstax/utilities/text"
16
17
  require "openstax/utilities/network"
17
18
  require "openstax/utilities/action_list"
19
+ require "openstax/utilities/acts_as_numberable"
20
+ require "openstax/utilities/delegate_access_control"
18
21
 
19
22
  require "openstax/utilities/classy_helper"
23
+ require "openstax/utilities/helpers/misc"
20
24
  require "openstax/utilities/helpers/blocks"
21
25
  require "openstax/utilities/helpers/partials"
22
26
  require "openstax/utilities/helpers/action_list"
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openstax_utilities
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
5
- prerelease:
4
+ version: 1.2.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - JP Slavinsky
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-11-07 00:00:00.000000000 Z
11
+ date: 2014-02-21 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rails
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ! '>='
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ! '>='
28
25
  - !ruby/object:Gem::Version
@@ -30,7 +27,6 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: attribeautiful
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ~>
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ~>
44
39
  - !ruby/object:Gem::Version
@@ -50,6 +45,9 @@ executables: []
50
45
  extensions: []
51
46
  extra_rdoc_files: []
52
47
  files:
48
+ - MIT-LICENSE
49
+ - README.md
50
+ - Rakefile
53
51
  - app/assets/javascripts/openstax_utilities.js
54
52
  - app/assets/stylesheets/openstax_utilities.css
55
53
  - app/helpers/openstax/utilities/osu_helper.rb
@@ -60,12 +58,15 @@ files:
60
58
  - app/views/osu/shared/_table_row.html.erb
61
59
  - lib/openstax/utilities/access.rb
62
60
  - lib/openstax/utilities/action_list.rb
61
+ - lib/openstax/utilities/active_record_extensions.rb
62
+ - lib/openstax/utilities/acts_as_numberable.rb
63
63
  - lib/openstax/utilities/blocks/block_base.rb
64
64
  - lib/openstax/utilities/blocks/section_block.rb
65
65
  - lib/openstax/utilities/blocks/table_block.rb
66
66
  - lib/openstax/utilities/blocks/table_cell_block.rb
67
67
  - lib/openstax/utilities/blocks/table_row_block.rb
68
68
  - lib/openstax/utilities/classy_helper.rb
69
+ - lib/openstax/utilities/delegate_access_control.rb
69
70
  - lib/openstax/utilities/development.rb
70
71
  - lib/openstax/utilities/engine.rb
71
72
  - lib/openstax/utilities/enum.rb
@@ -73,6 +74,7 @@ files:
73
74
  - lib/openstax/utilities/helpers/action_list.rb
74
75
  - lib/openstax/utilities/helpers/blocks.rb
75
76
  - lib/openstax/utilities/helpers/datetime.rb
77
+ - lib/openstax/utilities/helpers/misc.rb
76
78
  - lib/openstax/utilities/helpers/partials.rb
77
79
  - lib/openstax/utilities/network.rb
78
80
  - lib/openstax/utilities/ruby.rb
@@ -80,14 +82,14 @@ files:
80
82
  - lib/openstax/utilities/text.rb
81
83
  - lib/openstax/utilities/version.rb
82
84
  - lib/openstax_utilities.rb
83
- - MIT-LICENSE
84
- - Rakefile
85
- - README.md
85
+ - test/dummy/README.rdoc
86
+ - test/dummy/Rakefile
86
87
  - test/dummy/app/assets/javascripts/application.js
87
88
  - test/dummy/app/assets/stylesheets/application.css
88
89
  - test/dummy/app/controllers/application_controller.rb
89
90
  - test/dummy/app/helpers/application_helper.rb
90
91
  - test/dummy/app/views/layouts/application.html.erb
92
+ - test/dummy/config.ru
91
93
  - test/dummy/config/application.rb
92
94
  - test/dummy/config/boot.rb
93
95
  - test/dummy/config/database.yml
@@ -103,45 +105,35 @@ files:
103
105
  - test/dummy/config/initializers/wrap_parameters.rb
104
106
  - test/dummy/config/locales/en.yml
105
107
  - test/dummy/config/routes.rb
106
- - test/dummy/config.ru
107
108
  - test/dummy/public/404.html
108
109
  - test/dummy/public/422.html
109
110
  - test/dummy/public/500.html
110
111
  - test/dummy/public/favicon.ico
111
- - test/dummy/Rakefile
112
- - test/dummy/README.rdoc
113
112
  - test/dummy/script/rails
114
113
  - test/integration/navigation_test.rb
115
114
  homepage: http://github.com/openstax/openstax_utilities
116
115
  licenses:
117
116
  - MIT
117
+ metadata: {}
118
118
  post_install_message:
119
119
  rdoc_options: []
120
120
  require_paths:
121
121
  - lib
122
122
  required_ruby_version: !ruby/object:Gem::Requirement
123
- none: false
124
123
  requirements:
125
124
  - - ! '>='
126
125
  - !ruby/object:Gem::Version
127
126
  version: '0'
128
- segments:
129
- - 0
130
- hash: -1961078437370851561
131
127
  required_rubygems_version: !ruby/object:Gem::Requirement
132
- none: false
133
128
  requirements:
134
129
  - - ! '>='
135
130
  - !ruby/object:Gem::Version
136
131
  version: '0'
137
- segments:
138
- - 0
139
- hash: -1961078437370851561
140
132
  requirements: []
141
133
  rubyforge_project:
142
- rubygems_version: 1.8.24
134
+ rubygems_version: 2.2.1
143
135
  signing_key:
144
- specification_version: 3
136
+ specification_version: 4
145
137
  summary: Utilities for OpenStax web sites
146
138
  test_files:
147
139
  - test/dummy/app/assets/javascripts/application.js