recordselect 3.2.4 → 3.2.5
Sign up to get free protection for your applications and to get access to all the features.
- metadata +21 -46
- data/app/assets/images/record_select/cross.gif +0 -0
- data/app/assets/images/record_select/next.gif +0 -0
- data/app/assets/images/record_select/previous.gif +0 -0
- data/app/assets/javascripts/jquery/record_select.js +0 -543
- data/app/assets/javascripts/prototype/record_select.js +0 -419
- data/app/assets/javascripts/record_select.js.erb +0 -5
- data/app/assets/stylesheets/record_select.css.erb +0 -133
- data/app/views/record_select/_browse.html.erb +0 -8
- data/app/views/record_select/_list.html.erb +0 -31
- data/app/views/record_select/_search.html.erb +0 -20
- data/app/views/record_select/browse.js.erb +0 -1
- data/config/locales/en.yml +0 -9
- data/config/locales/es.yml +0 -13
- data/lib/record_select.rb +0 -36
- data/lib/record_select/actions.rb +0 -68
- data/lib/record_select/conditions.rb +0 -100
- data/lib/record_select/config.rb +0 -103
- data/lib/record_select/engine.rb +0 -4
- data/lib/record_select/extensions/active_record.rb +0 -9
- data/lib/record_select/extensions/localization.rb +0 -13
- data/lib/record_select/extensions/routing_mapper.rb +0 -20
- data/lib/record_select/form_builder.rb +0 -25
- data/lib/record_select/helpers/record_select_helper.rb +0 -217
- data/lib/record_select/version.rb +0 -9
- data/lib/recordselect.rb +0 -14
@@ -1,8 +0,0 @@
|
|
1
|
-
<%
|
2
|
-
controller ||= params[:controller]
|
3
|
-
record_select_id = record_select_id(controller)
|
4
|
-
-%>
|
5
|
-
<div class="record-select" id="<%= record_select_id -%>">
|
6
|
-
<%= render_record_select :partial => 'search', :locals => {:controller => controller, :record_select_id => record_select_id} %>
|
7
|
-
<%= render_record_select :partial => 'list', :locals => {:controller => controller, :page => @page, :record_select_id => record_select_id} %>
|
8
|
-
</div>
|
@@ -1,31 +0,0 @@
|
|
1
|
-
<%
|
2
|
-
controller ||= params[:controller]
|
3
|
-
|
4
|
-
pagination_url_params = params.merge(:controller => controller, :action => :browse, :search => params[:search], :update => 1)
|
5
|
-
prev_url = url_for(pagination_url_params.merge(:page => page.prev.number, :escape => false)) if page.prev?
|
6
|
-
next_url = url_for(pagination_url_params.merge(:page => page.next.number, :escape => false)) if page.next?
|
7
|
-
-%>
|
8
|
-
<ol>
|
9
|
-
<li class="found"><%= rs_(:records_found, :count => page.pager.count,
|
10
|
-
:model => record_select_config.model.model_name.human(:count => page.pager.count).downcase) %></li>
|
11
|
-
<% if page.prev? -%>
|
12
|
-
<li class="pagination previous">
|
13
|
-
<%= link_to image_tag('record_select/previous.gif', :alt => rs_(:previous)) + " " + rs_(:previous_items,
|
14
|
-
:count => page.pager.per_page),
|
15
|
-
{:url => prev_url},
|
16
|
-
{:href => prev_url, :method => :get, :remote => true} %>
|
17
|
-
</li>
|
18
|
-
<% end -%>
|
19
|
-
<% page.items.each do |record| -%>
|
20
|
-
<li class="record <%= cycle 'odd', 'even' %>" id="rs<%= record.id -%>">
|
21
|
-
<%= render_record_in_list(record, controller) %>
|
22
|
-
</li>
|
23
|
-
<% end -%>
|
24
|
-
<% if page.next? -%>
|
25
|
-
<li class="pagination next">
|
26
|
-
<%= link_to (rs_(:next_items, :count => page.pager.per_page) + " " + image_tag('record_select/next.gif', :alt => rs_(:next))).html_safe,
|
27
|
-
{:url => next_url},
|
28
|
-
{:href => next_url, :method => :get, :remote => true} %>
|
29
|
-
</li>
|
30
|
-
<% end -%>
|
31
|
-
</ol>
|
@@ -1,20 +0,0 @@
|
|
1
|
-
<% url_options = params.merge(:controller => controller, :action => :browse, :page => 1, :update => 1, :escape => false) -%>
|
2
|
-
<%= form_tag url_options, {:method => :get, :remote => true, :id => record_select_search_id} -%>
|
3
|
-
<%= text_field_tag 'search', params[:search], :autocomplete => 'off', :class => 'text-input' %>
|
4
|
-
<%= submit_tag 'search', :class => "search_submit" %>
|
5
|
-
</form>
|
6
|
-
|
7
|
-
<script type="text/javascript">
|
8
|
-
//<![CDATA[
|
9
|
-
<% if RecordSelect::Config.js_framework == :prototype %>
|
10
|
-
var i = $(<%= record_select_search_id.to_json.html_safe %>).down('input.text-input');
|
11
|
-
Form.Element.AfterActivity(i, function() {
|
12
|
-
$(<%= record_select_search_id.to_json.html_safe -%>).down('input.search_submit').click();
|
13
|
-
}, 0.35);
|
14
|
-
<% elsif RecordSelect::Config.js_framework == :jquery %>
|
15
|
-
jQuery(<%= "##{record_select_search_id}".to_json.html_safe %>).find('input.text-input').delayedObserver(0.35, function() {
|
16
|
-
jQuery(<%= "##{record_select_search_id}".to_json.html_safe %>).trigger("submit");});
|
17
|
-
<% end %>
|
18
|
-
//]]>
|
19
|
-
</script>
|
20
|
-
|
@@ -1 +0,0 @@
|
|
1
|
-
RecordSelect.render_page('<%= record_select_id %>', '<%= escape_javascript(render_record_select(:partial => 'list', :locals => {:page => @page})) %>');
|
data/config/locales/en.yml
DELETED
data/config/locales/es.yml
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
es:
|
2
|
-
record_select:
|
3
|
-
next: "Siguiente"
|
4
|
-
next_items:
|
5
|
-
one: "Siguente"
|
6
|
-
other: "%{count} siguentes"
|
7
|
-
previous: "Anterior"
|
8
|
-
previous_items:
|
9
|
-
one: "Anterior"
|
10
|
-
other: "%{count} anteriores"
|
11
|
-
records_found:
|
12
|
-
one: "1 %{model} encontrado"
|
13
|
-
other: "%{count} %{model} encontrados"
|
data/lib/record_select.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
module RecordSelect
|
2
|
-
def self.included(base)
|
3
|
-
base.send :extend, ClassMethods
|
4
|
-
end
|
5
|
-
|
6
|
-
module ClassMethods
|
7
|
-
# Enables and configures RecordSelect on your controller.
|
8
|
-
#
|
9
|
-
# *Options*
|
10
|
-
# +model+:: defaults based on the name of the controller
|
11
|
-
# +per_page+:: records to show per page when browsing
|
12
|
-
# +notify+:: a method name to invoke when a record has been selected.
|
13
|
-
# +order_by+:: a SQL string to order the search results
|
14
|
-
# +search_on+:: an array of searchable fields
|
15
|
-
# +full_text_search+:: a boolean for whether to use a %?% search pattern or not. default is false.
|
16
|
-
# +label+:: a proc that accepts a record as argument and returns an option label. default is to call record.to_label instead.
|
17
|
-
# +include+:: as for ActiveRecord::Base#find. can help with search conditions or just help optimize rendering the results.
|
18
|
-
# +link+:: a boolean for whether wrap the text returned by label in a link or not. default is true. set to false when
|
19
|
-
# label returns html code which can't be inside a tag. You can use record_select_link_to_select in your proc
|
20
|
-
# or partial to add a link to select action
|
21
|
-
#
|
22
|
-
# You may also pass a block, which will be used as options[:notify].
|
23
|
-
def record_select(options = {})
|
24
|
-
options[:model] ||= self.to_s.split('::').last.sub(/Controller$/, '').pluralize.singularize.underscore
|
25
|
-
@record_select_config = RecordSelect::Config.new(options.delete(:model), options)
|
26
|
-
self.send :include, RecordSelect::Actions
|
27
|
-
self.send :include, RecordSelect::Conditions
|
28
|
-
end
|
29
|
-
|
30
|
-
attr_reader :record_select_config
|
31
|
-
|
32
|
-
def uses_record_select?
|
33
|
-
!record_select_config.nil?
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
module RecordSelect
|
2
|
-
module Actions
|
3
|
-
# :method => :get
|
4
|
-
# params => [:page, :search]
|
5
|
-
def browse
|
6
|
-
conditions = record_select_conditions
|
7
|
-
klass = record_select_model.where(conditions).includes(record_select_includes)
|
8
|
-
@count = klass.count
|
9
|
-
@count = @count.length if @count.is_a? ActiveSupport::OrderedHash
|
10
|
-
pager = ::Paginator.new(@count, record_select_config.per_page) do |offset, per_page|
|
11
|
-
klass.select(record_select_select).includes(record_select_config.include).order(record_select_config.order_by).limit(per_page).offset(offset).all
|
12
|
-
end
|
13
|
-
@page = pager.page(params[:page] || 1)
|
14
|
-
|
15
|
-
respond_to do |wants|
|
16
|
-
wants.html { render_record_select :partial => 'browse'}
|
17
|
-
wants.js {
|
18
|
-
if params[:update]
|
19
|
-
render_record_select :template => 'browse.js', :layout => false
|
20
|
-
else
|
21
|
-
render_record_select :partial => 'browse'
|
22
|
-
end
|
23
|
-
}
|
24
|
-
wants.yaml {}
|
25
|
-
wants.xml {}
|
26
|
-
wants.json {}
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# :method => :post
|
31
|
-
# params => [:id]
|
32
|
-
def select
|
33
|
-
klass = record_select_model
|
34
|
-
record = klass.find(params[:id])
|
35
|
-
if record_select_config.notify.is_a? Proc
|
36
|
-
record_select_config.notify.call(record)
|
37
|
-
elsif record_select_config.notify
|
38
|
-
send(record_select_config.notify, record)
|
39
|
-
end
|
40
|
-
render :nothing => true
|
41
|
-
end
|
42
|
-
|
43
|
-
protected
|
44
|
-
|
45
|
-
def record_select_config #:nodoc:
|
46
|
-
self.class.record_select_config
|
47
|
-
end
|
48
|
-
|
49
|
-
def render_record_select(options = {}) #:nodoc:
|
50
|
-
[:template,:partial].each do |template_name|
|
51
|
-
if options[template_name] then
|
52
|
-
options[template_name] = File.join(record_select_views_path, options[template_name])
|
53
|
-
end
|
54
|
-
end
|
55
|
-
if block_given? then yield options else render options end
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
def record_select_views_path
|
61
|
-
"record_select"
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def record_select_model
|
66
|
-
record_select_config.model
|
67
|
-
end
|
68
|
-
end
|
@@ -1,100 +0,0 @@
|
|
1
|
-
module RecordSelect
|
2
|
-
module Conditions
|
3
|
-
protected
|
4
|
-
# returns the combination of all conditions.
|
5
|
-
# conditions come from:
|
6
|
-
# * current search (params[:search])
|
7
|
-
# * intelligent url params (e.g. params[:first_name] if first_name is a model column)
|
8
|
-
# * specific conditions supplied by the developer
|
9
|
-
def record_select_conditions
|
10
|
-
conditions = []
|
11
|
-
|
12
|
-
merge_conditions(
|
13
|
-
record_select_conditions_from_search,
|
14
|
-
record_select_conditions_from_params,
|
15
|
-
record_select_conditions_from_controller
|
16
|
-
)
|
17
|
-
end
|
18
|
-
|
19
|
-
# an override method.
|
20
|
-
# here you can provide custom conditions to define the selectable records. useful for situational restrictions.
|
21
|
-
def record_select_conditions_from_controller; end
|
22
|
-
|
23
|
-
# another override method.
|
24
|
-
# define any association includes you want for the finder search.
|
25
|
-
def record_select_includes; end
|
26
|
-
|
27
|
-
def record_select_like_operator
|
28
|
-
@like_operator ||= ::ActiveRecord::Base.connection.adapter_name == "PostgreSQL" ? "ILIKE" : "LIKE"
|
29
|
-
end
|
30
|
-
|
31
|
-
# define special list of selected fields,
|
32
|
-
# mainly to define extra fields that can be used for
|
33
|
-
# specialized sorting.
|
34
|
-
def record_select_select; end
|
35
|
-
|
36
|
-
# generate conditions from params[:search]
|
37
|
-
# override this if you want to customize the search routine
|
38
|
-
def record_select_conditions_from_search
|
39
|
-
search_pattern = record_select_config.full_text_search? ? '%?%' : '?%'
|
40
|
-
|
41
|
-
if params[:search] and !params[:search].strip.empty?
|
42
|
-
if record_select_config.full_text_search?
|
43
|
-
tokens = params[:search].strip.split(' ')
|
44
|
-
else
|
45
|
-
tokens = []
|
46
|
-
tokens << params[:search].strip
|
47
|
-
end
|
48
|
-
|
49
|
-
where_clauses = record_select_config.search_on.collect { |sql| "#{sql} #{record_select_like_operator} ?" }
|
50
|
-
phrase = "(#{where_clauses.join(' OR ')})"
|
51
|
-
|
52
|
-
sql = ([phrase] * tokens.length).join(' AND ')
|
53
|
-
tokens = tokens.collect{ |value| [search_pattern.sub('?', value)] * record_select_config.search_on.length }.flatten
|
54
|
-
|
55
|
-
conditions = [sql, *tokens]
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
# instead of a shotgun approach, this assumes the user is
|
60
|
-
# searching vs some SQL field (possibly built with CONCAT())
|
61
|
-
# similar to the record labels.
|
62
|
-
# def record_select_simple_conditions_from_search
|
63
|
-
# return unless params[:search] and not params[:search].empty?
|
64
|
-
#
|
65
|
-
# search_pattern = record_select_config.full_text_search? ? '%?%' : '?%'
|
66
|
-
# search_string = search_pattern.sub('?', value.downcase)
|
67
|
-
#
|
68
|
-
# ["LOWER(#{record_select_config.search_on})", search_pattern.sub('?', value.downcase)]
|
69
|
-
# end
|
70
|
-
|
71
|
-
# generate conditions from the url parameters (e.g. users/browse?group_id=5)
|
72
|
-
def record_select_conditions_from_params
|
73
|
-
conditions = nil
|
74
|
-
params.each do |field, value|
|
75
|
-
next unless column = record_select_config.model.columns_hash[field]
|
76
|
-
conditions = merge_conditions(
|
77
|
-
conditions,
|
78
|
-
record_select_condition_for_column(column, value)
|
79
|
-
)
|
80
|
-
end
|
81
|
-
conditions
|
82
|
-
end
|
83
|
-
|
84
|
-
# generates an SQL condition for the given column/value
|
85
|
-
def record_select_condition_for_column(column, value)
|
86
|
-
if value.blank? and column.null
|
87
|
-
"#{column.name} IS NULL"
|
88
|
-
elsif column.text?
|
89
|
-
["LOWER(#{column.name}) LIKE ?", value]
|
90
|
-
else
|
91
|
-
["#{column.name} = ?", column.type_cast(value)]
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def merge_conditions(*conditions) #:nodoc:
|
96
|
-
c = conditions.find_all {|c| not c.nil? and not c.empty? }
|
97
|
-
c.empty? ? nil : c.collect{|c| record_select_config.model.send(:sanitize_sql, c)}.join(' AND ')
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
data/lib/record_select/config.rb
DELETED
@@ -1,103 +0,0 @@
|
|
1
|
-
module RecordSelect
|
2
|
-
# a write-once configuration object
|
3
|
-
class Config
|
4
|
-
def initialize(klass, options = {})
|
5
|
-
@klass = klass
|
6
|
-
|
7
|
-
@notify = block_given? ? proc : options[:notify]
|
8
|
-
|
9
|
-
@per_page = options[:per_page]
|
10
|
-
|
11
|
-
@search_on = [options[:search_on]].flatten unless options[:search_on].nil?
|
12
|
-
|
13
|
-
@order_by = options[:order_by]
|
14
|
-
|
15
|
-
@full_text_search = options[:full_text_search]
|
16
|
-
|
17
|
-
@label = options[:label]
|
18
|
-
|
19
|
-
@include = options[:include]
|
20
|
-
|
21
|
-
@link = options[:link]
|
22
|
-
end
|
23
|
-
|
24
|
-
def self.js_framework=(framework)
|
25
|
-
@@js_framework = framework
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.js_framework
|
29
|
-
@@js_framework ||= if defined? Jquery
|
30
|
-
:jquery
|
31
|
-
elsif defined? PrototypeRails
|
32
|
-
:prototype
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# The model object we're browsing
|
37
|
-
def model
|
38
|
-
@model ||= klass.to_s.camelcase.constantize
|
39
|
-
end
|
40
|
-
|
41
|
-
# Records to show on a page
|
42
|
-
def per_page
|
43
|
-
@per_page ||= 10
|
44
|
-
end
|
45
|
-
|
46
|
-
# The method name or proc to notify of a selection event.
|
47
|
-
# May not matter if the selection event is intercepted client-side.
|
48
|
-
def notify
|
49
|
-
@notify
|
50
|
-
end
|
51
|
-
|
52
|
-
# A collection of fields to search. This is essentially raw SQL, so you could search on "CONCAT(first_name, ' ', last_name)" if you wanted to.
|
53
|
-
# NOTE: this does *NO* default transforms (such as LOWER()), that's left entirely up to you.
|
54
|
-
def search_on
|
55
|
-
@search_on ||= self.model.columns.collect{|c| c.name if [:text, :string].include? c.type}.compact
|
56
|
-
end
|
57
|
-
|
58
|
-
def order_by
|
59
|
-
@order_by ||= "#{model.table_name}.#{model.primary_key} ASC" unless @order_by == false
|
60
|
-
end
|
61
|
-
|
62
|
-
def full_text_search?
|
63
|
-
@full_text_search ? true : false
|
64
|
-
end
|
65
|
-
|
66
|
-
def include
|
67
|
-
@include
|
68
|
-
end
|
69
|
-
|
70
|
-
# If a proc, must accept the record as an argument and return a descriptive string.
|
71
|
-
#
|
72
|
-
# If a symbol or string, must name a partial that renders a representation of the
|
73
|
-
# record. The partial should assume a local "record" variable, and should include a
|
74
|
-
# <label> tag, even if it's not visible. The contents of the <label> tag will be used
|
75
|
-
# to represent the record once it has been selected. For example:
|
76
|
-
#
|
77
|
-
# record_select_config.label = :user_description
|
78
|
-
#
|
79
|
-
# > app/views/users/_user_description.erb
|
80
|
-
#
|
81
|
-
# <div class="user_description">
|
82
|
-
# <%= image_tag url_for_file_column(record, 'avatar') %>
|
83
|
-
# <label><%= record.username %></label>
|
84
|
-
# <p><%= record.quote %></p>
|
85
|
-
# </div>
|
86
|
-
#
|
87
|
-
def label
|
88
|
-
@label ||= proc {|r| r.to_label}
|
89
|
-
end
|
90
|
-
|
91
|
-
# whether wrap the text returned by label in a link or not
|
92
|
-
def link?
|
93
|
-
@link.nil? ? true : @link
|
94
|
-
end
|
95
|
-
|
96
|
-
protected
|
97
|
-
|
98
|
-
# A singularized underscored version of the model we're browsing
|
99
|
-
def klass
|
100
|
-
@klass
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
data/lib/record_select/engine.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
# Provides a simple pass-through localizer for RecordSelect. If you want
|
2
|
-
# to localize RS, you need to override this method and route it to your
|
3
|
-
# own system.
|
4
|
-
class Object
|
5
|
-
def rs_(key, options = {})
|
6
|
-
unless key.blank?
|
7
|
-
text = I18n.translate "#{key}", {:scope => [:record_select], :default => key.is_a?(String) ? key : key.to_s.titleize}.merge(options)
|
8
|
-
# text = nil if text.include?('translation missing:')
|
9
|
-
end
|
10
|
-
text ||= key
|
11
|
-
text
|
12
|
-
end
|
13
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module ActionDispatch
|
2
|
-
module Routing
|
3
|
-
RECORD_SELECT_ROUTING = {
|
4
|
-
:collection => {:browse => :get},
|
5
|
-
:member => {:select => :post}
|
6
|
-
}
|
7
|
-
class Mapper
|
8
|
-
module Base
|
9
|
-
def record_select_routes
|
10
|
-
collection do
|
11
|
-
ActionDispatch::Routing::RECORD_SELECT_ROUTING[:collection].each {|name, type| send(type, name)}
|
12
|
-
end
|
13
|
-
member do
|
14
|
-
ActionDispatch::Routing::RECORD_SELECT_ROUTING[:member].each {|name, type| send(type, name)}
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|