The thing with Ruby on Rails and Colons



我以前更喜欢Java,现在尝试切换到Ruby on Rails。 但是我遇到了一些困难,信不信由你,我喜欢大括号和分号。给出一些方向。

但问题是: 现在我正在参加 RoR 的在线课程,我突然想到,我在如何使用符号、哈希等方面总是错误的。

示例 1: 让我们看一下这行代码,例如:

form_for(:session, :html => {class: "form-horizontal", role: "form"}, url: login_path)  

这就是我读它的方式:

方法/函数名称为

form_for  

解析为此方法的参数包括:

:session, :html => {class: "form-horizontal", role: "form"}, url: login_path 

让我们将它们分解为

:session 
:html => {class: "form-horizontal", role: "form"} 
url: login_path 

我到底应该知道如何声明这些参数? 为什么 :session 和 :html 作为键和 url 传入? :html 符号是 Hashmap 符号吗?

  1. 示例:

在模型文件中,您声明了这样的 n:m 关系(例如,用户<->股票)

has_many :users, through: :user_stocks

好的,我知道第一个参数是:users,第二个参数与

:through => :user_stocks

正确?

但以同样的方式,让我们看一下来自同一项目的 routes.rb 配置:

resources :user_stocks, except: [:show, :edit, :update]

现在我们在 except 哈希上使用一个键数组,对吗? 在编写问题时确实会变得更清晰,但是,是否有关于何时使用的经验法则/惯例

:name
name: value
:name => {values}? 
name: [values]

还是只是个人喜好?在这种情况下,我应该希望我的在线老师保持一致。

一般来说,我对参数语法约定如何以及何时使用什么(什么类型的参数)感到非常困惑。 仅仅是因为我从 Ruby 开始还是我错过了一些惯例。

我希望我的问题可以理解,并原谅我的英语 - 非母语人士。 我真的很喜欢与 RoR 相处,但现在观看在线课程有时会让我比以前更困惑,因为如果我自己做,我会使用完全不同的方式。

我到底应该知道如何声明这些参数?

您在文档中查找该方法并阅读有关它的信息。

解析为此方法的参数包括:

:session, 
:html => {class: "form-horizontal", role: "form"}, 
url: login_path

我到底应该知道如何声明这些参数?为什么 :session 和 :html 作为键和 url 传入不是?是 :html 符号 哈希图符号?

在 ruby 中,如果在参数列表的末尾传入一系列键值对,Ruby 会将它们全部收集到一个哈希中,并将它们作为一个参数传递给方法。 下面是一个示例:

def go(x, y)
p x
p y
end

go(:hello, a: 10, b: 20)
--output:--
:hello
{:a=>10, :b=>20}

再比如:

def go(x, y)
p x
p y
end
go(
:session,
:html => {class: "form-horizontal", role: "form"}, 
url: 'xyz'
)
--output:--
:session
{:html=>{:class=>"form-horizontal", :role=>"form"}, :url=>"xyz"}
has_many :users, through: :user_stocks

好的,我知道第一个参数是:users,第二个参数是相同的 如

:through => :user_stocks

正确?

正确。 在旧的 ruby 中,哈希中的键值对是这样写的:

'a' => 'hello'

如果值是一个符号,那么它看起来像这样:

'a' => :hello

如果钥匙也是一个符号,那么你写道:

:a => :hello

在现代红宝石中,如果键是一个符号,你可以写:

a: 'hello'

这是以下的快捷方式:

:a => 'hello'

如果值也是一个符号,那么在现代红宝石中,它看起来像这样:

a: :hello

这是以下的快捷方式:

:a => :hello
resources :user_stocks, except: [:show, :edit, :update]

现在我们在 except 哈希上使用一个键数组,对吗?

哈希没有命名为except,但除此之外你是对的。

关于何时使用的经验法则/惯例

:name             #  Single symbol argument
name: value       #  A key-value pair in a hash.  The key is a symbol.
:name => {values}?   #A key-value pair in a hash.  The value looks like a hash, but the syntax is incorrect.
name: [values]       #A key-value pair in a hash.  The value is your notation for an array.

