2014-03-25 4 views
0

업 후, 그는 어떻게든지 2..3 대신 Product 경우 레코드루비 블록이 <a href="http://railscasts.com/episodes/396-importing-csv-and-excel" rel="nofollow">screencast</a>을

def save 
    puts "--- imported_products: #{imported_products.inspect}" 
    // --- imported_products: 2..3 
    if imported_products.map(&:valid?).all? 
     imported_products.each(&:save!) 
     true 
    else 
     imported_products.each_with_index do |product, index| 
     product.errors.full_messages.each do |message| 
      errors.add :base, "Row #{index+2}: #{message}" 
     end 
     end 
     false 
    end 
end 

def imported_products 
    @imported_products ||= load_imported_products 
end 

def load_imported_products 
    spreadsheet = open_spreadsheet 
    header = spreadsheet.row(1) 
    (2..spreadsheet.last_row).each do |i| 
    row = Hash[[header, spreadsheet.row(i)].transpose] 
    product = Product.find_by_id(row['id']) || Product.new 
    product.attributes = row.to_hash.slice(*accessible_attributes) 
    product 
    end 
end 

답변

2

load_imported_products 방법은 each 블록을 포함 복귀. 이 블록은 메소드의 마지막 '라인'이므로 블록의 반환 값은 메소드의 반환 값이됩니다. 당신이 load_imported_products 방법에 대해 얘기하고 있다면, 다음 배열을 반환하는 대신 배열에 각 제품을 추가하려고

def load_imported_products 
    spreadsheet = open_spreadsheet 
    header = spreadsheet.row(1) 
    products = [] 
    (2..spreadsheet.last_row).each do |i| 
    row = Hash[[header, spreadsheet.row(i)].transpose] 
    product = Product.find_by_id(row['id']) || Product.new 
    product.attributes = row.to_hash.slice(*accessible_attributes) 
    products << product 
    end 
    products 
end 
+1

포스터의 원래 방법에서 #each 대신 #collect (http://www.ruby-doc.org/core-2.1.1/Array.html#method-iCollect)를 사용하십시오. – RipTheJacker

+0

@mattwise에 감사드립니다. Ryan이'ruby 1.9.2'와 함께'rails 3.2.9'와 동일한 코드를 사용하고 있기 때문에 ruby ​​나 rails 버전 문제로 생각했습니다. –

0

:

은 다음보십시오.

정확히 어떤 메소드가 반환되는지는 확실하지 않지만 제품 컬렉션을 명시 적으로 반환해야합니다.

그래서

def load_imported_products 
    products = [] 
    spreadsheet = open_spreadsheet 
    header = spreadsheet.row(1) 
    (2..spreadsheet.last_row).each do |i| 
    row = Hash[[header, spreadsheet.row(i)].transpose] 
    product = Product.find_by_id(row['id']) || Product.new 
    product.attributes = row.to_hash.slice(*accessible_attributes) 
    products << product 
    end 
    return products 
end 
+0

루비에서는 항상 마지막 문장을 반환하기 때문에 explicit return은 불필요합니다. 제품은 충분할 것입니다.) setter 메소드의 경우를 제외하고는 set 값을 리턴합니다. – engineersmnky

+0

고마워, 너 말이 맞아. 나는 그것이 불필요하다는 것을 안다. 그러나 나는 읽기 능력에 도움이 될 것이라고 생각했다. 특히, 그 방법이 왜 그것이 예정되어 있던 것을 돌려 보내지 않는지를 묻는 것이기 때문에. 호기심에서 벗어나 방법에서 값을 반환하고 싶을 때 왜 'return'이라고 입력하지 않으시겠습니까? 몇 번의 키 스트로크를 줄일 수는 있지만 그 값을 반환하기를 원한다는 것을 명확하게하는 것이 가치가 있지 않습니까? – user3446496

+1

적절한 컨벤션으로 간주되지 않습니다. 어떤 사람들은 루프 나 조건문에서 그것을 사용하는 것이 실제로 잘못된 것은 아니지만 일반적으로 명시 적으로 반환하면 모국어 코드의 냄새가 발생하며이를 피하기 위해 코드를 작성할 수있는 더 좋은 방법이 있음을 나타냅니다. – engineersmnky

1

또는 사용지도

def load_imported_products 
    spreadsheet = open_spreadsheet 
    header = spreadsheet.row(1) 
    products = (2..spreadsheet.last_row).map do |i| 
    row = Hash[[header, spreadsheet.row(i)].transpose] 
    product = Product.find(row['id'].to_i) || Product.new 
    product.attributes = row.to_hash.slice(*accessible_attributes) 
    product 
    end 
end 

또한 나는 그것이 nil 또는 string로 저장했다 경우 정수로 강제 있지만 find 방법은 id를 사용하여 필요하지 않습니다 find_by_id.