openstax_utilities 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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