你能解释一下这个Ruby代码中发生了什么吗?

时间:2009-07-04 17:52:21

标签: ruby-on-rails ruby

我正在尝试学习Ruby以及Ruby on Rails。我正在跟随Learning Rails,第1版,但我很难理解一些代码。

我通常使用C,C ++或Java工作,所以Ruby对我来说是一个很大的变化。

我目前难以使用以下数据库迁移器代码块:

  def self.up
    create_table :entries do |t|
      t.string :name
      t.timestamps
    end
  end

t变量来自哪里?它究竟代表什么?它有点像for(i = 0; i< 5; i ++)语句中的'i'吗?

此外,在哪里:条目定义在? (条目是我的控制器的名称,但该功能如何知道?)

10 个答案:

答案 0 :(得分:9)

:entries是一个符号文字,它是一个像7"a string"这样的字面值。没有什么可定义的(顺便说一句,该函数不知道你的控制器的名称)。

t是您传递给create_tables方法的块的参数。你在这里写的大致类似于:

void anonymous_block(Table *t) {
   t->string("name");
   t->timestamps();
}

...

create_table("entries", &anonymous_block);

在C ++中。 create_table调用您的块并向其传递一个参数,您将其命名为t。我建议你得到一本关于 ruby​​ 的入门书,而不是rails。我推荐David A. Black的 Ruby For Rails

答案 1 :(得分:2)

我会接受t的事情。 create_table方法就像一个C函数,它接受一个带有一个参数的函数指针,即表定义对象(原谅我不存在的C技能):

void entries_table_constructor(TableDef table_definition) {
  table_def_add_string_column(table_definition, "name");
  table_def_add_timestamps_column(table_definition);
}    

create_table("entries", entries_table_constructor);

但是在Ruby中,传递函数的定义可以在调用create_table方法时完成。因此,doend之间的位与entries_table_constructor函数类似,t变量类似于table_definition参数。

然而,C中的函数指针和Ruby中的块之间存在很大差异。在Ruby中,块内的所有局部变量都可以在块中使用:

a = 10
create_table :entries do |t|
  puts a
  ...
end

查看Ruby中的yield关键字,了解如何编写自己的方法,例如create_table

答案 2 :(得分:1)

create_table是接受lambda表达式的方法(某种委托),t是委托的参数。因此,当您执行create_table时,执行

t.string :name
t.timestamps
像伪代码

之类的东西
delegate d = funciton (t) {
   t.string :name
   t.timestamps
}
create_table(d);

java中的直接模拟是一个非常类的..

addReturnBackListener(new Listener<EventObject>() {
  public void handle(EventObject e) {
     refreshAndShowAndList();
  }
});

“:entries”根本没有定义,它只是标识符。你可以将它视为简单的字符串(但不需要花费内存来保持字符)。

答案 3 :(得分:1)

:entries是对Rails中条目表的引用。

当我根据我的理解给出'生成控制器'命令时,迁移器就会知道它(与Rails专业合作一年,但仍然在学习)。

至于| t |这是一个块。引用Pickaxe书(你应该立即获得pdf或死树版本的副本):

  

块可用于定义必须在某种事务控制下运行的代码块。例如,您经常打开一个文件,对其内容执行某些操作,然后确保在完成后关闭该文件。尽管您可以使用传统代码执行此操作,但有一个参数可以使文件负责关闭自身。我们可以用块来做到这一点。

所以,上面发生的是| t |是处理设置与数据库的连接,根据其特定类型创建行,然后关闭连接的块。

这是另一个例子:

output_string = "Let's print this to file"

File.open('outputfile.txt','w') do |f| #f for file
  f.print output_string
end

至于你的迭代器,是的,你也可以这样做:

an_array = [1,2,3,4]
an_array.each do |line|#line is the block for the elements of the array during iteration
   puts "Now we are at: #{line.to_s}!" 
end

答案 4 :(得分:1)

create_table方法是Ruby中的块,t是该块的本地变量(t只是Rails迁移中的一个约定。为“表”)。这是Ruby块的另一个更明显的例子:

10.times do |i|
  print "i is #{i}"
end

:entries是一个Ruby符号,它是一种用于命名事物的轻量级字符串。您可以同样使用"entries"。符号的一个常见用途是用于指定散列中的键。在任何一种情况下,正在创建的表都被命名为“条目”。

答案 5 :(得分:1)

我正好在一个同时拥有Entry型号/ entries表的应用上工作。这是我的迁移:

class CreateEntries < ActiveRecord::Migration
  def self.up
    create_table :entries do |t|
      t.string :title
      t.text :entry
      # ...
    end
  end

  def self.down
    drop_table :entries
  end
end

非常类似于你所看到的。

首先,第一行,声明一个名为CreateEntries的类,它扩展了ActiveRecord::Migration

接下来,声明一个名为up()的类方法。与实例方法相对的类方法属于类,而不属于类的特定对象。它是“self”关键字,使其成为一种类方法。

接下来调用create_table()并传递两件事:

  1. 符号(“:entries”),如上所述,就像一个字符串文字。这告诉ActiveRecord应该调用它创建的表。假设您手动输入此代码 - 忘记生成器一分钟。您键入“:entries”因为您知道按照惯例,Rails应用程序中的表以多个名词命名,并且您知道连接到此表的模型类将被称为Entry

  2. 同样传递一个区块。

  3. 一个块可以包含在......

    `do ... end`
    

    `{ ... }`
    

    一个块可以包含两个“|”所包含的参数。在这种情况下,create_table方法将块TableDefinition的对象传递给块,因此,为了回答您的一个问题,t是保存该对象的var。然后在块中,我们调用TableDefinition的各种实例方法。

    TableDefinition对象来自哪里?这种情况发生在create_table()方法中。它包含实例化新TableDefinition对象的代码,并将其“产生”到块....

    ActiveRecord源代码......

    def create_table(table_name, options = {})
      table_definition = TableDefinition.new(self)
      table_definition.primary_key(options[:primary_key] || "id") unless options[:id] == false
    
      yield table_definition
    
      # ...
    
    end
    

答案 6 :(得分:0)

这是Ruby中块的典型用法。 create_table方法在ActiveRecord中定义,如:

def create_table(table_name)
  table_object = some_table_setup
  yield(table_object) # your code block which was passed implicitly is invoked here
  create_table(table_object)
end

答案 7 :(得分:0)

条目是对Entry模型的引用 - 每个模型都假定表名与其名称相同,除了tableized(http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/String/Inflections.html#M001653

t是传递给create_table方法的块参数,有关更好的示例,请参阅http://www.rubycentral.com/book/tut_containers.html。在这种情况下,t表示已创建的表(http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#M002191

希望这足以帮助你

答案 8 :(得分:0)

:正在定义entries。代码使用两个参数调用方法create_table - 表的所需名称和代码块。

create_table将构造一个TableDefinition对象,然后屈服于代码块,将该对象提供给它。在代码块中,它将被命名为t。最后,该代码块调用t上的一些方法来构建列。

答案 9 :(得分:0)

因为,来自Python,我很难自己理解这个构造,我会给你的代码片段的unpythonic翻译。

首先,您必须将函数create_table定义为此函数(它只是一个骨架):

def create_table(name, setup):
    t = Table(name)
    setup(t)

然后,对于每个表,您将创建一个设置函数:

def setup_entries(t): # <-- here is your |t|, just a function argument
    t.string("name")
    t.timestamps()

最后你会通过调用:

来创建表
create_table("entries", setup_entries)

这不是用Python做的方式。如果您对如何在Python中创建表感兴趣,您应该看看djangosqlalchemy如何处理它。