Problem z CarrierWave

Wyskakuje mi błąd :

undefined method `photo’ for 1:Fixnum

Posiadam widok parszal, z którego korzystam w kliku miejscach
_products.html.erb

<% products.each_slice(3) do |slice| %>                                                       
 <div class="row">                                                                        
   <% slice.each do |product| %>                                                         
       <div class="col-md-4">                                                            
         <div class="thumbnail">                                                          
           <%= link_to product_path(product) do %>
              <% image_tag product.photo.url(:thumb)  %>
           <% end %>
           <div class="caption">
             <h3><%= link_to Faker::Hacker.noun.titleize, product_path(1) %></h3>                  
             <p><%= simple_format(truncate(Faker::Hacker.say_something_smart, length: 90)) %></p>  
             <p class="lead"><%= number_to_currency Faker::Number.decimal(2, 2) %></p>            
             <p>
               <%= link_to "#", class: "btn btn-primary" do %>
                   <span class="fa fa-shopping-cart"></span> Dodaj do koszyka             
               <% end %>
             </p>
           </div>
         </div>
       </div>
   <% end %>
 </div>
<% end %>

Wygenerowany uploader za pomoca CarrierWawe
product_photo_uploader.rb

 class ProductPhotoUploader < CarrierWave::Uploader::Base 

    include CarrierWave::MiniMagick
    storage :file

    def store_dir
       "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
    end
    
     version :thumb do
         process :resize_to_fit => [320, 240]
     end

     version :details do
        process :resize_to_fit => [640, 480]
     end
 end

modele produktu i kategorii

class Product < ActiveRecord::Base
   belongs_to :category

  validates :name, presence: true                        
  validates :description, presence: true                
  validates :price, numericality: { greater_than: 0.0 }  
  validates :category, presence: true                    


  mount_uploader :photo, ProductPhotoUploader
  
     def to_param
         "#{id}-#{name}".parameterize
     end
  end


class Category < ActiveRecord::Base
      has_many :products
      validates :name, presence: true  
end

Kontroler:

  class ProductsController < ApplicationController
    def index
      @products = Product.order(created_at: :desc).limit(9)
    end

   def show
     @product = Product.find(params[:id])
     @category = @product.category
   end
end

BazaDanych

  ActiveRecord::Schema.define(version: 20170120184859) do

       create_table "categories", force: :cascade do |t|
          t.string   "name",       limit: 255
          t.datetime "created_at",             null: false
          t.datetime "updated_at",             null: false
       end

       create_table "products", force: :cascade do |t|
          t.string   "name",             limit: 255
          t.text     "description",      limit: 65535
          t.text     "long_description", limit: 65535
          t.string   "photo",            limit: 255
          t.decimal  "price",                          precision: 10
          t.integer  "category_id",      limit: 4
          t.datetime "created_at",                                    null: false
          t.datetime "updated_at",                                    null: false
       end

      add_index "products", ["category_id"], name: "index_products_on_category_id", using: :btree

      add_foreign_key "products", "categories"
  end

Oraz mam takze seedy ktorymi wypelniam BD

      8.times do                                                   
       Category.create! name: Faker::Hacker.ingverb.capitalize    
      end

      category_ids = Category.pluck(:id)                         
                                                         
                                                          

      print "Product "
      200.times do       
           product = Product.create! name: "#{Faker::Hacker.verb} #{Faker::Hacker.noun}".capitalize, # dajemy naze
                          description: Faker::Hacker.say_something_smart,                 
                          long_description: Faker::Lorem.paragraphs(3).join("\n\n"),      
                          category_id: category_ids.sample,                              
                          price: Faker::Number.decimal(3, 2)                              
           product.remote_photo_url = Faker::Avatar.image(                  
               product.name.parameterize,
                 "640x480",                  # ma miec rozmiar
                 "jpg",                      # byc w formacie jpg
                 "set#{[1, 2, 3].sample}", 
                 "bg#{[1, 2].sample}"        
           )
            product.save   
            print "."      
       end
   puts

Gemfile wyglada tak:

 source 'https://rubygems.org'
  gem 'rails', '4.2.5.1'
  gem 'mysql2', '>= 0.3.13', '< 0.5'
  gem 'sass-rails', '~> 5.0'
  gem 'uglifier', '>= 1.3.0'
  gem 'coffee-rails', '~> 4.1.0'
  gem 'jquery-rails'
  gem 'turbolinks'
  gem 'jbuilder', '~> 2.0'
  gem 'sdoc', '~> 0.4.0', group: :doc
  gem 'thor', '~> 0.19.3'

  gem 'faker'                     
  gem 'letter_opener'           
  gem 'carrierwave'               
  gem 'mini_magick'               
  gem 'simple_form'              
  gem 'twitter-bootstrap-rails'  
  gem 'ransack'                  
  gem 'kaminari'             
  gem 'rails-i18n'              
  gem 'statesman'     

  group :development, :test do
     gem 'byebug'
  end

  group :development do
    gem 'web-console', '~> 2.0'

  gem 'spring'
 end

Routes:

 resources :products, only: [:show, :index], path: "produkt"    
 resources :categories, only: [:show], path: "kategoria"          
 root to: 'products#index'

Widok index

   <h1>Najnowsze produkty</h1>
   <%= render partial: 'products', locals: { products: (1..9) } %>

W czym może być problem, ktos coś ?

chyba powinno być <%= …

<%= image_tag product.photo.url(:thumb)  %>

Niestety nie

w kontrolerze definiujesz:

@products = …

w widoku używasz

<% products.each_slice(3)…

używasz jakiegoś helpera ?

zamień na:

@products.each_slice(3)

brakuje: @

I tutaj masz racje.

<% @products.each_slice(3) do |slice| %>
I tak używam helpera
Będę wyswietlac 9 elementow, wiec od 1 do 9 sobie wyliczymy i uzyjemy helpera each_slice ktory nam podzieli te tablice na iles tablic, ktora kazda z nich bedzie zawierala po trzy elementy - w skrócie.

Nie wiem czemu nadal nie wyswietla mi zdjecia z FAKERA.
Baza zaladowana z seedow i wypelniona danymi,
wszystko wczytalo typu, name, opis, cena itd. lecz nie zdjecia
ktos cos?

w akcji index dodaj linijkę

render text: @products.first.photo.url(:thumb)

i wklej co dała przeglądarka

jakby dało pustą stronę to dodaj inspect na końcu

render text: @products.first.photo.url(:thumb).inspect

coś musi pokazać :slight_smile:

zwraca nil

a samo product.photo.url coś ci zwraca?

weź pod lupę store_dir

a raczej mam na myśl path generowany_przez store_dir

czy są na tym path uprawnienia do zapisu

sprawdzimy czy processing wykonał się poprawnie

czy coś fizycznie jest w katalogu uploads/product/ po seedzie bazy?

zrób w bash tree dla katalogu uploads/product
`

