Rails 4:从Javascript调用的操作看不到模型关联(NoMethodError)



我正在处理"轨道:向上&Running,第二版";,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]包含正确的值。

如果有任何建议,我将不胜感激。

谢谢!

**Leigh


以下是解决方案:

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

";幻灯片;协会工作在视图/幻灯片/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 %>

幻灯片#show:

# 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>)> 

如果@slideshow是哈希,则需要使用键访问其内容(例如,不要像javascript中那样使用点表示法)。

@slideshow[:some_key]

编辑:

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

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

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

最新更新