motr 0.0.5 → 0.0.6

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.
data/README.rdoc CHANGED
@@ -2,11 +2,10 @@
2
2
 
3
3
  {Official Documentation}[http://rubydoc.info/github/kurbmedia/motr/master/frames]
4
4
 
5
- Motr is a basic Rails engine which adds additional functionality to your applications, and creates the ability to "extend" models
5
+ Motr is a basic Rails engine which adds additional functionality to your applications, and creates the ability to "mod" models and classes
6
6
  easily to support routine functionality. The {core Motr}[http://github.com/kurbmedia/motr] engine
7
7
  provides a number of helpers and functionality geared towards bringing the ease of Rails back-end development, to the front-end. It
8
- also implements a {Devise}[https://github.com/plataformatec/devise] inspired "hook" system to support easily adding data functionality to
9
- models in a similar manner to how Devise adds session management functionality.
8
+ also implements a "modding" system to support easily adding data functionality to classes/models.
10
9
 
11
10
  Rails view helpers and form builders are convenient an easy to use, however some aren't very design/html friendly (whose idea was it to
12
11
  wrap fields with errors in a div?). The goal is to keep html valid and sensible where possible, and make things like javascript integration
@@ -23,7 +22,7 @@ feature requests, especially from designers/front-end developers who spend a lot
23
22
 
24
23
  == Credits
25
24
 
26
- Thanks to José Valim and {Devise}[https://github.com/plataformatec/devise] which inspired the model hook functionality.
25
+ Thanks to José Valim and {Devise}[https://github.com/plataformatec/devise] which inspired the "modding" concept.
27
26
 
28
27
  == License
29
28
 
data/lib/motr.rb CHANGED
@@ -3,15 +3,12 @@ require 'active_support/dependencies'
3
3
  require 'set'
4
4
 
5
5
  require 'motr/forms'
6
- require 'motr/model'
6
+ require 'motr/modding'
7
+ require 'motr/mods'
8
+ require 'motr/dash'
7
9
 
8
10
  module Motr
9
11
 
10
- module Schema
11
- autoload :Base, 'motr/schema/base'
12
- autoload :Generator, 'motr/schema/generator'
13
- end
14
-
15
12
  module Controller #:nodoc:
16
13
  autoload :Helpers, 'motr/controller/helpers'
17
14
  autoload :Responder, 'motr/controller/responder'
@@ -29,52 +26,26 @@ module Motr
29
26
  autoload :ModuleMissing, 'motr/errors/module_missing'
30
27
  end
31
28
 
32
- # Store configurations for included models
33
- ALL = []
34
- CONFIGS = {}
35
29
 
36
30
  ##
37
31
  #
38
- # Enable adding models to the core Motr library. These modules
39
- # can then be included/initialized using the +motr+ method.
32
+ # Enable autoloading of mods
40
33
  #
41
34
  # @param [Symbol] module_name The name of the module to be added (underscored)
42
- # @param [Hash] config Default configuration options for the module
43
- #
44
- # @option config [String, Boolean] :autoload The path to autoload the module from (optional)
35
+ # @param [Hash] options Hash including options for the mod
45
36
  #
46
- # All other configuration options are considered default options for that particular module.
37
+ # @option options [String, Boolean] :autoload The path to autoload the module from (optional)
47
38
  #
48
39
  #
49
- def self.add_module(module_name, config = {})
40
+ def self.add_mod(module_name, options = {})
50
41
 
51
- # Store a reference to any module loaded
52
- ALL << module_name
53
- config.assert_valid_keys(:autoload)
54
-
55
42
  const_name = ActiveSupport::Inflector.camelize(module_name.to_s)
56
43
 
57
- # Setup autoloading for this module if necessary
58
- if autoload_path = config.delete(:autoload)
59
- path = (autoload_path == true ? "motr/model/#{module_name.to_s}" : autoload_path)
60
- Motr::Model.send(:autoload, const_name, path)
44
+ if autoload_path = options.delete(:autoload)
45
+ path = (autoload_path == true ? "motr/mods/#{module_name.to_s}" : autoload_path)
46
+ Motr::Mods.send(:autoload, const_name, path)
61
47
  end
62
48
 
63
- # Setup placeholder for configuration
64
- Motr::CONFIGS[module_name] ||= {}
65
-
66
- # Setup configuration method for module.
67
- #
68
- self.class_eval <<-METHOD, __FILE__, __LINE__ + 1
69
- def self.#{module_name.to_s}(options = {})
70
- raise Motr::Errors::InvalidOptions.new('Configuration for #{module_name} must be a hash.') unless options.is_a?(Hash)
71
- Motr::CONFIGS[:#{module_name.to_s}].merge!(options)
72
- end
73
- METHOD
74
-
75
- # Apply any defaults
76
- Motr.send(:"#{module_name}", config)
77
-
78
49
  end
79
50
 
80
51
  # Support initializer configuration
@@ -71,7 +71,7 @@ module Motr
71
71
  # @deprecated Use add_response_meta
72
72
  #
73
73
  def enable_script_events(opts = {})
74
- ActiveSupport::Deprecation.issue_warning("enable_script_events is deprecated. Please use the 'add_response_meta helper'")
74
+ ActiveSupport::Deprecation.warn("enable_script_events is deprecated. Please use the 'add_response_meta helper'")
75
75
  response_metadata = opts
76
76
  end
77
77
 
data/lib/motr/dash.rb ADDED
@@ -0,0 +1,33 @@
1
+ require 'active_support'
2
+
3
+ module Motr
4
+ ##
5
+ # Motr::Dash is basically a dashboard for an entire rails app.
6
+ # It does things like setting up app-wide configurations etc.
7
+ #
8
+ module Dash
9
+
10
+ ##
11
+ # Defines an application-wide configuration hash created from config/config.yml
12
+ #
13
+ def config
14
+ return @motr_application_config unless @motr_application_config.nil?
15
+ begin
16
+ config_data = YAML::load(File.open("#{Rails.root}/config/config.yml"))
17
+ rescue
18
+ warn("Motr::Dash: Application configuration not found, please create a config.yml at #{Rails.root}/config/config.yml")
19
+ config_data = {}
20
+ end
21
+ @motr_application_config = ActiveSupport::HashWithIndifferentAccess::new(config_data[Rails.env] ||= {})
22
+ end
23
+
24
+ ##
25
+ # Force reload of application configuration (without server restart)
26
+ #
27
+ def reconfigure!
28
+ @motr_application_config = nil
29
+ end
30
+
31
+ end
32
+
33
+ end
data/lib/motr/defaults.rb CHANGED
@@ -1 +1 @@
1
- Motr.add_module(:sluggable, :autoload => true)
1
+ Motr.add_mod(:sluggable, :autoload => true)
@@ -51,6 +51,8 @@ module Motr
51
51
  #
52
52
  def flash_messages(attrs = {})
53
53
 
54
+ return if flash.nil? or flash.empty?
55
+
54
56
  wrapper = attrs.delete(:wrapper) || :div
55
57
  closer = attrs.delete(:closer)
56
58
  unless closer === false
@@ -60,10 +62,10 @@ module Motr
60
62
  klasses << "flash_message"
61
63
  content = ""
62
64
 
63
- flash.each_key do |k|
64
- klasses << "flash_message_#{k.to_s.underscore}"
65
- msg_attrs = attrs.merge(:class => [k.to_s, klasses].flatten.join(' '))
66
- content.concat content_tag(wrapper, "#{flash[k]} #{closer}".html_safe, msg_attrs).html_safe
65
+ flash.each do |key, value|
66
+ klasses << "flash_message_#{key.to_s.underscore}"
67
+ msg_attrs = attrs.merge(:class => [key.to_s, klasses].flatten.join(' '))
68
+ content.concat content_tag(wrapper, "#{value} #{closer}".html_safe, msg_attrs).html_safe
67
69
  end
68
70
 
69
71
  content.html_safe
@@ -75,8 +75,8 @@ module Motr
75
75
  # @private
76
76
  def update_link_attrs(path, attrs)
77
77
 
78
- proc = attrs.delete(:proc)
79
- regex = attrs.delete(:matcher)
78
+ proc = attrs.delete(:proc) || false
79
+ regex = attrs.delete(:matcher) || false
80
80
  klasses = attrs.delete(:class).try(:split, ' ')
81
81
  on_class = attrs.delete(:active_class) || "on"
82
82
  wrapper_attrs = attrs.delete(:wrapper) || {}
@@ -85,11 +85,20 @@ module Motr
85
85
  klasses ||= []
86
86
  wklasses ||= []
87
87
 
88
- if ((proc && proc.call(path)) || (regex && request.path =~ regex) || (request.path == path || request.path.match(/#{path}\/.*/i)))
88
+ matcher = (proc || regex || request.path)
89
+
90
+ active = case matcher
91
+ when Proc then proc.call(path)
92
+ when Regexp then request.path.match(regex)
93
+ when String then (request.path == path || request.path.match(/#{path}\/\w/im))
94
+ else raise Motr::Errors::InvalidOptions.new('Proc, Regexp or String required... passed #{matcher.class}.')
95
+ end
96
+
97
+ if active
89
98
  klasses << on_class
90
99
  wklasses << on_class
91
100
  end
92
-
101
+
93
102
  attrs.merge!(:class => klasses.join(" ")) unless klasses.compact.empty?
94
103
  wrapper_attrs.merge!(:class => wklasses.join(" ")) unless wklasses.compact.empty?
95
104
 
@@ -0,0 +1,7 @@
1
+ module Motr
2
+ ##
3
+ # Mapper handles configuring mod based routes within an application
4
+ #
5
+ module Mapper
6
+ end
7
+ end
@@ -0,0 +1,98 @@
1
+ ##
2
+ #
3
+ # Each mod extends Motr::Mod which provides necessary functionality to
4
+ # perform setup and configuration.
5
+ #
6
+ module Motr
7
+ module Modding
8
+
9
+ def append_features(base)
10
+ return false if base < self
11
+ super
12
+ # Apply any orm specific configurations
13
+ #
14
+ if instance_variable_defined?("@_mod_config_for_orm")
15
+ @_mod_config_for_orm.each do |orm, configs|
16
+ # Each orm should implement a motr_orm_type value which identifies
17
+ # itself to mods (ie :active_record, :mongoid)
18
+ next unless base.respond_to?(:motr_orm_type) && base.__send__(:motr_orm_type).to_s === orm.to_s
19
+ [configs].flatten.each{ |conf| base.class_eval(&conf) }
20
+ end
21
+ end
22
+
23
+ base.extend const_get("ClassMethods") if const_defined?("ClassMethods")
24
+ base.send :include, const_get("InstanceMethods") if const_defined?("InstanceMethods")
25
+ base.class_eval(&@_mod_config_callback) if instance_variable_defined?("@_mod_config_callback")
26
+
27
+ end
28
+
29
+ ##
30
+ # Apply is run each time a mod is applied to a model. As opposed to the configure method,
31
+ # apply blocks are run each time modded_with :your_mod is called.
32
+ #
33
+ # @param [Block] &block The callback to be run when the mod is applied
34
+ #
35
+ # @example Configure a before_save callback to be applied to each instance
36
+ #
37
+ # module MyMod
38
+ # apply do
39
+ # before_save :something_each_time
40
+ # end
41
+ # end
42
+ #
43
+ def apply(&block)
44
+ @_mod_apply_callback = block
45
+ end
46
+
47
+
48
+ ##
49
+ # Each mod can pass an optional configuration block (or one global config and one per orm) which
50
+ # is run when a particular class or model implements that mod. Configure methods are only run on first inclusion.
51
+ # To run functionality each time the mod is applied, see Motr::Mod.apply
52
+ #
53
+ # Orm specific functionality can be configured by passing an :orm as the first option
54
+ #
55
+ # @param [Symbol] orm The name of the orm in which this configuration applies
56
+ #
57
+ # @example Configure a before_filter callback when a model implements your mod
58
+ #
59
+ # module MyMod
60
+ # configure do
61
+ # before_filter :something_awesome
62
+ # end
63
+ # end
64
+ #
65
+ # @example Configure mongoid only functionality
66
+ #
67
+ # module MyMod
68
+ # configure(:mongoid) do
69
+ # embeds_many :somethings
70
+ # end
71
+ # end
72
+ #
73
+ def configure(orm = nil, &block)
74
+ if orm.nil?
75
+ @_mod_config_callback = block
76
+ else
77
+ (@_mod_config_for_orm ||= {})[orm] = block
78
+ end
79
+ end
80
+
81
+ ##
82
+ # Each mod can specify any number of options that may be passed to it
83
+ # when applied to a class/model.
84
+ #
85
+ # @param [Array] *options Argument list of options to create.
86
+ #
87
+ # @example Create configuration options on a module
88
+ # module Motr::Mods::Sample
89
+ # options(:sample, :option1, :option2)
90
+ # end
91
+ #
92
+ #
93
+ def options(*options)
94
+ @_mod_options = options
95
+ end
96
+
97
+ end
98
+ end
data/lib/motr/mods.rb ADDED
@@ -0,0 +1,67 @@
1
+ module Motr
2
+ module Mods
3
+
4
+ ##
5
+ # modded_with provides the "hook" functionality to mod a model/class with a particular mod.
6
+ # Multiple mods can be applied at once, with options.
7
+ #
8
+ # @param [Array] *mods Argument list of mods, and/or options
9
+ # @option *mods [Hash] options Options to be applied to each included mod
10
+ #
11
+ # @example Mod a model with the sluggable mod
12
+ #
13
+ # class Awesome < ActiveRecord::Base
14
+ # modded_with :sluggable, :fields => :title, :as => :slug
15
+ # end
16
+ #
17
+ #
18
+ def modded_with(*mods)
19
+
20
+ options = mods.extract_options!
21
+ modules = mods.map(&:to_sym).uniq
22
+
23
+ modules.each do |mod|
24
+ const_name = mod.to_s.classify
25
+ next unless Motr::Mods.const_defined?(:"#{const_name}")
26
+
27
+ const_incl = Motr::Mods.const_get(:"#{const_name}")
28
+
29
+ # Apply passed options to modules where applicable.
30
+ #
31
+ if const_incl.instance_variable_defined?("@_mod_options")
32
+ mod_opts = const_incl.instance_variable_get("@_mod_options")
33
+
34
+ new_opts = mod_opts.inject({}) do |hsh, option|
35
+ next hsh unless options.key?(option)
36
+ hsh.merge!(option => options.delete(option))
37
+ end
38
+
39
+ (class << self; self; end).class_eval do
40
+ define_method("#{mod}_mod_options"){ motr_mod_options[mod.to_s] }
41
+ define_method("#{mod}_mod_options="){ |opts| motr_mod_options[mod.to_s] = opts }
42
+ end
43
+
44
+ write_inheritable_attribute(:motr_mod_options, {}) if motr_mod_options.nil?
45
+ motr_mod_options[mod.to_s] = new_opts
46
+
47
+ end
48
+
49
+ if const_incl.instance_variable_defined?("@_mod_apply_callback")
50
+ self.class_eval(&const_incl.instance_variable_get("@_mod_apply_callback"))
51
+ end
52
+
53
+ include const_incl
54
+
55
+ end
56
+
57
+ end
58
+
59
+ def motr_mod_options
60
+ read_inheritable_attribute(:motr_mod_options)
61
+ end
62
+
63
+ alias :motr :modded_with
64
+ alias :mod_with :modded_with
65
+
66
+ end
67
+ end
@@ -0,0 +1,65 @@
1
+ module Motr
2
+ module Mods
3
+ ##
4
+ # Sluggable generates a url-friendly "slug" from a particular attribute.
5
+ # @param [Hash] options Options for generating a slug or slugs
6
+ # @option options [Hash,Symbol,String] :fields The fields that will be slugged
7
+ # @option options [Array, Symbol] :on The callback(s) in which slugs will be created (:create, :save, etc)
8
+ # @option options [Symbol, String] :as The attribute that receives the slugged value
9
+ # If an array is passed to both :fields and :as, :as will be used in order of the arrays.
10
+ #
11
+ # @example Slugify a "title" attribute into the "slug" attribute when new instances are saved
12
+ # modded_with :sluggable, :fields => :title, :on => :create, :as => :slug
13
+ #
14
+ # @example Slugify a "title" as a "slug" and a "subtitle" into itself
15
+ # modded_with :sluggable, :fields => [:title, :subtitle], :as => [:slug]
16
+ #
17
+ module Sluggable
18
+ extend Motr::Modding
19
+
20
+ options(:fields, :on, :as)
21
+
22
+ configure do
23
+ pos = sluggable_mod_options[:on] || "create"
24
+ send(:"before_#{pos.to_s}", :_create_slugged_fields)
25
+ end
26
+
27
+ def _create_slugged_fields
28
+
29
+ slug_opts = self.class.sluggable_mod_options
30
+ slug_fields = slug_opts[:fields]
31
+ slug_as = [slug_opts[:as]].flatten
32
+
33
+ [slug_fields].flatten.map(&:to_sym).each_with_index do |atr, i|
34
+
35
+ next if self.send(atr).nil?
36
+ unless slug_as.empty? || slug_as[i].nil?
37
+ self.send(:"#{slug_as[i]}=", self.send(atr).to_slug)
38
+ else
39
+ self.send(:"#{atr.to_s}=", self.send(atr).to_slug)
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+ end
49
+
50
+ ##
51
+ # Original implementation by Ludo van den Boom's to_slug plugin
52
+ # @see to_slug (https://github.com/ludo/to_slug)
53
+ #
54
+ module ToSlug #:nodoc:
55
+ def to_slug
56
+ value = self.mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/n, '').to_s
57
+ value.gsub!(/[']+/, '')
58
+ value.gsub!(/\W+/, ' ')
59
+ value.strip!
60
+ value.downcase!
61
+ value.gsub!(' ', '-')
62
+ value
63
+ end
64
+ end
65
+ String.send(:include, ToSlug)
@@ -5,11 +5,11 @@ module Motr
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
8
- extend Motr::Model
8
+ extend Motr::Mods
9
9
  end
10
10
 
11
- module Schema
12
- include Motr::Schema::Base
11
+ module ClassMethods
12
+ def motr_orm_type; :active_record; end
13
13
  end
14
14
 
15
15
  end
@@ -2,28 +2,13 @@ module Motr
2
2
  module Orm
3
3
 
4
4
  module Mongoid #:nodoc:
5
- def motrize_model!
6
- extend Schema
7
- yield
8
- motrize_schema!
9
- end
10
-
11
- module Schema
12
- include Motr::Schema::Base
13
-
14
- def apply_motr_schema(field_name, field_type, options = {})
15
- field_type = Time if field_type == DateTime
16
- field field_name, { :type => field_type }.merge!(options)
17
- end
18
-
19
- end
20
-
5
+ def motr_orm_type; :mongoid; end
21
6
  end
22
7
 
23
8
  end
24
9
  end
25
10
 
26
11
  Mongoid::Document::ClassMethods.class_eval do
27
- include Motr::Model
12
+ include Motr::Mods
28
13
  include Motr::Orm::Mongoid
29
14
  end
data/lib/motr/rails.rb CHANGED
@@ -1,12 +1,14 @@
1
1
  module Motr
2
2
  class Engine < ::Rails::Engine #:nodoc:
3
- config.motr = Motr
3
+ config.motr = Motr
4
4
 
5
5
  # Add load paths straight to I18n, so engines and application can overwrite it.
6
6
  require 'active_support/i18n'
7
7
  I18n.load_path << File.expand_path('../../config/locales/en.yml', __FILE__)
8
8
 
9
9
  initializer 'motr.initializer' do
10
+ require 'motr/orm/mongoid' if defined?(Mongoid)
11
+
10
12
  ActiveSupport.on_load(:action_view) do
11
13
  include Motr::Helpers::LayoutHelpers
12
14
  include Motr::Helpers::Navigation
@@ -18,9 +20,8 @@ module Motr
18
20
  include Motr::Controller::Helpers
19
21
  self.responder = Motr::Controller::Responder
20
22
  end
21
- ActiveSupport.on_load(:after_initialize) do
22
- require 'motr/orm/mongoid' if defined?(Mongoid)
23
- require 'motr/orm/active_record' if defined?(ActiveRecord)
23
+ ActiveSupport.on_load(:active_record) do
24
+ require 'motr/orm/active_record'
24
25
  end
25
26
 
26
27
  end
data/lib/motr/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Motr #:nodoc:
2
- VERSION = "0.0.5".freeze
2
+ VERSION = "0.0.6".freeze
3
3
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: motr
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.5
5
+ version: 0.0.6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Brent Kirby
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-05-11 00:00:00 -04:00
13
+ date: 2011-05-18 00:00:00 -04:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -125,6 +125,7 @@ files:
125
125
  - lib/generators/templates/post_install
126
126
  - lib/motr/controller/helpers.rb
127
127
  - lib/motr/controller/responder.rb
128
+ - lib/motr/dash.rb
128
129
  - lib/motr/defaults.rb
129
130
  - lib/motr/errors/invalid_options.rb
130
131
  - lib/motr/errors/module_missing.rb
@@ -136,13 +137,13 @@ files:
136
137
  - lib/motr/helpers/elements.rb
137
138
  - lib/motr/helpers/layout_helpers.rb
138
139
  - lib/motr/helpers/navigation.rb
139
- - lib/motr/model/sluggable.rb
140
- - lib/motr/model.rb
140
+ - lib/motr/mapper.rb
141
+ - lib/motr/modding.rb
142
+ - lib/motr/mods/sluggable.rb
143
+ - lib/motr/mods.rb
141
144
  - lib/motr/orm/active_record.rb
142
145
  - lib/motr/orm/mongoid.rb
143
146
  - lib/motr/rails.rb
144
- - lib/motr/schema/base.rb
145
- - lib/motr/schema/generator.rb
146
147
  - lib/motr/version.rb
147
148
  - lib/motr.rb
148
149
  - config/en.yml
@@ -164,7 +165,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
164
165
  requirements:
165
166
  - - ">="
166
167
  - !ruby/object:Gem::Version
167
- hash: -3118347757184532695
168
+ hash: -2994942846918813196
168
169
  segments:
169
170
  - 0
170
171
  version: "0"
data/lib/motr/model.rb DELETED
@@ -1,134 +0,0 @@
1
- module Motr
2
-
3
- ##
4
- # Provides a interface for extending models and controllers with additional Motr libraries.
5
- # To create a new library, sub-class/module Motr::Model or Motr::Controller depending on the
6
- # functionality to include. To 'attach' functionality call motr :module_name
7
- #
8
- # @example Create a "postable" model using Motr::Model::Postable (see the motr-content gem)
9
- # class MyPost
10
- # motr :postable
11
- # end
12
- #
13
- module Model
14
- ##
15
- # Stores a list of available options for a model. This way when
16
- # options are passed at load-time, they can be applied to the proper modules.
17
- #
18
- # @param [Class, Module] mod The module to configure
19
- # @param [Symbol] cfg_name The name of the configuration to modify
20
- # @param [Array] *options Argument list of options to create.
21
- #
22
- # @example Create configuration options on a module
23
- # module Motr::Model::Sample
24
- # module ClassMethods
25
- # Motr::Model.config(self, :sample, :option1, :option2)
26
- # end
27
- # end
28
- #
29
- #
30
- def self.config(mod, cfg_name, *options)
31
- (class << mod; self; end).send(:attr_accessor_with_default, :motr_options, {})
32
- mod.motr_options[cfg_name] ||= []
33
-
34
- options.each do |option|
35
- mod.motr_options[cfg_name] << option
36
- fullname = [cfg_name, option].map(&:to_s).join("_")
37
-
38
- mod.class_eval <<-METHOD, __FILE__, __LINE__ + 1
39
- def #{fullname}
40
- if defined?(@#{fullname})
41
- @#{fullname}
42
- elsif superclass.respond_to?(:#{fullname})
43
- superclass.#{fullname}
44
- else
45
- Motr::CONFIGS[:#{cfg_name}][:#{option}]
46
- end
47
- end
48
- def #{fullname}=(value)
49
- @#{fullname} = value
50
- end
51
- METHOD
52
- end
53
- end
54
-
55
- ##
56
- # The motr method enables loading other motr libraries into application modules/classes.
57
- #
58
- # @example Create a model include to hook into any model class
59
- # module Motr::Model::Sample
60
- # def instance_method
61
- # end
62
- #
63
- # module ClassMethods
64
- # def class_method
65
- # end
66
- # end
67
- # end
68
- #
69
- # class SomeModel < ActiveRecord::Base
70
- # motr :sample
71
- # end
72
- #
73
- #
74
- def motr(*mods)
75
-
76
- options = mods.extract_options!
77
- modules = mods.map(&:to_sym).uniq
78
-
79
- # Track what modules have been added to each class.
80
- self.class_eval do
81
- class_attribute :motr_modules, :instance_writer => false unless defined?(self.motr_modules)
82
- self.motr_modules ||= []
83
- end
84
-
85
- motrize_model! do
86
-
87
- modules.each do |mod|
88
- const_name = mod.to_s.classify
89
- raise Motr::Model.load_failure("Motr::Model::#{const_name}") unless Motr::ALL.include?(mod)
90
-
91
- begin
92
- const_incl = Motr::Model.const_get(:"#{const_name}")
93
- rescue NameError
94
- raise Motr::Errors.ModuleMissing.new("Motr::Model::#{const_name} could not be found. Perhaps try adding the module with the :autoload option.")
95
- end
96
-
97
- if const_incl.const_defined?('ClassMethods')
98
- class_incl = const_incl.const_get("ClassMethods")
99
- extend class_incl
100
- end
101
- # # Apply passed options to modules where applicable.
102
- #
103
- if class_incl.respond_to?(:motr_options)
104
- class_incl.motr_options[mod].each do |option|
105
- next unless options.key?(option)
106
- send(:"#{mod}_#{option}=", options.delete(option))
107
- end
108
- end
109
-
110
- include const_incl
111
-
112
- end
113
-
114
- self.motr_modules |= modules
115
-
116
- end
117
-
118
- end
119
-
120
- # Raise a ModuleMissing error if a module cannot be loaded.
121
- # @private
122
- #
123
- def self.load_failure(mod) #:nodoc:
124
- Motr::Errors::ModuleMissing.new("The module #{mod} wasn't found. Add it with Motr.add_module(#{mod})") and return
125
- end
126
-
127
- # Override motrize_model! to create specific functionality on a model
128
- # @private
129
- def motrize_model! #:nodoc:
130
- yield
131
- end
132
-
133
- end
134
- end
@@ -1,45 +0,0 @@
1
- module Motr
2
- module Model
3
-
4
- module Sluggable #:nodoc:
5
- extend ActiveSupport::Concern
6
-
7
- included do
8
- callback_opt = (self.sluggable_on || "save")
9
- send(:"before_#{callback_opt.to_s}", :make_sluggable_fields)
10
- end
11
-
12
- # @private
13
- def make_sluggable_fields #:nodoc:
14
- [self.class.sluggable_fields].flatten.each do |atr|
15
- orig = self.send(:"#{atr}")
16
- self.send(:"#{atr}=", orig.to_slug)
17
- end
18
- end
19
-
20
- # @private
21
- module ClassMethods #:nodoc:
22
- Motr::Model.config(self, :sluggable, :fields, :on)
23
- end
24
-
25
- end
26
-
27
- end
28
- end
29
-
30
- ##
31
- # Original implementation by Ludo van den Boom's to_slug plugin
32
- # @see to_slug (https://github.com/ludo/to_slug)
33
- #
34
- module ToSlug #:nodoc:
35
- def to_slug
36
- value = self.mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/n, '').to_s
37
- value.gsub!(/[']+/, '')
38
- value.gsub!(/\W+/, ' ')
39
- value.strip!
40
- value.downcase!
41
- value.gsub!(' ', '-')
42
- value
43
- end
44
- end
45
- String.send(:include, ToSlug)
@@ -1,20 +0,0 @@
1
- module Motr
2
- module Schema
3
-
4
- ##
5
- # Stubs schema methods to ensure ORM's implement them
6
- # @private
7
- #
8
- module Base #:nodoc:
9
-
10
- def motrize_schema!
11
- Motr::Schema::Generator.set_target(self)
12
- end
13
-
14
- def apply_motr_schema(name, type, options={})
15
- raise NotImplementedError
16
- end
17
- end
18
-
19
- end
20
- end
@@ -1,79 +0,0 @@
1
- module Motr
2
- module Schema
3
- ##
4
- # Generates a schema for a Motr module. To define a module schema, create a
5
- # subclass that implements a "generate" class method. Generator classes
6
- # should follow the convention Motr::Schema::ModuleGenerator where "Module" is the module the
7
- # schema applies to. For instance if you have a module: Motr::Model::Sample, your generator class
8
- # would be called Motr::Schema::SampleGenerator
9
- #
10
- # @example A generator for the module "sample"
11
- #
12
- # class Motr::Schema::SampleGenerator < Motr::Schema::Generator
13
- # def self.generate
14
- # apply(:field_name, String, {}) # => creates the field "field_name" with the type of String
15
- #
16
- # # only run for mongoid models
17
- # apply_for(:mongoid) do
18
- # embeds_many :children
19
- # end
20
- # end
21
- # end
22
- #
23
- #
24
- class Generator
25
-
26
- # Make er clean
27
- instance_methods.each { |m| undef_method m unless m =~ /^(__.*__|object_id)$/ }
28
-
29
- class_attribute :schema_runner, :instance_writer => false
30
-
31
- # @private
32
- # Delegates callbacks to a particular class/module. This allows generators to be flexible and
33
- # somewhat similar to migrations.
34
- #
35
- def self.set_target(target) #:nodoc:
36
- self.schema_runner = target
37
- end
38
-
39
- # Override in subclasses to run.
40
- #
41
- def self.generate
42
- raise NotImplementedError
43
- end
44
-
45
- protected
46
-
47
- ##
48
- # Apply a callback only if the including module implements the specified ORM
49
- #
50
- # @param [Symbol] orm The ORM which handles the block (ie: :mongoid or :active_record)
51
- # @param [Block] &block The block to be run.
52
- #
53
- # @example Apply an option only to mongoid based models
54
- # apply_for(:mongoid) do |model|
55
- # model.embeds_many :children
56
- # end
57
- #
58
- def self.apply_for(orm, &block)
59
- # TODO: This should maybe be more efficient?
60
- puts self.schema_runner.inspect
61
- return unless self.schema_runner.ancestors.map(&:to_s).detect{ |a| a.to_s.match(/#{orm.to_s.classify}/) }
62
- yield self.schema_runner
63
- end
64
-
65
- ##
66
- # Creates a field on the model (or migration method in ActiveRecord)
67
- #
68
- # @param [Symbol] name The name of the field to create
69
- # @param [Class] type The class type to create (ie: String, DateTime...)
70
- # @param [Hash] options Specific options for the class type (ie: :default => nil)
71
- #
72
- def self.apply(name, type, options = {})
73
- self.schema_runner.__send__(:apply_motr_schema, name, type, options)
74
- end
75
-
76
- end
77
-
78
- end
79
- end