merb-admin 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -11,7 +11,7 @@ http://github.com/sferik/merb-admin/raw/master/screenshots/edit.png
11
11
  == Installation
12
12
  $ gem install merb-admin -s http://gemcutter.org
13
13
  In your app, add the following dependency to <tt>config/dependencies.rb</tt>:
14
- dependency "merb-admin", "0.6.2"
14
+ dependency "merb-admin", "0.6.3"
15
15
  Add the following route to <tt>config/router.rb</tt>:
16
16
  add_slice(:merb_admin, :path_prefix => "admin")
17
17
  Then, run the following rake task:
@@ -37,6 +37,7 @@ There are many ways to contribute:
37
37
  * by writing documentation
38
38
  * by writing specifications
39
39
  * by writing code (no patch is too small: fix typos in comments or inconsistent whitespace)
40
+ * by refactoring code
40
41
  * by reviewing patches
41
42
  * financially[http://pledgie.com/campaigns/5428]
42
43
 
data/Rakefile CHANGED
@@ -9,8 +9,8 @@ AUTHOR = "Erik Michaels-Ober"
9
9
  EMAIL = "sferik@gmail.com"
10
10
  HOMEPAGE = "http://github.com/sferik/merb-admin"
11
11
  SUMMARY = "MerbAdmin is a Merb plugin that provides an easy-to-use interface for managing your data."
12
- GEM_VERSION = "0.6.2"
13
- MERB_GEM_VERSION = "1.0.12"
12
+ GEM_VERSION = "0.6.3"
13
+ MERB_GEM_VERSION = "1.0.15"
14
14
 
15
15
  spec = Gem::Specification.new do |s|
16
16
  s.rubyforge_project = "merb"
@@ -3,9 +3,10 @@ require File.join( File.dirname(__FILE__), '..', '..', 'lib', 'abstract_model' )
3
3
  class MerbAdmin::Main < MerbAdmin::Application
4
4
  include Merb::MerbAdmin::MainHelper
5
5
 
6
- before :find_models, :only => ['index']
7
- before :find_model, :exclude => ['index']
8
- before :find_object, :only => ['edit', 'update', 'delete', 'destroy']
6
+ before :get_models, :only => ['index']
7
+ before :get_model, :exclude => ['index']
8
+ before :get_object, :only => ['edit', 'update', 'delete', 'destroy']
9
+ before :get_attributes, :only => ['create', 'update']
9
10
 
10
11
  def index
11
12
  render(:layout => 'dashboard')
@@ -13,29 +14,25 @@ class MerbAdmin::Main < MerbAdmin::Application
13
14
 
14
15
  def list
15
16
  options = {}
16
- merge_query!(options)
17
- merge_filter!(options)
18
- merge_sort!(options)
19
- merge_sort_reverse!(options)
20
-
17
+ options.merge!(sort)
18
+ options.merge!(sort_reverse)
19
+ options.merge!(query(options))
20
+ options.merge!(filter(options))
21
+ # merge_query!(options)
22
+ # merge_filter!(options)
23
+ per_page = MerbAdmin[:per_page]
21
24
  if params[:all]
22
- options = {
23
- :limit => MerbAdmin[:per_page] * 2,
24
- }.merge(options)
25
+ options.merge!(:limit => per_page * 2)
25
26
  @objects = @abstract_model.all(options).reverse
26
27
  else
27
28
  @current_page = (params[:page] || 1).to_i
28
- options = {
29
- :page => @current_page,
30
- :per_page => MerbAdmin[:per_page],
31
- }.merge(options)
29
+ options.merge!(:page => @current_page, :per_page => per_page)
32
30
  @page_count, @objects = @abstract_model.paginated(options)
33
31
  options.delete(:page)
34
32
  options.delete(:per_page)
35
33
  options.delete(:offset)
36
34
  options.delete(:limit)
37
35
  end
38
-
39
36
  @record_count = @abstract_model.count(options)
40
37
  render(:layout => 'list')
41
38
  end
@@ -50,47 +47,19 @@ class MerbAdmin::Main < MerbAdmin::Application
50
47
  end
51
48
 
52
49
  def create
53
- object = params[@abstract_model.singular_name] || {}
54
- # Delete fields that are blank
55
- object.each do |key, value|
56
- object[key] = nil if value.blank?
57
- end
58
- has_one_associations = @abstract_model.has_one_associations.map{|association| [association, (params[:associations] || {}).delete(association[:name])]}
59
- has_many_associations = @abstract_model.has_many_associations.map{|association| [association, (params[:associations] || {}).delete(association[:name])]}
60
- @object = @abstract_model.new(object)
61
- if @object.save && has_one_associations.each{|association, id| update_association(association, id)} && has_many_associations.each{|association, ids| update_associations(association, ids.to_a)}
62
- if params[:_continue]
63
- redirect(url(:merb_admin_edit, :model_name => @abstract_model.singular_name, :id => @object.id), :message => {:notice => "#{@abstract_model.pretty_name} was successfully created"})
64
- elsif params[:_add_another]
65
- redirect(url(:merb_admin_new, :model_name => @abstract_model.singular_name), :message => {:notice => "#{@abstract_model.pretty_name} was successfully created"})
66
- else
67
- redirect(url(:merb_admin_list, :model_name => @abstract_model.singular_name), :message => {:notice => "#{@abstract_model.pretty_name} was successfully created"})
68
- end
50
+ @object = @abstract_model.new(@attributes)
51
+ if @object.save && update_all_associations
52
+ redirect_on_success
69
53
  else
70
- message[:error] = "#{@abstract_model.pretty_name} failed to be created"
71
- render(:new, :layout => 'form')
54
+ render_error
72
55
  end
73
56
  end
74
57
 
75
58
  def update
76
- object = params[@abstract_model.singular_name] || {}
77
- # Delete fields that are blank
78
- object.each do |key, value|
79
- object[key] = nil if value.blank?
80
- end
81
- has_one_associations = @abstract_model.has_one_associations.map{|association| [association, (params[:associations] || {}).delete(association[:name])]}
82
- has_many_associations = @abstract_model.has_many_associations.map{|association| [association, (params[:associations] || {}).delete(association[:name])]}
83
- if @object.update_attributes(object) && has_one_associations.each{|association, id| update_association(association, id)} && has_many_associations.each{|association, ids| update_associations(association, ids.to_a)}
84
- if params[:_continue]
85
- redirect(url(:merb_admin_edit, :model_name => @abstract_model.singular_name, :id => @object.id), :message => {:notice => "#{@abstract_model.pretty_name} was successfully updated"})
86
- elsif params[:_add_another]
87
- redirect(url(:merb_admin_new, :model_name => @abstract_model.singular_name), :message => {:notice => "#{@abstract_model.pretty_name} was successfully updated"})
88
- else
89
- redirect(url(:merb_admin_list, :model_name => @abstract_model.singular_name), :message => {:notice => "#{@abstract_model.pretty_name} was successfully updated"})
90
- end
59
+ if @object.update_attributes(@attributes) && update_all_associations
60
+ redirect_on_success
91
61
  else
92
- message[:error] = "#{@abstract_model.pretty_name} failed to be updated"
93
- render(:edit, :layout => 'form')
62
+ render_error
94
63
  end
95
64
  end
96
65
 
@@ -108,70 +77,91 @@ class MerbAdmin::Main < MerbAdmin::Application
108
77
 
109
78
  private
110
79
 
111
- def find_models
80
+ def get_models
112
81
  @abstract_models = MerbAdmin::AbstractModel.all
113
82
  end
114
83
 
115
- def find_model
84
+ def get_model
116
85
  model_name = params[:model_name].camel_case
117
86
  @abstract_model = MerbAdmin::AbstractModel.new(model_name)
118
- find_properties
87
+ get_properties
119
88
  end
120
89
 
121
- def find_properties
90
+ def get_properties
122
91
  @properties = @abstract_model.properties
123
92
  end
124
93
 
125
- def find_object
94
+ def get_object
126
95
  @object = @abstract_model.get(params[:id])
127
96
  raise NotFound unless @object
128
97
  end
129
98
 
130
- def merge_query!(options)
131
- return unless params[:query]
99
+ def sort
100
+ sort = params[:sort]
101
+ sort ? {:sort => sort} : {}
102
+ end
103
+
104
+ def sort_reverse
105
+ sort_reverse = params[:sort_reverse]
106
+ sort_reverse ? {:sort_reverse => sort_reverse == "true"} : {}
107
+ end
108
+
109
+ def query(options)
110
+ query = params[:query]
111
+ return {} unless query
132
112
  statements = []
133
113
  values = []
134
114
  conditions = options[:conditions] || [""]
135
- @properties.each do |property|
136
- next unless property[:type] == :string
115
+
116
+ @properties.select{|property| property[:type] == :string}.each do |property|
137
117
  statements << "#{property[:name]} LIKE ?"
138
- values << "%#{params[:query]}%"
118
+ values << "%#{query}%"
139
119
  end
120
+
140
121
  conditions[0] += " AND " unless conditions == [""]
141
122
  conditions[0] += statements.join(" OR ")
142
123
  conditions += values
143
- options.merge!(:conditions => conditions) unless conditions == [""]
124
+ conditions != [""] ? {:conditions => conditions} : {}
144
125
  end
145
126
 
146
- def merge_filter!(options)
147
- return unless params[:filter]
127
+ def filter(options)
128
+ filter = params[:filter]
129
+ return {} unless filter
148
130
  statements = []
149
131
  values = []
150
132
  conditions = options[:conditions] || [""]
151
- params[:filter].each_pair do |key, value|
152
- @properties.each do |property|
153
- next unless property[:name] == key.to_sym
154
- next unless property[:type] == :boolean
133
+
134
+ filter.each_pair do |key, value|
135
+ @properties.select{|property| property[:type] == :boolean && property[:name] == key.to_sym}.each do |property|
155
136
  statements << "#{key} = ?"
156
137
  values << (value == "true")
157
138
  end
158
139
  end
140
+
159
141
  conditions[0] += " AND " unless conditions == [""]
160
142
  conditions[0] += statements.join(" AND ")
161
143
  conditions += values
162
- options.merge!(:conditions => conditions) unless conditions == [""]
144
+ conditions != [""] ? {:conditions => conditions} : {}
163
145
  end
164
146
 
165
- def merge_sort!(options)
166
- return unless params[:sort]
167
- sort = params[:sort] || "id"
168
- options.merge!(:sort => sort)
147
+ def get_attributes
148
+ @attributes = params[@abstract_model.singular_name] || {}
149
+ # Delete fields that are blank
150
+ @attributes.each do |key, value|
151
+ @attributes[key] = nil if value.blank?
152
+ end
169
153
  end
170
154
 
171
- def merge_sort_reverse!(options)
172
- return unless params[:sort_reverse]
173
- reverse = params[:sort_reverse] == "true"
174
- options.merge!(:sort_reverse => reverse)
155
+ def update_all_associations
156
+ @abstract_model.associations.each do |association|
157
+ ids = (params[:associations] || {}).delete(association[:name])
158
+ case association[:type]
159
+ when :has_one
160
+ update_association(association, ids)
161
+ when :has_many
162
+ update_associations(association, ids.to_a)
163
+ end
164
+ end
175
165
  end
176
166
 
177
167
  def update_association(association, id = nil)
@@ -190,4 +180,23 @@ class MerbAdmin::Main < MerbAdmin::Application
190
180
  end
191
181
  end
192
182
 
183
+ def redirect_on_success
184
+ singular_name = @abstract_model.singular_name
185
+ pretty_name = @abstract_model.pretty_name
186
+ action = params[:action]
187
+ if params[:_continue]
188
+ redirect(url(:merb_admin_edit, :model_name => singular_name, :id => @object.id), :message => {:notice => "#{pretty_name} was successfully #{action}d"})
189
+ elsif params[:_add_another]
190
+ redirect(url(:merb_admin_new, :model_name => singular_name), :message => {:notice => "#{pretty_name} was successfully #{action}d"})
191
+ else
192
+ redirect(url(:merb_admin_list, :model_name => singular_name), :message => {:notice => "#{pretty_name} was successfully #{action}d"})
193
+ end
194
+ end
195
+
196
+ def render_error
197
+ action = params[:action]
198
+ message[:error] = "#{@abstract_model.pretty_name} failed to be #{action}d"
199
+ render(:new, :layout => 'form')
200
+ end
201
+
193
202
  end
@@ -5,8 +5,7 @@
5
5
  label = association[:pretty_name]
6
6
  required = false
7
7
  errors_exist = !(@object.errors[child_key].nil? || @object.errors[child_key].empty?)
8
- @properties.each do |property|
9
- next unless property[:name] == child_key
8
+ @properties.select{|property| property[:name] == child_key}.each do |property|
10
9
  required = true unless property[:nullable?]
11
10
  end
12
11
  %>
@@ -6,8 +6,7 @@
6
6
  label = association[:pretty_name]
7
7
  required = false
8
8
  errors_exist = !(@object.errors[child_key].nil? || @object.errors[child_key].empty?)
9
- @properties.each do |property|
10
- next unless property[:name] == child_key
9
+ @properties.select{|property| property[:name] == child_key}.each do |property|
11
10
  required = true unless property[:nullable?]
12
11
  end
13
12
  %>
@@ -1,11 +1,9 @@
1
1
  <fieldset class="module aligned">
2
2
  <% belongs_to_keys = @abstract_model.belongs_to_associations.map{|b| b[:child_key].first} %>
3
- <% properties.each do |property| %>
3
+ <% properties.reject{|property| [:id, :created_at, :created_on, :deleted_at, :updated_at, :updated_on, :deleted_on].include?(property[:name]) || belongs_to_keys.include?(property[:name])}.each do |property| %>
4
4
  <% property_name = property[:name] %>
5
5
  <% property_type = property[:type] %>
6
6
  <% errors_exist = !(@object.errors[property_name].nil? || @object.errors[property_name].empty?) %>
7
- <% next if [:id, :created_at, :created_on, :deleted_at, :updated_at, :updated_on, :deleted_on].include?(property_name) %>
8
- <% next if belongs_to_keys.include?(property_name) %>
9
7
  <div class="<%= errors_exist ? "form-row errors" : "form-row" %>">
10
8
  <% if errors_exist %>
11
9
  <ul class="errorlist">
@@ -4,8 +4,7 @@
4
4
  <%= @abstract_model.pretty_name %>: <%= link_to(object_name(@object), url(:merb_admin_edit, :model_name => @abstract_model.singular_name, :id => @object.id)) %>
5
5
  <ul>
6
6
  <% @abstract_model.has_many_associations.each do |association| %>
7
- <% @object.send(association[:name]).each do |child| %>
8
- <% next if child.nil? %>
7
+ <% @object.send(association[:name]).reject{|child| child.nil?}.each do |child| %>
9
8
  <li>
10
9
  One or more <%= @abstract_model.pretty_name.pluralize.downcase %> in <%= association[:pretty_name].downcase %>: <%= link_to(object_name(child), url(:merb_admin_edit, :model_name => association[:name].to_s.singularize.to_sym, :id => child.id)) %>
11
10
  </li>
@@ -6,36 +6,27 @@ module MerbAdmin
6
6
  def self.all
7
7
  return @models if @models
8
8
  @models ||= []
9
- case Merb.orm
10
- when :activerecord
9
+ orm = Merb.orm
10
+ case orm
11
+ when :activerecord, :sequel
11
12
  Dir.glob(Merb.dir_for(:model) / Merb.glob_for(:model)).each do |filename|
12
- # FIXME: This heuristic for finding ActiveRecord models could be too strict
13
- File.read(filename).scan(/^class ([\w\d_\-:]+) < ActiveRecord::Base$/).flatten.each do |m|
14
- model = lookup(m.to_s.to_sym)
13
+ File.read(filename).scan(/class ([\w\d_\-:]+)/).flatten.each do |model_name|
14
+ model = lookup(model_name.to_sym)
15
15
  @models << new(model) if model
16
16
  end
17
17
  end
18
- @models.sort!{|a, b| a.model.to_s <=> b.model.to_s}
19
18
  when :datamapper
20
- DataMapper::Resource.descendants.each do |m|
19
+ @models = []
20
+ DataMapper::Model.descendants.each do |model_name|
21
21
  # Remove DataMapperSessionStore because it's included by default
22
22
  next if m == Merb::DataMapperSessionStore if Merb.const_defined?(:DataMapperSessionStore)
23
- model = lookup(m.to_s.to_sym)
23
+ model = lookup(model_name.to_s.to_sym)
24
24
  @models << new(model) if model
25
25
  end
26
- @models.sort!{|a, b| a.model.to_s <=> b.model.to_s}
27
- when :sequel
28
- Dir.glob(Merb.dir_for(:model) / Merb.glob_for(:model)).each do |filename|
29
- # FIXME: This heuristic for finding Sequel models could be too strict
30
- File.read(filename).scan(/^class ([\w\d_\-:]+) < Sequel::Model$/).flatten.each do |m|
31
- model = lookup(m.to_s.to_sym)
32
- @models << new(model) if model
33
- end
34
- end
35
- @models.sort!{|a, b| a.model.to_s <=> b.model.to_s}
36
26
  else
37
- raise "MerbAdmin does not support the #{Merb.orm} ORM"
27
+ raise "MerbAdmin does not support the #{orm} ORM"
38
28
  end
29
+ @models.sort!{|x, y| x.model.to_s <=> y.model.to_s}
39
30
  end
40
31
 
41
32
  # Given a symbol +model_name+, finds the corresponding model class
@@ -48,22 +39,24 @@ module MerbAdmin
48
39
 
49
40
  case Merb.orm
50
41
  when :activerecord
51
- return model if superclasses(model).include?(ActiveRecord::Base)
42
+ model if superclasses(model).include?(ActiveRecord::Base)
52
43
  when :datamapper
53
- return model if model.include?(DataMapper::Resource)
44
+ model if model.include?(DataMapper::Resource)
54
45
  when :sequel
55
- return model if superclasses(model).include?(Sequel::Model)
46
+ model if superclasses(model).include?(Sequel::Model)
47
+ else
48
+ nil
56
49
  end
57
- nil
58
50
  end
59
51
 
60
52
  attr_accessor :model
61
53
 
62
54
  def initialize(model)
63
55
  model = self.class.lookup(model.to_s.camel_case) unless model.is_a?(Class)
56
+ orm = Merb.orm
64
57
  @model = model
65
58
  self.extend(GenericSupport)
66
- case Merb.orm
59
+ case orm
67
60
  when :activerecord
68
61
  require 'activerecord_support'
69
62
  self.extend(ActiverecordSupport)
@@ -74,7 +67,7 @@ module MerbAdmin
74
67
  require 'sequel_support'
75
68
  self.extend(SequelSupport)
76
69
  else
77
- raise "MerbAdmin does not support the #{Merb.orm} ORM"
70
+ raise "MerbAdmin does not support the #{orm} ORM"
78
71
  end
79
72
  end
80
73
 
@@ -133,6 +133,10 @@ module MerbAdmin
133
133
  end
134
134
 
135
135
  module InstanceMethods
136
+ def update_attributes(attributes)
137
+ update(attributes)
138
+ end
139
+
136
140
  def clear_association(association)
137
141
  association.clear
138
142
  end
@@ -92,7 +92,7 @@ def load_data
92
92
  end
93
93
 
94
94
  puts "Loading current MLB leagues, divisions, teams, and players"
95
- MLB::Teams.all.each do |mlb_team|
95
+ MLB::Team.all.each do |mlb_team|
96
96
  unless league = MerbAdmin::AbstractModel.new("League").first(:conditions => ["name = ?", mlb_team.league])
97
97
  league = MerbAdmin::AbstractModel.new("League").create(:name => mlb_team.league)
98
98
  end
@@ -102,8 +102,7 @@ def load_data
102
102
  unless team = MerbAdmin::AbstractModel.new("Team").first(:conditions => ["name = ?", mlb_team.name])
103
103
  team = MerbAdmin::AbstractModel.new("Team").create(:name => mlb_team.name, :logo_url => mlb_team.logo_url, :manager => mlb_team.manager, :ballpark => mlb_team.ballpark, :mascot => mlb_team.mascot, :founded => mlb_team.founded, :wins => mlb_team.wins, :losses => mlb_team.losses, :win_percentage => ("%.3f" % (mlb_team.wins.to_f / (mlb_team.wins + mlb_team.losses))).to_f, :division => division, :league => league)
104
104
  end
105
- mlb_team.players.each do |player|
106
- next if player.number.nil?
105
+ mlb_team.players.reject{|player| player.number.nil?}.each do |player|
107
106
  MerbAdmin::AbstractModel.new("Player").create(:name => player.name, :number => player.number, :position => player.position, :team => team)
108
107
  end
109
108
  end
@@ -114,8 +113,8 @@ def copy_models(orm = nil)
114
113
  puts "Copying sample #{orm} models into host application - resolves any collisions"
115
114
  seen, copied, duplicated = [], [], []
116
115
  Dir.glob(File.dirname(__FILE__) / ".." / ".." / "spec" / "models" / orm.to_s.downcase / MerbAdmin.glob_for(:model)).each do |source_filename|
117
- destination_filename = Merb.dir_for(:model) / File.basename(source_filename)
118
116
  next if seen.include?(source_filename)
117
+ destination_filename = Merb.dir_for(:model) / File.basename(source_filename)
119
118
  mirror_file(source_filename, destination_filename, copied, duplicated)
120
119
  seen << source_filename
121
120
  end
@@ -128,8 +127,8 @@ def copy_migrations(orm = nil)
128
127
  puts "Copying sample #{orm} migrations into host application - resolves any collisions"
129
128
  seen, copied, duplicated = [], [], []
130
129
  Dir.glob(File.dirname(__FILE__) / ".." / ".." / "spec" / "migrations" / orm.to_s.downcase / "*.rb").each do |source_filename|
131
- destination_filename = Merb.root / "schema" / "migrations" / File.basename(source_filename)
132
130
  next if seen.include?(source_filename)
131
+ destination_filename = Merb.root / "schema" / "migrations" / File.basename(source_filename)
133
132
  mirror_file(source_filename, destination_filename, copied, duplicated)
134
133
  seen << source_filename
135
134
  end
data/lib/merb-admin.rb CHANGED
@@ -23,7 +23,7 @@ if defined?(Merb::Plugins)
23
23
 
24
24
  # Slice metadata
25
25
  self.description = "MerbAdmin is a Merb plugin that provides an easy-to-use interface for managing your data."
26
- self.version = "0.6.2"
26
+ self.version = "0.6.3"
27
27
  self.author = "Erik Michaels-Ober"
28
28
 
29
29
  # Stub classes loaded hook - runs before LoadClasses BootLoader
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: merb-admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Erik Michaels-Ober
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-02 00:00:00 -08:00
12
+ date: 2009-11-05 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 1.0.12
23
+ version: 1.0.15
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: merb-assets
@@ -30,7 +30,7 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 1.0.12
33
+ version: 1.0.15
34
34
  version:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: merb-helpers
@@ -40,7 +40,7 @@ dependencies:
40
40
  requirements:
41
41
  - - ">="
42
42
  - !ruby/object:Gem::Version
43
- version: 1.0.12
43
+ version: 1.0.15
44
44
  version:
45
45
  - !ruby/object:Gem::Dependency
46
46
  name: builder