Home Php C# Sql C C++ Javascript Python Java Go Android Git Linux Asp.net Django .net Node.js Ios Xcode Cocoa Iphone Mysql Tomcat Mongodb Bash Objective-c Scala Visual-studio Apache Elasticsearch Jar Eclipse Jquery Ruby-on-rails Ruby Rubygems Android-studio Spring Lua Sqlite Emacs Ubuntu Perl Docker Swift Amazon-web-services Svn Html Ajax Xml Java-ee Maven Intellij-idea Rvm Macos Unix Css Ipad Postgresql Css3 Json Windows-server Vue.js Typescript Oracle Hibernate Internet-explorer Github Tensorflow Laravel Symfony Redis Html5 Google-app-engine Nginx Firefox Sqlalchemy Lucene Erlang Flask Vim Solr Webview Facebook Zend-framework Virtualenv Nosql Ide Twitter Safari Flutter Bundle Phonegap Centos Sphinx Actionscript Tornado Register | Login | Edit Tags | New Questions | 繁体 | 简体


10 questions online user: 10

10
votes
answers
28 views
+10

如何检查红宝石中2个范围是否以任何方式相交?

我正在尝试用红宝石编写Gosu内的hitbox,并想检查2个范围是否符合(范围是合作)我希望它只是给出真或假

我看了进入它并找到range.cover?代码,但是在测试后显示它只检查一个范围是否完全适合另一个范围,而不是它们是否只是部分连接。

  #both sprite是具有以下结构的数组#[image_data,sprite_x,sprite_y] #image_data.width将返回图像的宽度#X和y是精灵def hit_scan的左上角(sprite1,sprite2)x_connect =(sprite1 [1 ] .. sprite1 [1] + sprite1 [0] .width).cover?(sprite2 [1] ..(sprite2 [1] + sprite2 [0] .width))y_connect =(sprite1 [2] .. sprite1 [ 2] + sprite1 [0]。高度)。
    
        
沙发
+60
+50

你可以检查一个范围是否包括另一个范围的开始或结束:

  r1 =(1..5)r2 =(4..8)r1.include?(r2。开始)|| r1.include?(r2.end)|| r2.include?(r1.begin)|| r2.include?(r1.end)  

在你的情况下:

  r1 =(sprite1 [1] .. sprite1 [1] + sprite1 [ 0] .width)r2 =(sprite2 [1] .. sprite2 [1] + sprite2 [0] .width)r1.include?(sprite2 [1])|| r1.include?(sprite2 [1] + sprite2 [0] .width)|| r2.include(sprite1 [1])|| r2.include(sprite1 [1] + sprite1 [0] .width)  

假设范围不是无穷无尽。

你删除了额外的东西后我试了一下你不小心投入了,并且错误地说未定义方法'+ @'为假:FalseClass(NoMethodError) - Pixelz 8月29日20:54

修复它,现在尝试 - mrzasa 8月29日21:09

小心:(1 ... 10).end ==(1..10).end和(1 ..)。end == nil所以一般都有边缘情况。 - 亩太短了8月29日21:11

如果r2 = 0..8怎么办? - Cary Swoveland 8月29日23:49

固定为0..8 - mrzasa 8月30日12:56

+40

@muistooshort在评论中指出,有许多案例需要考虑。

我假设范围的元素是整数,如示例所示。

代码

确定的最简单方法如果两个范围相交则是否定一个确定它们是否相交的表达式。

  def overlap?(r1,r2)如果r1.size.zero则返回false?|| r2.size.zero?!(range_last(r1)< r2.begin || range_last(r2)< r1.begin)end def range_last(r)如果r.end == Float :: INFINITY ||则返回Float :: INFINITY r.end.nil?r.include?(r.end)?r.end:r.end-1 end   

