e9_rails 0.0.10 → 0.0.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.
@@ -7,6 +7,11 @@ module E9Rails::ActiveRecord
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  included do
10
+ #
11
+ # NOTE
12
+ #
13
+ attribute_method_suffix "_with_inheritable_options"
14
+
10
15
  class_inheritable_accessor :options_column
11
16
  self.options_column = :options
12
17
 
@@ -16,16 +21,17 @@ module E9Rails::ActiveRecord
16
21
  class_inheritable_accessor :options_class
17
22
  self.options_class = Options
18
23
 
24
+ class_inheritable_accessor :delegate_options_methods
25
+ self.delegate_options_methods = false
26
+
19
27
  self.options_class.lookup_ancestors = lookup_ancestors
20
28
  end
21
29
 
22
30
  def options=(hash={})
23
- _serialize_inheritable_options_column unless _inheritable_options_column_serialized?
24
31
  write_attribute(options_column, hash.stringify_keys)
25
32
  end
26
33
 
27
34
  def options
28
- _serialize_inheritable_options_column unless _inheritable_options_column_serialized?
29
35
  opts = read_attribute(options_column) || {}
30
36
  opts.reverse_merge! Hash[options_parameters.map(&:to_s).zip([nil])]
31
37
  options_class.new(opts, self)
@@ -33,18 +39,32 @@ module E9Rails::ActiveRecord
33
39
 
34
40
  protected
35
41
 
36
- def _serialize_inheritable_options_column
37
- self.class.serialized_attributes[options_column.to_s] = Hash
42
+ module ClassMethods
43
+ def define_method_attribute_with_inheritable_options(attr_name)
44
+ initialize_inheritable_options
45
+ end
46
+
47
+ def inheritable_options_initialized?
48
+ serialized_attributes[self.options_column.to_s].present?
38
49
  end
39
50
 
40
- def _inheritable_options_column_serialized?
41
- self.class.serialized_attributes[options_column.to_s].present?
51
+ def initialize_inheritable_options
52
+ return if inheritable_options_initialized?
53
+ serialized_attributes[self.options_column.to_s] = Hash
54
+
55
+ if self.delegate_options_methods
56
+ self.options_parameters.each do |param|
57
+ delegate param, "#{param}=", :to => :options
58
+ end
59
+ end
42
60
  end
61
+ end
43
62
 
44
63
  class Options < HashWithIndifferentAccess
45
64
  extend ActiveModel::Naming
46
65
  extend ActiveModel::Translation
47
66
 
67
+ # implementation of lookup_ancestors for AM & i18n
48
68
  class_inheritable_accessor :lookup_ancestors
49
69
 
50
70
  attr_reader :base
@@ -0,0 +1,20 @@
1
+ module E9Rails::ActiveRecord
2
+ module Initialization
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ alias :initialize_without_defaults :initialize
7
+
8
+ def initialize(attributes = nil, &block)
9
+ initialize_without_defaults(attributes) do
10
+ self.send(:_assign_initialization_defaults)
11
+ yield self if block_given?
12
+ end
13
+ end
14
+ end
15
+
16
+ def _assign_initialization_defaults; end
17
+
18
+ protected :_assign_initialization_defaults
19
+ end
20
+ end
@@ -6,51 +6,80 @@ module E9Rails::Controllers
6
6
  module Orderable
7
7
  extend ActiveSupport::Concern
8
8
 
9
- def default_ordered_on; 'created_at' end
10
-
11
- def default_ordered_dir; 'DESC' end
9
+ included do
10
+ helper HelperMethods
12
11
 
13
- def ordered_if; params[:action] == 'index' end
12
+ helper_method :default_ordered_dir
14
13
 
