新手问题 一对多关系图片显示的问题

yeyong14 · 2013年08月01日 · 最后由 xiaoniuniu 回复于 2013年08月13日 · 7199 次阅读

有两个 model,Product, Photo;

class Product < ActiveRecord::Base
has_many :photos

class Photo < ActiveRecord :: Base
belongs_to :product

现在就想在首页展示,迭代出来,但只要第一张图片

<% @products.each do |product| %>
<%= image_tag(product.photos.first.image_url) %>
<% end %>

undefined methodimage_url' for nil:NilClass` 但在 show 里面,没有迭代

<%= imge_tag(@product.photos.first.image_url) %>

居然可以显示出来。


已经解决!

controller 里给 @products 赋值了吗……

@messiahxu 我的控制器是这样的 @product = Product.new @product.photos,build

@messiahxu 当我去掉image_url 显示的是数组 [#<photo id: 1, image: "2011108xxxxx"]

楼主是不是把。写成,了?

@Teddy 哦。上面我写的地方写错了,但在控制器和视图里面没有写错

是不是数据问题,可以在 each 调试了看下数据。

controller 你写的是@product,页面循环用的@products,这能出来么?

image_url哪里定义的?而且去掉image_url后怎么可能会是数组呢?提示不是写的 for nil:NilClass吗?应该是你的product.photos的结果是一个空数组吧?

楼主是不是在 index action 里边忘了给@products挨个生成图片了,因为看你的代码

@product = Product.new
@product.photos.build

这个应该是show这个 action 里的吧? index里边是不是应该这样:

@products = Product.all
@products.each do |product|
  product.photos.build
end

最后建议楼主学一下 markdown 的排版。

楼主你应该把相关的代码全部贴出来,不应该叫回帖的人凭空乱猜你的代码有什么问题。

@Martin91 解决了。你说的很对,我是没有在 index 加入 build,谢谢你

@Martin91 你怎么让代码颜色显示的

#15 楼 @yeyong14 遵循 Markdown 的语法就行了,http://wowubuntu.com/markdown/ , 代码块是新行以 ``` 加上语言名称开头,比如我在 9 楼的回复的原文是:

@Martin91 还真谢谢你啊。又多学了一些

#17 楼 @yeyong14 不客气哈,不过你现在的这些应该还是有错误的吧?看颜色都不对

请问楼主的首页怎么写的?我是菜鸟。。。

#20 楼 @Martin91 我现在遇到的问题是 我用数据库管理 products 但是首页不显示 很郁闷。所以问问是不是要在 home.html.erb 里面调用一下 products?我是菜鸟,请不要鄙视我。。

#21 楼 @xiaoniuniu 是的,需要先在你的 action 里边读取@products,然后在你的erb文件里边处理。比如:

<% @products.each do |product| %>
  <%# render your product %>
<% end %>

#22 楼 @Martin91 我是这么做的,在 controller 里面: def index @products = Product.all end 在 viewer 的 index.html.erb 中: <% @products.each do |product| %> <%= render product.image_url%>//假设我就显示一下每个 product 的图片 <% end %> 然后我喜欢这些图片能在 localhost:3000 也就是首页中出现。 事实上是没有。。。我想问是不是我需要在 home.html.erb 中写些什么?

#23 楼 @xiaoniuniu Oh, 你应该注意一下代码的排版。用 markdown 语法。 你应该用的是:

<%= image_tag product.image_url%>

render方法是用来渲染 view 文件的,显示图片直接用image_tag。另外你的首页的route是怎么写的啊?

#24 楼 @Martin91 抱歉 刚才源代码不在身边,我自己手动敲的。。。谢谢指点,我修改了之后,可是首页(localhost:3000)还是不显示,这是为什么呢?

#23 楼 @xiaoniuniu 另外建议你不同主题的话就另开新帖吧

#25 楼 @xiaoniuniu 你首页的view代码里边是不是没有渲染@products?如果没有相关的代码,肯定就没有啊

#24 楼 @Martin91 我刚才还在 index.html.erb 尝试随便打印一些字符串,可是在首页都不显示。我不清楚我是否需要在 home.html.erb 做什么处理吗?还是我哪儿有别的问题。这个看上去很低级的问题纠缠了我几天了 5555

#28 楼 @xiaoniuniu 你的 index.html.erb 文件是在public目录下的?或者你把你config/routes.rb里的代码贴一下。肯定是你自己搞错了

#27 楼 @Martin91 首页的 view 代码就是 home.html.erb?怎么渲染@products啊?求指点!我现在就去开新主题。。。。

#29 楼 @Martin91 index.html.erb 文件是在 view/products/下

#29 楼 @Martin91 我的 config/routes.rb Mxj::Application.routes.draw do get "products/new" resources :users resources :sessions, only: [:new, :create, :destroy] resources :microposts, only: [:create, :destroy] resources :products

root to: 'static_pages#home'

get "static_pages/home" get "static_pages/faq" get "static_pages/about" get "static_pages/contact"

match '/index', to: 'products#index', via: 'get' match '/faq', to: 'static_pages#faq', via: 'get' match '/about', to: 'static_pages#about', via: 'get' match '/contact', to: 'static_pages#contact', via: 'get' match '/signup', to: 'users#new', via: 'get' match '/signin', to: 'sessions#new', via: 'get' match '/signout', to: 'sessions#destroy', via: 'delete'

#31 楼 @xiaoniuniu 那你应该在config/routes.rb文件里边指定:

root to: 'products#index'

看一下:http://guides.rubyonrails.org/v3.2.13/routing.html#using-root

#32 楼 @xiaoniuniu 你的首页都指到'static_pages#home'了,为什么是static_pages呢?你的首页是静态页面?你的首页要显示什么东西呢?

#33 楼 @Martin91 我有点搞不懂了。那我原本的static_page#home怎么办呢?

#35 楼 @xiaoniuniu 你先说说你都要在首页上显示什么咯

#36 楼 @Martin91 基本的用户注册、登陆,然后有一个瀑布流的产品展示。我现在希望在首页能有个瀑布流的产品。我用的方式是产品都通过数据库 product 处理。但是现在不知道怎么显示出来

#37 楼 @xiaoniuniu 那你就这样做吧:

# app/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
  def home
    # Other codes
    @products = Product.all
  end
end

View 的代码:

<!-- app/views/static_pages/home.html.erb -->
<% @products.each do |product| %>
  <%= image_tag product.image_url%>
<% end %>

但是建议你不要用static_pages这个名字,因为你的页面根本就不是静态页面

@Martin91 一对一教学啊

#39 楼 @yeyong14 不敢,我也是新手,分享而已,讲的也不一定对,对的也不一定是好的解决方案。

#39 楼 @yeyong14 多谢@Martin91 我受宠若惊啊!!!^_^

#40 楼 @Martin91 我按照你说的方式试了一下 有一个错误我猜是忽略了什么。。NameError: uninitialized constant StaticPagesController::Product

#41 楼 @xiaoniuniu 不客气哈,感觉你需要多读 rails guides

#42 楼 @xiaoniuniu 能贴一下你的controller的代码吗?看一下:http://ruby-china.org/topics/13152,看看如何高亮代码

#43 楼 @Martin91 不能同意更多!我解决了这个问题就回去看书了。。。。

#44 楼 @Martin91

class StaticPagesController < ApplicationController
  def home
    @products = Product.all
    if signed_in?
      @micropost  = current_user.microposts.build
      @feed_items = current_user.feed.paginate(page: params[:page])
    end

  end

  def help
  end

  def about
  end

  def contact
  end
end

@xiaoniuniu 你确实要把代码贴出来。这样好解决问题,@Martin91 已经很有耐心的教你了

#44 楼 @Martin91 我之前学了这套书http://railstutorial-china.org/ 所以在他得基础上改代码中~我对我的歪楼行径表示道歉!我只是一时半会没找到发帖的地方。下不为例!坚决不犯第二次错误。。。

Views里面home的代码呢,也一起贴出来

#46 楼 @xiaoniuniu 你的Product在哪定义的?

#50 楼 @Martin91 我...没....定义....我 generate 了一个 product 的 DB 就自己在 DB 里面加东西了

#48 楼 @xiaoniuniu 我也是从rails tutorial学起的,但是都是似懂非懂,建议你学到新的知识的时候就上http://guides.rubyonrails.org/搜一下详细的解释

#49 楼 @yeyong14


<div class="container-fluid">
   <div class="row-fluid">
       <div class="span2">
              <h2>this is on the left bar</h2>
       </div>
          <div class="span10">
               <h2>This is  the right bar</h2>
                <% @products.each do |product| %>
                <%= image_tag product.image_url%>
                <% end %>
          </div>

        </div>
    </div>

<% if signed_in? %>
<h2>
  <div class="span2">
<%= render 'shared/user_info'%>
</div>
<div class="span10">
<%= render 'shared/micropost_form'%>
<%= render 'shared/feed'%>
</div>
</h2>
             <% end %>

#51 楼 @xiaoniuniu 那肯定就报错了啊,你应该要有Product这个model的,没定义Product的话自然就报错。你是怎么 generate 数据库的?

model里面的product是怎么样

#54 楼 @Martin91 这是我的 model/products.rb 中的代码 我是不是少写了什么?

class Products < ActiveRecord::Base
  has_many :microposts
end

没有字段啊

执行一下 rails g migration add_imag_url_to_products imag_url:string

#56 楼 @xiaoniuniu 你不是少写了,你是多写了,model 是不需要复数形式的,一个 model 就是一个个体,所以把你的Products改为Product

#57 楼 @yeyong14 能不能具体一点,我实在很菜鸟

@xiaoniuniu 在终端里面执行 还有就是@Martin91 已经说了,model里面的类别是单数的

#59 楼 @Martin91 犀利啊!!!!

#58 楼 @yeyong14 运行后,这段代码会在 product.rb 中自动生成?

@xiaoniuniu 在执行那个rake migrate 如果是 rails4 以下的,需要在model里的 product 写入 attr_accessible :image_url

@xiaoniuniu 那就写入上面的代码

#66 楼 @yeyong14 不行不行 会报错。。。

#66 楼 @yeyong14 我刚看你写的 imag 少了 e 又加上上去 结果出现了更大的错误

rake aborted! An error has occurred, this and all later migrations canceled:

SQLite3::SQLException: duplicate column name: imag_url: ALTER TABLE "products" ADD "imag_url" varchar(255)/Users/joytony/.rvm/gems/ruby-2.0.0-p247/gems/sqlite3-1.3.7/lib/sqlite3/database.rb:91:in `initialize'

#59 楼 @Martin91 我按照你说的改了,不过最后出现 2 个错误都是 ActionView::Template::Error: undefined method `each' for nil:NilClass 第一次碰到。。。不懂呢~

#69 楼 @xiaoniuniu 你的数据库表里还没有数据表吧

#70 楼 @Martin91 有的 我在 console 里面确认过了,有两个数据,手动输入的:)

#70 楼 @Martin91 不对 我刚才重新搞了一下 果然没有了!Martin 能发我一个学习 git 版本控制的链接吗?我真心搞不懂这个。。。。

#72 楼 @xiaoniuniu 链接的话我也没有,书的话或许可以看一下《git 权威指南》,我自己没看过,但同事说挺好的,你可以尝试一下。你现在是自己一个人弄 rails 吗

#72 楼 @xiaoniuniu 或者你可以试下这个,是在论坛的 wiki 上找到的 http://rogerdudler.github.io/git-guide/index.zh.html

#74 楼 @Martin91 好的,我自己一个人在学,自己也感觉问的问题有点对不住大家。。。面壁去!刚才的问题解决了。我可以在首页显示 product 了。多谢多谢哈~

#75 楼 @xiaoniuniu 提问是好事,只不过提问前可以适当考虑先尽量通过谷歌或者官方文档解决你的问题,实在搞不定了就发问,没有什么对不对得住的。

#66 楼 @yeyong14 我和你采用类似的处理方法,不过我想在产品页遍历相关的图片信息,这么写对吗?

<div class="col-lg-7">
                <div class='img-polaroid'>
                 <%= i = 0 %>
                 <% if @products.photos[i].product_id == @products.id%>
                     <%= image_tag(@products.photos[i].image_url) %>
                     <%= i =+ 1  %>
                <%else%>
                break
                <% end %>

                </div>

#9 楼 @Martin91 我还是有问题~ 我有 product 和 photo 两个 model,和楼主基本一样,image_url 在 photo 中 product_controller.rb

class ProductsController < ApplicationController

  def index
    @products = Product.all
    @products.each do |product|
    product.photos.build
    end
    end

    def show
      @products = Product.find(params[:id])
      @products.photos.build

    end
  end

show.html.erb

<%= image_tag(@products.photos.image_url) %>

出错说是:undefined method `image_url' for # 如果把 products.photos[0].image_url 就能显示图片了 可是我的每个 product 都对应不同的 photo,所以。。。我不会处理了。。求解释

#78 楼 @xiaoniuniu 原因很明显啊,你的productphoto是一对多的关系吧,那你@products.photos返回的就是多个photo的集合了,而不是单纯的一个Photo的实例,所以报undefined_method异常。而你products.photos[0]则是得到了集合中的第一个元素,也就是一个Photo的实例,这时候再调用image_url自然就没问题了。既然是一对多关系,你就要遍历一下所有photo了,如:

<%= @products.photos.each do |photo| %>
  <%= image_tag photo.image_url %>
<% end %>

PS: 如果是单个的 product 的话,干嘛要用复数呢??

#79 楼 @Martin91 厉害厉害!我果然还是没有搞的特别懂。。。问题解决了~谢谢!我用数据库管理 product 的,所以有很多 product,哈哈就用复数了:)

#80 楼 @xiaoniuniu 数据库里肯定是有很多 products,但是你在 show 页面应该只是取出一个 product 而已

@products = Product.find(params[:id])

这个取到的是Product的一个实例。

#81 楼 @Martin91 哈哈 是的是的!我想用 pinterest 首页做展示,然后就挑了http://www.wookmark.com/ 插件。不过我在处理图片的时候,发现他的 index.html 是一张一张图片处理的,而不能用之前我们讨论的代码批量处理。

<% @products.each do |product| %>
<%= image_tag(product.photos.first.image_url) %>
<% end %>

我理解的对吗?我觉得一张一张图片 key 到首页好麻烦的啊~而且怎么控制图片的大小呢(需要安装别的插件吗)?还是说我理解的有问题。

抱歉我是新手,还没有资格自己发帖。我想这个贴就是在讨论图片处理,所以就蹭一下@yeyong14 的宝地啦~顺带感谢一下@yeyong14 :)

#82 楼 @xiaoniuniu 哎哟,你的链接能修改一下吗,排版都乱了。

我觉得一张一张图片 key 到首页好麻烦的啊

这个真不明白你的意思 图片处理可以用carrierwave 或者是paperclip。再结合 css 控制就够了。

另外,你是想要有瀑布流的布局吧?这个的话你可以上网谷歌一下,有很多 jquery 插件已经实现了。

#83 楼 @Martin91 我把所有关于产品的信息都放在数据库里面了(我后台手动在数据库中输入的) 之前在首页调用每个产品第一张图的时候,我用

<%=  image_tag(@product.photos.first.image_url) %>

就可以,但是这段代码 https://github.com/GBKS/Wookmark-jQuery/blob/master/example/index.html 这个应该就是你说的 jquery 的某一个插件吧。

<div id="container">
    <header>
      <h1>jQuery Wookmark Plug-in Example</h1>
      <p>Resize the browser window or click a grid item to trigger layout updates.</p>
    </header>
    <div id="main" role="main">

      <ul id="tiles">
        <!-- These are our grid blocks -->
        <li><img src="../sample-images/image_1.jpg" width="200" height="283"><p>1</p></li>
        <li><img src="../sample-images/image_2.jpg" width="200" height="300"><p>2</p></li>
        <li><img src="../sample-images/image_3.jpg" width="200" height="252"><p>3</p></li>
        <li><img src="../sample-images/image_4.jpg" width="200" height="158"><p>4</p></li>
        <li><img src="../sample-images/image_5.jpg" width="200" height="300"><p>5</p></li>
        <li><img src="../sample-images/image_6.jpg" width="200" height="297"><p>6</p></li>
        <li><img src="../sample-images/image_7.jpg" width="200" height="200"><p>7</p></li>
        <li><img src="../sample-images/image_8.jpg" width="200" height="200"><p>8</p></li>
        <li><img src="../sample-images/image_9.jpg" width="200" height="398"><p>9</p></li>
        <li><img src="../sample-images/image_10.jpg" width="200" height="267"><p>10</p></li>
        <li><img src="../sample-images/image_1.jpg" width="200" height="283"><p>11</p></li>
        <li><img src="../sample-images/image_2.jpg" width="200" height="300"><p>12</p></li>
        <li><img src="../sample-images/image_3.jpg" width="200" height="252"><p>13</p></li>
        <li><img src="../sample-images/image_4.jpg" width="200" height="158"><p>14</p></li>
        <li><img src="../sample-images/image_5.jpg" width="200" height="300"><p>15</p></li>
        <li><img src="../sample-images/image_6.jpg" width="200" height="297"><p>16</p></li>
        <li><img src="../sample-images/image_7.jpg" width="200" height="200"><p>17</p></li>
        <li><img src="../sample-images/image_8.jpg" width="200" height="200"><p>18</p></li>
        <li><img src="../sample-images/image_9.jpg" width="200" height="398"><p>19</p></li>
        <li><img src="../sample-images/image_10.jpg" width="200" height="267"><p>20</p></li>
        <li><img src="../sample-images/image_1.jpg" width="200" height="283"><p>21</p></li>
        <li><img src="../sample-images/image_2.jpg" width="200" height="300"><p>22</p></li>
        <li><img src="../sample-images/image_3.jpg" width="200" height="252"><p>23</p></li>
        <li><img src="../sample-images/image_4.jpg" width="200" height="158"><p>24</p></li>
        <li><img src="../sample-images/image_5.jpg" width="200" height="300"><p>25</p></li>
        <li><img src="../sample-images/image_6.jpg" width="200" height="297"><p>26</p></li>
        <li><img src="../sample-images/image_7.jpg" width="200" height="200"><p>27</p></li>
        <li><img src="../sample-images/image_8.jpg" width="200" height="200"><p>28</p></li>
        <li><img src="../sample-images/image_9.jpg" width="200" height="398"><p>29</p></li>
        <li><img src="../sample-images/image_10.jpg" width="200" height="267"><p>30</p></li>
        <!-- End of grid blocks -->
      </ul>

    </div>
  </div>

这是不是意味着我用瀑布流的时候,首页的每一张图片都需要手动输入地址呢?比如第一张图,我就输入 app/assets/images/001.jpg?而不可以直接用循环语句调用吗? 而且事实上我每张图的宽度和高度后台都不知道 应该怎么处理呢?

类似的问题还出现在文本编译上。我把 product 相关的文字也放在 product 的数据库中了。我只能“一坨一坨”的显示文字,不知道在首页应该用什么工具来调整文字格式。

哈哈 不知道我这样表述是否清楚。

#84 楼 @xiaoniuniu 肯定是要代码遍历的啊,如果不能遍历,就一定是代码有问题。尺寸问题可以先统一一个高度或者宽度,其他的应该交给插件处理就可以了。或者是用 gem 包处理成同样的尺寸。

#85 楼 @Martin91 那你觉得 https://github.com/GBKS/Wookmark-jQuery/blob/master/example/index.html 这个代码是不是有问题呢?因为我看着觉得图片的路径不一样,每个图片对应的尺寸也不一样。那不是就只能手动输入不能遍历了吗?

#86 楼 @xiaoniuniu 你的图片是怎么存储的?难道不是后台上传的吗?

#87 楼 @Martin91 我建立了一个 product 和一个 photo 的数据库(之间关系就是 belong_to 和 has_mang),然后我在 photos.image_url 手动在输了图片的名字比如 001.jpg 然后把 001.jpg 拷贝到 app/asset/images 的文件夹下面。我这样做是不是有问题?哎呀...我晕了

#88 楼 @xiaoniuniu 问题很大,你要明白,放在 app/assets/images 目录下的文件是要经过预编译的,而且也不符合规范。产品图片应该是由程序来管理的,不应该是你去手工输入的。你这个项目是不是开源项目啊?我觉得直接给你提交 PR 会更直观点,一直这样说也很麻烦。

#89 楼 @Martin91 不是开源呢。。直接邮件你了~

需要 登录 后方可回复, 如果你还没有账号请 注册新账号