示例

 重叠?1..3,2 .. 5#=> 真的重叠?1..3,4..5#=> 假重叠?3..1,0..5#=> 假重叠?1..4,4..8#=> 真的重叠?1 ... 4,4..8#=> 假重叠?4 ..,1..4#=> 真的重叠?4 ..,1 ... 4#=> 假重叠?-Float :: INFINITY..Float :: INFINITY,1..1#=> 真的重叠?-Float :: INFINITY..7,7..8#=> 真的重叠?-Float :: INFINITY ... 7,7..8#=> 假重叠?-4..Float :: INFINITY,-6 ..- 4#=> 真的重叠?-4..Float :: INFINITY,6 ...- 4#=> false   

观察范围< 3 rd 示例中的代码> 3..1 为空。

另请注意:

  range_last(1 .. )#=&gt; Infinity range_last(1..Float :: INFINITY)#=&gt; Infinity range_last(1..3)#=&gt; 3 range_last(1 ... 3)#=&gt; 2   

如果两个范围 r1 r2 是有限的,并且两点范围可以替换 range_last(r),带 r.last )#=&gt; Infinity range_last(1..Float :: INFINITY)#=&gt; Infinity range_last(1..3)#=&gt; 3 range_last(1 ... 3)#=&gt; 2

如果两个范围 r1 r2 是有限的,并且两点范围可以替换 range_last(r),带 r.last )#=&gt; Infinity range_last(1..Float :: INFINITY)#=&gt; Infinity range_last(1..3)#=&gt; 3 range_last(1 ... 3)#=&gt; 2

如果两个范围 r1 r2 是有限的,并且两点范围可以替换 range_last(r),带 r.last

我对r.include不太确定?(r.end)?r.end:r.end-1,虽然......你认为它是一个整数范围,对吧? - Eric Duminil 8月30日9:19

@Eric, yes. See my second sentence. You’ve been AWOL. - Cary Swoveland Aug 30 at 15:08

0

如果您没有无尽的范围,也许您可??以考虑使用Set intersection方法设置#&amp;

 需要'设置'def重叠?(a,b)(a.to_set&amp; b。 to_set)。任何?结束 
     
			
        

请注意,它不适用于浮动。 - Eric Duminil 8月30日13:10

0

难道你们不是太难了吗?也许我错过了一些东西,但检查交叉点的简单方法如下。

  #use splat operator` *`将我们的范围更改为数组r1 = *(1..5) #[1,2,3,4,5] r2 = *(4..8)#[4,5,6,7,8]#并给出与交叉算子的交点&amp; #如果它是一个空数组,它们不会与r1和amp相交 r2#[4,5]#或(r1&amp; r2).any?#real   

注意:数组的顺序与结果无关。

当然,但您只考虑具有有限整数数的范围,并且您可能会创建巨大的,大多数无用的数组。 - Eric Duminil 8月31日17:31

0
votes
answers
67 views
+10

問題與軌道5升級

0

期間schema.rb文件升級到Rails 5之後,我收到類似以下每次我嘗試從模式加載時間(建立一個新的計算機上的應用程序的錯誤信息,運行rails db:test:prepare運行測試之前,等):問題與軌道5升級

ActiveRecord::StatementInvalid: PG::UndefinedObject: ERROR: type "serial" does not exist 
LINE 1: SELECT 'serial'::regtype::oid 

搜索周圍沒有產生太大的幫助。最相關的線程是這一個:https://github.com/rails/rails/issues/30298但我並不想運行任何新的遷移,也不會在schema_plus_indexes寶石似乎有什麼關係問題(在該線程所描述的兩個問題)。

沙发
0
0

在我們的例子中,我們不要讓他們已經對所有數據庫運行後周圍的遷移文件。因此,在升級到rails 5時,存在0個遷移文件。這個問題似乎是,如果您實際運行遷移文件(即使嘗試rails db:migrate而沒有遷移文件存在將不起作用),rails只會自動「修復」您的schema.rb文件。

的解決方案,對我們來說,是創建一個空白的遷移和爲了得到正確格式化的schema.rb文件運行rails db:migrate

0
votes
answers
39 views
+10

