我该如何解决NoMethodError

时间:2015-01-30 11:34:55

标签: ruby-on-rails ruby ruby-on-rails-3

请帮我解决以下错误。 错误:

NoMethodError in VideosController#create

undefined method `uid=' for #<Video:0x2034f00>
Rails.root: C:/Site/tube1

Application Trace | Framework Trace | Full Trace
app/models/video.rb:8:in `block in <class:Video>'
app/controllers/videos_controller.rb:10:in `create'

应检查以下代码段以解决错误。

控制器/ videos_controller.rb

class VideosController < ApplicationController
  def index
    @videos = Video.order('created_at DESC')
  end
  def new
    @video = Video.new
  end
  def create
    @video = Video.new(params[:video])
    if @video.save
      flash[:success] = 'Video added!'
      redirect_to :action => 'index'
    else
      render 'new'
    end
  end
end

视图/视频/ new.html.erb

<div class="container">
  <h1>New video</h1>

  <%= form_for :video,:url => {:action => 'create'} do |f| %>
      <%= render 'errors', object: @video %>

      <div class="form-group">
        <%= f.label :link %>
        <%= f.text_field :link, class: 'form-control', required: true %>
        <span class="help-block">A link to the video on YouTube.</span>
      </div>

      <%= f.submit "Save video",class: 'btn btn-default' %>
  <% end %>
</div>

模型/ video.rb

class Video < ActiveRecord::Base
  attr_accessible :author, :dislikes, :duration, :likes, :link, :title
  YT_LINK_FORMAT = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/i

  before_create -> do
    uid = link.match(YT_LINK_FORMAT)

    self.uid = uid[2] if uid && uid[2]

    if self.uid.to_s.length != 11
      self.errors.add(:link, 'is invalid.')
      false
    elsif Video.where(uid: self.uid).any?
      self.errors.add(:link, 'is not unique.')
      false
    else
      get_additional_info
    end
  end

  validates :link, presence: true, format: YT_LINK_FORMAT

  private

  def get_additional_info
    begin
      client = YouTubeIt::OAuth2Client.new(dev_key:'AIzaSyDwHHcqDmPun5HStQZkMrL1DsbTbliL1-g')
      video = client.video_by(uid)
      self.title = video.title
      self.duration = parse_duration(video.duration)
      self.author = video.author.name
      self.likes = video.rating.likes
      self.dislikes = video.rating.dislikes
    rescue
      self.title = '' ; self.duration = '00:00:00' ; self.author = '' ; self.likes = 0 ; self.dislikes = 0
    end
  end

  def parse_duration(d)
    hr = (d / 3600).floor
    min = ((d - (hr * 3600)) / 60).floor
    sec = (d - (hr * 3600) - (min * 60)).floor

    hr = '0' + hr.to_s if hr.to_i < 10
    min = '0' + min.to_s if min.to_i < 10
    sec = '0' + sec.to_s if sec.to_i < 10

    hr.to_s + ':' + min.to_s + ':' + sec.to_s
  end
end

我正在使用rails版本-3.2.19和ruby 1.9.3。请帮我解决上述错误。谢谢。

2 个答案:

答案 0 :(得分:0)

您需要传递模型对象:

before_create do |video|
  uid = video.link.match(YT_LINK_FORMAT)
  if uid && uid[2]
    video.uid = uid[2]
    video.save
  end

  if video.uid.to_s.length != 11
    video.errors.add(:link, 'is invalid.')
    false
  elsif Video.where(uid: self.uid).any?
    video.errors.add(:link, 'is not unique.')
    false
  else
    video.send :get_additional_info
  end
end

#uid=方法适用于Video模型的实例,但不适用于Video本身。在block使用 hook 方法时,self本身就是Video类,而不是调用它的对象。由于selfVideo,并且没有方法Video::uid=,但Video#uid=。这就是你收到错误的原因。

答案 1 :(得分:0)

您完成了迁移吗?

rake db:migrate