motr 0.0.5 → 0.0.6

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