草庐IT

java - 如何使 JavaCompiler.CompilationTask 使用自定义 ClassLoader 或将 .class 文件用于 missin .java 文件?

coder 2024-04-05 原文

更具体:我自己写了ClassLoader , 加载

  1. .jar来自全局库路径的文件
  2. .jar来自项目特定路径的文件
  3. 编译.java项目特定路径中的文件
  4. 加载所有.class项目特定路径中的文件

到目前为止,这分离了我的项目实例,从所有(子)目录加载一切正常,适用于 (1) 所有库和 (2) 子库,(3) 可以编译所有 .java文件,(4) 可以加载 .class文件,我还可以重新实例化已经加载的类,因为我的 ClassLoader管理子ClassLoader允许这样做。

现在,我想改进的是,在 (3) 处调用编译器时,我不想.java 重新编译一次目录中的文件,但只有那些,其中对应的 .class文件不存在或时间戳错误。

所以我只传递那些 .java需要重新编译的文件,而不是全部,结果是编译器无法找到所有需要的类(在我没有传递给他编译的那些 .java 文件中)。相反,编译器应该从我的类加载器中获取它缺少的编译信息(.class 文件而不是 .java 文件),它已经加载了那些 .class 文件。文件。

为了意识到这一点,我实现了自己的 FileManager ,我传递给 JavaCompiler.getTask() .在那个习俗中 FileManager ,我在 FileManager.getClassLoader() 返回我的 ClassLoader .

应该是这样的:

  1. .jar来自全局库路径的文件
  2. .jar来自项目特定路径的文件
  3. 只编译一些 .java项目特定路径中的文件,从 .class 加载缺少的类定义文件(由我的特定 ClassLoader 加载)
  4. 加载所有.class项目特定路径中的文件

但是JavaCompiler.CompilationTask运行,它从不访问我的 ClassLoader 的 .loadClass().findClass()方法,因此没有找到必要的 .class文件,因此“抛出”我一个编译错误。 (即我得到诊断,并将它们转换为异常)

所以,我的实际问题是:

  • 我的概念有问题吗?
  • 有可能吗?或者是编译器无法使用 .class文件而不是 .java文件?
  • 有什么卑鄙的把戏吗?

好的,所以我要发布我编写的部分代码,但这使用了我的很多库和更多的内部类,所以你不会让这段代码工作!!

另请注意,这要复杂得多,因为我存储了很多额外的信息,而我要求的任务不需要这些信息。

因此以此为指导。 基本上,您可以省去我在 Maps/Multimaps 中存储数据的所有信息处理,它们主要用于跟踪资源。

此外,JcDirLoader 不必为工作扩展 ClassLoader,这也是为“更高”目的而设计的;-) 而且ClassLoader之间相互调用的方式也可以大大简化!

package jc.lib.lang.reflect.loader;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;

import com.sun.org.apache.xalan.internal.xsltc.compiler.CompilerException;

import jc.lib.collection.list.JcList;
import jc.lib.collection.map.JcHashMap;
import jc.lib.collection.map.JcMultiMap;
import jc.lib.io.files.finder.JcFileFinder;
import jc.lib.lang.JcUFile;
import jc.lib.lang.JcUFileType;
import jc.lib.lang.reflect.classfileanalyzer.JcClassFileInfo;
import jc.lib.lang.reflect.compiler.JcJavaFileCompiler;
import jc.lib.lang.reflect.loader.classes.JcClassFileLoader;
import jc.lib.lang.reflect.loader.classes.JcUClassLoader;
import jc.lib.lang.reflect.loader.jars.JcUJarfileLoader;
import jc.lib.lang.reflect.loader.util.ClassName;
import jc.lib.lang.reflect.loader.util.ClassState;
import jc.lib.lang.reflect.loader.util.JcClassLoaderInfo;



public class JcDirLoader extends ClassLoader {



    private final JcHashMap<File, ClassName>                mFile2Classname         = new JcHashMap<>();
    private final JcHashMap<ClassName, JcClassLoaderInfo>   mClassname2Classinfo    = new JcHashMap<>();

    private final JcMultiMap<ClassName, JcClassFileLoader>  mClassname2Loaders      = new JcMultiMap<>();
    private final ArrayList<JcClassFileLoader>              mAvailableFileLoaders   = new ArrayList<>();

    private final ClassLoader mParentLoader;

