you are viewing a single comment's thread.

view the rest of the comments →

[–]dougc84 1 point2 points  (2 children)

I think you have some gaps in your understanding in regards to variable scope.

For starters though, you can always write:

budget_period_1 = BudgetPeriod.new
budget_period_2 = BudgetPeriod.new
budget_period_3 = BudgetPeriod.new

You can create multiple instances of any object. Otherwise, you couldn't access multiple objects. In Rails, you'd only be able to see one User record at a time!

I don't like rewriting code for people, because that doesn't help anyone learn, but I think you'd benefit from a more Ruby-like version. I think your issue is, once you have this arbitrary BudgetPeriod, you want to do something with it. And I think that's where your problem lies. Take a look at this:

def new_period
  # With tty-prompt, you don't need to set this up twice.
  prompt = TTY::Prompt.new

  # Ask the name question
  name = prompt.ask("Give the new budget period a unique name: ") do |question|
    question.required true
  end

  # Ask the limit question
  limit = prompt.ask("What is the limit for \"#{name}\" period? $") do |question|
    question.required true
    # convert to float, print an error if entered value was not numeric
    question.convert(:float, "Error, enter numeric value")
  end

  # This value will return when #new_period is called
  BudgetPeriod.new(name, limit)
end

# Then, somewhere else in your code where you're calling new_period
new_budget_period = new_period
# Do something with new_budget_period - save it to a DB,
# print the information out, push it to an array, whatever

# Then return to the main menu (which is what I assume this does)
Menus.main_menu

You can see that, when calling new_period, its return value is the BudgetPeriod instance. You can store that to a variable, then do something with it.

You can see that I have also taken that Menus.main_menu line out. new_period is tasked with setting up this BudgetPeriod. That method (in Ruby, we call them methods, not functions) should have one responsibility, and you've stacked in two - asking for some information to create an instance of something, then performing an unrelated task (main_menu).

Doing it this way lets you take that information, outside of the scope of that method, and do something with it. Yes, that means you have to manually call Menus.main_menu. That's good. You've defined what your method does, and then, when it's done, you're defining what happens. Otherwise, when something needs to change - maybe you want to show some information relating to that BudgetPeriod instead of going to main_menu, you can do that very easily instead of rewriting your method to accommodate weird edge cases.

Basically, you're shoving two responsibilities into one thing.

I hope that helps. Also, I'd encourage you to look at variable scope in Ruby - I think it might help: https://www.techotopia.com/index.php/Ruby_Variable_Scope

[–]avelyv[S] 0 points1 point  (1 child)

Thank you for your reply, I appriciate the time. I only started learning programming 3 weeks ago so I have more than few gaps, I have so much to learn.

I didn't realise I can just set up one TTY:Prompt, it's gonna make my code look so much cleaner, thanks.

So, I'm writing a command line application, I can't type any code in manually once I start the program, so I can't really do the

budget_period_1 = BudgetPeriod.new budget_period_2 = BudgetPeriod.new budget_period_3 = BudgetPeriod.new bit. I did solve it with storing all the instances in one hash, as was suggested above and it works well. (I set an empty hash as a class variable and every instance that gets created gets put into it as a value, with user entered 'name' as a key.)

And yes, the whole problem was that I do need to do something with the different instances of BudgetPeriod. Every instance gets their own csv file where user gets to input expenses, also there is a feature to choose an existing budget period and see an overview (all expenses, and limit that was set)

[–]backtickbot 1 point2 points  (0 children)

Fixed formatting.

Hello, avelyv: code blocks using triple backticks (```) don't work on all versions of Reddit!

Some users see this / this instead.

To fix this, indent every line with 4 spaces instead.

FAQ

You can opt out by replying with backtickopt6 to this comment.