e9_rails 0.0.10 → 0.0.11

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