15
- included do
16
- if respond_to?(:resource_class)
17
- has_scope :ordered_on, :if => :ordered_if, :default => lambda {|c| c.send(:default_ordered_on) } do |controller, scope, val|
18
- begin
19
- # determine the dir from params or controller default
20
- dir = case controller.params[:dir]
21
- when /^desc$/i then 'DESC'
22
- when /^asc$/i then 'ASC'
23
- else controller.send(:default_ordered_dir) rescue ''
24
- end
25
-
26
- # split the ordered_param on commas and periods, the idea being that
27
- # it can take multiple columns, and on assocation columns
28
- val = val.split(',').map {|v| v.split('.') }
29
-
30
- val = val.map {|v|
31
- # if val split on '.', try to constantize the parsed class
32
- if v.length > 1
33
- klass = v.first.classify.constantize rescue nil
34
- # and if it succeeds
35
- if klass
36
- # apply the join to the scope.
37
- # NOTE there's no checking whatsoever here as to:
38
- # A.) is this class an association?
39
- # B.) does this class have the passed column?
40
- scope = scope.joins(v.first.underscore.to_sym)
41
- "#{klass.table_name}.#{v.last} #{dir}"
14
+ has_scope :order, :if => :ordered_if, :default => lambda {|c| c.send(:default_ordered_on) } do |controller, scope, columns|
15
+ begin
16
+ # determine the dir from params or controller default
17
+ dir = case controller.params[:sort]
18
+ when /^desc$/i then 'DESC'
19
+ when /^asc$/i then 'ASC'
20
+ else controller.try(:default_ordered_dir) || ''
42
21
  end
43
- else
44
- # else we're assuming the column is on the table
45
- "#{resource_class.table_name}.#{v.last} #{dir}"
22
+
23
+ # split the ordered_param on commas and periods, the idea being that
24
+ # it can take multiple columns, and on assocation columns
25
+ columns = columns.split(',').map {|n| n.split('.') }
26
+
27
+ columns = columns.map {|v|
28
+ # if column split on '.', try to constantize the parsed class
29
+ if v.length > 1
30
+ klass = v.first.classify.constantize rescue nil
31
+
32
+ # and if it succeeds
33
+ if klass
34
+ # apply the join to the scope.
35
+ # NOTE there's no checking whatsoever here as to:
36
+ # A.) is this class an association?
37
+ # B.) does this class have the passed column?
38
+ scope = scope.includes(v.first.underscore.to_sym)
39
+ "#{klass.table_name}.#{v.last} #{dir}"
46
40
  end
47
- }.compact.join(', ')
41
+ else
42
+ # else we're assuming the column is on the table
43
+ "#{controller.send(:resource_class).table_name}.#{v.last} #{dir}"
44
+ end
45
+ }.compact.join(', ')
46
+
47
+ scope.order(columns)
48
+ rescue => e
49
+ Rails.logger.error("Orderable ordered_on scope : #{e.message}")
50
+ scope
51
+ end
52
+ end
53
+ end
54
+
55
+ def default_ordered_on
56
+ 'created_at'
57
+ end
58
+
59
+ def default_ordered_dir
60
+ 'DESC'
61
+ end
62
+
63
+ def ordered_if
64
+ params[:action] == 'index'
65
+ end
66
+
67
+ module HelperMethods
68
+ def orderable_column_link(column, override_name = nil)
69
+ link_text = resource_class.human_attribute_name(override_name || column)
70
+
71
+ column = column.join(',') if column.is_a?(Array)
72
+
73
+ co, lo = if params[:order] == column.to_s
74
+ params[:sort] =~ /^desc$/i ? %w(DESC ASC) : %w(ASC DESC)
75
+ else
76
+ [nil, default_ordered_dir.presence || 'DESC']
77
+ end
78
+
79
+ css_classes = ["order-gfx", co, "h-#{lo}"].compact.join(' ').downcase
48
80
 
49
- scope.order(val)
50
- rescue => e
51
- Rails.logger.error("Orderable ordered_on scope : #{e.message}")
52
- scope
53
- end
81
+ content_tag(:div, :class => 'ordered-column') do
82
+ link_to(link_text, :order => column, :sort => lo).safe_concat tag(:span, :class => css_classes)
54
83
  end