    public JcDirLoader() {
        //      super(JcUClassLoader.getThreadContextClassLoader());
        // JcDirLoader.class.getClassLoader();
        mParentLoader = JcUClassLoader.getThreadContextClassLoader();
    }



    public JcList<JcClassLoaderInfo> getLoadedClasses() {
        final JcList<JcClassLoaderInfo> ret = new JcList<>(mClassname2Classinfo.values());
        return ret;
    }

    public Class<?> forName(final ClassName pClassName) throws ClassNotFoundException {
        final JcClassLoaderInfo ret = mClassname2Classinfo.get(pClassName);
        if (ret != null) return ret.mClass;

        final Class<?> ret2 = mParentLoader.loadClass(pClassName.toString());
        return ret2;
    }

    public JcClassLoaderInfo getClassInfo(final ClassName pClassName) {
        return mClassname2Classinfo.get(pClassName);
    }
    public ArrayList<JcClassLoaderInfo> getClassInfos() {
        return new ArrayList<>(mClassname2Classinfo.values());
    }



    public void loadDirectory(final File pDir) throws ClassNotFoundException, IOException, CompilerException {
        // collect all files
        final JcList<File> files = JcFileFinder.findInDir(pDir, true);
        final JcList<File> jarFiles = new JcList<>();
        final JcList<File> classFiles = new JcList<>();
        final JcList<File> javaFiles = new JcList<>();
        for (final File file : files) {
            if (JcUFileType.isJavaPackedFile(file)) jarFiles.addItem(file);
            if (JcUFileType.isJavaClassFile(file)) classFiles.addItem(file);
            if (JcUFileType.isJavaSourceFile(file)) javaFiles.addItem(file);
        }

        // handle .jar files
        handleJars(jarFiles);

        // compile .java files
        final boolean reloadNecessary = handleJavaFiles(javaFiles, jarFiles);
        if (reloadNecessary) {
            classFiles.removeAllItems();
            final JcList<File> files2 = JcFileFinder.findInDir(pDir, true);
            for (final File file : files2) {
                if (JcUFileType.isJavaClassFile(file)) classFiles.addItem(file);
            }
        }

        // handle .class files
        handleClassFiles(classFiles);
    }



    /*
     * .jar files
     */
    private void handleJars(final JcList<File> pAvailableJarFiles) throws MalformedURLException, IOException {
        System.out.println("\tLoading " + pAvailableJarFiles.getItemCount() + " .jar files:");
        final JcList<JcClassLoaderInfo> loadedClasses = JcUJarfileLoader.loadJars(pAvailableJarFiles);
        for (final JcClassLoaderInfo ci : loadedClasses) {
            mFile2Classname.put(ci.mContainingFile, ci.mClassName);
            mClassname2Classinfo.put(ci.mClassName, ci);
        }
        for (final File file : pAvailableJarFiles) {
            System.out.println("\t\t" + file + " OK");
        }
        System.out.println("\t\tAll OK");
    }



    /*
     * .class files
     */
    private ArrayList<Class<?>> handleClassFiles(final JcList<File> pClassFiles) throws FileNotFoundException, IOException, ClassNotFoundException {
        System.out.println("\tLoading " + pClassFiles.getItemCount() + " .class files:");

        for (final File file : pClassFiles) {
            final JcClassFileInfo cfi = new JcClassFileInfo(file);
            final ClassName className = ClassName.fromClassFileInfo(cfi);

            final JcClassLoaderInfo info = new JcClassLoaderInfo(null, file, className, null, ClassState.CLASS_FILE, file.lastModified(), null);
            mFile2Classname.put(file, className);
            mClassname2Classinfo.put(className, info);
        }

        final ArrayList<Class<?>> ret = new ArrayList<>();
        for (final File file : pClassFiles) {
            final Class<?> cls = handleClassFile(file);
            ret.add(cls);
        }

        System.out.println("\t\t" + pClassFiles.getItemCount() + " .class files loaded.");
        return ret;
    }
    private Class<?> handleClassFile(final File pFile) throws FileNotFoundException, IOException, ClassNotFoundException {
        final JcClassFileInfo cfi = new JcClassFileInfo(pFile);
        final ClassName className = ClassName.fromClassFileInfo(cfi);
        final JcClassLoaderInfo existing = mClassname2Classinfo.get(className);
        if (!needsReloading(existing, pFile)) return existing.mClass;

        final JcClassFileLoader fileLoader = getCompatibleFileLoader(className);
        fileLoader.setInfo(pFile, className);
        final Class<?> c = fileLoader.loadClass(className.toString());

        final JcClassLoaderInfo info = new JcClassLoaderInfo(null, pFile, className, c, ClassState.CLASS_FILE, pFile.lastModified(), fileLoader);
        mFile2Classname.put(pFile, className);
        mClassname2Classinfo.put(className, info);

        return c;
    }
    static private boolean needsReloading(final JcClassLoaderInfo pExisting, final File pNewFile) {
        if (pExisting == null) return true;
        if (pExisting.mClass == null) return true;
        if (!pNewFile.equals(pExisting.mContainingFile)) return true;
        if (pNewFile.lastModified() != pExisting.mContainingFile.lastModified()) return true;
        return false;
    }