顯示在滑軌

0

若干嵌套形式我有這種選擇在滑軌顯示在滑軌

<%= g.select :num_periods, options_for_select([["Mensual", 12], ["Semestral", 6], ["Trimestral", 4], ["Anual", 1]]) %> 

根據我想顯示n次此嵌套形式所選擇的選項。 (我有一個循環,現在顯示它)

<% for i in (1..4) %> 
    <%= g.fields_for :periods do |p| %> 
    <%= p.label "Propuesto" %> 
    <%= p.number_field :proposed, class:"form" %> 
    <%= p.hidden_field :reached, :value => -1 %> 
<% end %> 

我發現,這可能使用JQuery達到,但我不知道怎麼了,可能有人幫助我嗎?

+0

繼續看看你的循環的HTML輸出,並編寫一個jQuery函數,將它輸出到所需容器的'x'次。如果不知道你要在這裏做什麼,很難解釋得更徹底。 –

沙发
0
0

select選項將生成html,即您的起點編寫jquery函數。你需要與chrome developer tolls檢查在你的頁面生成的HTML

<%= g.select :num_periods, options_for_select([["Mensual", 12], ["Semestral", 6], ["Trimestral", 4], ["Anual", 1]]) %> 

它看起來應該像這樣從ActionView::Helpers::FormOptionsHelper的API頁面:

<select name="g[num_periods]" id="g_num_periods"> 
    <option value="12">Mensual</option> 
    <option value="6">Semestral</option> 
    <option value="4">Trimestral</option> 
</select> 

那麼容易的選擇,在視圖中顯示所有輸入字段,並根據您的需要隱藏那些不需要的字段。因此,他們都將被隱藏,你可以告訴你需要用一個:

$('select').change(function(){ 
    $('select option:selected').click(function() { 
     var option_selected = $(this).text(); 
     //now you need to find the div to show and use the .show function to display it 
     }); 
}); 

這是我jsfiddle

我知道這是不是一個很好的解決方案,但我沒有全部來自信息你的代碼也,我不知道該附加格的形式將允許你這樣做POST請求,因爲在防止CSRF

形式的authenticity_token另外這給你更多的信息關於authenticity token

0
votes
answers
67 views
+10

在外部腳本中調用模型及其方法

0

我試圖使用rails runner訪問activerecord模型。我通過了以下內容:rails runner "TabAccount.find_by_id(1).screen_name"。我知道這個模型是有效的,因爲我可以使用它並查看我的Rails應用程序中的條目。在外部腳本中調用模型及其方法

最終我想做一個班,這是一個孩子TabAccount,我越來越掛了。我想象中的腳本看起來會沿着這個線路:

require Rails.root.join('app', 'models', 'tab_account.rb') 
class TwitterAccount < TabAccount 

    def initialize() 
    @screen_name = TabAccount.find_by_id(1).screen_name 
    end 
end 

我可以假設我很密切,有一些挑剔細節,我忽略了?

沙发
0
0

對於這個特定的問題,我掛斷了是爲了確保我可以訪問模型,顯然我需要做的就是驗證這個模型是否在rails r "puts TabAccount.find_by_id(1).screen_name"中。然後我在腳本中做同樣的事情來驗證這種情況下的模型。

0
votes
answers
57 views
+10

從HTML表單運行Ruby文件提交

0

我有一個Ruby程序讀取文件並返回特定的輸出。我必須現在使用Sinatra創建此程序的Web應用程序。我創建了一個包含所有文件選項的form,並且現在我想要在按下提交按鈕後從表單中選擇該文件來運行該Ruby代碼。從HTML表單運行Ruby文件提交

基本上,我不知道如何讓這個外部Ruby程序運行時,用戶從HTML form中選擇的文件名。

Ruby程序(example.rb)以定義def read_grammar_defs(filename)開頭。

// sinatra_main.rb 

require 'sinatra' 
require 'sinatra/reloader' if development? #gem install sinatra-contrib 
require './rsg.rb' 