55
84
  end
56
85
  end
@@ -12,10 +12,26 @@ module E9Rails::Controllers
12
12
  module Sortable
13
13
  extend ActiveSupport::Concern
14
14
 
15
+ included do
16
+ class_inheritable_accessor :sortable_column
17
+ self.sortable_column = :position
18
+
19
+ class_inheritable_accessor :sortable_scope_proc
20
+ self.sortable_scope_proc = lambda {|_, scope, _| scope.order(sortable_column) }
21
+
22
+ #
23
+ # NOTE whatever the sortable column value, the proc will override the default.
24
+ # the 'default' is only specified here to ensure that the scope is always called
25
+ #
26
+ has_scope :sortable_order, :only => :index, :default => sortable_column.to_s do |controller, scope, value|
27
+ sortable_scope_proc.call(controller, scope, value)
28
+ end
29
+ end
30
+
15
31
  def update_order(options = {}, &block)
16
32
  if params[:ids].is_a?(Array)
17
33
  pos = 0
18
- params[:ids].each {|id| pos += 1; _do_position_update(id, :position => pos) }
34
+ params[:ids].each {|id| pos += 1; _do_position_update(id, sortable_column => pos) }
19
35
  flash[:notice] = I18n.t(:notice, :scope => :"flash.actions.update_order")
20
36
  else
21
37
  flash[:alert] = I18n.t(:alert, :scope => :"flash.actions.update_order")
@@ -23,11 +23,11 @@ module E9Rails::Helpers
23
23
  return ''
24
24
  end
25
25
 
26
+ errors = object.errors.map {|attribute, msg| msg }.flatten.map {|m| "<li>#{m}</li>"}.join("\n")
27
+
26
28
  <<-HTML.html_safe
27
29
  <div id="errorExplanation">
28
- <ul>
29
- #{ object.errors.map {|attribute, msg| "<li>#{msg}</li>" }.join }
30
- </ul>
30
+ <ul>#{errors}</ul>
31
31
  </div>
32
32
  HTML
33
33
  rescue => e
@@ -0,0 +1,84 @@
1
+ module E9Rails::Helpers
2
+ module ResourceLinks
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ helper HelperMethods
7
+
8
+ unless self._helper_methods.member?(:parent)
9
+ def parent; end
10
+ protected :parent
11
+ helper_method :parent
12
+ end
13
+ end
14
+
15
+ module HelperMethods
16
+ def link_to_resource(resource, options = {})
17
+ options.symbolize_keys!
18
+
19
+ path_options = options.slice!(:scope, :action, :method, :remote, :confirm, :class)
20
+
21
+ klass = resource.is_a?(Class) ? resource : resource.class
22
+
23
+ action = options.delete(:action)
24
+ action = klass == resource ? :new : (action || :show).to_sym
25
+
26
+ scopes = [*(options[:scope] || @route_scope), parent].compact
27
+ path = case action
28
+ when :new; new_polymorphic_path(scopes << klass, path_options)
29
+ when :edit; edit_polymorphic_path(scopes << resource, path_options)
30
+ else polymorphic_path(scopes << resource, path_options)
31
+ end
32
+
33
+ mn = klass.model_name
34
+
35
+ translation_options = {
36
+ :model => mn.human,
37
+ :models => mn.human.pluralize,
38
+ :collection => mn.collection,
39
+ :element => mn.element
40
+ }
41
+
42
+ if action == :destroy
43
+ defaults = klass.lookup_ancestors.map {|k|
44
+ :"#{klass.i18n_scope}.links.#{k.model_name.underscore}.confirm_destroy"
45
+ } << :"#{klass.i18n_scope}.links.confirm_destroy"
46
+
47
+ options[:method] = :delete
48
+ options.reverse_merge!({
49
+ :remote => true,
50
+ :confirm => I18n.t(defaults.shift, translation_options.merge(:default => defaults))
51
+ })
52
+ end
53
+
54
+ #
55
+ # Mimic ActiveModel's lookup chain for attributes
56
+ #
57
+ defaults = klass.lookup_ancestors.map do |k|
58
+ :"#{klass.i18n_scope}.links.#{k.model_name.underscore}.#{action}"
59
+ end
60
+
61
+ defaults << :"#{klass.i18n_scope}.links.#{action}"
62
+ defaults << action.to_s.humanize
63
+
64
+ link_to I18n.t(defaults.shift, translation_options.merge(:default => defaults)), path, options
65
+ end
66
+
67
+ def link_to_show_resource(resource, options = {})
68
+ link_to_resource(resource, options.merge(:action => :show))
69
+ end
70
+
71
+ def link_to_edit_resource(resource, options = {})
72
+ link_to_resource(resource, options.merge(:action => :edit))
73
+ end
74
+
75
+ def link_to_new_resource(resource, options = {})
76
+ link_to_resource(resource, options.merge(:action => :new))
77
+ end
78
+
79
+ def link_to_destroy_resource(resource, options = {})
80
+ link_to_resource(resource, options.merge(:action => :destroy))
81
+ end
82
+ end
83
+ end
84
+ end
@@ -1,3 +1,3 @@
1
1
  module E9Rails