    /*
     * .java files
     */
    private boolean handleJavaFiles(final JcList<File> pJavaFiles, final JcList<File> pAvailableJarFiles) throws IOException, CompilerException {
        System.out.println("\tChecking " + pJavaFiles.getItemCount() + " .java files:");

        final boolean recompile = needRecompiling(pJavaFiles);
        if (!recompile) {
            System.out.println("\t\tNo Java files needed recompiling.");
            return false;
        }

        final JcList<File> javaFilesToCompile = pJavaFiles;

        // info
        System.out.print("\t\tRecompiling files: ");
        for (final File file : javaFilesToCompile) {
            System.out.print(file.getName() + " ");
        }
        System.out.println();

        // recompile
        final String[] jarFileNames = new String[pAvailableJarFiles.getItemCount()];
        for (int i = 0; i < pAvailableJarFiles.getItemCount(); i++) {
            final File jarFile = pAvailableJarFiles.getItem(i);
            jarFileNames[i] = jarFile.getAbsolutePath();
        }
        JcJavaFileCompiler.compileFiles(pJavaFiles.toArray(), this, jarFileNames);

        // set time of compiled files to match dates
        for (final File f : pJavaFiles) {
            final long timestamp = f.lastModified();
            final File cls = getClassfileForSourcefile(f);
            cls.setLastModified(timestamp);
        }

        // return results
        final JcList<JcClassLoaderInfo> ret = new JcList<>();
        for (final File file : javaFilesToCompile) {
            final File classFile = getClassfileForSourcefile(file);
            if (!classFile.exists()) throw new FileNotFoundException("File '" + classFile.getAbsolutePath() + "' could not be found, but was compiled from '" + file.getAbsolutePath() + "'!");

            final JcClassLoaderInfo ci = new JcClassLoaderInfo(file, classFile, null, null, ClassState.JAVA_FILE, classFile.lastModified(), null);
            ret.addItem(ci);
        }

        System.out.println("\t\t" + pJavaFiles.getItemCount() + " Java files recompiled.");
        return true;
    }
    static private boolean needRecompiling(final JcList<File> pJavaFiles) {
        for (final File file : pJavaFiles) {
            if (!JcUFileType.isJavaSourceFile(file)) continue;

            final long sourceDate = file.lastModified();
            final File classFile = getClassfileForSourcefile(file);
            final long classDate = !classFile.exists() ? 0 : classFile.lastModified();
            if (sourceDate > classDate) return true;
        }

        return false;
    }

    private JcClassFileLoader getCompatibleFileLoader(final ClassName pClassName) {
        // check if can re-use another existing loader
        final HashSet<JcClassFileLoader> oldLoaders = mClassname2Loaders.getUniqueValues(pClassName);
        for (final JcClassFileLoader loader : mAvailableFileLoaders) {
            if (oldLoaders.contains(loader)) continue;

            mClassname2Loaders.put(pClassName, loader);
            //          System.out.println("\tUsing " + loader + " for " + pClassName);
            return loader;
        }

        // create new loader
        final JcClassFileLoader newLoader = new JcClassFileLoader(mParentLoader, this);
        mAvailableFileLoaders.add(newLoader);
        mClassname2Loaders.put(pClassName, newLoader);
        //      System.out.println("Created new " + newLoader + " for " + pClassName);
        return newLoader;
    }



    static public File getClassfileForSourcefile(final File pSourceFile) {
        final String classFilename = JcUFile.toString(pSourceFile, true, true, true, false) + JcUFileType.CLASS_EXTENSION;
        final File classFile = new File(classFilename);
        return classFile;
    }