还是只是个人喜好?在这种情况下,我应该希望我的在线老师保持一致。

同样,可以定义一个方法来接受任何类型的参数。 因为 ruby 变量没有类型,所以你必须检查文档。 如果某个方法希望您传入一个哈希值,其中键 :name 的值是哈希,那么您需要这样做。 另一方面,如果该方法希望您传入一个哈希,其中键 :name 的值是一个数组,那么您需要这样做。

一般来说,我对参数语法如何感到非常困惑 约定是以及何时使用什么(什么类型的参数)。只是吗 因为我是从 Ruby 开始的,还是我错过了一些 公约。

Ruby 有很多快捷方式,这可能会让初学者感到困惑。 然后是整个String v. Symbol概念。如果您能理解符号和字符串之间的实际区别,那么您将领先于游戏。 符号就像一个整数。 因此,当 ruby 必须比较符号是否相等时,ruby 会比较两个整数,这很快。 如果 ruby 必须比较字符串,那么 ruby 必须将一个字符串中每个字母的 ascii 代码与另一个字符串中每个字母的 ascii 代码进行比较,直到 ruby 找到差异。 例如,为了让 ruby 比较以下两个字符串:

"helloX" v. "helloY"

Ruby 在进行了六个整数比较之前不会发现差异:

'h' v 'h' => equal
'e' v 'e' => equal
...
...
'X' v 'Y' => not equal

另一方面,如果 ruby 比较:

:helloX  v.  :helloY

符号基本上存储为单个整数,如下所示:

341343   v.  134142  => not equal

比较它们只需要一个整数比较,所以速度更快。 正如有人肯定会指出的那样,这不是符号的实现方式,但细节并不重要。 知道符号比较比字符串比较更快就足够了,至于为什么这是真的,上面的示例足以证明至少有一个实现可以为真。

哈希

:哈希火箭与文字

在 Ruby 中,哈希可以使用"hashrockets"或更新的文字表示法(从 Ruby 1.9 开始):

# hashrockets
{ :foo => "bar" }
# literal
{ foo: "bar" }

他们都做完全相同的事情。他们创建一个哈希值,符号:foo作为键。现在通常首选文字语法。

Hashrockets应该只在今天使用,如果你有符号以外的东西作为键(你可以用数字,字符串或任何对象作为键):

{ 1 => 'a', 2 => 'b' }
# using literals won't work here since it will cast the keys to symbols:
{ 1: 'a', 2: 'b' } # => { :1 => 'a', :2 => 'b' }

由于 Ruby 是模糊的类型哈希可以包含任何类型的值:

{ foo: "bar" }
{ foo: [:bar, :baz] }
{ foo: { bar: :baz } }

哈希选项

在 Ruby 中,方法可以接收序号参数和带有选项的哈希:

def foo(bar, hash = {})
@test= hash[:] 
end

哈希选项必须位于参数列表中的位置参数之后。

# syntax error
foo(a: 2, "test")
# good
foo("test", a: 2)

传递哈希选项时,您可以放弃周围的括号,因为它们是隐含的:

foo("test", { a: 1, b: 2 })
# same result but nicer to read 
foo("test", a: 1, b: 2 )

Ruby 2.0 引入了关键字参数,减少了解析选项所需的样板代码量:

def foo(bar, test: nil)
@test= test
end
def foo(bar, test: nil, **kwargs)
@test= test
# all the options except test
puts kwargs.inspect 
end
# will raise an error if the test key is not passed
def foo(bar, test:)
@test= test
end

假设参数与哈希选项

假设参数更短且理想,其中参数的顺序是不言自明的:

class Number
def add(x)
@val += x
end
end

当您拥有具有大量参数的更复杂的方法时,跟踪顺序可能会很棘手:

def book_flight(destination, seats, airline_preference= nil, special_meals= nil)
end

这就是哈希选项出现并大放异彩的地方,因为您可以拥有大量选项,并且程序不会因为您在通话中忘记了零而爆炸。

最新更新