我正在尝试学习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'吗?
此外,在哪里:条目定义在? (条目是我的控制器的名称,但该功能如何知道?)
答案 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
方法时完成。因此,do
和end
之间的位与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()
并传递两件事:
符号(“:entries
”),如上所述,就像一个字符串文字。这告诉ActiveRecord应该调用它创建的表。假设您手动输入此代码 - 忘记生成器一分钟。您键入“:entries
”因为您知道按照惯例,Rails应用程序中的表以多个名词命名,并且您知道连接到此表的模型类将被称为Entry
。
同样传递一个区块。
一个块可以包含在......
中`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中创建表感兴趣,您应该看看django或sqlalchemy如何处理它。