Rails 4:从Javascript调用的动作没有看到模型关联(NoMethodError)

时间:2016-04-13 20:44:19

标签: javascript jquery ruby-on-rails ruby-on-rails-4

我正在研究" Rails:Up&跑步,第2版。",http://shop.oreilly.com/product/9780596522018.do。我是Javascript的新手,对Rails中的关联经验有限。

我正在尝试使用Rails 4中的jQuery而不是原始中使用的Prototype来实现幻灯片循环。

当我从' show.rs.erb'调用show_slide操作时,Rails没有看到关联:

NoMethodError (undefined method `slides' for #<Hash:0x007f8f71d49a60> Did you mean? slice slice!)

使用pry我可以看到session[:slideshow]session[:slide_index]包含正确的值。

我很感激任何建议。

谢谢!

**雷

以下是解决方案:

def show
  @slideshow = Slideshow.find(params[:id])
  session[:slideshow_id] = params[:id]
  session[:slide_index] = 0
  @slide = @slideshow.slides[0]
end

def show_slide
  @slideshow = Slideshow.find(session[:slideshow_id])
  session[:slide_index] += 1
  @slide = @slideshow.slides[session[:slide_index]] 
  if @slide == nil 
     session[:slide_index] = 0 
     @slide = @slideshow.slides[0] 
  end 
  render :partial => "show_slide"
end

代码详情

show.js.erb:

$(document).ready(
  function(){
    setInterval(function(){
      $('#slides').load('/show_slide');
    }, 2000);
  });

幻灯片#show_slide:

  def show_slide
    @slideshow = session[:slideshow]
    session[:slide_index] += 1
    # binding.pry
    @slide = @slideshow.slides[session[:slide_index]] # => NoMethodError (undefined method `slides' for #<Hash:0x007f8f71d49a60> Did you mean? slice slice!)
    if @slide == nil
      session[:slide_index] = 0
      @slide = @slideshow.slides[0]
    end
    render :partial => "show_slide"
  end

&#34; slideshow.slides&#34;关联适用于views / slideshows / index.html.erb:

<% for slideshow in @slideshows %> 
  <div class="slideshow-summary"> 
    <div class="slideshow-caption"> 
        <strong><%= slideshow.name %> </strong>
      <small>(<%= slideshow.slides.size %> slides)</small> 
    </div> 
    <div class="slideshow-thumbnails"> 
      <% 5.times do |i| -%> 
        <%= thumbnail_tag slideshow.slides[i] %> 
      <% end -%> 
      &nbsp;<strong>. . .</strong> 
    </div> 
    <div class="slideshow-controls"> 
        <%= link_to 'Play', slideshow, :remote => true %> 
        <%= link_to 'Edit', edit_slideshow_path(slideshow) %> 
        <%= link_to 'Delete', slideshow, :confirm => 'Are you sure?', :method => :delete %> 
    </div> 
  </div> 
  <br /> 
<% end %> 

但不在这里:

# class SlideshowsController < ApplicationController
def show_slide
  @slideshow = session[:slideshow]
  session[:slide_index] += 1
  # binding.pry
  @slide = @slideshow.slides[session[:slide_index]] # NoMethodError (undefined method `slides' for #<Hash:0x007fa574ac11d0> Did you mean? slice slice!)

  if @slide == nil
    session[:slide_index] = 0
    @slide = @slideshow.slides[0]
  end
  render :partial => "show_slide"
end

show_slide.html.erb:

<%= image_tag "photos/#{@slide.photo.filename}" %>
<h4><%= get_photo_name_from_filename(@slide.photo) %></h4>

show.html.erb:

<p><i><%= @slideshow.name %></i></p>
<% if @slide %>
<div id="slides">
  <%= render :partial => "show_slide"%>
</div>
<% end %>

幻灯片#显示:

# class SlideshowsController < ApplicationController
  def show
    @slideshow = Slideshow.find(params[:id])
    session[:slideshow] = @slideshow
    session[:slide_index] = 0
    @slide = @slideshow.slides[0]
  end

型号:

class Slideshow < ActiveRecord::Base
  has_many  :slides
end

class Photo < ActiveRecord::Base
  has_many :slides
  has_and_belongs_to_many :categories

  validates_presence_of :filename 

    scope :with_filetype_jpg, lambda {{:conditions => "filename like '%.jpg'" }}
  scope :with_thumbnail, lambda {{:conditions => "thumbnail not null and thumbnail != ''"}}
  scope :with_filetype, 
    lambda {|ftype| {:conditions => ["filename like ?", "%.#{ftype}"] } } 
end

class Slide < ActiveRecord::Base
  belongs_to  :slideshow
  belongs_to  :photo

  acts_as_list  :scope => "slideshow_id"
end

的Gemfile:

source 'https://rubygems.org'
gem 'rails', '4.2.5.2'
gem 'sqlite3'
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
group :development, :test do
  gem 'byebug'
end
group :development do
  gem 'better_errors'
  gem 'binding_of_caller'
  gem 'meta_request'
  gem 'pry-rails'
  gem 'spring'
end
gem 'bootstrap-sass'
gem 'bootstrap-generators', '~> 3.3.4'
gem 'acts_as_list'
gem 'acts_as_tree'

调试器会话:

slideshows_controller.rb @ line 15 SlideshowsController#show:

    12: def show
    13:   @slideshow = Slideshow.find(params[:id])
    14:   session[:slideshow] = @slideshow
 => 15:   binding.pry
    16:   session[:slide_index] = 0
    17:   @slide = @slideshow.slides[0]
    18: end

[1] pry(#<SlideshowsController>)> @slideshow
=> #<Slideshow:0x007f86dce8c320
 id: 1,
 name: "Interesting Pictures",
 created_at: Thu, 24 Mar 2016 21:03:56 UTC +00:00,
 updated_at: Thu, 24 Mar 2016 21:03:56 UTC +00:00>
[2] pry(#<SlideshowsController>)> session[:slideshow]
=> #<Slideshow:0x007f86dce8c320
 id: 1,
 name: "Interesting Pictures",
 created_at: Thu, 24 Mar 2016 21:03:56 UTC +00:00,
 updated_at: Thu, 24 Mar 2016 21:03:56 UTC +00:00>
[3] pry(#<SlideshowsController>)> exit
slideshows_controller.rb @ line 23 SlideshowsController#show_slide:

    21: def show_slide
    22:   @slideshow = session[:slideshow]
 => 23:   binding.pry
    24:   session[:slide_index] += 1
    25:   @slide = @slideshow.slides[0]
    26:   # @slide = @slideshow.slides[session[:slide_index]]
    27:   if @slide == nil
    28:     session[:slide_index] = 0
    29:     @slide = @slideshow[:slides][0]
    30: 
    31:     # @slide = @slideshow.slides[0]
    32:   end
    33:   render :partial => "show_slide"
    34: end

[1] pry(#<SlideshowsController>)> @slideshow
=> {"id"=>1,
 "name"=>"Interesting Pictures",
 "created_at"=>"2016-03-24T21:03:56.000Z",
 "updated_at"=>"2016-03-24T21:03:56.000Z"}
[2] pry(#<SlideshowsController>)> session[:slideshow]
=> {"id"=>1,
 "name"=>"Interesting Pictures",
 "created_at"=>"2016-03-24T21:03:56.000Z",
 "updated_at"=>"2016-03-24T21:03:56.000Z"}
[3] pry(#<SlideshowsController>)> 

1 个答案:

答案 0 :(得分:0)

如果@slideshow是哈希,则需要使用密钥访问其内容(例如,不像在javascript中那样使用点符号)。

@slideshow[:some_key]

修改

但在您的情况下,您需要一个模型实例,因此您实际上希望从数据库而不是从会话对象加载@slideshow

将幻灯片的ID存储在会话中(假设您需要跨请求访问它),然后在后续请求中通过该ID读取数据库。

您还可以在会话中存储幻灯片中所需的任何相关信息,并避免每次都从数据库中读取。但总的来说,你要小心你在会话中存储的内容。请参阅Rails session security