get '/' do 
erb :home 
end 

post '/p' do 
    //call program to read file with the parameter from form 
end 




// layout.erb 

<!doctype html> 
<html lang="en"> 
<head> 
    <title><%= @title || "RSG" %></title> 
    <meta charset="UTF8"> 
</head> 
<body> 
<h1>RubyRSG Demo</h1> 
<p>Select grammar file to create randomly generated sentence</p> 
<form action="/p" method="post"> 
    <select name="grammar_file"> 
     <option value="Select" hidden>Select</option> 
     <option value="Poem">Poem</option> 
     <option value="Insult">Insult</option> 
     <option value="Extension-request">Extension-request</option> 
     <option value="Bond-movie">Bond-movie</option> 
</select> 
<br><br> 
</form> 
<button type="submit">submit</button> 
<section> 
<%= yield %> 
</section> 
</body> 
</html> 
沙发
0
1

最簡單的方法如下:

  1. 包的example.rb代碼到一個類或模塊,像這樣:

    class FileReader 
        def self.read_grammar_defs(filename) 
        # ... 
        end 
    end 
    
  2. 從西納特拉服務器所需要的文件

  3. post的動作中,讀取在PARAMS和調用方法:

    post '/p' do 
        @result = FileReader.read_grammar_defs(params[:grammar_file]) 
        erb :home 
    end 
    

有了這個代碼,提交表單後,它將填充@result變量和渲染:home模板。實例變量可以從ERB訪問,所以如果你想顯示結果,你可以從那裏訪問它。

雖然這是一個潛在的問題 - 當頁面呈現時,url仍然會說"your_host.com/p",如果用戶重新加載頁面,他們將得到404 /「路由未找到」錯誤,因爲沒有get "/p"定義。

作爲一種變通方法,可以redirect '/'並使用session如上所述in this StackOverflow answerSinatra' official FAQ傳遞的結果值。

+0

我在home.erb中有<%= rsg(params [:grammar_file])%>,但是它打印到控制檯而不是頁面 – msc

+0

將它放在post方法中,如rsg(params [:grammar_file])也打印在控制檯...不知道爲什麼 – msc

+0

什麼?我被卡住了幾小時 – msc

0
votes
answers
47 views
+10

在視圖中動態加載簡單內容

0

我跟着this tutorial構建一個簡單的功能:點擊一個按鈕加載存儲在部分內容中的內容。我想稍後在不希望使用信息重載視圖的各個地方使用它,以便讓它們保持輕微,但如果需要,則允許用戶訪問信息。在視圖中動態加載簡單內容

繼教程這是代碼:

# in view: knowledge/index.html.haml 

.container 
    .row 
    .col-xs-12 
     = link_to 'Show more info', fetch_adus_path, :remote => true 
     #adus 

-

# in: config/routes.rb 

get '/knowledge/fetch_adus', to: 'knowledge#selected_adus', as: 'fetch_adus' 

-

# my partial: knowledge/_adus_all.html.haml 

%p Content will be added here 

-

# in: knowledge_controller.rb 

def selected_adus 
    respond_to do |format| 
    format.js 
    end 
end 

-

# knowledge/selected_adus.js.haml 

$("#adus").html("#{escape_javascript(render partial: 'adus_all')}"); 

在知識(索引頁) - 當我將鼠標懸停在「顯示詳細信息」瀏覽器表明它應該鏈接到本地??主機:3000 /知識/ fetch_adus但是當我點擊它沒有任何反應。我在控制檯得到一個錯誤:

GET http://localhost:3000/knowledge/fetch_adus 500 (Internal Server Error) jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:10255

這(點擊後)導致這行代碼:

xhr.send((options.hasContent && options.data) || null);

爲了提供更多的情況下,當我兩次單擊鏈接我得到一個更簡單錯誤:

knowledge/fetch_adus Failed to load resource: the server responded with a status of 500 (Internal Server Error)

導致此軌錯誤頁面:

ActionController::UnknownFormat in KnowledgeController#selected_adus

ActionController::UnknownFormat

Extracted source (around line #25):

respond_to do |format|

我是新來的鐵軌,如果任何人有任何想法如何解決它,或者如果有任何其他方式建立我所描述的功能,我將非常感謝任何建議。

+0

顯示請求發出時的服務器日誌和完整的控制器代碼 – dstull

+0

@dstull我檢查了日誌,發現了什麼問題。在部分文件中,我有一些被註釋掉的代碼,但奇怪的是它導致了模板錯誤。刪除它和兩個js解決方案(escape_javascript和j渲染 - 翻譯成哈姆 - 工作)。不知何故,我沒有檢查日誌。將其添加到我的個人調試場景清單中。非常感謝! – Socha

沙发
0
1

的解決方案是簡單的比預期的。感謝@dstull,我檢查了日誌,發現了什麼問題。在部分我有一些代碼已被註釋掉,但奇怪的是它導致模板錯誤。刪除它和兩個js解決方案(escape_javascript和j渲染 - 翻譯成哈姆 - 工作)。始終檢查日誌是一種很好的做法。

板凳
0
0

看起來像你的知識問題/ selected_adus.js.haml文件

嘗試重新格式化$("#adus").html("#{escape_javascript(render partial: 'adus_all')}");$("#adus").html("<%= j render partial: 'knowledge/adus_all' %>");

+0

感謝@Zubin--看起來這兩種解決方案都是正確的,問題出在其他地方 - 在一個已被註釋掉的代碼中,但仍然導致模板錯誤。 – Socha

0
votes
answers
45 views
+10

如何在更復雜的Rails應用程序中考慮模型和關係?

0

我已經學習Ruby on Rails很長一段時間了,並且已經構建了幾個玩具應用程序。我參加過很多課程(如Hartl,Code School,Udemy等)。現在我正在研究一個相當複雜的寵物項目 - 許多模型和關係。如何在更復雜的Rails應用程序中考慮模型和關係?

這是我的問題:我如何從模型和關係角度思考一個複雜的應用程序?在我看來,應該有一些可視化的方法來對所有這些進行建模,但是我沒有在任何課程中看到過有關這種建模的討論。當然,Rails指南中有非常簡單的圖表,但我如何將它擴展到更復雜的東西?或者,我是否讓這個過於複雜?我是否剛剛開始編碼模型和關係,並查看它對我的影響?看起來這種特殊的方法很容易讓我進入一個角落,如果我把自己描繪成一個角落,就必須從頭開始。

是否有工具或博客文章可以幫助我?

(注:我也張貼在Reddit.Com/r/Rails了這個問題https://www.reddit.com/r/rails/comments/7c9zbf/how_to_think_about_rails_web_application/

+1

我不知道你希望得到什麼答案。關於rails的書籍,視頻,博客等清單?指向數據庫圖表教程的鏈接?關於如何設計應用程序的個人意見?這不是一個非常具體的問題,所以我不知道如何回答。 –

沙发
0
3

這聽起來像你追求的是一個架構設計師。我會在這篇文章的底部連接一個。模式設計器將允許您可視化應用程序中的所有關係,並查看一個模型如何連接到另一個模型。它們在編寫複雜的數據庫查詢中非常有用。我附上了一個相當簡單的設計示例,只是爲了讓您瞭解它們的作用。您還可以添加模型在設計中的所有列,我通常只是將它用於關係。 http://ondras.zarovi.cz/sql/demo/ schema expample

板凳
0
1

完全基於我的經驗/意見了......

最終你會改變你的數據庫設計幾次爲您打造您的應用程序。

我會從白板開始,然後考慮使用架構設計器作爲@aram提到的。

當你看到大局時,從今天的功能需要的關係開始。您可以繼續參考原始設計,以便您可以看到更大的圖像,但是您不希望在需要之前過度佔用體系結構,因爲它會改變。

在您編寫一些代碼並構建這些關係之後,您可以使用rails-erd gem以編程方式生成應用程序的模式來檢查自己。

+0

雖然我給了@Aram的答案,但我想說「謝謝」你的回答,特別是提到rails-erd Gem。真的很高興看到我的模型作爲圖! –

0
votes
answers
49 views
+10

Socket.read()將不會在紅寶石

1

塊I具有用於Ruby的一個簡單的TCP服務器下面的代碼:Socket.read()將不會在紅寶石

# server.rb 
require 'socket' 

class Server 
    def initialize(port) 
    @port = port 
    end 

    def run 
    Socket.tcp_server_loop(@port) do |connection| 
     Thread.new do 
     loop do 
      puts "IO: #{IO.select([connection]).inspect} - data: #{connection.read}" 
     end 
     end 
    end 
    end 
end 

server = Server.new(16451) 
server.run 

除了這一點瑣碎TCP客戶端代碼:

# client.rb 
require 'socket' 

client = TCPSocket.new('localhost', 16451) 
client.write('stuff') 

我的理解是connection.readserver.rb應該阻塞,如果沒有數據出現在套接字上。然而,當我在我的MacBook(OS X 10.12.5),它不斷吐出下面的輸出運行此:

IO: [[#<Socket:fd 12>], [], []] - data: stuff 
IO: [[#<Socket:fd 12>], [], []] - data: 
IO: [[#<Socket:fd 12>], [], []] - data: 
IO: [[#<Socket:fd 12>], [], []] - data: 
IO: [[#<Socket:fd 12>], [], []] - data: 
IO: [[#<Socket:fd 12>], [], []] - data: 
IO: [[#<Socket:fd 12>], [], []] - data: 
IO: [[#<Socket:fd 12>], [], []] - data: 
... 

似乎IO.select認爲有可用的插槽上讀取數據,而沒有這樣的數據已發送。

如何在使用Ruby中的套接字時實現阻塞讀取?我可以忽略一些東西嗎


馬特的回答指出了我的正確方向。對於未來的讀者,這裏是我的新代碼。

# server.rb 
require 'socket' 

class Server 
    BYTESIZE_OF_PACKED_INTEGER = [1].pack('i').bytesize 

    def initialize(port) 
    @port = port 
    end 

    def run 
    Socket.tcp_server_loop(@port) do |connection| 
     Thread.new do 
     while packed_msg_bytesize = connection.read(BYTESIZE_OF_PACKED_INTEGER) 
      msg_bytesize = packed_msg_bytesize.unpack('i').first 
      msg = connection.read(msg_bytesize) 
      puts msg 
     end 
     end 
    end 
    end 
end 

server = Server.new(16451) 
server.run 

和客戶端代碼。

# client.rb 
require 'socket' 

msg = 'stuff' 
msg_bytesize = msg.bytesize 
packed_msg_bytesize = [msg_bytesize].pack('i') 

client = TCPSocket.new('localhost', 16451) 
client.write(packed_msg_bytesize) 
client.write(msg) 
沙发
0
1

read將會阻塞,如果沒有數據,但不在EOF。所述IO#read docs say

當這個方法被稱爲在文件末尾,則返回nil"",取決於長度readread(nil),和read(0)返回""read(positive_integer)nil返回。

由於在EOF上調用read不會阻塞,因此select將立即返回IO。

在您的代碼中,第一次調用read將阻塞,直到全部數據從連接中讀取(即另一端已關閉它)。從那時起它將在EOF,所以select將返回它準備就緒,read將立即返回一個空字符串。

+0

你知道嗎,如果有什麼辦法阻止EOF?我在玩一個簡單的聊天服務器和客戶端,我希望在客戶端和服務器之間有一個長期的連接。我想要的最後一件事是服務器去100%cpu只是主動循環套接字大部分時間沒有數據。 – Reck

+0

您可能想要檢測並刪除這些連接,因此您不想跳過這些連接。請注意,沒有可用數據的套接字(它仍然連接到另一端)和EOF中的套接字(已斷開連接並且您只需關閉它)之間存在差異。 – matt

+0

你絕對正確! – Reck

0
votes
answers
71 views
+10

如何設置spree_static_content與狂歡3.x和導軌5生成我一直在試圖與大禮包3.X設置寶石spree_static_content和軌道5,但也有無盡的錯誤靜態頁面

0

(遷移不運行,gem依賴),這是未來。文檔已經過時,對任何寶石和大宗商業項目都沒有任何幫助。如果有人最近使用過這些項目,請分享調試結果。如何設置spree_static_content與狂歡3.x和導軌5生成我一直在試圖與大禮包3.X設置寶石spree_static_content和軌道5,但也有無盡的錯誤靜態頁面

沙发
0
0

當設置spree_static_content寶石和Rails 5.x和大禮包3.X有各種錯誤時只添加寶石spree_static_content到你的Gemfile你會得到。 安裝下面的寶石到你的Gemfile中,你不會得到任何錯誤,併爲您的應用程序的靜態內容將輕鬆地設置釐米。

gem 'spree_static_content', github: 'spree-contrib/spree_static_content' 

gem 'globalize', git: 'https://github.com/globalize/globalize' 
gem 'activemodel-serializers-xml' 

gem 'spree_i18n', github: 'spree-contrib/spree_i18n' 
gem 'spree_globalize', github: 'spree-contrib/spree_globalize' 

下一步,運行以下命令

bundle install 
bundle exec rails g spree_i18n:install 
bundle exec rails g spree_globalize:install 
bundle exec rails g spree_static_content:install 

現在,只需創建從管理頁面,但不要忘記選擇商店名稱複選框路線的大禮包3.x的工作

0
votes
answers
48 views
+10

爲什麼我會用to_proc而不是用Proc.new調用instance_eval的錯誤?

0

我這樣做的,它的工作原理:爲什麼我會用to_proc而不是用Proc.new調用instance_eval的錯誤?

class B 
    def value 
    "X" 
    end 
end 

class A 
    def initialize(context) 
    @context = context 
    end 

    def m 
    Proc.new do 
     value 
    end 
    end 

    def execute 
    @context.instance_eval(&m) 
    end 
end 

A.new(B.new).execute #=> "X" 

但調用??是不工作...

class B 
    def value 
    "X" 
    end 
end 

class A 
    def initialize(context) 
    @context = context 
    end 

    def m 
    value 
    end 

    def execute 
    @context.instance_eval(&m.to_proc) 
    end 
end 

A.new(B.new).execute #=> NameError: undefined local variable or method `value' for #<A:0x007fae2ab02040 @context=#<B:0x007fae2ab02108>> 

我想知道爲什麼這兩個例子是不同的,如何使它與to_proc

沙发
0
0

在第二個片段中,您打電話給m,返回調用的結果,這是未定義的。 (甚至如果如果不知何故神奇地調用B#value,然後B#value返回StringString■不要到to_proc迴應,所以你會得到一個NoMethodError那裏。)在第一個片段,你叫m,它返回一個Proc

它看起來像你試圖通過方法m本身而不是調用它的結果。在Ruby中,方法不是對象,所以你不能只抓住它們並傳遞它們(即使方法是對象,那麼m仍然是調用m的語法,而不是用於引用它)。你必須先問一下Ruby的反射API爲方法的反射代理,使用Object#method方法,該方法返回一個代表該方法的Method對象:

@context.instance_eval(&method(:m).to_proc) 

注意,調用to_proc是完全多餘的,在這裏,因爲&無論如何,如果參數已不是Proc,將會調用to_proc。 (您可能已經看到過類似foo.map(&:bar)之前,調用Symbol#to_proc

@context.instance_eval(&method(:m)) 
+0

對不起,我錯過了「&」前'm.to_proc'到PROC轉換成塊,並仍然沒有工作。 – Leantraxxx