首先,非常重要的是,没有“Ruby on Rails 中的可变语法”之类的东西。
Ruby on Rails 只是一个用 Ruby 编写的框架。 Ruby 不允许用户代码更改基本语言语法。因此,Ruby on Rails 中的变量语法与 Sinatra 或 Padrino 中的变量语法完全相同,只是 Ruby 中的变量语法。这与 ECMAScript 相同,其中也没有“Express 中的可变语法”或“JQuery 中的可变语法”。
事实上,几乎所有语言都可以工作;允许用户代码更改语法的语言,更不用说更改诸如变量之类的基本事物的语法了,这只是主流之外的极少数方式。
据我了解,@posts 和 @ 是从模型文件夹中的 Post 类实例化的变量。
我必须承认我无法解析你的意思。 Ruby 没有“文件夹”的概念,因此完全不相关。而且我不明白您所说的“实例化”是什么意思。但无论如何我都会尝试回答:
@posts 是一个instance variable。与 ECMAScript 中最接近的类似物是 private instance field。实例变量属于实例 (duh) aka 对象,而不是您最常看到的其他类型的变量:local variables belong to the lexical scope。
请注意,这 不同于 private 字段,例如Java,其中 other 相同类型的对象被允许访问private 字段。 Ruby 具有真正的面向对象封装,其中只有对象本身被允许访问其实例变量。 (我相信 ECMAScript 提案具有相同的语义。)
但是 :post 和 : 到底是什么意思和
这是一个 Symbol 文字。 ECMAScript 也有 Symbols,但与 Ruby 不同,它没有文字语法。
Ruby 从其祖先 Lisp 和 Smalltalk 继承了 Symbols。顺便说一句,它们也是 ECMAScript 的祖先(Lisp 通过 Scheme 和 Smalltalk 通过 NewtonScript → Act-1 → Self),因此两者之间有相似之处也就不足为奇了。
就像在 ECMAScript、Smalltalk 和 Lisp 中一样,Ruby 中的 Symbol 是一种表示“标签”或“名称”概念的数据类型。因此,每当您需要“命名”某些东西时,您都可以使用Symbol。例如,当您定义一个方法时,该方法定义的计算结果为 Symbol:
def foo; end
#=> :foo
当你向 Ruby 询问对象的方法列表时,它会返回 Array 的 Symbols:
''.methods
#=> [:unpack1, :encode!, :include?, :%, :*, :+, :count, :partition, :sum, :next, :casecmp, :casecmp?, :insert, :<=>, :bytesize, :match?, :succ!, :match, :==, :===, :next!, :=~, :index, :[], :[]=, :getbyte, :rindex, :replace, :upto, :chr, :scrub, :empty?, :eql?, :undump, :scrub!, :setbyte, :byteslice, :clear, :+@, :-@, :capitalize, :upcase, :downcase, :downcase!, :dump, :upcase!, :split, :capitalize!, :swapcase!, :freeze, :inspect, :grapheme_clusters, :lines, :swapcase, :oct, :codepoints, :crypt, :bytes, :hex, :concat, :ljust, :length, :size, :chars, :succ, :scan, :reverse, :reverse!, :chop, :<<, :strip, :end_with?, :lstrip, :prepend, :rjust, :to_str, :to_sym, :intern, :delete_prefix, :chomp, :sub!, :to_s, :to_i, :to_f, :delete_suffix, :lstrip!, :gsub!, :chop!, :center, :sub, :ord, :start_with?, :delete_prefix!, :delete_suffix!, :chomp!, :rstrip, :delete, :rstrip!, :gsub, :tr_s!, :tr, :tr_s, :strip!, :squeeze, :tr!, :each_codepoint, :delete!, :squeeze!, :each_line, :each_byte, :each_char, :force_encoding, :each_grapheme_cluster, :hash, :slice!, :rpartition, :encoding, :unpack, :b, :valid_encoding?, :slice, :unicode_normalize, :unicode_normalize!, :unicode_normalized?, :ascii_only?, :to_c, :to_r, :encode, :clamp, :<=, :between?, :>=, :>, :<, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :methods, :untrusted?, :trust, :singleton_methods, :tainted?, :private_methods, :untrust, :frozen?, :method, :public_send, :public_method, :singleton_method, :protected_methods, :define_singleton_method, :extend, :to_enum, :enum_for, :!~, :respond_to?, :object_id, :send, :display, :singleton_class, :nil?, :class, :yield_self, :clone, :dup, :itself, :untaint, :then, :taint, :!, :equal?, :!=, :instance_eval, :instance_exec, :__id__, :__send__]
当你要求 Ruby 在两个方法之间创建一个别名时,你会给它现有方法的名称,别名为Symbols:
alias_method :foo, :bar
等等。
不过,Ruby 和 ECMAScript 的 Symbols 之间有两个区别。
第一个是语法的区别,我在上面提到过:Ruby 有Symbols (:foo) 的字面语法,ECMAScript 没有。
第二个是重要的语义区别。 (您只询问了语法,但我相信这种差异对于具有 ECMAScript 背景的人来说很重要。)在 Ruby 中,Symbols 始终是实习生,这意味着当您按名称引用 Symbol 时,它总是相同的Symbol。换句话说:
:foo.equal?(:foo)
#=> true
'foo'.to_sym.equal?('foo'.to_sym)
#=> true
:foo.equal?('foo'.to_sym)
#=> true
等等。
而在 ECMAScript 中,完全相反是正确的:两个 Symbols从不相同,即使它们具有相同的名称 :
Symbol('foo') === Symbol('foo')
//=> false
这允许将 ECMAScript 中的 Symbols 用作不可伪造的安全令牌。例如,如果我想确保只有我信任的人可以调用特定方法,那么我可以将该方法存储在名称为 Symbol 的属性中:
const foo = {
[Symbol('bar')]: () => console.log('Hello')
}
而没有人将能够调用bar,因为不可能构造一个匹配属性键的Symbol。只有当我给某人 exact Symbol 我用来存储该方法时,他们才能访问它。 (其实连我都不能调用这个方法,因为我忘了把Symbol放在某个地方,现在连我都不能再构造了!)
[注意:要使其真正起作用,我还必须使属性不可枚举,否则我仍然可以通过迭代对象来发现它。]
Ruby Symbols 无法做到这一点。
ECMAScript 有一个全局符号注册表,我可以使用Symbol.for 来存储和检索Symbols。 Ruby 的 Symbols 的行为就像在 ECMAScript 中使用 Symbol.for 一样。
params 来自哪里,它是什么?
如果您在没有发布的上下文的情况下问这个问题,答案将是:它可能是或者是一个局部变量或一个消息发送(在 ECMAScript 中它将被称为“方法调用”)具有隐式接收器且没有参数列表。从语法上讲,在 Ruby 中,无法区分取消引用局部变量和发送带有隐式接收器且没有参数列表的消息。在 ECMAScript 中,这种歧义是不存在的,因为方法调用总是需要一个参数列表,即使它是空的。
为了知道它是消息还是局部变量,我们必须考虑上下文:局部变量是在对变量的第一次赋值被解析时创建的。 (注意,这很重要:它是在赋值被解析时创建的,而不是在求值时创建的。例如,if false then foo = 42 end 将创建局部变量 foo。)
在你的代码中,我们可以清楚的看到之前在本地范围内没有给params赋值(实际上params是范围内的第一个token,所以没有“之前”),这意味着它不能是局部变量,它必须是消息发送。
因此等价于
this.params().require(Symbol.for('post')).permit(Symbol.for('title'), Symbol.for('body'))