Прежде всего, и что очень важно, нет такой вещи, как "переменный синтаксис в Ruby on Rails" .
Ruby on Rails - это просто фреймворк, написанный на Ruby. Ruby не позволяет пользовательскому коду изменять основной синтаксис языка. Таким образом, синтаксис переменной в Ruby on Rails точно такой же, как и синтаксис переменной в Sinatra, Padrino или чем-то еще, это просто синтаксис переменной в Ruby. Это идентично ECMAScript, где также отсутствует «переменный синтаксис в Express» или «переменный синтаксис в JQuery».
На самом деле почти все языки работают;языки, в которых пользовательскому коду разрешено изменять синтаксис, не говоря уже о том, чтобы изменять синтаксис чего-либо как основополагающего, поскольку переменные представляют собой незначительное меньшинство за пределами основного потока.
Из того, что я понимаю @posts
с помощью @
- это переменная, которая создается из класса Post
в папке моделей.
Должен признать, у меня проблемы с анализом того, что вы имеете в виду. В Ruby нет понятия «папка», так что это совершенно неактуально. И я не понимаю, что вы имеете в виду под "экземплярами". Но я все равно попытаюсь ответить:
@posts
- это переменная экземпляра . Наиболее близким аналогом к этому в ECMAScript будет частное поле экземпляра . Переменные экземпляра принадлежат экземплярам (duh), то есть объектам, в отличие от других типов переменных, которые вы чаще всего видите: локальные переменные относятся к лексической области видимости .
Обратите внимание, что это в отличие от поля private
, например, в Java, где другим объектам того же типа разрешен доступ к полям private
. Ruby имеет истинную объектно-ориентированную инкапсуляцию, где только самому объекту разрешен доступ к его переменным экземпляра. (Я считаю, что предложение ECMAScript имеет ту же семантику.)
Но что именно означает :post
со средним значением :
и
Это Symbol
буквальный. ECMAScript также имеет Symbol
s , но в отличие от Ruby он не имеет буквального синтаксиса для них.
Ruby унаследовал Symbol
s от своих предков Lisp и Smalltalk. Между прочим, они также являются предками ECMAScript (Lisp через Scheme и Smalltalk через NewtonScript → Act-1 → Self), поэтому неудивительно, что между ними есть сходство.
Как и в ECMAScript, Smalltalk,и Lisp, Symbol
в Ruby - это тип данных, который обозначает концепцию «метки» или «имени». Поэтому, когда вам нужно «назвать» что-то, вы используете Symbol
. Например, когда вы определяете метод, определение метода оценивается как Symbol
:
def foo; end
#=> :foo
Когда вы запрашиваете у Ruby список методов объекта, он возвращает Array
из Symbol
s:
''.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 создать псевдоним между двумя методами, вы дадите ему имя существующего метода и псевдоним как Symbol
s:
alias_method :foo, :bar
и т. Д.
Между Ruby и ECMAScript Symbol
s есть два различия.
Первое - это синтаксическая разница, и я намекалвыше: Ruby имеет буквальный синтаксис для Symbol
s (:foo
), ECMAScript - нет.
Второй является важным семантическим различием. (Вы спрашивали только о синтаксисе, но я считаю, что это различие важно для кого-то с фоном ECMAScript.) В Ruby Symbol
всегда интернированы, что означает, что когда вы ссылаетесь на Symbol
по имени, это всегда то же самое Symbol
. Другими словами:
:foo.equal?(:foo)
#=> true
'foo'.to_sym.equal?('foo'.to_sym)
#=> true
:foo.equal?('foo'.to_sym)
#=> true
и т. Д.
В то время как в ECMAScript прямо противоположно верно: два Symbol
с никогда идентичны , даже если они имеют одинаковое имя :
Symbol('foo') === Symbol('foo')
//=> false
Это позволяет использовать Symbol
в ECMAScript в качестве не поддающихся фальсификации маркеров безопасности. Например, если я хочу убедиться, что только тот, кому я доверяю, может вызвать определенный метод, тогда я могу сохранить метод в свойстве, имя которого Symbol
:
const foo = {
[Symbol('bar')]: () => console.log('Hello')
}
И никто не сможет вызвать bar
, потому что невозможно построить Symbol
, который соответствует ключу свойства. Только когда я дам кому-то точное Symbol
, которое я использовал для хранения метода, они могут получить к нему доступ. (На самом деле, даже я не могу вызвать этот метод, потому что я забыл хранить где-то Symbol
, и теперь даже я не могу создать его снова!)
[Примечание: чтобы это действительно работало, ятакже пришлось бы сделать свойство не перечисляемым, в противном случае я все еще мог бы обнаружить его, перебирая объект.]
Этого нельзя сделать с Ruby Symbol
s.
ECMAScript имеет Глобальный регистр символов , и я могу сохранять и извлекать из него Symbol
с помощью Symbol.for
. Symbol
в Ruby ведут себя как всегда, используя Symbol.for
в ECMAScript.
, откуда берется params
и что это?
Если вы спрашивали этовопрос без контекста, который вы разместили, ответ будет таким: или может быть локальной переменной или отправка сообщения (в ECMAScript это называется "вызовом метода") снеявный получатель и без списка аргументов. Синтаксически, в Ruby невозможно различить разыменование локальной переменной и отправку сообщения с неявным получателем и без списка аргументов. В ECMAScript эта неоднозначность не существует, так как вызов метода всегда нуждается в списке аргументов, даже если он пустой.
Чтобы узнать, является ли это сообщение или локальная переменная, мы должны рассмотреть контекст: локальная переменная создается, когда первое присваивание переменной проанализировано . (Обратите внимание, это важно: оно создается, когда присвоение проанализировано , а не когда оно оценено . Например, if false then foo = 42 end
создаст локальную переменную foo
.)
В вашем коде мы ясно видим, что до param
s в локальной области видимости нет присваивания ранее (на самом деле, params
является первым токеном в области, поэтому «до» нет)Это означает, что она не может быть локальной переменной, это должно быть отправленное сообщение.
Следовательно, оно эквивалентно
this.params().require(Symbol.for('post')).permit(Symbol.for('title'), Symbol.for('body'))