Filtering users by criteria in Ruby on Rails











up vote
3
down vote

favorite












I am a fairly new (RubyonRails) developer. I desire to improve my coding skills so I used climate to do some review on my code. It gave me a flag for this method that its complex. Is it characterised as complex because of having several "actions/tasks" in a single method?



Will it be better if I extract some code segments to a different method?



Is there something else I am not seeing?



  def search
filter_mapping = {"cost" => "rcost", "quality" => "rquality", "time" => "rtime", "experience" => "rexperience", "communication" => "rcommunication"}
@filters = params[:filter].split(",") rescue
@sort = params[:sort]

@user_type = params[:s_user_type]
@skills = params[:s_skills]
@location = params[:location]
@max_rate = params[:max_rate]
@availability = params[:availability]

@users = User.scoped.joins(:user_skills)
@users = @users.where('user_type = ?', @user_type) if @user_type.present?
@users = @users.where('user_skills.skill_id in (?)', @skills.map(&:to_i)) if @skills.present? && @skills.size > 0
@users = @users.where('availability = ?', @availability) if @availability.present?
@users = @users.where('location_country = ?', @location) if @location.present?
@users = @users.where('rate < ?', @max_rate.to_i) if @max_rate.present?
@users = @users.page(params[:page]).per(PER_PAGE)

@filters.each do |f|
if filter_mapping.keys.include?(f)
@users = @users.order("#{filter_mapping[f]} desc")
end
end

@users = @users.order('id asc') if @filters.empty?
@advanced_link = @location.blank? && @max_rate.blank? && @availability.blank?
render :index
end


Update



I figured out that I can extract the scopes into a method like that:



  def get_users_where_scopes
@users = User.scoped.joins(:user_skills)
@users = @users.where('user_type = ?', @user_type) if @user_type.present?
@users = @users.where('user_skills.skill_id in (?)', @skills.map(&:to_i)) if @skills.present? && @skills.size > 0
@users = @users.where('availability = ?', @availability) if @availability.present?
@users = @users.where('location_country = ?', @location) if @location.present?
@users = @users.where('rate < ?', @max_rate.to_i) if @max_rate.present?
@users = @users.page(params[:page]).per(PER_PAGE)
end


and then call it with @users = get_users_where_scopes(). But now the complexity of this method seems wrong to me.










