dm-cutie-ui 0.0.2

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/History.txt ADDED
File without changes
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2009, Cory ODaniel
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a
4
+ copy of this software and associated documentation files (the "Software"),
5
+ to deal in the Software without restriction, including without limitation
6
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
7
+ and/or sell copies of the Software, and to permit persons to whom the
8
+ Software is furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19
+ DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,61 @@
1
+ Description
2
+ =============
3
+ dm-cutie-ui is a live reporting tool for dm-cutie. http://github.com/coryodaniel/dm-cutie
4
+
5
+
6
+ Adding Custom Columns
7
+ ======================
8
+ The partial 'grid' takes three keys to create its local variables: :columns, :records, :adhoc_columns (discussed next)
9
+
10
+ Columns should be respond to #each, it will generally be a DataMapper PropertySet. Each element in columns will be used in a #send method call on each of the elements in records. That means instead of doing the standard
11
+ partial :grid, :locals => { :columns => MyModel.properties, :records => @my_collection}
12
+
13
+ You can add any other columns you want as long as there is a method that a 'record' will respond to. For example, every object has a 'class' method, so you could do
14
+ partial :grid,
15
+ :locals => {
16
+ :columns => MyModel.properties.to_a + [:class],
17
+ :records => @my_collection
18
+ }
19
+
20
+ This would cause the class name to be output in a column (pretty useless), but you can add any method you want to the class and simply add its name to the set of elements being passed to :columns
21
+
22
+
23
+ As an alternative method you can pass a column name to a proc in the :adhoc_columns parameter
24
+ partial :grid,
25
+ :locals => {
26
+ :columns => MyModel.properties,
27
+ :records => @my_collection,
28
+ :adhoc_columns => {
29
+ :my_cool_class_name => lambda{|my_record| my_record.class }
30
+ }
31
+ }
32
+
33
+ This would result in a column named 'my_cool_class_name' with a value of 'MyModel'. Obviously you can be more creative :)
34
+
35
+ Note: the proc should accept one parameter, the specific record from the collection of items passed to :records
36
+
37
+ IMPORTANT NOTE:
38
+ Remember, if you are adding additional columns to the grid, make sure you pass the column names to the 'menu' partial if you want the ability to hide that column.
39
+
40
+
41
+ DataMapper Default Context
42
+ ==========================
43
+ DataMapper requires a 'default' repository. In DM UI all users use their own repository, so a fake repository is stubbed as
44
+
45
+ DataMapper.setup :default, "abstract://null"
46
+
47
+ All calls should be done through the Sinatra helper method #repo.
48
+
49
+
50
+ TODOS
51
+ =====
52
+ * If you boot a server with extras and then browse to a dm-cutie repo with out those extras you get an error
53
+ * should probably change extras loaded to a 'per repository' thing
54
+ * Make *.erbs more dry, its probably possible to get ride of them all together if the hooks had the following methods display_views, display_relationships
55
+ * Make this app less ugly, I suck horribly at CSS :)
56
+ * Deal w/ the super fields
57
+ * --include-hooks=this,that/there,etc
58
+ * figure out how to support including hooks/views that aren't a part of dm-cutie or dm-cutie-extras
59
+ * dm-pagination
60
+ * If someone built a merb-slice version of this, they would be awesome.
61
+ * Sinatra shutdown hook to clean up the tmp directory
data/Rakefile ADDED
@@ -0,0 +1,100 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require 'rubygems/specification'
4
+ require 'date'
5
+ require 'merb-core/version'
6
+ require 'merb-core/tasks/merb_rake_helper'
7
+ require "extlib"
8
+
9
+ require 'rake'
10
+ require 'rake/clean'
11
+ require 'spec/rake/spectask'
12
+ require "spec"
13
+ require 'rake/rdoctask'
14
+ require 'rake/gempackagetask'
15
+
16
+ ROOT = Pathname(__FILE__).dirname.expand_path
17
+ require ROOT + 'lib/dm-cutie-ui/version'
18
+
19
+ @spec = Gem::Specification.new do |s|
20
+ s.name = %q{dm-cutie-ui}
21
+ s.version = DmCutieUI::VERSION
22
+
23
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
24
+ s.authors = ["Cory ODaniel"]
25
+ s.date = %q{2009-10-15}
26
+ s.summary = s.description = %q{An interface to DM Cutie repos.}
27
+ s.email = %q{cutie@coryodaniel.com}
28
+ s.bindir = 'bin'
29
+ s.executables = ['dm-cutie-ui']
30
+ s.extra_rdoc_files = ["README.markdown", "LICENSE", "History.txt"]
31
+ s.files = ["LICENSE", "README.markdown", "Rakefile", "History.txt",
32
+ "config.ru",
33
+ "bin/dm-cutie-ui",
34
+ "lib/dm-cutie-ui.rb",
35
+ "lib/dm-cutie-ui/config.rb",
36
+ "lib/dm-cutie-ui/server.rb",
37
+ "lib/dm-cutie-ui/version.rb",
38
+ ]
39
+ s.files += Dir["lib/dm-cutie-ui/server/**/*"]
40
+ s.has_rdoc = true
41
+ s.homepage = "http://github.com/coryodaniel/dm-cutie-ui"
42
+
43
+ s.add_dependency 'sinatra', '=0.9.4'
44
+ s.add_dependency 'extlib', ">=0.9.13"
45
+ s.add_dependency "dm-core", ">=0.10.1"
46
+ s.add_dependency "dm-aggregates", ">=0.10.1"
47
+ s.add_dependency "data_objects", '>=0.10.0'
48
+ s.add_dependency "dm-cutie", '>=0.3.0'
49
+ s.require_paths = ["lib"]
50
+ s.rubygems_version = %q{1.2.0}
51
+ end
52
+
53
+ [ ROOT, ROOT.parent ].each do |dir|
54
+ Pathname.glob(dir.join('tasks/**/*.rb').to_s).each { |f| require f }
55
+ end
56
+
57
+ NAME = @spec.name
58
+ GEM_VERSION = DmCutieUI::VERSION
59
+
60
+ Rake::GemPackageTask.new(@spec) do |pkg|
61
+ pkg.gem_spec = @spec
62
+ end
63
+
64
+ desc "install the plugin locally"
65
+ task :install => [:package] do
66
+ sh %{sudo gem install #{install_home} pkg/#{NAME}-#{GEM_VERSION} --no-update-sources}
67
+ end
68
+
69
+ desc "create a gemspec file"
70
+ task :make_spec do
71
+ File.open("#{NAME}.gemspec", "w") do |file|
72
+ file.puts @spec.to_ruby
73
+ end
74
+ end
75
+
76
+ Rake::RDocTask.new do |rdoc|
77
+ files = ["README.markdown", "History.txt", "LICENSE", "lib/**/*.rb"]
78
+ rdoc.rdoc_files.add(files)
79
+ rdoc.main = "README.markdown"
80
+ rdoc.title = "DM CutieUI"
81
+
82
+ rdoc.rdoc_dir = "doc/rdoc"
83
+ rdoc.options << "--line-numbers" << "--inline-source"
84
+ end
85
+
86
+ Spec::Rake::SpecTask.new do |t|
87
+ t.spec_files = Dir["./spec/**/*_spec.rb"]
88
+ t.spec_files.unshift './spec/spec_helper.rb'
89
+
90
+ t.libs = ['lib']
91
+ t.spec_opts << "--color" << "--format" << "specdoc" #"progress"
92
+
93
+ if ENV['RCOV']
94
+ t.rcov = true
95
+ t.rcov_opts << '--exclude' << 'pkg,spec,interactive.rb,install_test_suite.rb,lib/gems,' + Gem.path.join(',')
96
+ t.rcov_opts << '--text-summary'
97
+ t.rcov_opts << '--sort' << 'coverage' << '--sort-reverse'
98
+ t.rcov_opts << '--only-uncovered'
99
+ end
100
+ end
data/bin/dm-cutie-ui ADDED
@@ -0,0 +1,50 @@
1
+ #! /usr/bin/env ruby
2
+ require 'rubygems' #its poison, i know.
3
+
4
+ if `which rackup`.empty?
5
+ abort "** Can't find `rackup` in PATH."
6
+ end
7
+
8
+ if ARGV.include?('-h') || ARGV.include?('--help')
9
+ puts <<-USAGE_INFO
10
+ Usage: dm-cutie-ui [cutie-options] [ruby-options] [rack-options]
11
+
12
+ Starts the dm-cutie front end
13
+
14
+ DmCutieUI Options:
15
+ ==================================================
16
+ --extras= # A comma seperated list of extras for dm-cutie to look for
17
+ (should match what you had in your app)
18
+ Examples:
19
+ dm-cutie-ui --extras=sqlite3_execution_plan
20
+ dm-cutie-ui --extras=mysql_execution_plan,mysql_warning
21
+
22
+ Rack Options:
23
+ ==================================================
24
+ -s, --server SERVER serve using SERVER (webrick/mongrel)
25
+ -o, --host HOST listen on HOST (default: 0.0.0.0)
26
+ -p, --port PORT use PORT (default: 9292)
27
+ -E, --env ENVIRONMENT use ENVIRONMENT for defaults (default: development)
28
+ -D, --daemonize run daemonized in the background
29
+ -P, --pid FILE file to store PID (default: rack.pid)
30
+
31
+ USAGE_INFO
32
+
33
+ else
34
+ __DIR__ = File.expand_path( File.join(File.dirname(__FILE__), '..') )
35
+
36
+ # Simple ARGV Parser, @note include-hooks is a TODO
37
+ # Remove cutie's argv from ARGV and let Sinatra have it.
38
+ cutie_flags = [:extras, :'include-hooks']
39
+ cutie_argv = ARGV.select{|arg| arg =~ /(\-\-(#{cutie_flags.join('|')}))/}
40
+ ARGV.delete_if{|arg| cutie_argv.member?(arg)}
41
+
42
+ args = ARGV
43
+ ENV['RUBYLIB'] = ENV['RUBYLIB'].to_s + ':' + File.join(__DIR__,'lib')
44
+ args.unshift '-e', %Q{require "dm-cutie-ui"; CUTIE_ARGV=%w{#{cutie_argv.join(' ')}}}
45
+ args.push File.expand_path(
46
+ File.join(__DIR__, "config.ru")
47
+ )
48
+
49
+ exec "rackup", *args
50
+ end
data/config.ru ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.expand_path(
4
+ File.join(File.dirname(__FILE__), 'lib')
5
+ )
6
+ require 'dm-cutie-ui/config'
7
+ require 'dm-cutie-ui/server'
8
+
9
+ use Rack::ShowExceptions
10
+ run DmCutieUI::Server.new
@@ -0,0 +1,107 @@
1
+ require 'rubygems'
2
+ require 'digest/md5'
3
+ require 'logger'
4
+
5
+ gem 'extlib', ">=0.9.13"
6
+ require 'extlib'
7
+
8
+ gem 'dm-cutie', '>=0.3.0'
9
+ require 'dm-cutie'
10
+
11
+ gem 'dm-aggregates', '>=0.10.1'
12
+ require 'dm-aggregates'
13
+
14
+ gem 'dm-core', '>=0.10.1'
15
+ require 'dm-core'
16
+
17
+ gem "data_objects", '>=0.10.0'
18
+ require 'data_objects'
19
+
20
+ # SEt up a faux adapter. DM requires a default repository
21
+ # Repository names are hashes of the Normalized URI and are stored in CutieUI.
22
+ DataMapper.setup :default, "abstract://null"
23
+
24
+ module DmCutieUI
25
+ class << self
26
+ def logger
27
+ @_logger ||= Logger.new(STDOUT)
28
+ end
29
+ def view_root
30
+ @_view_root ||= File.join('', 'tmp', 'dm-cutie-ui', Time.now.to_i.to_s)
31
+ end
32
+ # - routes - Routes for cutie models
33
+ #
34
+ def routes
35
+ @__routes ||={}
36
+ end
37
+
38
+ # - repos - Cache of connection strings used since boot time
39
+ #
40
+ # @return [String] connection string
41
+ def repos
42
+ @__repos ||= {}
43
+ end
44
+
45
+ # - connect - Connects to a datamapper repository
46
+ # This takes the password as an additional parameter for 'security' reasons since
47
+ # it caches all connection strings for a user
48
+ #
49
+ # @param connection [Hash]
50
+ # - string [String] connection string
51
+ # - password [String] connection password
52
+ #
53
+ # @return [String] -
54
+ #
55
+ def connect( connection )
56
+ connection_options = DataMapper::Adapters.send(:normalize_options, connection[:string])
57
+
58
+ # Cache this before adding the password if the person decided they didn't want it cached by leaving it out
59
+ normalized_uri = begin
60
+ query = connection_options.except(:adapter, :user, :password, :host, :port, :path, :fragment, :scheme, :query, :username, :database)
61
+ query = nil if query.empty?
62
+
63
+ DataObjects::URI.new(
64
+ connection_options[:adapter],
65
+ connection_options[:user] || connection_options[:username],
66
+ nil, #Dont put the password in the cache
67
+ connection_options[:host],
68
+ connection_options[:port],
69
+ connection_options[:path] || connection_options[:database],
70
+ query,
71
+ connection_options[:fragment]
72
+ )
73
+ end
74
+
75
+ # Create a hash of the normalized_uri
76
+ token = Digest::MD5.hexdigest(normalized_uri.to_s).to_sym
77
+
78
+ # Cache the uri
79
+ DmCutieUI.repos[token] = normalized_uri.to_s
80
+
81
+ # Add the password if it was provided
82
+ connection_options[:password] = connection[:password] unless connection[:password].blank?
83
+
84
+ adapter = DataMapper::Adapters.new token, connection_options
85
+
86
+ DataMapper::Repository.adapters[adapter.name] = adapter
87
+
88
+ if DataMapper::Cutie.valid_repo? adapter.name
89
+ return token
90
+ else
91
+ return false
92
+ end
93
+ end
94
+
95
+ def root
96
+ @_root_path ||= File.expand_path(File.dirname(__FILE__)) / 'dm-cutie-ui'
97
+ end
98
+ end
99
+ end
100
+
101
+ require DmCutieUI.root / :version
102
+
103
+ class String
104
+ def truncate(len,repl='...')
105
+ (self.length <= (len - repl.length)) ? self : self.slice(0,len) + repl.to_s
106
+ end
107
+ end
@@ -0,0 +1,63 @@
1
+ require 'fileutils'
2
+ puts CUTIE_ARGV
3
+
4
+ cutie_ui_config = CUTIE_ARGV.inject({}) do |conf, arg|
5
+ config_key, config_vals = arg.split('=')
6
+
7
+ if config_key
8
+ # { :extras => ['mysql', 'sqlite3'] }
9
+ config_value = config_vals.blank? ? true : config_vals.split(',')
10
+
11
+ conf[config_key.gsub('--','').to_sym] = config_value
12
+ conf
13
+ else
14
+ conf
15
+ end
16
+ end
17
+
18
+
19
+ # dm-cutie-ui has a bunch of views, but views may also come from dm-cutie-extras and eventually add'l plugins
20
+ # since we need a path to all the views, we create a temp folder and copy the views their
21
+ # as well as any other views from additional gems/reqs
22
+
23
+ # Configure DmCutieUI
24
+ FileUtils.mkdir_p DmCutieUI.view_root
25
+ FileUtils.cp_r(
26
+ File.join(DmCutieUI.root, "server", "views"), DmCutieUI.view_root
27
+ )
28
+ DmCutieUI.logger.info "View temp directory: #{DmCutieUI.view_root}"
29
+
30
+
31
+ # If extras were requested, get them.
32
+ if cutie_ui_config[:extras]
33
+ begin
34
+ require 'dm-cutie-extras'
35
+ rescue LoadError => ex
36
+ DmCutieUI.logger.error "dm-cutie-extras were requested, but the gem was not found: gem install dm-cutie-extras"
37
+ exit(1)
38
+ end
39
+
40
+ cutie_ui_config[:extras].each do |extra|
41
+ begin
42
+ # Load the extra
43
+ DataMapper::Cutie::Extras.load extra.to_sym
44
+
45
+ # move the hook's view into the DmCutieUI.view_root/cutie_models directory
46
+ #/tmp/dm-cutie-ui/view/1258150564/views/cutie_models/#{extra}.erb
47
+ # render a extras views by doing
48
+ # render :'cutie_models/#{extra}'
49
+
50
+ FileUtils.cp DataMapper::Cutie::Extras.view_path[extra.to_sym], DmCutieUI.view_root / 'views' / 'cutie_models'
51
+ rescue LoadError => ex
52
+ DmCutieUI.logger.error "dm-cutie-extra '#{extra}' does not exist."
53
+ exit(2)
54
+ end
55
+ end
56
+ end
57
+
58
+ # Thanks to dkubb: this make sure that the PropertySet always contains remote keys
59
+ descendants = DataMapper::Model.descendants.to_a
60
+ while model = descendants.shift
61
+ descendants.concat(model.descendants.to_a - [ model ])
62
+ model.send(:assert_valid)
63
+ end
@@ -0,0 +1,222 @@
1
+ require 'sinatra/base'
2
+ require 'erb'
3
+
4
+ module DmCutieUI
5
+ class Server < Sinatra::Base
6
+ dir = File.dirname(File.expand_path(__FILE__))
7
+ set :sessions, true
8
+ set :static, true
9
+ set :public, dir / "server" / "public"
10
+ set :views, DmCutieUI.view_root / 'views'
11
+
12
+ # BEGIN ROUTES
13
+ get('/help') { erb :'default/help' }
14
+
15
+ get '/' do
16
+ session["history"].each do |repo_key|
17
+ # Remove the key from the cookie, it was from a previous server boot
18
+ session["history"].delete(repo_key) if DmCutieUI.repos[repo_key].blank?
19
+ end if session["history"]
20
+
21
+ session.delete('current') if params['disconnect']
22
+
23
+ if !DmCutieUI.repos[session["current"]].blank?
24
+ erb :'default/index'
25
+ else
26
+ erb :'default/login'
27
+ end
28
+ end
29
+
30
+ post '/' do
31
+ begin
32
+ # This will be used by the repo method to get access to the repo the user selected
33
+ repo_key = DmCutieUI.connect params[:connection]
34
+
35
+ if repo_key
36
+ session["history"] ||= []
37
+
38
+ session["history"] << repo_key unless session["history"].member?(repo_key)
39
+ session["current"] = repo_key.to_sym
40
+ erb :'default/index'
41
+ else
42
+ @connection_error = "That repository is missing some dm-cutie storages (#{DataMapper::Cutie.missing_storage.join(', ')})"
43
+ erb :'default/login'
44
+ end
45
+ rescue Exception => ex
46
+ # DataObjects::SyntaxError, LoadError
47
+ @connection_error = ex.message
48
+ erb :'default/login'
49
+ end
50
+ end
51
+
52
+
53
+ ###################### GENERATE ROUTES ####################
54
+ # Generate routes for all files in 'sinatra/views/cutie_models'
55
+ # TODO: Create routes for --include-hooks once its supported
56
+ DataMapper::Cutie::MODELS.each do |model|
57
+ view_name = model.to_s.pluralize
58
+ view_path = DmCutieUI.view_root / 'views' / 'cutie_models' / "#{view_name}.erb"
59
+ view_uri = "/#{view_name}"
60
+ if File.exist? view_path
61
+ DmCutieUI.routes[view_uri] = {
62
+ :model => model,
63
+ :file => view_path,
64
+ :view_name => view_name
65
+ }
66
+
67
+ # Create the 'controller'
68
+ get view_uri do
69
+ if !DmCutieUI.repos[session["current"]].blank?
70
+ # The cutie model being viewed
71
+
72
+ @view_name = DmCutieUI.routes[ request.path_info ][:view_name]
73
+ @cutie_model = DataMapper::Cutie.get_klass DmCutieUI.routes[ request.path_info ][:model]
74
+
75
+ @title = DmCutieUI.routes[ request.path_info ][:model]
76
+
77
+ # Keep the response scoped to the users selected Cutie Repo
78
+ user_current_repo { erb(:"cutie_models/#{@view_name}") }
79
+ else
80
+ @connection_error = "Select a DM repository to connect to"
81
+ redirect '/'
82
+ end
83
+ end
84
+
85
+ elsif !@model.blank?
86
+ puts "A view was not found for: #{@model}. This is probably an anonymous resource."
87
+ end # else probably an anonymous resource
88
+ end
89
+
90
+ # END ROUTES
91
+
92
+ # BEGIN HELPERS
93
+ helpers do
94
+ include Rack::Utils
95
+ alias_method :h, :escape_html
96
+
97
+ ################
98
+ # DM Cutie UI doesn't need your applications models
99
+ # she knows what she needs to know about them through
100
+ # what DM Cutie stored in her tables
101
+ # TODO - Remove the need for uniq by grouping these, also consider a smart way to cache them per user
102
+ ################
103
+
104
+ # Gets a list of repo names from the Cutie Repo
105
+ def repository_names
106
+ user_current_repo do
107
+ RepositoryStorage.all().map{ |rs| rs.repo_name }.uniq
108
+ end
109
+ end
110
+
111
+ # Gets a list of model names from the Cutie Repo
112
+ def model_names
113
+ user_current_repo do
114
+ RepositoryStorage.all().map{ |rs| rs.model_name }.uniq
115
+ end
116
+ end
117
+
118
+ # Gets a list of adapter names from the Cutie Repo
119
+ def adapter_names
120
+ user_current_repo do
121
+ RepositoryStorage.all().map{ |rs| rs.adapter_name }.uniq
122
+ end
123
+ end
124
+
125
+ # Get the users chosen repository context
126
+ def user_current_repo
127
+ repository( session["current"] ) { yield }
128
+ end
129
+
130
+ def partial(template, *args)
131
+ template = File.join('shared',"_#{template}").to_sym
132
+ options = args.last.is_a?(Hash) ? args.pop : {}
133
+ options.merge!(:layout => false)
134
+
135
+
136
+ if collection = options.delete(:collection) then
137
+ collection.inject([]) do |buffer, member|
138
+ buffer << erb(template, options.merge(
139
+ :layout => false,
140
+ :locals => {template.to_sym => member}
141
+ )
142
+ )
143
+ end.join("\n")
144
+ else
145
+ erb(template, options)
146
+ end
147
+ end
148
+
149
+ # Parses the params hash looking for params that are properties of the model
150
+ #
151
+ def parse_params(model)
152
+ params.only *model.properties.map{|p| p.name.to_s} # Have to string this since sinatra params isnt a mash
153
+ end
154
+
155
+ def link_to(text,href)
156
+ %Q{<a href="#{href}">#{text}</a>}
157
+ end
158
+
159
+ # ram_filters - Filters for repository, adapter, and model
160
+ #
161
+ # An access for params[*_filter]
162
+ # Should be passed to determine the records to pass to display (Default provided: _grid partial)
163
+ def ram_filters
164
+ {
165
+ :repository => params['repository_filter'],
166
+ :adapter => params['adapter_filter'],
167
+ :model => params['model_filter']
168
+ }
169
+ end
170
+
171
+ # This is just a helper to get the property name or return the symbol if multiple data types are passed to
172
+ # the 'grid' partials :columns attribute
173
+ #
174
+ # @param col [DataMapper::Property|Symbol]
175
+ # @returns [Symbol]
176
+ #
177
+ def column_name(col)
178
+ if col.is_a?(Symbol)
179
+ return col
180
+ else
181
+ return col.name.to_sym
182
+ end
183
+ end
184
+
185
+ # Adds a help link to the top of the page
186
+ def help_link
187
+ @help_link = %q{<a href="#help" class="help_link">help</a>}
188
+ end
189
+
190
+ # Creates a hyperlink to a filtered related model
191
+ #
192
+ def relationship_link(relationship, record)
193
+ relationship_name = relationship.name
194
+
195
+ # This isnt going to work if multipart keys are ever used because its just doing parent_key.first
196
+ if relationship.parent_model == @cutie_model
197
+ filter_value = record.send relationship.parent_key.first.name
198
+ remote_model_key = relationship.child_key.first.name
199
+ remote_model = relationship.child_model
200
+ else #its the child model
201
+ filter_value = record.send relationship.child_key.first.name
202
+ remote_model_key = relationship.parent_key.first.name
203
+ remote_model = relationship.parent_model
204
+ end
205
+
206
+ remote_model_name = DataMapper::Cutie.get_human_name(remote_model).to_s.pluralize
207
+ total_remote_records = remote_model.all( remote_model_key => filter_value ).count
208
+ link_to "View: #{total_remote_records}", "/#{remote_model_name}?#{remote_model_key}=#{filter_value}"
209
+ end
210
+
211
+ # Returns 'selected="selected"' to reselect filter drop downs
212
+ def apply_selected_attribute(filter_name, filter_value)
213
+ if ram_filters[filter_name] == filter_value
214
+ 'selected="SELECTED"'
215
+ end
216
+ end
217
+ end
218
+
219
+ # END HELPERS
220
+
221
+ end
222
+ end