Class: Query
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- Query
- Includes:
- Redmine::SubclassFactory
- Defined in:
- app/models/query.rb
Overview
Direct Known Subclasses
Defined Under Namespace
Classes: StatementInvalid
Constant Summary collapse
- VISIBILITY_PRIVATE =
0
- VISIBILITY_ROLES =
1
- VISIBILITY_PUBLIC =
2
Class Method Summary collapse
- .add_available_column(column) ⇒ Object
-
.build_from_params(params, attributes = {}) ⇒ Object
Builds a new query from the given params and attributes.
-
.operators_labels ⇒ Object
Returns a hash of localized labels for all filter operators.
-
.visible(*args) ⇒ Object
Scope of visible queries, can be used from subclasses only.
Instance Method Summary collapse
-
#add_available_filter(field, options) ⇒ Object
Adds an available filter.
- #add_filter(field, operator, values = nil) ⇒ Object
- #add_filter_error(field, message) ⇒ Object
-
#add_filters(fields, operators, values) ⇒ Object
Add multiple filters using
add_filter
. - #add_short_filter(field, expression) ⇒ Object
- #all_projects ⇒ Object
- #all_projects_values ⇒ Object
- #as_params ⇒ Object
- #assigned_to_values ⇒ Object
- #author_values ⇒ Object
- #available_block_columns ⇒ Object
-
#available_filters ⇒ Object
Return a hash of available filters.
-
#available_filters_as_json ⇒ Object
Returns a representation of the available filters for JSON serialization.
- #available_inline_columns ⇒ Object
- #available_totalable_columns ⇒ Object
- #block_columns ⇒ Object
-
#build_from_params(params) ⇒ Object
Builds the query from the given params.
- #column_names=(names) ⇒ Object
- #columns ⇒ Object
- #css_classes ⇒ Object
- #default_columns_names ⇒ Object
- #default_sort_criteria ⇒ Object
- #default_totalable_names ⇒ Object
-
#delete_available_filter(field) ⇒ Object
Removes an available filter.
- #editable_by?(user) ⇒ Boolean
- #fixed_version_values ⇒ Object
- #group_by_column ⇒ Object
-
#group_by_sort_order ⇒ Object
Returns the SQL sort order that should be prepended for grouping.
- #group_by_statement ⇒ Object
-
#groupable_columns ⇒ Object
Returns an array of columns that can be used to group the results.
-
#grouped? ⇒ Boolean
Returns true if the query is a grouped query.
- #has_column?(column) ⇒ Boolean
- #has_custom_field_column? ⇒ Boolean
- #has_default_columns? ⇒ Boolean
- #has_filter?(field) ⇒ Boolean
-
#initialize(attributes = nil, *args) ⇒ Query
constructor
A new instance of Query.
- #inline_columns ⇒ Object
- #is_private? ⇒ Boolean
- #is_public? ⇒ Boolean
-
#issue_custom_fields ⇒ Object
Returns a scope of issue custom fields that are available as columns or filters.
-
#issue_statuses_values ⇒ Object
Returns a scope of issue statuses that are available as columns for filters.
- #label_for(field) ⇒ Object
- #operator_for(field) ⇒ Object
- #principals ⇒ Object
- #project_statement ⇒ Object
- #project_values ⇒ Object
- #queried_table_name ⇒ Object
-
#result_count_by_group ⇒ Object
Returns the result count by group or nil if query is not grouped.
- #sort_clause ⇒ Object
- #sort_criteria ⇒ Object
- #sort_criteria=(arg) ⇒ Object
- #sort_criteria_key(index) ⇒ Object
- #sort_criteria_order(index) ⇒ Object
-
#sortable_columns ⇒ Object
Returns a Hash of columns and the key for sorting.
- #statement ⇒ Object
- #subproject_values ⇒ Object
-
#total_by_group_for(column) ⇒ Object
Returns a hash of the sum of the given column for each group, or nil if the query is not grouped.
-
#total_for(column) ⇒ Object
Returns the sum of values for the given column.
- #totalable_columns ⇒ Object
- #totalable_names ⇒ Object
- #totalable_names=(names) ⇒ Object
- #totals {|totals| ... } ⇒ Object
- #totals_by_group {|totals| ... } ⇒ Object
- #trackers ⇒ Object
- #type_for(field) ⇒ Object
- #users ⇒ Object
- #validate_query_filters ⇒ Object
- #value_for(field, index = 0) ⇒ Object
- #values_for(field) ⇒ Object
-
#visible?(user = User.current) ⇒ Boolean
Returns true if the query is visible to
user
or the current user.
Constructor Details
#initialize(attributes = nil, *args) ⇒ Query
Removed at 4.0.0
Returns a new instance of Query
363 364 365 366 |
# File 'app/models/query.rb', line 363 def initialize(attributes=nil, *args) super attributes @is_for_all = project.nil? end |
Class Method Details
.add_available_column(column) ⇒ Object
657 658 659 |
# File 'app/models/query.rb', line 657 def self.add_available_column(column) self.available_columns << (column) if column.is_a?(QueryColumn) end |
.build_from_params(params, attributes = {}) ⇒ Object
Builds a new query from the given params and attributes
386 387 388 |
# File 'app/models/query.rb', line 386 def self.build_from_params(params, attributes={}) new(attributes).build_from_params(params) end |
.operators_labels ⇒ Object
Returns a hash of localized labels for all filter operators
456 457 458 |
# File 'app/models/query.rb', line 456 def self.operators_labels operators.inject({}) {|h, operator| h[operator.first] = l(*operator.last); h} end |
.visible(*args) ⇒ Object
Scope of visible queries, can be used from subclasses only. Unlike other visible scopes, a class methods is used as it let handle inheritance more nicely than scope DSL.
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 |
# File 'app/models/query.rb', line 301 def self.visible(*args) if self == ::Query # Visibility depends on permissions for each subclass, # raise an error if the scope is called from Query (eg. Query.visible) raise Exception.new("Cannot call .visible scope from the base Query class, but from subclasses only.") end user = args.shift || User.current base = Project.allowed_to_condition(user, , *args) scope = joins("LEFT OUTER JOIN #{Project.table_name} ON #{table_name}.project_id = #{Project.table_name}.id"). where("#{table_name}.project_id IS NULL OR (#{base})") if user.admin? scope.where("#{table_name}.visibility <> ? OR #{table_name}.user_id = ?", VISIBILITY_PRIVATE, user.id) elsif user.memberships.any? scope.where("#{table_name}.visibility = ?" + " OR (#{table_name}.visibility = ? AND #{table_name}.id IN (" + "SELECT DISTINCT q.id FROM #{table_name} q" + " INNER JOIN #{table_name_prefix}queries_roles#{table_name_suffix} qr on qr.query_id = q.id" + " INNER JOIN #{MemberRole.table_name} mr ON mr.role_id = qr.role_id" + " INNER JOIN #{Member.table_name} m ON m.id = mr.member_id AND m.user_id = ?" + " INNER JOIN #{Project.table_name} p ON p.id = m.project_id AND p.status <> ?" + " WHERE q.project_id IS NULL OR q.project_id = m.project_id))" + " OR #{table_name}.user_id = ?", VISIBILITY_PUBLIC, VISIBILITY_ROLES, user.id, Project::STATUS_ARCHIVED, user.id) elsif user.logged? scope.where("#{table_name}.visibility = ? OR #{table_name}.user_id = ?", VISIBILITY_PUBLIC, user.id) else scope.where("#{table_name}.visibility = ?", VISIBILITY_PUBLIC) end end |
Instance Method Details
#add_available_filter(field, options) ⇒ Object
Adds an available filter
581 582 583 584 585 |
# File 'app/models/query.rb', line 581 def add_available_filter(field, ) @available_filters ||= ActiveSupport::OrderedHash.new @available_filters[field] = QueryFilter.new(field, ) @available_filters end |
#add_filter(field, operator, values = nil) ⇒ Object
603 604 605 606 607 608 609 610 611 |
# File 'app/models/query.rb', line 603 def add_filter(field, operator, values=nil) # values must be an array return unless values.nil? || values.is_a?(Array) # check if field is defined as an available filter if available_filters.has_key? field = available_filters[field] filters[field] = {:operator => operator, :values => (values || [''])} end end |
#add_filter_error(field, message) ⇒ Object
438 439 440 441 |
# File 'app/models/query.rb', line 438 def add_filter_error(field, ) m = label_for(field) + " " + l(, :scope => 'activerecord.errors.messages') errors.add(:base, m) end |
#add_filters(fields, operators, values) ⇒ Object
Add multiple filters using add_filter
624 625 626 627 628 629 630 |
# File 'app/models/query.rb', line 624 def add_filters(fields, operators, values) if fields.is_a?(Array) && operators.is_a?(Hash) && (values.nil? || values.is_a?(Hash)) fields.each do |field| add_filter(field, operators[field], values && values[field]) end end end |
#add_short_filter(field, expression) ⇒ Object
613 614 615 616 617 618 619 620 621 |
# File 'app/models/query.rb', line 613 def add_short_filter(field, expression) return unless expression && available_filters.has_key?(field) field_type = available_filters[field][:type] operators_by_filter_type[field_type].sort.reverse.detect do |operator| next unless expression =~ /^#{Regexp.escape(operator)}(.*)$/ values = $1 add_filter field, operator, values.present? ? values.split('|') : [''] end || add_filter(field, '=', expression.to_s.split('|')) end |
#all_projects ⇒ Object
481 482 483 |
# File 'app/models/query.rb', line 481 def all_projects @all_projects ||= Project.visible.to_a end |
#all_projects_values ⇒ Object
485 486 487 488 489 490 491 492 493 494 |
# File 'app/models/query.rb', line 485 def all_projects_values return @all_projects_values if @all_projects_values values = [] Project.project_tree(all_projects) do |p, level| prefix = (level > 0 ? ('--' * level + ' ') : '') values << ["#{prefix}#{p.name}", p.id.to_s] end @all_projects_values = values end |
#as_params ⇒ Object
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 |
# File 'app/models/query.rb', line 390 def as_params if new_record? params = {} filters.each do |field, | params[:f] ||= [] params[:f] << field params[:op] ||= {} params[:op][field] = [:operator] params[:v] ||= {} params[:v][field] = [:values] end params[:c] = column_names params[:sort] = sort_criteria.to_param params[:set_filter] = 1 params else {:query_id => id} end end |
#assigned_to_values ⇒ Object
538 539 540 541 542 543 |
# File 'app/models/query.rb', line 538 def assigned_to_values assigned_to_values = [] assigned_to_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged? assigned_to_values += (Setting.issue_group_assignment? ? principals : users).collect{|s| [s.name, s.id.to_s] } assigned_to_values end |
#author_values ⇒ Object
531 532 533 534 535 536 |
# File 'app/models/query.rb', line 531 def = [] << ["<< #{l(:label_me)} >>", "me"] if User.current.logged? += users.collect{|s| [s.name, s.id.to_s] } end |
#available_block_columns ⇒ Object
694 695 696 |
# File 'app/models/query.rb', line 694 def available_block_columns available_columns.reject(&:inline?) end |
#available_filters ⇒ Object
Return a hash of available filters
595 596 597 598 599 600 601 |
# File 'app/models/query.rb', line 595 def available_filters unless @available_filters initialize_available_filters @available_filters ||= {} end @available_filters end |
#available_filters_as_json ⇒ Object
Returns a representation of the available filters for JSON serialization
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 |
# File 'app/models/query.rb', line 461 def available_filters_as_json json = {} available_filters.each do |field, filter| = {:type => filter[:type], :name => filter[:name]} [:remote] = true if filter.remote if has_filter?(field) || !filter.remote [:values] = filter.values if [:values] && values_for(field) missing = Array(values_for(field)).select(&:present?) - [:values].map(&:last) if missing.any? && respond_to?(method = "find_#{field}_filter_values") [:values] += send(method, missing) end end end json[field] = .stringify_keys end json end |
#available_inline_columns ⇒ Object
690 691 692 |
# File 'app/models/query.rb', line 690 def available_inline_columns available_columns.select(&:inline?) end |
#available_totalable_columns ⇒ Object
698 699 700 |
# File 'app/models/query.rb', line 698 def available_totalable_columns available_columns.select(&:totalable) end |
#block_columns ⇒ Object
686 687 688 |
# File 'app/models/query.rb', line 686 def block_columns columns.reject(&:inline?) end |
#build_from_params(params) ⇒ Object
Builds the query from the given params
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 |
# File 'app/models/query.rb', line 369 def build_from_params(params) if params[:fields] || params[:f] self.filters = {} add_filters(params[:fields] || params[:f], params[:operators] || params[:op], params[:values] || params[:v]) else available_filters.keys.each do |field| add_short_filter(field, params[field]) if params[field] end end self.group_by = params[:group_by] || (params[:query] && params[:query][:group_by]) self.column_names = params[:c] || (params[:query] && params[:query][:column_names]) self.totalable_names = params[:t] || (params[:query] && params[:query][:totalable_names]) self.sort_criteria = params[:sort] || (params[:query] && params[:query][:sort_criteria]) self end |
#column_names=(names) ⇒ Object
710 711 712 713 714 715 716 717 718 719 720 721 722 723 |
# File 'app/models/query.rb', line 710 def column_names=(names) if names names = names.select {|n| n.is_a?(Symbol) || !n.blank? } names = names.collect {|n| n.is_a?(Symbol) ? n : n.to_sym } if names.delete(:all_inline) names = available_inline_columns.map(&:name) | names end # Set column_names to nil if default columns if names == default_columns_names names = nil end end write_attribute(:column_names, names) end |
#columns ⇒ Object
674 675 676 677 678 679 680 |
# File 'app/models/query.rb', line 674 def columns # preserve the column_names order cols = (has_default_columns? ? default_columns_names : column_names).collect do |name| available_columns.find { |col| col.name == name } end.compact available_columns.select(&:frozen?) | cols end |
#css_classes ⇒ Object
925 926 927 928 929 930 931 |
# File 'app/models/query.rb', line 925 def css_classes s = sort_criteria.first if s.present? key, asc = s "sort-by-#{key.to_s.dasherize} sort-#{asc}" end end |
#default_columns_names ⇒ Object
702 703 704 |
# File 'app/models/query.rb', line 702 def default_columns_names [] end |
#default_sort_criteria ⇒ Object
754 755 756 |
# File 'app/models/query.rb', line 754 def default_sort_criteria [] end |
#default_totalable_names ⇒ Object
706 707 708 |
# File 'app/models/query.rb', line 706 def default_totalable_names [] end |
#delete_available_filter(field) ⇒ Object
Removes an available filter
588 589 590 591 592 |
# File 'app/models/query.rb', line 588 def delete_available_filter(field) if @available_filters @available_filters.delete(field) end end |
#editable_by?(user) ⇒ Boolean
443 444 445 446 447 448 449 |
# File 'app/models/query.rb', line 443 def editable_by?(user) return false unless user # Admin can edit them all and regular users can edit their private queries return true if user.admin? || (is_private? && self.user_id == user.id) # Members can not edit public queries that are for all project (only admin is allowed to) is_public? && !@is_for_all && user.allowed_to?(:manage_public_queries, project) end |
#fixed_version_values ⇒ Object
545 546 547 548 549 550 551 552 553 |
# File 'app/models/query.rb', line 545 def fixed_version_values versions = [] if project versions = project.shared_versions.to_a else versions = Version.visible.where(:sharing => 'system').to_a end Version.sort_by_status(versions).collect{|s| ["#{s.project.name} - #{s.name}", s.id.to_s, l("version_status_#{s.status}")] } end |
#group_by_column ⇒ Object
797 798 799 |
# File 'app/models/query.rb', line 797 def group_by_column groupable_columns.detect {|c| c.groupable && c.name.to_s == group_by} end |
#group_by_sort_order ⇒ Object
Returns the SQL sort order that should be prepended for grouping
785 786 787 788 789 790 |
# File 'app/models/query.rb', line 785 def group_by_sort_order if column = group_by_column order = (sort_criteria.order_for(column.name) || column.default_order || 'asc').try(:upcase) Array(column.sortable).map {|s| "#{s} #{order}"} end end |
#group_by_statement ⇒ Object
801 802 803 |
# File 'app/models/query.rb', line 801 def group_by_statement group_by_column.try(:groupable) end |
#groupable_columns ⇒ Object
Returns an array of columns that can be used to group the results
662 663 664 |
# File 'app/models/query.rb', line 662 def groupable_columns available_columns.select {|c| c.groupable} end |
#grouped? ⇒ Boolean
Returns true if the query is a grouped query
793 794 795 |
# File 'app/models/query.rb', line 793 def grouped? !group_by_column.nil? end |
#has_column?(column) ⇒ Boolean
725 726 727 728 |
# File 'app/models/query.rb', line 725 def has_column?(column) name = column.is_a?(QueryColumn) ? column.name : column columns.detect {|c| c.name == name} end |
#has_custom_field_column? ⇒ Boolean
730 731 732 |
# File 'app/models/query.rb', line 730 def has_custom_field_column? columns.any? {|column| column.is_a? QueryCustomFieldColumn} end |
#has_default_columns? ⇒ Boolean
734 735 736 |
# File 'app/models/query.rb', line 734 def has_default_columns? column_names.nil? || column_names.empty? end |
#has_filter?(field) ⇒ Boolean
632 633 634 |
# File 'app/models/query.rb', line 632 def has_filter?(field) filters and filters[field] end |
#inline_columns ⇒ Object
682 683 684 |
# File 'app/models/query.rb', line 682 def inline_columns columns.select(&:inline?) end |
#is_private? ⇒ Boolean
351 352 353 |
# File 'app/models/query.rb', line 351 def is_private? visibility == VISIBILITY_PRIVATE end |
#is_public? ⇒ Boolean
355 356 357 |
# File 'app/models/query.rb', line 355 def is_public? !is_private? end |
#issue_custom_fields ⇒ Object
Returns a scope of issue custom fields that are available as columns or filters
566 567 568 569 570 571 572 |
# File 'app/models/query.rb', line 566 def issue_custom_fields if project project.rolled_up_custom_fields else IssueCustomField.all end end |
#issue_statuses_values ⇒ Object
Returns a scope of issue statuses that are available as columns for filters
556 557 558 559 560 561 562 563 |
# File 'app/models/query.rb', line 556 def issue_statuses_values if project statuses = project.rolled_up_statuses else statuses = IssueStatus.all.sorted end statuses.collect{|s| [s.name, s.id.to_s]} end |
#label_for(field) ⇒ Object
652 653 654 655 |
# File 'app/models/query.rb', line 652 def label_for(field) label = available_filters[field][:name] if available_filters.has_key?(field) label ||= queried_class.human_attribute_name(field, :default => field) end |
#operator_for(field) ⇒ Object
640 641 642 |
# File 'app/models/query.rb', line 640 def operator_for(field) has_filter?(field) ? filters[field][:operator] : nil end |
#principals ⇒ Object
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 |
# File 'app/models/query.rb', line 509 def principals @principal ||= begin principals = [] if project principals += project.principals.visible unless project.leaf? principals += Principal.member_of(project.descendants.visible).visible end else principals += Principal.member_of(all_projects).visible end principals.uniq! principals.sort! principals.reject! {|p| p.is_a?(GroupBuiltin)} principals end end |
#project_statement ⇒ Object
805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 |
# File 'app/models/query.rb', line 805 def project_statement project_clauses = [] active_subprojects_ids = [] active_subprojects_ids = project.descendants.active.map(&:id) if project if active_subprojects_ids.any? if has_filter?("subproject_id") case operator_for("subproject_id") when '=' # include the selected subprojects ids = [project.id] + values_for("subproject_id").map(&:to_i) project_clauses << "#{Project.table_name}.id IN (%s)" % ids.join(',') when '!' # exclude the selected subprojects ids = [project.id] + active_subprojects_ids - values_for("subproject_id").map(&:to_i) project_clauses << "#{Project.table_name}.id IN (%s)" % ids.join(',') when '!*' # main project only project_clauses << "#{Project.table_name}.id = %d" % project.id else # all subprojects project_clauses << "#{Project.table_name}.lft >= #{project.lft} AND #{Project.table_name}.rgt <= #{project.rgt}" end elsif Setting.display_subprojects_issues? project_clauses << "#{Project.table_name}.lft >= #{project.lft} AND #{Project.table_name}.rgt <= #{project.rgt}" else project_clauses << "#{Project.table_name}.id = %d" % project.id end elsif project project_clauses << "#{Project.table_name}.id = %d" % project.id end project_clauses.any? ? project_clauses.join(' AND ') : nil end |
#project_values ⇒ Object
496 497 498 499 500 501 502 503 |
# File 'app/models/query.rb', line 496 def project_values project_values = [] if User.current.logged? && User.current.memberships.any? project_values << ["<< #{l(:label_my_projects).downcase} >>", "mine"] end project_values += all_projects_values project_values end |
#queried_table_name ⇒ Object
359 360 361 |
# File 'app/models/query.rb', line 359 def queried_table_name @queried_table_name ||= self.class.queried_class.table_name end |
#result_count_by_group ⇒ Object
Returns the result count by group or nil if query is not grouped
894 895 896 897 898 |
# File 'app/models/query.rb', line 894 def result_count_by_group grouped_query do |scope| scope.count end end |
#sort_clause ⇒ Object
780 781 782 |
# File 'app/models/query.rb', line 780 def sort_clause sort_criteria.sort_clause(sortable_columns) end |
#sort_criteria ⇒ Object
764 765 766 767 768 769 770 |
# File 'app/models/query.rb', line 764 def sort_criteria c = read_attribute(:sort_criteria) if c.blank? c = default_sort_criteria end Redmine::SortCriteria.new(c) end |
#sort_criteria=(arg) ⇒ Object
758 759 760 761 762 |
# File 'app/models/query.rb', line 758 def sort_criteria=(arg) c = Redmine::SortCriteria.new(arg) write_attribute(:sort_criteria, c.to_a) c end |
#sort_criteria_key(index) ⇒ Object
772 773 774 |
# File 'app/models/query.rb', line 772 def sort_criteria_key(index) sort_criteria[index].try(:first) end |
#sort_criteria_order(index) ⇒ Object
776 777 778 |
# File 'app/models/query.rb', line 776 def sort_criteria_order(index) sort_criteria[index].try(:last) end |
#sortable_columns ⇒ Object
Returns a Hash of columns and the key for sorting
667 668 669 670 671 672 |
# File 'app/models/query.rb', line 667 def sortable_columns available_columns.inject({}) {|h, column| h[column.name.to_s] = column.sortable h } end |
#statement ⇒ Object
839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 |
# File 'app/models/query.rb', line 839 def statement # filters clauses filters_clauses = [] filters.each_key do |field| next if field == "subproject_id" v = values_for(field).clone next unless v and !v.empty? operator = operator_for(field) # "me" value substitution if %w(assigned_to_id author_id user_id watcher_id updated_by last_updated_by).include?(field) if v.delete("me") if User.current.logged? v.push(User.current.id.to_s) v += User.current.group_ids.map(&:to_s) if field == 'assigned_to_id' else v.push("0") end end end if field == 'project_id' if v.delete('mine') v += User.current.memberships.map(&:project_id).map(&:to_s) end end if field =~ /^cf_(\d+)\.cf_(\d+)$/ filters_clauses << sql_for_chained_custom_field(field, operator, v, $1, $2) elsif field =~ /cf_(\d+)$/ # custom field filters_clauses << sql_for_custom_field(field, operator, v, $1) elsif field =~ /^cf_(\d+)\.(.+)$/ filters_clauses << sql_for_custom_field_attribute(field, operator, v, $1, $2) elsif respond_to?(method = "sql_for_#{field.gsub('.','_')}_field") # specific statement filters_clauses << send(method, field, operator, v) else # regular field filters_clauses << '(' + sql_for_field(field, operator, v, queried_table_name, field) + ')' end end if filters and valid? if (c = group_by_column) && c.is_a?(QueryCustomFieldColumn) # Excludes results for which the grouped custom field is not visible filters_clauses << c.custom_field.visibility_by_project_condition end filters_clauses << project_statement filters_clauses.reject!(&:blank?) filters_clauses.any? ? filters_clauses.join(' AND ') : nil end |
#subproject_values ⇒ Object
505 506 507 |
# File 'app/models/query.rb', line 505 def subproject_values project.descendants.visible.collect{|s| [s.name, s.id.to_s] } end |
#total_by_group_for(column) ⇒ Object
Returns a hash of the sum of the given column for each group, or nil if the query is not grouped
907 908 909 910 911 |
# File 'app/models/query.rb', line 907 def total_by_group_for(column) grouped_query do |scope| total_with_scope(column, scope) end end |
#total_for(column) ⇒ Object
Returns the sum of values for the given column
901 902 903 |
# File 'app/models/query.rb', line 901 def total_for(column) total_with_scope(column, base_scope) end |
#totalable_columns ⇒ Object
738 739 740 741 |
# File 'app/models/query.rb', line 738 def totalable_columns names = totalable_names available_totalable_columns.select {|column| names.include?(column.name)} end |
#totalable_names ⇒ Object
750 751 752 |
# File 'app/models/query.rb', line 750 def totalable_names [:totalable_names] || default_totalable_names || [] end |
#totalable_names=(names) ⇒ Object
743 744 745 746 747 748 |
# File 'app/models/query.rb', line 743 def totalable_names=(names) if names names = names.select(&:present?).map {|n| n.is_a?(Symbol) ? n : n.to_sym} end [:totalable_names] = names end |
#totals {|totals| ... } ⇒ Object
913 914 915 916 917 |
# File 'app/models/query.rb', line 913 def totals totals = totalable_columns.map {|column| [column, total_for(column)]} yield totals if block_given? totals end |
#totals_by_group {|totals| ... } ⇒ Object
919 920 921 922 923 |
# File 'app/models/query.rb', line 919 def totals_by_group totals = totalable_columns.map {|column| [column, total_by_group_for(column)]} yield totals if block_given? totals end |
#trackers ⇒ Object
451 452 453 |
# File 'app/models/query.rb', line 451 def trackers @trackers ||= (project.nil? ? Tracker.all : project.rolled_up_trackers).visible.sorted end |
#type_for(field) ⇒ Object
636 637 638 |
# File 'app/models/query.rb', line 636 def type_for(field) available_filters[field][:type] if available_filters.has_key?(field) end |
#users ⇒ Object
527 528 529 |
# File 'app/models/query.rb', line 527 def users principals.select {|p| p.is_a?(User)} end |
#validate_query_filters ⇒ Object
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 |
# File 'app/models/query.rb', line 410 def validate_query_filters filters.each_key do |field| if values_for(field) case type_for(field) when :integer add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && !v.match(/\A[+-]?\d+(,[+-]?\d+)*\z/) } when :float add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && !v.match(/\A[+-]?\d+(\.\d*)?\z/) } when :date, :date_past case operator_for(field) when "=", ">=", "<=", "><" add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && (!v.match(/\A\d{4}-\d{2}-\d{2}(T\d{2}((:)?\d{2}){0,2}(Z|\d{2}:?\d{2})?)?\z/) || parse_date(v).nil?) } when ">t-", "<t-", "t-", ">t+", "<t+", "t+", "><t+", "><t-" add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && !v.match(/^\d+$/) } end end end add_filter_error(field, :blank) unless # filter requires one or more values (values_for(field) and !values_for(field).first.blank?) or # filter doesn't require any value ["o", "c", "!*", "*", "t", "ld", "w", "lw", "l2w", "m", "lm", "y", "*o", "!o"].include? operator_for(field) end if filters end |
#value_for(field, index = 0) ⇒ Object
648 649 650 |
# File 'app/models/query.rb', line 648 def value_for(field, index=0) (values_for(field) || [])[index] end |
#values_for(field) ⇒ Object
644 645 646 |
# File 'app/models/query.rb', line 644 def values_for(field) has_filter?(field) ? filters[field][:values] : nil end |
#visible?(user = User.current) ⇒ Boolean
Returns true if the query is visible to user
or the current
user.
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 |
# File 'app/models/query.rb', line 334 def visible?(user=User.current) return true if user.admin? return false unless project.nil? || user.allowed_to?(self.class., project) case visibility when VISIBILITY_PUBLIC true when VISIBILITY_ROLES if project (user.roles_for_project(project) & roles).any? else user.memberships.joins(:member_roles).where(:member_roles => {:role_id => roles.map(&:id)}).any? end else user == self.user end end |