Thinking about logic Ruby

Embody what you want to do with code

It's easy to say in a word, but it's difficult to sung. I'll increase the number of expressions I can use, but rather I'm bound by the restrictions of what I've learned, and this can only be used like this, so many people are wondering how to do what they want to do in the code ... I'm still immature. , I have a lot of experiences like this. This time, I will summarize what I learned from the problems in my code for each case and organize my thoughts.

First, the expression is redundant

arr_year.rb


     date = []

     registerd_list.each do |data|
       date.push data.createdAt
     end

     cnt = 0
     date.each do |data|
       if date.year == data.year
         cnt += 1
       end
     end
     cnt

This is a substitute that loops the data of an object that inherits a certain Enumerable class, plunges the created date in the data into an array, and counts only those whose year corresponds to the present. .. This is fine, but

arr_year_kai.rb


registerd_list.select {|data| data.created_at.year == date.year}.size

It can be expressed in just one line. We are using the select and size methods here. ruby has quite a lot of methods that can be used for each class. There are quite a few methods for array manipulation.

class Array Ruby Reference

select method

Returns an array containing all the elements for which the value that evaluated the block was true for each element. Returns an empty array if none of the elements are true.

It's convenient. It is a method that has the ability of each and if to loop and put conditions in it.

size method

Returns the length of the array. Returns 0 if the array is empty.

It is the same expression as length or count.

You can chain methods with {} .size. It seems that you can also do end.size. With this, the processing of several lines of code can be crushed in just one line, both in the rabbit and in the corner. No, I'm afraid.

Secondly, there are many literal notations

What is the number used in a single shot, also called a magic number? When reading back the code that becomes, or when someone reads it, it is necessary to eliminate it as much as possible by saying that it is difficult to understand what this number represents, or to devise something such as giving meaning. There is.

Example of eliminating the magic number

magick_num.rb


 def self.get_year

     year = Time.new.year + 1
     years = []
     while year > 2017 do
       year = year - 1
       years.push year
     end
     years
   end

This is a process made to make a select form from 2017 to this year, but I think that it will be +1 or -1, but if you do not do this, it will come out from 2017 to this year. That's right. Since it is a Time object from this year.

improved_year.rb


 def self.get_years
     (2017..Time.new.year).to_a.reverse
   end

Yes, it was done in just one line. I am using to_a and reverse that use the range object and make the method chain there.

to_a method

Returns self. However, when called for an instance of a subclass of Array, it returns a conversion of itself to Array.

reverse method

reverse creates and returns a new array of its elements in reverse order. reverse! Sorts itself destructively. reverse! returns self.

By saying that, by re-arranging and reversing the elements, it has been possible to arrange it neatly from the latest year, and the magic number has also disappeared.

Compare days of the week with numbers

w.rb


      if full_week_of_one_month.wday ==  0
        calculation_result_of_amounts.push cnt
        cnt = 0
      else
        calculation_result_of_amounts.push " "
      end

The above is a part of the code when creating an array of calculation results, but I wanted to push only on a specific day of the week, so I use the day of the week in the conditional expression. In ruby, the day of the week is expressed as 1 is Monday and 0 is Sunday, so I wanted to judge Sunday, so I used 0, but it seems that this is 6.

w_kai.rb


      WEEK_SUNDAY = 0

      if full_week_of_one_month.wday ==  WEEK_SUNDAY
        calculation_result_of_amounts.push cnt
        cnt = 0
      else
        calculation_result_of_amounts.push " "
      end

In such a case, give meaning to the numbers and solve it. If you make it a constant, you can reuse it in another place. This will make it easier to understand what you mean by the comparison.

Third, understand initialization

Importance of initialization and assignment. It's natural enough to breathe, but it's easy to forget. The code below loops infinitely. That's because, of course, we haven't re-entered the year, so it's going to stay bigger than 2017.

infiniting_roop.rb


def self.get_year
     year = Time.new.year + 1

     while year > 2017 do
       year - 1
       p year
     end
   end

If you fix it, it will look like the following. If you put it back in the variable, the year -1 will be used as the year in the conditional expression when the next loop occurs, so you only have to subtract until the condition is reached using the number of years properly subtracted.

modified_roop.rb


def self.get_year
     year = Time.new.year + 1

     while year > 2017 do
       year = year - 1
       p year
     end
   end

Use of initialization

This is a part of the code that is processing to move to the count of the next week after aggregating the data for one week. It is a process that loops the outline for one month's date, creates a loop that aggregates the date for one week in it, pushes the data to the array when one week is reached, and initializes the count at this point. .. It is a translation that puts it in the loop as a conditional expression and returns the cnt numerical value to 0.

calk_date.rb


    cnt = 0
    amounts_of_calculation_result = []
    (beginning_week..last_week_of_next_month).each do |date|
      users_dates.each do |user_date|
        if date.year == user_date.year && date.day == user_date.day
            cnt += 1
        end
      end

      if date.wday ==  WEEK_SUNDAY
        amounts_of_calculation_result.push cnt
        cnt = 0
      end
    end
    amounts_of_calculation_result

No, it ’s difficult, it ’s complicated.

So, when thinking about logic, there are abundant methods, avoiding literal expressions or making sense, and using initialization to express what you want to do. It's about combining the expressions you get to create logic. I would like to output each time I do not forget the expressions that have become usable.

Recommended Posts

Thinking about logic Ruby
About Ruby symbols
About ruby ​​form
About Ruby arrays
About Ruby inheritance
About Ruby Hashes
About Ruby Symbols
About Ruby methods
About Ruby Kernel Module
About Ruby error messages
About Ruby Hashes (continued)
About eval in Ruby
[ruby] About here documents
About Ruby if statement
[Ruby] About instance generation
About the [ruby] operator
Explanation about Ruby Range object
About Ruby hashes and symbols
Ruby About various iterative processes
About Ruby and object model
Explanation about Ruby String object
About the behavior of ruby Hash # ==
About Ruby single quotes and double quotes
About Ruby product operator (&) and sum operator (|)
[Super Introduction] About Symbols in Ruby
About =
About object-oriented inheritance and about yield Ruby
[Ruby] Review about nesting of each
Explanation about Array object of Ruby
Have you stopped thinking about using BeanUtils.copyProperties?
[Ruby on Rails] About bundler (for beginners)
[Ruby on Rails] About Active Record callbacks
Ruby Gem Code Reading settings logic Part 1