Skip to content

Conversation

@hemahg
Copy link

@hemahg hemahg commented Dec 18, 2019

No description provided.

RackApp/app.rb Outdated
Comment on lines 55 to 71
if req.path.match('/users/hema') && req.params["tz"] == "IST"
user = User.new("hema")
time = CountryTime.new("Kolkata")
view = View.new(user, time)
['200', {"Content-Type" => "text/html"}, [view.render]]
elsif
req.path.match('/users/hery') && req.params["tz"] == "UTC"
user = User.new("Hery")
time = CountryTime.new("Eastern Time (US & Canada)")
view = View.new(user, time)
['200', {"Content-Type" => "text/html"}, [view.render]]
elsif
req.path.match('/users/Cadu') && req.params["tz"] == "AST"
user = User.new("Cadu")
time = CountryTime.new("Asia/Kuwait")
view = View.new(user, time)
['200', {"Content-Type" => "text/html"}, [view.render]]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those are quite similar, can you refactor?

RackApp/app.rb Outdated
Comment on lines 47 to 51
class WebApp
def initialize

end
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class does nothing sadly, can you remove or add logic there?

RackApp/app.rb Outdated
@@ -0,0 +1,85 @@
require 'erb'
require 'rack'
require 'active_support/all'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not need to require all active_support. Always require only the necessary library if it is small

RackApp/app.rb Outdated
require 'active_support/all'

class View
attr_reader :person, :time

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your editor is configured to use 4 spaces as indentation, for various reason and better readability use 2 spaces

<html>
<head>
<b>
persons nick name is <%= person.nickname%> and current time in the timezone is <%= time.timezone %>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add space inside the ERB tags

Suggested change
persons nick name is <%= person.nickname%> and current time in the timezone is <%= time.timezone %>
persons nick name is <%= person.nickname %> and current time in the timezone is <%= time.timezone %>

RackApp/app.rb Outdated
class Display
def self.call(env)
req = Rack::Request.new(env)
if req.path.match('/users/hema') && req.params["tz"] == "IST"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So those are static values, can you make them dynamic?:

  • Display what you have in path as the nickname
  • Select the Timezone from the tz parameter as timezone

RackApp/app.rb Outdated
require 'rack'
require 'active_support/all'

class View

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is more a controller than a view

RackApp/app.rb Outdated
@@ -0,0 +1,71 @@
require "erb"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to use rubocop to check for code styling ;)
You can make another commit for it

Example, rubocop will tell you to not forget about # frozen_string_literal: true

Some good reads why we use such tools: https://rubystyle.guide/

Also about the magic comment frozen_string_literal: true

https://www.mikeperham.com/2018/02/28/ruby-optimization-with-one-magic-comment/

This might go probably in Ruby 3.0 default https://bugs.ruby-lang.org/issues/11473 (still in discussion)

RackApp/app.rb Outdated
nickname = req.params["nickname"]
tz = req.params["tz"]
if req.path.match("/users") && nickname && tz
user = User.new("#{nickname}")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can avoid String interpolation by using above nickane = params['nickname'].to_s and son on

end

class CountryTime
attr_reader :zone, :timezone
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attr_reader method creates a getter method within CountryTime class, getter class means/looks like this:

def timezone
  @timezone 
end

so by defining def timezone again, you're rewriting the created getter created by attr_reader :timezone

so either you use the created getter or create your own:

  1. created getter by attr_reader :timezone
class CountryTime

  attr_reader :zone, :timezone

  def initialize(zone)
    @zone = zone
    Time.zone = zone
    @timezone = Time.zone.now
  end
end
  1. manually created "getter" by a method
class CountryTime
  attr_reader :zone

  def initialize(zone)
    @zone = zone
  end

  def timezone
    Time.zone = zone
    Time.zone.now
  end
end

I would prefer the first way in this case, so timezone is being generated only once, it the second case you would generate the timezone in every method call.

if req.path.match('/users') && nickname && tz && f
user = User.new(nickname.to_s)
time = CountryTime.new(tz.to_s)
view = MyController.new(user, time)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why time is being sent to MyController as a parameter and then never used?

also format could be another parameter and then you would call just view.render

