nupac
nupac

Reputation: 2489

Ruby on Rails filter array using three fields

I am trying to search through my model using 3 columns. Also if the column is empty, it is valid. This is how I am doing it

def getactivityfortoday
@temp = params[:temp]
logger.debug "params temp:#{@temp.inspect}"
@sky = params[:sky]
@day = params[:day]
@todaysactivities = []
@activities=[]
@finaldata = []
@activities = Weatherclockactivity.all
@attemptactivities = []
@attemptactivities = @user.attempts
for activity in @activities do
  logger.debug "activity: #{activity.attributes.inspect}"
  if @temp.to_i < activity.temperatureMax.to_i && @temp.to_i > activity.temperatuureMin.to_i
    if @sky == activity.sky || activity.sky == ""
      if @day == activity.day 
        @todaysactivities << activity
      end
    end
  end
end
for activity in @todaysactivities
  for attempt in @attemptactivities
    if attempt == activity
      finaldata << {activity: activity, attempt: "yes"}
    else
      finaldata << {activity: activity, attempt: "no"}
    end
  end
end

respond_to do |format|  
    format.html { render action: "new" }
    format.json { render json: @finaldata }
end

The response I get is an empty array but I should be getting 3 rows as a response.

Upvotes: 0

Views: 361

Answers (3)

engineersmnky
engineersmnky

Reputation: 29318

spelling mistake here

activity.temperatuureMin.to_i  

And

finaldata << {activity: activity, attempt: "yes"}

should be

@finaldata << {activity: activity, attempt: "yes"}

Also you could be more concise

def getactivityfortoday
  @temp = params[:temp]
  logger.debug "params temp:#{@temp.inspect}"
  @sky = params[:sky]
  @day = params[:day]
  @activities = Weatherclockactivity.all
  @attemptactivities = @user.attempts
  @finaldata = @activities.map do |activity|
    if (activity.temperatureMin.to_i + 1...activity.temperatureMax.to_i).include?(@temp.to_i)  && ( @sky == activity.sky || activity.sky == "") && @day
       @attemptactivities.include?(activity) ? {activity: activity, attempt: "yes"} : {activity: activity, attempt: "no"}  
    end 
  end.compact
  respond_to do |format|  
    format.html { render action: "new" }
    format.json { render json: @finaldata }
  end
end

Upvotes: 1

nikolayp
nikolayp

Reputation: 17919

The best and flexible way is to use ActiveModel::Model It allows you to use many more useful methods. it will seems like: app/models/activity_report.rb

Class ActivityReport
  include ActiveModel::Model

  attr_accessor :day, :activity # and etc.

  validates :day, presence: true

  def day
    @day.to_s # for example
  end

  def day=(value)
    @day = value - 1.month # for example every date which user set will set on one month ago
  end

  # and etc
end

app/controllers/posts_controller.rb

...
def index
  @activity = ActivityReport.new(params[:activity])
end

def create
  @activity.create!
end
...

app/views/posts/index.html.haml

= form_for @activity do |f|
  = f.day

For more information you could take a look at: http://edgeapi.rubyonrails.org/classes/ActiveModel/Model.html
http://railscasts.com/episodes/219-active-model (old)
http://railscasts.com/episodes/416-form-objects (newer, but a little complex)

Upvotes: 0

Sherwin Yu
Sherwin Yu

Reputation: 3230

How about something like this?

I tried to make it a balance of readability and conciseness. First we filter for the desired activities. Then we structure the output. This should be easier to debug.

def getactivityfortoday
  @temp = params[:temp].to_i
  @sky = params[:sky]
  @day = params[:day]

  @activities = Weatherclockactivity.all

  @attemptactivities = @user.attempts

  selected_activities = @activities.select do |activity|
    # Make sure it's the right temperaure
    return false unless (activity.temperatureMin.to_i + 1 ... activity.temperatureMax.to_i).include? @temp

    # Make sure the sky matches, or the sky is blank
    return false unless (@sky.blank? || @sky.activity == activity.sky)

    # Make sure the day matches
    return false unless @day == activity.day

    # Otherwise, it's good!
    return true
  end

  selected_attempted_activities = selected_activities.map do|activity| 
    ret = {activity: activity}
    ret[:attempt] = @attemptactivities.include?(activity) ? "yes" : "no"
    ret
  end

  respond_to do |format|  
    format.html { render action: "new" }
    format.json { render json: selected_attempted_activities }
  end
end

There are a few typos in your original (for instance, @finaldata not finaldata). Make sure that you spell instance variables (things starting with @, like @sky) correctly, since if you try to access an undefined instance variable, it'll silently default to nil.

Upvotes: 0

Related Questions