2
- VERSION = "0.0.10"
2
+ VERSION = "0.0.11"
3
3
  end
data/lib/e9_rails.rb CHANGED
@@ -4,9 +4,10 @@ module E9Rails
4
4
  autoload :Version, 'e9_rails/version'
5
5
 
6
6
  module ActiveRecord
7
- autoload :STI, 'e9_rails/active_record/sti'
8
7
  autoload :AttributeSearchable, 'e9_rails/active_record/attribute_searchable'
9
8
  autoload :InheritableOptions, 'e9_rails/active_record/inheritable_options'
9
+ autoload :Initialization, 'e9_rails/active_record/initialization'
10
+ autoload :STI, 'e9_rails/active_record/sti'
10
11
  end
11
12
 
12
13
  module Controllers
@@ -15,9 +16,10 @@ module E9Rails
15
16
  end
16
17
 
17
18
  module Helpers
18
- autoload :Translation, 'e9_rails/helpers/translation'
19
+ autoload :Pagination, 'e9_rails/helpers/pagination'
19
20
  autoload :ResourceErrorMessages, 'e9_rails/helpers/resource_error_messages'
21
+ autoload :ResourceLinks, 'e9_rails/helpers/resource_links'
20
22
  autoload :Title, 'e9_rails/helpers/title'
21
- autoload :Pagination, 'e9_rails/helpers/pagination'
23
+ autoload :Translation, 'e9_rails/helpers/translation'
22
24
  end
23
25
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: e9_rails
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.10
5
+ version: 0.0.11
6
6
  platform: ruby
7
7
  authors:
8
8
  - Travis Cox
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-05-02 00:00:00 -04:00
13
+ date: 2011-05-12 00:00:00 -04:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -53,11 +53,13 @@ files:
53
53
  - lib/e9_rails.rb
54
54
  - lib/e9_rails/active_record/attribute_searchable.rb
55
55
  - lib/e9_rails/active_record/inheritable_options.rb
56
+ - lib/e9_rails/active_record/initialization.rb
56
57
  - lib/e9_rails/active_record/sti.rb
57
58
  - lib/e9_rails/controllers/orderable.rb
58
59
  - lib/e9_rails/controllers/sortable.rb
59
60
  - lib/e9_rails/helpers/pagination.rb
60
61
  - lib/e9_rails/helpers/resource_error_messages.rb
62
+ - lib/e9_rails/helpers/resource_links.rb
61
63
  - lib/e9_rails/helpers/title.rb
62
64
  - lib/e9_rails/helpers/translation.rb
63
65
  - lib/e9_rails/version.rb