RackApp/app.rb Outdated
puts env.inspect
nickname = req.params['nickname']
tz = req.params['tz']
f = req.params['f']
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

f is not the ideal name for a variable.. the code should be readable as a book, so the variable names should make some sense.. timezone instead of tz, format instead of f

RackApp/app.rb Outdated
end

def file(format)
File.read(File.join(__dir__, "template.#{format}.erb"))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can take it a bit forward and check if the file actually exists.. if not, we can throw some meaningful error.

do you know how to do it? or should I help you for a bit? :)

RackApp/app.rb Outdated
Comment on lines 15 to 21
def file(format)
File.read(File.join(__dir__, "template.#{format}.erb"))
end

def template(format)
ERB.new(file(format))
end
Copy link

@hallelujah hallelujah Jan 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like belonging to another class, name it View or Template

Something like that

class MyController
  # This next line could be extracted to a BaseController :)
  class_attribute :template_name, instance_writer: false
  template_name 'template'
  

  def template(format)
    Template.new(template_name, format)
  end
end

  # rest of the code

 class Template

   def initialize(name, format)
     @erb = file(name, format)
  end
 
  def file(name, format)
     File.read(File.join(__dir__, 'templates', "#{name}.#{format}.erb"))
  end
 end

personname = 'hema'
Time.zone = 'UTC'
puts @timezone = Time.zone.now
data = <<-HTML
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comparing the whole website is not the best idea. You would need to change this test every time you change a view HTML. Better to use https://apidock.com/ruby/Test/Unit/Assertions/assert_match and check for just small strings, something like:

assert_match "name is #{personname} and current", last_response.body

got the idea?


def test_pagenotfound
get '/users/nickname'
assert_equal last_response.body, '<html><body><b><em>404 Page not found</em></b></body></html>'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the same as: 0c74d6c#r374548506

just check for 404 Page not found.

Copy link

@macejmic macejmic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are integration tests, there are useful to check "response" behaviour as you did.. user should see this message and HTML should include this and that.. but along with integration tests would be good to add some unit tests too.

something like: https://en.wikibooks.org/wiki/Ruby_Programming/Unit_testing

if File.exist?(file_path)
File.read(file_path)
else
'ERROR:The file doesnot exist'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

raise an error instead ;)
Otherwise the result of the file will be displayed to the User
It is better to catch the error when it is really necessary and not assuming what it should do

def call(env)
@app&.call(env)
req = Rack::Request.new(env)
puts env.inspect

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove this when you are done

assert_equal last_response.body, '<html><body><b><em>404 Page not found</em></b></body></html>'
end

def test_undefinedfileformat

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use underscores to separate words

end
end

class View
Copy link

@hallelujah hallelujah Feb 17, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normally I would like this class to be tested

def initialize(zone)
@zone = zone
Time.zone = zone
@timezone = Time.zone.now

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not get this, Time.zone.now will return an instance of Time.

Though the name timezone is in fact equal to zone

timezone = req.params['timezone']
format = req.params['format']
nickname_match = req.path.match('/users/nickname/(\w+)')
nickname = nickname_match[1] if nickname_match

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
nickname = nickname_match[1] if nickname_match
nickname = $1

end
end

class CountryTime

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to test this class

What if I send an invalid timezone?

user = User.new(nickname)
time = CountryTime.new(timezone.to_s)
view = MyController.new(user, time)
['200', { 'Content-Type' => response_format(format) }, [view.render_template(format)]]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if I send an invalid format?

format = req.params['format']
nickname_match = req.path.match('/users/nickname/(\w+)')
nickname = nickname_match[1] if nickname_match
if nickname && timezone && format

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should check about validity of the data more than the presence

end

def test_jsonoutput
puts Time.zone = 'UTC'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are assigning Time.zone to 'UTC', is it intended?


def test_jsonoutput
puts Time.zone = 'UTC'
puts @timezone = Time.zone.now

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove the debugging lines when all is clean


def test_undefinedfileformat
get '/users/nickname/hema?timezone=UTC&format=xtml'
assert_equal last_response.body, 'ERROR:The file doesnot exist'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect a status code 415 if the format does not exist

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants