My classes can't use Shoes methods like para

2020-04-20 08:23发布

问题:

Tldr: how do I 'include Shoes methods' into the Array class and classes ive created, with minimal code, without totally restructuring everything?

I've written a functioning program in Ruby, and now I want to make a Shoes app from it.

I'm having the problem described at the beginning of the manual - Shoes.app is a sort of block in itself, so self always refers to it, and Shoes methods like "para" aren't necessarily going to be available everywhere the way "puts" is in Ruby. But I'm not smart enough to fix it (I've only just got my head around using self and return in pure Ruby, bear with me)

For example, I've created a new method for Array: putdata, which loops through a student's test score array displaying each automatically as a list:

self.each do |ea|
    puts/para "#{ea.topic}: #{ea.score}"
end

Works in ruby. Doesn't work in Shoes: Array class doesn't have access to the method para. I've tried:

  • making Array < Shoes (it really doesn't like that)
  • adding stack.app do...end at various places in the program (no impact)
  • trying to call Shoes::para instead of para (farts)
  • I've tried using require 'file with all my classes and methods in.rb' instead of the same code in the file (reports no method for class)
  • tried requiring my code directly before calling a method, to ensure my code is in the scope of Shoes (reports no method for class)
  • making my custom classes (Course and Student) < Shoes, so it'd have access to its methods (causes a runtime error)

I've got it to function by: 1. Removing this bit of code from the Array class, and making it a floating/generic method rather than an Array method 2. Private method error --> then rephrasing it so instead of an Array method (array.putdata) it's a generic method which takes an array as an argument (putdata(array))

But I really, really don't want to go through my code and individually un-organise it like this.

It's my first 1000 line program, with 42 methods, and I worked hard on making it as maintainable and neat as possible, with everything tucked away in classes or methods for easy upkeep. I got it from everything in massive, step-by-step generic methods down to lots of snappy ones, which seemed a bit more like how OOP is meant to go. Now the only way I can see to make this work is to UN-OOP it, and have no class methods or anything.

I was hoping I could Shoes the program fairly seamlessly from this tidy, functional back-end: the Ruby program has lots of "if string == "SAVE", save(student); else...", so I was hoping to straightforwardly pop in "button.click {save(student)}" with the same back code.

#

Is there something fundamental I'm missing to let me do this? And can I fix the para problem easily, seeing as all my classes contain ways of displaying their own data? I'd like to copypasta "include 'Shoes methods'" at the top of each class and be done.

Or do I need to be writing with the GUI in mind from the start in future?

(Info about my program:

Layout is a series of pages, linked from a sidebar, using index with linked pages as copied straight from the Nobody Knows Shoes book, or the class-book sample.

Students can input their new levels, and view a readout of their current progress.

There are generic methods for major "parts" of the program, which have things like the title of the page and some instructions, and which then call on student objects or Module methods to do the things as instructed by the user.

Higher up: student is a custom class, with methods like "save", "display flattened data ", "add one to your level IF this ELSE don't", and associated bits of data, like an array with all their course objects in.

Each course is also a custom class ("Module"), which has the score, the module name etc as variables, and some tiny methods like display formatted name, or add one to this module.)

回答1:

I'm glad to see a question about shoes, it's been a long time. You'r new on SO so first: your question is way too elaborated, too much to read and far too little information to help you. You need to provide piecess of code that give error or don't do what you expect, things we can take over and try. This means extracting from your code tests or pieces of code that run by themself and show the problem.

We also need to know which Ruby version and which version and color of shoes you are using. The example I'll be using is green shoes.

I'm sure the following isn't exactly what you were after but I've made a sample based on your description of an Array that needs to be listed both by puts and para.

Change the question or make a new one if this is not what you are after.

require 'green_shoes'

s = Struct.new(:topic, :score)
s1 = s.new("test1", 1)
s2 = s.new("test2", 2)
A = [s1, s2]

class Array
  def putsdata(shoes = nil)
    if shoes.class == Shoes::App
      self.each do |ea|
        shoes.para "#{ea.topic}: #{ea.score}"
      end
    else
      self.each do |ea|
        puts "#{ea.topic}: #{ea.score}"
      end
    end
  end
end

A.putsdata

# gives in the console
# test1: 1
# test2: 2

Shoes.app do
  A.putsdata(self)
end

# gives in a graphic window
# test1: 1
# test2: 2

The puts also works in the shoes block, but of course the result doesn't come in the graphic window but on the console where you started, after the first list.



标签: ruby shoes