我正在缩短网球作为学习练习。除了访问模型(这个问题并不重要),它还有一个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
答案 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 object
与original
字段匹配来查找现有网址。由于某种原因(我不知道原因)会返回ActiveRecord::Relation
,而不是您期望的nil
。
我认为你应该在这里更改代码:
@link = Link.shorten(@url)
到
@link = Link.shorten(@url.original)
我认为您不必首先保存@url
,因为您只查找已存储的网址,而是要添加的新网址。