    @Override public Class<?> loadClass(final String pClassname) throws ClassNotFoundException {
        System.out.println(" -> JcDirLoader.loadClass(" + pClassname + ")");
        try {
            final ClassName cn = ClassName.fromString(pClassname);
            final JcClassLoaderInfo ci = getClassInfo(cn);
            if (ci == null) return mParentLoader.loadClass(pClassname);

            final File f = ci.mContainingFile;
            final Class<?> cls = handleClassFile(f);
            return cls;

        } catch (final Exception e) {
            throw new ClassNotFoundException(pClassname, e);
        }
    }

    @Override public Class<?> findClass(final String pClassname) throws ClassNotFoundException {
        System.out.println(" -> JcDirLoader.findClass(" + pClassname + ")");

        final ClassName cn = ClassName.fromString(pClassname);
        final JcClassLoaderInfo ci = getClassInfo(cn);
        if (ci != null) return ci.mClassLoader.loadClass(pClassname);

        final Class<?> test = loadClass(pClassname);
        if (test != null) return test;

        System.out.println("XXX -> " + pClassname);
        return super.findClass(pClassname);
    }

    @Override public URL getResource(final String pName) {
        return super.getResource(pName);
    }



}

更多代码

public class JcUJarfileLoader {

    static public JcList<JcClassLoaderInfo> loadJars(final JcList<File> pJarFiles) throws MalformedURLException, IOException {
        final JcList<JcClassLoaderInfo> ret = new JcList<>();
        if (pJarFiles == null || pJarFiles.getItemCount() < 1) return ret;

        // convert files to URL to make all jars available to all requests
        final ArrayList<URL> urls = new ArrayList<>(pJarFiles.getItemCount());
        for (final File jarFile : pJarFiles) {
            final URL url = jarFile.toURI().toURL();
            urls.add(url);
        }
        final URL[] urlArr = urls.toArray(new URL[0]);

        // iterate through jar, load all inner classes
        try (final URLClassLoader classLoader = new URLClassLoader(urlArr);) { //
            for (final File jarFile : pJarFiles) {
                try (final JarFile file = new JarFile(jarFile);) {
                    final Enumeration<JarEntry> entries = file.entries();
                    while (entries.hasMoreElements()) {
                        final JarEntry jarEntry = entries.nextElement();
                        if (!JcUFileType.isJavaClassFile(jarEntry)) continue;

                        try {
                            //                          System.out.println("reloading1 " + jarEntry);
                            final ClassName className = ClassName.fromZipEntry(jarEntry);
                            final Class<?> cls = classLoader.loadClass(className.toString());
                            final JcClassLoaderInfo i = new JcClassLoaderInfo(null, jarFile, className, cls, ClassState.CLASS_FILE_IN_JAR, jarFile.lastModified(), classLoader);
                            ret.addItem(i);

                        } catch (final ClassNotFoundException e2) {
                            System.out.println("JcUJarfileLoader.reloadJar(e2) " + e2);
                        }
                    }
                }
            }
        }

        return ret;
    }



}

还有更多

package jc.lib.lang.reflect.compiler;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;

import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

import com.sun.org.apache.xalan.internal.xsltc.compiler.CompilerException;

import jc.lib.lang.JcUFile;
import jc.lib.lang.reflect.loader.JcDirLoader;
import jc.lib.lang.string.JcUString;



public class JcJavaFileCompiler {



    static public void compileCode(final String pCode) throws IOException, CompilerException {
        final File tempFile = File.createTempFile("jccompiler_", ".java");
        try {
            JcUFile.writeString_UTF8(tempFile, pCode);
            compileFiles(new File[] { tempFile }, null);

        } finally {
            tempFile.deleteOnExit();
        }
    }

