create_table :documents do |t|
t.string :title, null: false
end
create_table :related_documents do |t|
t.integer :source_document_id, null: false
t.integer :related_document_id, null: false
end
add_index :related_documents, [:source_document_id, :related_document_id], unique: true
add_foreign_key :related_documents, :documents, column: :source_document_id
add_foreign_key :related_documents, :documents, column: :related_document_id
class Document < ActiveRecord::Base
# We have many document relationships where this document is the source document
has_many :related_documents, foreign_key: :source_document_id
validates :title,
presence: true
end
class RelatedDocument < ActiveRecord::Base
after_create :add_reciprocal_relationship
after_destroy :remove_reciprocal_relationship
belongs_to :source_document, class_name: Document
belongs_to :related_document, class_name: Document
validates :source_document,
presence: true
validates :related_document,
presence: true,
uniqueness: {
scope: :source_document
}
private
# Creates a reciprocal relationship
def add_reciprocal_relationship
RelatedDocument.find_or_create_by(
related_document: self.source_document,
source_document: self.related_document
)
end
# Safely removes a reciprocal relationship if it exists
def remove_reciprocal_relationship
RelatedDocument.find_by(
related_document: self.source_document,
source_document: self.related_document
)&.destroy
end
end
如何在上面的操作中转换字符串?
答案 0 :(得分:1)
您可以使用transpile
功能。这将允许您编译任意字符串:
import * as typescript from 'typescript';
let template = `
let hello: string = 'hello,world';
class test{}
`
let errors : typescript.Diagnostic[] = []
let result = typescript.transpile(template, {}, undefined, errors);
// The result
console.log(result);
// The erorrs
for(let err of errors) console.log(err.messageText);
修改强>
上面的解决方案有效,但它只检查语法错误而不是语义错误。执行模块解析并将检查语义错误的版本是:
function transpileWithAllErrors(input: string, compilerOptions?: typescript.CompilerOptions, fileName: string = "dynamic.ts", diagnostics?: typescript.Diagnostic[]): string {
let result: string;
let host = typescript.createCompilerHost({});
let sourceFile = typescript.createSourceFile(fileName, template, typescript.ScriptTarget.ES5);
let orginalGetSourceFile = host.getSourceFile;
host.getSourceFile = (file, languageVersion, onError, shouldCreateNewSourceFile) =>
file == fileName ?
sourceFile :
orginalGetSourceFile(file, languageVersion, onError, shouldCreateNewSourceFile);
host.getCurrentDirectory = () => "";
host.getDefaultLibLocation = () => "node_modules/typescript/lib";
host.getDefaultLibFileName = () => "node_modules/typescript/lib/lib.d.ts";
let program = typescript.createProgram([fileName], {}, host);
// Capture output,
host.writeFile = (wFileName, data) =>{
if(wFileName.endsWith(".js")) {
result = data;
}
};
if (diagnostics != null) {
diagnostics.push(...program.getSyntacticDiagnostics(sourceFile));
diagnostics.push(...program.getSemanticDiagnostics(sourceFile));
diagnostics.push(...program.getOptionsDiagnostics());
}
program.emit(sourceFile);
return result;
}
用法:
let diagnostics: typescript.Diagnostic[] = []
let result = transpileWithAllErrors(template, {}, undefined, diagnostics);
for (let err of diagnostics) console.log(err.messageText);
console.log(result);
注意:此方法执行相对于当前路径的模块分辨率,以便脚本可以访问当前路径中安装的任何模块。此外,我没有对代码进行大量测试,但它应该可以工作。