Search code examples
ruby-on-railsrubyruby-on-rails-4activerecordgon

Rails 4 - Remove attributes from an already filtered Active Record query


In one of my ruby on Rails 4 controller, I have a method that injects data necessary to a View.

The data needed vary between the data needed by the html and the data needed by the javascript. I am using gon to inject the data into the js scripts.

My app works fine but gon is injecting in the HTML (FYI in a script just below the body tag) too much data as I only need for Gon/Javascript 2 of the 5 attributes needed by the HTML view. (Reason for wishing that: As I load a lot of objects, the difference in bytes for the HTML file is very significant)

def inject_deal_steps_data
      # Used in html view     
      @steps = @deal.steps.select(:attribute1,
                                  :attribute2,
                                  :attribute3,
                                  :attribute4,                                             
                                  :attribute5). order(attribute4: :asc)

      # Used in js file
      gon.push( { deal_steps: @steps } ) if @steps
    end

I tried using methods such as unscope like below but it did not work.

def inject_deal_steps_data
          # Used in html view     
          @steps = @deal.steps.select(:attribute1,
                                      :attribute2,
                                      :attribute3,
                                      :attribute4,                                             
                                      :attribute5). order(attribute4: :asc)

          # Used in js file
          gon.push( { deal_steps: @steps.unscope(:attribute1,:attribute3,:attribute4 } ) if @steps
        end

I don't want to create another new selection like below as it creates a new request/hit on the database.

@steps = @deal.steps.select(:attribute1,
                                      :attribute2,
                                      :attribute3,
                                      :attribute4,                                             
                                      :attribute5). order(attribute4: :asc)
gon.push( { deal_steps: @deal.steps.select(:attribute2,:attribute5) } ) if @deal.steps

I want to re-use for GON the same @steps created for the HTML but remove 3 attributes from it.


Solution

  • You can use as_json to control what will be exposed by the to_json. gon calls to_json internally, in order to convert ruby object to javascript object and exposes it to the view.

    Try the following:

    def inject_deal_steps_data
      # Used in html view     
      @steps = @deal.steps.select(
        :attribute1,
        :attribute2,
        :attribute3,
        :attribute4,                                             
        :attribute5
      ).order(attribute4: :asc)
    
      # Used in js file
      gon.push({ 
        deal_steps: @steps.as_json(except: [:attribute1,:attribute3,:attribute4])
      }) if @steps
    end
    

    Review as_json for more information.