    static public void compileFiles(final File pFiles[], @SuppressWarnings("unused") final JcDirLoader pClassLoader_Nullable, final String... pBindingLibraries) throws IOException, CompilerException {
        if (pFiles == null || pFiles.length < 1) return;
        for (final File f : pFiles) {
            if (!f.exists()) throw new FileNotFoundException(f.getAbsolutePath());
        }

        final DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
        final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        if (compiler == null) throw new NoClassDefFoundError("ToolProvider.getSystemJavaCompiler() cannot find a compiler! Make sure you're running on JDK or have linked tools.jar into the classpath!");

        try (final StandardJavaFileManager fileManager2 = compiler.getStandardFileManager(diagnostics, null, null);
        /*JcJavaFileManager fileManager = new JcJavaFileManager(pClassLoader_Nullable, fileManager2);*/) {
            String addLibs = "";
            if (pBindingLibraries != null) for (final String l : pBindingLibraries) {
                if (l == null || l.length() < 1) continue;
                addLibs += ";" + l;
            }
            final ArrayList<String> optionList = new ArrayList<>();
            optionList.add("-classpath");
            optionList.add(System.getProperty("java.class.path") + addLibs);

            final Iterable<? extends JavaFileObject> compilationUnit = /*fileManager*/fileManager2.getJavaFileObjectsFromFiles(Arrays.asList(pFiles));
            final JavaCompiler.CompilationTask task = compiler.getTask(null, /*fileManager*/ fileManager2, diagnostics, optionList, null, compilationUnit);
            final boolean done = task.call().booleanValue();
            if (done) return;

            // collect error data and throw
            final StringBuilder sb = new StringBuilder();
            for (final Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
                sb.append(diagnostic + "\n");
            }
            throw new CompilerException(sb.toString());

        } catch (final IOException e) {
            e.printStackTrace();
            throw e;
        }
    }

    static public String getClassNameFromJavaCode(final File pJavaFile) throws IOException {
        String code = JcUFile.loadString(pJavaFile);
        code = JcUString.removeJavaComments(code);

        final String pkg = JcUString.getBetween(code, "package ", ";");
        final String name = JcUFile.toString(pJavaFile, false, true, false, false);
        return pkg + "." + name;
    }

    static public Class<?> getClass(final String pFullClassName) throws ClassNotFoundException, IOException {
        try (final URLClassLoader classLoader = new URLClassLoader(new URL[] { new File("./").toURI().toURL() });) {
            final Class<?> loadedClass = classLoader.loadClass(pFullClassName);
            return loadedClass;
        }
    }



}

今天的最后一个文件

package jc.lib.lang.reflect.loader.classes;

import java.io.File;
import java.io.IOException;

import jc.lib.lang.JcUFile;
import jc.lib.lang.reflect.loader.JcDirLoader;
import jc.lib.lang.reflect.loader.util.ClassName;
import jc.lib.lang.string.JcUString;



/**
 * Our Custom Class Loader to load the classes. Any class in the com.journaldev
 * package will be loaded using this ClassLoader. For other classes, it will
 * delegate the request to its Parent ClassLoader.
 *
 */
public class JcClassFileLoader extends ClassLoader {



    private final JcDirLoader mJcDirLoader;

    private File        mFile;
    private ClassName   mClassname;

    public JcClassFileLoader(final ClassLoader parent, final JcDirLoader pJcDirLoader) {
        super(parent);
        mJcDirLoader = pJcDirLoader;
    }



    public void setInfo(final File pFile, final ClassName pClassname) {
        mFile = pFile;
        mClassname = pClassname;
    }



    @Override public Class<?> loadClass(final String pClassname) throws ClassNotFoundException {
        //      System.out.println(" *** JcClassFileLoader.loadClass(" + pClassname + ") primed with (" + mFile + "," + mClassname + ")");
        if (!JcUString.equals(pClassname, mClassname.toString())) return super.loadClass(pClassname);

        try {
            final byte[] b = JcUFile.readBytes(mFile);
            final Class<?> c = defineClass(mClassname.toString(), b, 0, b.length);
            resolveClass(c);
            //          System.out.println("LOADED: " + c.getSimpleName() + "\t" + c.getName() + "\t" + c.getPackage());
            return c;

        } catch (final LinkageError e) {
            throw new LinkageError("Error while loading file '" + mFile + "' as Class '" + mClassname + "'", e);
        } catch (final IOException e) {
            e.printStackTrace();
            return null;
        }
    }



    @Override protected Class<?> findClass(final String pName) throws ClassNotFoundException {
        System.out.println(" *** JcClassFileLoader.findClass(" + pName + ")");
        return mJcDirLoader.findClass(pName);
    }



}

最佳答案

Eclipse 具有可以独立使用的增量编译器,应该可以根据您的需要对其进行调整。我认为使用标准 javac 不可能完成您尝试的操作,但了解 oracle 编译器人员对此的想法会很有趣。

Gradle中也有增量编译器,但不确定重用它有多容易。

关于java - 如何使 JavaCompiler.CompilationTask 使用自定义 ClassLoader 或将 .class 文件用于 missin .java 文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50333117/

有关java - 如何使 JavaCompiler.CompilationTask 使用自定义 ClassLoader 或将 .class 文件用于 missin .java 文件?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  4. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  5. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  6. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  7. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  8. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  9. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  10. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

随机推荐