tree uploads/product/

pusty
przeszukam kod jeszcze

zanim ruszysz carrier_wave

bieżemy pod lupę seeds.rb

pytanie czy Faker wogóle coś robi

wycinek z seeds.rb

zrób z tego jedną linijkę i wstaw do naszego

  render text: ...

w kontrolerze

wynik poproszę

Ogółem:

product.remote_photo_url = Faker::Avatar.image(    # Generujemy losowy obrazek produktu
    product.name.parameterize,
    "640x480",                  # ma miec rozmiar
    "jpg",                      # byc w formacie jpg
    "set#{[1, 2, 3].sample}",   # obrazek ma byc wykorzystany ze wszystkich setow 1-set wyswietla roboty, 2-set twarze robotow, 3-set potworki
    "bg#{[1, 2].sample}"        # tutaj mowimy z ktorego tla losoego bedziemy korzystac
)

a po wykonaniu tego co wkleiłeś

product.remote_photo_url

dostaje url do pliku czy tylko nil ?

odpal

rails c

sprawdzimy na przykładzie czy Faker wie co ma robić w konsoli railsów

p = Product.new
p.remote_photo_url = Faker....(wszystkie parametry z twojego poprzedniego posta)

# jeżeli tu będzie nil to Faker nie umie zrobić url do pliku
p.remote_photo_url.inspect

Po odpaleniu apki i wstawieniu w jeden z widokow ( <%= render text: @products.first.photo.url(:thumb).inspect %>), dostaje nila
a w konsoli sprawdzam.
I tu masz racje, zerne na dokumentacje FAKERA
zerknij na priv

Nie no nie będę stawiał całego Twojego stacka :slight_smile:

Jesteśmy blisko z rozwiązaniem

Widze 2 drogi a raczej 3 :blush:
1.

zapominasz na chwilę że masz carrier_wave I w konsoli railsów manipulujesz parametrami Fakera aż zrozumie o co chodzi

Pomijasz Fakera wstawiasz normalnie ręcznie w uruchomionej aplikacji jakiś produkt … myślę że masz widok/akcję products/new i jakiś plik graficzny fizycznie na dysku

Jeżeli nie masz jeszcze akcji new robisz ręczny test carrier_wave uploadera na pojedynczym pliku graficznym

wybierz jakiś plik graficzny z prostą ścieżką i nazwą

w konsoli railsów:

# mam nadzieje że w development masz chodziaż jeden produkt
product = Product.first

uploader = ProductPhotoUploader.new(product, :photo)
File.open("/home/uzytkownik/..../pełna_ścieżka_do_pliku.jpg") { |img|
  uploader.store!(img)  
}

i po tym zrób wspomniane już tree w bash :slight_smile:

jak pojawi się pliik w odpowiednich subfolderach wersji to carrier_wave działa a Faker no cóż można sobie bazę spreparować ręcznie :slight_smile:

jak uploader nie utworzy ręcznie wersji to każdy processing z osobna trzeba będzie tymczasowo zakomentować żeby znaleźć winowajcę :slight_smile:

z naszych wcześniejszych postów wynika że nigdy kod nie dotarł do carrier_wave :slight_smile: więc jestem ciekaw czy pójdzie ręcznie