Rails:belongs_to和has_one关联创建的方法

时间:2012-09-11 03:54:16

标签: ruby-on-rails

我正在缩短网球作为学习练习。除了访问模型(这个问题并不重要),它还有一个Url和一个链接模型,我已经加入了协会。 Url类属于Link,Link类属于has_one:url。

简而言之,问题是当我在Link类中调用shorten方法时(来自Url控制器中的create方法),我收到此错误消息

undefined method `link' for #<ActiveRecord::Relation:0x00000102f648b8>

应用程序跟踪指向Link类的'shorten'方法中的这一行(下面复制)

return url.link if url 

所以,我理解这个错误意味着我不能在'url'上调用'link'。但是,我认为我创建的协会将允许我这样做。你能解释一下我做错了吗

相关代码

新表格

<%= simple_form_for @url do |f| %>
  <%= f.input :original,  :label => 'Original Link', :input_html => { :maxlength => 70 } %>
  <%#= f.input :custom,  :label => '(Optional) Create your own custom shortened link ' %>
  <%= f.button :submit %>
<% end %>

创建方法url controller

def create
    @url = Url.new(params[:url])
    @link = Link.shorten(@url) 

    respond_to do |format|
      if @url.save
        format.html { redirect_to action: "index", notice: 'Url was successfully created.' }
        format.json { render json: @url, status: :created, location: @url }
      else
        format.html { render action: "new" }
        format.json { render json: @url.errors, status: :unprocessable_entity }
      end
    end

  end

网址类

class Url < ActiveRecord::Base
  attr_accessible :original

  belongs_to :link
end

使用缩短方法链接类

class Link < ActiveRecord::Base
  attr_accessible :identifier
  has_one :url
  has_many :visits


  def self.shorten(original, custom=nil)
    url = Url.find_by_original(original) 

    return url.link if url        #this is the problem line
    link = nil
    if custom
      raise 'Someone has already taken this custom URL, sorry' unless Link.find(:identifier => custom).nil?  #this  Link.find
      raise 'This custom URL is not allowed because of profanity' if DIRTY_WORDS.include? custom
      transaction do |txn|
        link = Link.new(:identifier => custom)
        link.url = Url.create(:original => original)
        link.save        
      end
    else
      transaction do |txn|
        link = create_link(original)
      end    
    end
    return link
  end

3 个答案:

答案 0 :(得分:1)

您在创建之前将@url传递给Link.shorten。所以你在一个nil对象上调用link方法。

如果您希望它可以使用,则需要将其放在@url.save之后。

答案 1 :(得分:1)

Url.new(params[:url])方法中的create正在创建ActiveRecord对象,但尚未向数据库保存任何内容。 Url.find_by_original(original)方法中的shorten正在搜索数据库中的urls表,但找不到一个,因为尚未使用该original保存网址。在调用url之前,您需要先保存shorten

答案 2 :(得分:0)

您正在将@url传递给Link.shorten,而不是传递original网址字符串,并尝试通过将@url objectoriginal字段匹配来查找现有网址。由于某种原因(我不知道原因)会返回ActiveRecord::Relation,而不是您期望的nil

我认为你应该在这里更改代码:

@link = Link.shorten(@url) 

@link = Link.shorten(@url.original) 

我认为您不必首先保存@url,因为您只查找已存储的网址,而是要添加的新网址。