share|improve this question




























    up vote
    3
    down vote

    favorite












    I am a fairly new (RubyonRails) developer. I desire to improve my coding skills so I used climate to do some review on my code. It gave me a flag for this method that its complex. Is it characterised as complex because of having several "actions/tasks" in a single method?



    Will it be better if I extract some code segments to a different method?



    Is there something else I am not seeing?



      def search
    filter_mapping = {"cost" => "rcost", "quality" => "rquality", "time" => "rtime", "experience" => "rexperience", "communication" => "rcommunication"}
    @filters = params[:filter].split(",") rescue
    @sort = params[:sort]

    @user_type = params[:s_user_type]
    @skills = params[:s_skills]
    @location = params[:location]
    @max_rate = params[:max_rate]
    @availability = params[:availability]

    @users = User.scoped.joins(:user_skills)
    @users = @users.where('user_type = ?', @user_type) if @user_type.present?
    @users = @users.where('user_skills.skill_id in (?)', @skills.map(&:to_i)) if @skills.present? && @skills.size > 0
    @users = @users.where('availability = ?', @availability) if @availability.present?
    @users = @users.where('location_country = ?', @location) if @location.present?
    @users = @users.where('rate < ?', @max_rate.to_i) if @max_rate.present?
    @users = @users.page(params[:page]).per(PER_PAGE)

    @filters.each do |f|
    if filter_mapping.keys.include?(f)
    @users = @users.order("#{filter_mapping[f]} desc")
    end
    end

    @users = @users.order('id asc') if @filters.empty?
    @advanced_link = @location.blank? && @max_rate.blank? && @availability.blank?
    render :index
    end


    Update



    I figured out that I can extract the scopes into a method like that:



      def get_users_where_scopes
    @users = User.scoped.joins(:user_skills)
    @users = @users.where('user_type = ?', @user_type) if @user_type.present?
    @users = @users.where('user_skills.skill_id in (?)', @skills.map(&:to_i)) if @skills.present? && @skills.size > 0
    @users = @users.where('availability = ?', @availability) if @availability.present?
    @users = @users.where('location_country = ?', @location) if @location.present?
    @users = @users.where('rate < ?', @max_rate.to_i) if @max_rate.present?
    @users = @users.page(params[:page]).per(PER_PAGE)
    end


    and then call it with @users = get_users_where_scopes(). But now the complexity of this method seems wrong to me.










    share|improve this question


























      up vote
      3
      down vote

      favorite









      up vote
      3
      down vote

      favorite











      I am a fairly new (RubyonRails) developer. I desire to improve my coding skills so I used climate to do some review on my code. It gave me a flag for this method that its complex. Is it characterised as complex because of having several "actions/tasks" in a single method?



      Will it be better if I extract some code segments to a different method?



      Is there something else I am not seeing?



        def search
      filter_mapping = {"cost" => "rcost", "quality" => "rquality", "time" => "rtime", "experience" => "rexperience", "communication" => "rcommunication"}
      @filters = params[:filter].split(",") rescue
      @sort = params[:sort]

      @user_type = params[:s_user_type]
      @skills = params[:s_skills]
      @location = params[:location]
      @max_rate = params[:max_rate]
      @availability = params[:availability]

      @users = User.scoped.joins(:user_skills)
      @users = @users.where('user_type = ?', @user_type) if @user_type.present?
      @users = @users.where('user_skills.skill_id in (?)', @skills.map(&:to_i)) if @skills.present? && @skills.size > 0
      @users = @users.where('availability = ?', @availability) if @availability.present?
      @users = @users.where('location_country = ?', @location) if @location.present?
      @users = @users.where('rate < ?', @max_rate.to_i) if @max_rate.present?
      @users = @users.page(params[:page]).per(PER_PAGE)

      @filters.each do |f|
      if filter_mapping.keys.include?(f)
      @users = @users.order("#{filter_mapping[f]} desc")
      end
      end

      @users = @users.order('id asc') if @filters.empty?
      @advanced_link = @location.blank? && @max_rate.blank? && @availability.blank?
      render :index
      end


      Update



      I figured out that I can extract the scopes into a method like that:



        def get_users_where_scopes
      @users = User.scoped.joins(:user_skills)
      @users = @users.where('user_type = ?', @user_type) if @user_type.present?
      @users = @users.where('user_skills.skill_id in (?)', @skills.map(&:to_i)) if @skills.present? && @skills.size > 0
      @users = @users.where('availability = ?', @availability) if @availability.present?
      @users = @users.where('location_country = ?', @location) if @location.present?
      @users = @users.where('rate < ?', @max_rate.to_i) if @max_rate.present?
      @users = @users.page(params[:page]).per(PER_PAGE)
      end


      and then call it with @users = get_users_where_scopes(). But now the complexity of this method seems wrong to me.










      share|improve this question















      I am a fairly new (RubyonRails) developer. I desire to improve my coding skills so I used climate to do some review on my code. It gave me a flag for this method that its complex. Is it characterised as complex because of having several "actions/tasks" in a single method?



      Will it be better if I extract some code segments to a different method?



      Is there something else I am not seeing?



        def search
      filter_mapping = {"cost" => "rcost", "quality" => "rquality", "time" => "rtime", "experience" => "rexperience", "communication" => "rcommunication"}
      @filters = params[:filter].split(",") rescue
      @sort = params[:sort]

      @user_type = params[:s_user_type]
      @skills = params[:s_skills]
      @location = params[:location]
      @max_rate = params[:max_rate]
      @availability = params[:availability]

      @users = User.scoped.joins(:user_skills)
      @users = @users.where('user_type = ?', @user_type) if @user_type.present?
      @users = @users.where('user_skills.skill_id in (?)', @skills.map(&:to_i)) if @skills.present? && @skills.size > 0
      @users = @users.where('availability = ?', @availability) if @availability.present?
      @users = @users.where('location_country = ?', @location) if @location.present?
      @users = @users.where('rate < ?', @max_rate.to_i) if @max_rate.present?
      @users = @users.page(params[:page]).per(PER_PAGE)

      @filters.each do |f|
      if filter_mapping.keys.include?(f)
      @users = @users.order("#{filter_mapping[f]} desc")
      end
      end

      @users = @users.order('id asc') if @filters.empty?
      @advanced_link = @location.blank? && @max_rate.blank? && @availability.blank?
      render :index
      end


      Update



      I figured out that I can extract the scopes into a method like that:



        def get_users_where_scopes
      @users = User.scoped.joins(:user_skills)
      @users = @users.where('user_type = ?', @user_type) if @user_type.present?
      @users = @users.where('user_skills.skill_id in (?)', @skills.map(&:to_i)) if @skills.present? && @skills.size > 0
      @users = @users.where('availability = ?', @availability) if @availability.present?
      @users = @users.where('location_country = ?', @location) if @location.present?
      @users = @users.where('rate < ?', @max_rate.to_i) if @max_rate.present?
      @users = @users.page(params[:page]).per(PER_PAGE)
      end


      and then call it with @users = get_users_where_scopes(). But now the complexity of this method seems wrong to me.







      ruby ruby-on-rails active-record






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited yesterday









      200_success

      127k15149412




      127k15149412










      asked Apr 22 '14 at 12:15









      Stefanos.Ioannou

      1235




      1235






















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          1
          down vote



          accepted










          I'd say to first make a service object to keep the controller lean and clean, and to give yourself a place to put all the logic without fear of polluting the controller. Plus: It's reusable!



          # app/services/user_search.rb

          class UserSearch
          ORDER_MAPPING = {
          "cost" => "rcost",
          "quality" => "rquality",
          "time" => "rtime",
          "experience" => "rexperience",
          "communication" => "rcommunication"
          }.freeze

          def initialize(params)
          @params = params
          end

          def results
          @results ||= begin
          records = User.scoped.joins(:user_skills)
          records = scope(records)
          records = order(records)
          end
          end

          private

          def param(key)
          @params[key] if @params[key].present?
          end

          def scope(scoped)
          scoped = add_scope(scoped, 'user_type = ?', param(:user_type))
          scoped = add_scope(scoped, 'user_skills.skill_id in (?)', skill_ids)
          scoped = add_scope(scoped, 'availability = ?', param(:availability))
          scoped = add_scope(scoped, 'location_country = ?', param(:location))
          scoped = add_scope(scoped, 'rate < ?', max_rate)
          end

          def add_scope(scope, sql, *params)
          scope.where(sql, *params) if params.all?(&:present?)
          scope
          end

          def order(scope)
          terms = sanitized_order_terms || default_order_terms
          terms.each { |term| scope.order(term) }
          scope
          end

          def sanitized_order_terms
          terms = param(:filter).try(:split, ",")
          terms = terms.map { |term| ORDER_MAPPING[term] }
          terms = terms.compact
          terms if terms.any?
          end

          def default_order_terms
          ["id asc"]
          end

          def skill_ids
          param(:s_skills).try(:map, &:to_i)
          end

          def max_rate
          param(:max_rate).try(:to_i)
          end
          end


          I've intentionally kept the pagination in the controller, as it's pretty independent of the scoping and ordering. However, it'd be simple to add as arguments to the #results method



          In your controller:



          def search
          @users = UserSearch.new(params).results.page(params[:page]).per(PER_PAGE)

          advanced_params = %w(location max_rate availability).map { |p| params[p] }
          @advanced_link = advanced_params.all?(&:blank)

          render :index
          end


          I'd probably pick a more direct way of determining the @advanced_link, such as sending an advanced parameter along, and simply looking at that instead of the implicit state you have now.



          I have no idea what Code Climate thinks of the code above, but I imagine it'll be happier.






          share|improve this answer























          • what do you think of reusing the same name of variables to hold different values? for me it's a no-no...
            – tokland
            Apr 23 '14 at 8:39










          • @tokland If you're referring to the @advanced_link-thing in the controller, which is just me being lazy; I'll change that - thanks! But for the UserSearch class' methods it was a conscious choice. E.g. in #scope the scoped var does change, yes, but no more than it would if there was a self-modifying where! I could call on it. I just see it as breaking a where().where().where... chain up into single links. The value changes quantitatively, not qualitatively, so to speak. If it were anything else, I'd use different vars (like I should have done in the controller code)
            – Flambino
            Apr 23 '14 at 9:32













          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f47872%2ffiltering-users-by-criteria-in-ruby-on-rails%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          1
          down vote



          accepted










          I'd say to first make a service object to keep the controller lean and clean, and to give yourself a place to put all the logic without fear of polluting the controller. Plus: It's reusable!



          # app/services/user_search.rb

          class UserSearch
          ORDER_MAPPING = {
          "cost" => "rcost",
          "quality" => "rquality",
          "time" => "rtime",
          "experience" => "rexperience",
          "communication" => "rcommunication"
          }.freeze

          def initialize(params)
          @params = params
          end

          def results
          @results ||= begin
          records = User.scoped.joins(:user_skills)
          records = scope(records)
          records = order(records)
          end
          end

          private

          def param(key)
          @params[key] if @params[key].present?
          end

          def scope(scoped)
          scoped = add_scope(scoped, 'user_type = ?', param(:user_type))
          scoped = add_scope(scoped, 'user_skills.skill_id in (?)', skill_ids)
          scoped = add_scope(scoped, 'availability = ?', param(:availability))
          scoped = add_scope(scoped, 'location_country = ?', param(:location))
          scoped = add_scope(scoped, 'rate < ?', max_rate)
          end

          def add_scope(scope, sql, *params)
          scope.where(sql, *params) if params.all?(&:present?)
          scope
          end

          def order(scope)
          terms = sanitized_order_terms || default_order_terms
          terms.each { |term| scope.order(term) }
          scope
          end

          def sanitized_order_terms
          terms = param(:filter).try(:split, ",")
          terms = terms.map { |term| ORDER_MAPPING[term] }
          terms = terms.compact
          terms if terms.any?
          end

          def default_order_terms
          ["id asc"]
          end

          def skill_ids
          param(:s_skills).try(:map, &:to_i)
          end

          def max_rate
          param(:max_rate).try(:to_i)
          end
          end


          I've intentionally kept the pagination in the controller, as it's pretty independent of the scoping and ordering. However, it'd be simple to add as arguments to the #results method



          In your controller:



          def search
          @users = UserSearch.new(params).results.page(params[:page]).per(PER_PAGE)

          advanced_params = %w(location max_rate availability).map { |p| params[p] }
          @advanced_link = advanced_params.all?(&:blank)

          render :index
          end


          I'd probably pick a more direct way of determining the @advanced_link, such as sending an advanced parameter along, and simply looking at that instead of the implicit state you have now.



          I have no idea what Code Climate thinks of the code above, but I imagine it'll be happier.






          share|improve this answer























          • what do you think of reusing the same name of variables to hold different values? for me it's a no-no...
            – tokland
            Apr 23 '14 at 8:39










          • @tokland If you're referring to the @advanced_link-thing in the controller, which is just me being lazy; I'll change that - thanks! But for the UserSearch class' methods it was a conscious choice. E.g. in #scope the scoped var does change, yes, but no more than it would if there was a self-modifying where! I could call on it. I just see it as breaking a where().where().where... chain up into single links. The value changes quantitatively, not qualitatively, so to speak. If it were anything else, I'd use different vars (like I should have done in the controller code)
            – Flambino
            Apr 23 '14 at 9:32

















          up vote
          1
          down vote



          accepted










          I'd say to first make a service object to keep the controller lean and clean, and to give yourself a place to put all the logic without fear of polluting the controller. Plus: It's reusable!



          # app/services/user_search.rb

          class UserSearch
          ORDER_MAPPING = {
          "cost" => "rcost",
          "quality" => "rquality",
          "time" => "rtime",
          "experience" => "rexperience",
          "communication" => "rcommunication"
          }.freeze

          def initialize(params)
          @params = params
          end

          def results
          @results ||= begin
          records = User.scoped.joins(:user_skills)
          records = scope(records)
          records = order(records)
          end
          end

          private

          def param(key)
          @params[key] if @params[key].present?
          end

          def scope(scoped)
          scoped = add_scope(scoped, 'user_type = ?', param(:user_type))
          scoped = add_scope(scoped, 'user_skills.skill_id in (?)', skill_ids)
          scoped = add_scope(scoped, 'availability = ?', param(:availability))
          scoped = add_scope(scoped, 'location_country = ?', param(:location))
          scoped = add_scope(scoped, 'rate < ?', max_rate)
          end

          def add_scope(scope, sql, *params)
          scope.where(sql, *params) if params.all?(&:present?)
          scope
          end

          def order(scope)
          terms = sanitized_order_terms || default_order_terms
          terms.each { |term| scope.order(term) }
          scope
          end

          def sanitized_order_terms
          terms = param(:filter).try(:split, ",")
          terms = terms.map { |term| ORDER_MAPPING[term] }
          terms = terms.compact
          terms if terms.any?
          end

          def default_order_terms
          ["id asc"]
          end

          def skill_ids
          param(:s_skills).try(:map, &:to_i)
          end

          def max_rate
          param(:max_rate).try(:to_i)
          end
          end


          I've intentionally kept the pagination in the controller, as it's pretty independent of the scoping and ordering. However, it'd be simple to add as arguments to the #results method



          In your controller:



          def search
          @users = UserSearch.new(params).results.page(params[:page]).per(PER_PAGE)

          advanced_params = %w(location max_rate availability).map { |p| params[p] }
          @advanced_link = advanced_params.all?(&:blank)

          render :index
          end


          I'd probably pick a more direct way of determining the @advanced_link, such as sending an advanced parameter along, and simply looking at that instead of the implicit state you have now.



          I have no idea what Code Climate thinks of the code above, but I imagine it'll be happier.






          share|improve this answer























          • what do you think of reusing the same name of variables to hold different values? for me it's a no-no...
            – tokland
            Apr 23 '14 at 8:39










          • @tokland If you're referring to the @advanced_link-thing in the controller, which is just me being lazy; I'll change that - thanks! But for the UserSearch class' methods it was a conscious choice. E.g. in #scope the scoped var does change, yes, but no more than it would if there was a self-modifying where! I could call on it. I just see it as breaking a where().where().where... chain up into single links. The value changes quantitatively, not qualitatively, so to speak. If it were anything else, I'd use different vars (like I should have done in the controller code)
            – Flambino
            Apr 23 '14 at 9:32















          up vote
          1
          down vote



          accepted







          up vote
          1
          down vote



          accepted






          I'd say to first make a service object to keep the controller lean and clean, and to give yourself a place to put all the logic without fear of polluting the controller. Plus: It's reusable!



          # app/services/user_search.rb

          class UserSearch
          ORDER_MAPPING = {
          "cost" => "rcost",
          "quality" => "rquality",
          "time" => "rtime",
          "experience" => "rexperience",
          "communication" => "rcommunication"
          }.freeze

          def initialize(params)
          @params = params
          end

          def results
          @results ||= begin
          records = User.scoped.joins(:user_skills)
          records = scope(records)
          records = order(records)
          end
          end

          private

          def param(key)
          @params[key] if @params[key].present?
          end

          def scope(scoped)
          scoped = add_scope(scoped, 'user_type = ?', param(:user_type))
          scoped = add_scope(scoped, 'user_skills.skill_id in (?)', skill_ids)
          scoped = add_scope(scoped, 'availability = ?', param(:availability))
          scoped = add_scope(scoped, 'location_country = ?', param(:location))
          scoped = add_scope(scoped, 'rate < ?', max_rate)
          end

          def add_scope(scope, sql, *params)
          scope.where(sql, *params) if params.all?(&:present?)
          scope
          end

          def order(scope)
          terms = sanitized_order_terms || default_order_terms
          terms.each { |term| scope.order(term) }
          scope
          end

          def sanitized_order_terms
          terms = param(:filter).try(:split, ",")
          terms = terms.map { |term| ORDER_MAPPING[term] }
          terms = terms.compact
          terms if terms.any?
          end

          def default_order_terms
          ["id asc"]
          end

          def skill_ids
          param(:s_skills).try(:map, &:to_i)
          end

          def max_rate
          param(:max_rate).try(:to_i)
          end
          end


          I've intentionally kept the pagination in the controller, as it's pretty independent of the scoping and ordering. However, it'd be simple to add as arguments to the #results method



          In your controller:



          def search
          @users = UserSearch.new(params).results.page(params[:page]).per(PER_PAGE)

          advanced_params = %w(location max_rate availability).map { |p| params[p] }
          @advanced_link = advanced_params.all?(&:blank)

          render :index
          end


          I'd probably pick a more direct way of determining the @advanced_link, such as sending an advanced parameter along, and simply looking at that instead of the implicit state you have now.



          I have no idea what Code Climate thinks of the code above, but I imagine it'll be happier.






          share|improve this answer














          I'd say to first make a service object to keep the controller lean and clean, and to give yourself a place to put all the logic without fear of polluting the controller. Plus: It's reusable!



          # app/services/user_search.rb

          class UserSearch
          ORDER_MAPPING = {
          "cost" => "rcost",
          "quality" => "rquality",
          "time" => "rtime",
          "experience" => "rexperience",
          "communication" => "rcommunication"
          }.freeze

          def initialize(params)
          @params = params
          end

          def results
          @results ||= begin
          records = User.scoped.joins(:user_skills)
          records = scope(records)
          records = order(records)
          end
          end

          private

          def param(key)
          @params[key] if @params[key].present?
          end

          def scope(scoped)
          scoped = add_scope(scoped, 'user_type = ?', param(:user_type))
          scoped = add_scope(scoped, 'user_skills.skill_id in (?)', skill_ids)
          scoped = add_scope(scoped, 'availability = ?', param(:availability))
          scoped = add_scope(scoped, 'location_country = ?', param(:location))
          scoped = add_scope(scoped, 'rate < ?', max_rate)
          end

          def add_scope(scope, sql, *params)
          scope.where(sql, *params) if params.all?(&:present?)
          scope
          end

          def order(scope)
          terms = sanitized_order_terms || default_order_terms
          terms.each { |term| scope.order(term) }
          scope
          end

          def sanitized_order_terms
          terms = param(:filter).try(:split, ",")
          terms = terms.map { |term| ORDER_MAPPING[term] }
          terms = terms.compact
          terms if terms.any?
          end

          def default_order_terms
          ["id asc"]
          end

          def skill_ids
          param(:s_skills).try(:map, &:to_i)
          end

          def max_rate
          param(:max_rate).try(:to_i)
          end
          end


          I've intentionally kept the pagination in the controller, as it's pretty independent of the scoping and ordering. However, it'd be simple to add as arguments to the #results method



          In your controller:



          def search
          @users = UserSearch.new(params).results.page(params[:page]).per(PER_PAGE)

          advanced_params = %w(location max_rate availability).map { |p| params[p] }
          @advanced_link = advanced_params.all?(&:blank)

          render :index
          end


          I'd probably pick a more direct way of determining the @advanced_link, such as sending an advanced parameter along, and simply looking at that instead of the implicit state you have now.



          I have no idea what Code Climate thinks of the code above, but I imagine it'll be happier.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Apr 23 '14 at 9:33

























          answered Apr 22 '14 at 16:59









          Flambino

          31.6k23384




          31.6k23384












          • what do you think of reusing the same name of variables to hold different values? for me it's a no-no...
            – tokland
            Apr 23 '14 at 8:39










          • @tokland If you're referring to the @advanced_link-thing in the controller, which is just me being lazy; I'll change that - thanks! But for the UserSearch class' methods it was a conscious choice. E.g. in #scope the scoped var does change, yes, but no more than it would if there was a self-modifying where! I could call on it. I just see it as breaking a where().where().where... chain up into single links. The value changes quantitatively, not qualitatively, so to speak. If it were anything else, I'd use different vars (like I should have done in the controller code)
            – Flambino
            Apr 23 '14 at 9:32




















          • what do you think of reusing the same name of variables to hold different values? for me it's a no-no...
            – tokland
            Apr 23 '14 at 8:39










          • @tokland If you're referring to the @advanced_link-thing in the controller, which is just me being lazy; I'll change that - thanks! But for the UserSearch class' methods it was a conscious choice. E.g. in #scope the scoped var does change, yes, but no more than it would if there was a self-modifying where! I could call on it. I just see it as breaking a where().where().where... chain up into single links. The value changes quantitatively, not qualitatively, so to speak. If it were anything else, I'd use different vars (like I should have done in the controller code)
            – Flambino
            Apr 23 '14 at 9:32


















          what do you think of reusing the same name of variables to hold different values? for me it's a no-no...
          – tokland
          Apr 23 '14 at 8:39




          what do you think of reusing the same name of variables to hold different values? for me it's a no-no...
          – tokland
          Apr 23 '14 at 8:39












          @tokland If you're referring to the @advanced_link-thing in the controller, which is just me being lazy; I'll change that - thanks! But for the UserSearch class' methods it was a conscious choice. E.g. in #scope the scoped var does change, yes, but no more than it would if there was a self-modifying where! I could call on it. I just see it as breaking a where().where().where... chain up into single links. The value changes quantitatively, not qualitatively, so to speak. If it were anything else, I'd use different vars (like I should have done in the controller code)
          – Flambino
          Apr 23 '14 at 9:32






          @tokland If you're referring to the @advanced_link-thing in the controller, which is just me being lazy; I'll change that - thanks! But for the UserSearch class' methods it was a conscious choice. E.g. in #scope the scoped var does change, yes, but no more than it would if there was a self-modifying where! I could call on it. I just see it as breaking a where().where().where... chain up into single links. The value changes quantitatively, not qualitatively, so to speak. If it were anything else, I'd use different vars (like I should have done in the controller code)
          – Flambino
          Apr 23 '14 at 9:32




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f47872%2ffiltering-users-by-criteria-in-ruby-on-rails%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Mont Emei

          Province de Neuquén

          Journaliste