0

我正在製作一個rails應用程序,用戶可以在輸入字段中粘貼一個soundcloud鏈接。然後,將此鏈接發送到我的post_controller中的創建操作,並用於獲取該歌曲的JSON文件。Rails:在控制器中處理它們之前驗證參數?

# app/controllers/post_controller.rb 

def create 
    require 'open-uri' 

    raw_link = params[:post][:link] 

    raw_link.downcase.include? "soundcloud.com/" 
    tmp_media_json = JSON.load(open("http://soundcloud.com/oembed?format=json&url=#{raw_link}")) 
    if tmp_media_json['thumbnail_url']["placeholder"] 
    tmp_media_json['thumbnail_url'] = JSON.load(open("http://soundcloud.com/oembed?format=json&url=#{tmp_media_json['author_url']}"))['thumbnail_url'] 
    end 

    media_thumbnail = tmp_media_json['thumbnail_url'].gsub('t500x500.jpg', 't80x80.jpg') 
    media_title = tmp_media_json['title'] 
    media_iframe = tmp_media_json['html'] 
    media_type = params[:post][:media_type] 

    @post = Post.new(link: media_iframe, title: media_title, thumbnail: media_thumbnail, media_type: media_type) 

    respond_to do |format| 
    if @post.save 
     format.js { render :file => "/pages/create_new_post.js.erb" } 
     format.html { redirect_to @post, notice: 'Post was successfully created.' } 
     format.json { render action: 'show', status: :created, location: @post } 
    else 
     format.html { render action: 'new' } 
     format.json { render json: @post.errors, status: :unprocessable_entity } 
    end 
    end 
end 

Post模型中,我試圖運行validates :link, presence: true,但問題是,它似乎在以後創建操作所有的代碼來完成。我希望在創建操作中的所有代碼之前完成驗證。 (因爲如果沒有有效的鏈接,創建操作中的代碼將不起作用)。

我該怎麼做,或者有更好的做法?

+0

檢查這個網址:) [http://coverhound.com/blog/post/better-conditional-validations-in-rails] –

回答

0
class YourController < ApplicationController 
    before_filter :my_filter 
    before_filter :my_filter2, :except => [:index, :new, :create] 
    def my_filter 
    # your code gose here 
    end 
    def my_filter2 
    # your code gose here 
    end 
........ 
end 
1

您需要將json讀取代碼移出控制器並移入模型中。認爲單一職責原則(SRP):http://en.wikipedia.org/wiki/Single_responsibility_principle

此外,這個問題有點混淆,因爲你正在驗證來自soundcloud的JSON加載結果的「link」屬性,所以這種方式使你的問題無法實現。

話雖這麼說,保持控制器瘦

# controller... 
def create 
    @post = Post.new_from_link(params[:post][:link], params[:post][:media_type]) 
    @post.save 
    ...render... 

end 

# post model... 
class Post < ActiveRecord::Base 
    attr_accessor :raw_link, :raw_media_type 

    def new_from_link(raw_link, raw_media_type) 
    @raw_link = raw_link 
    @raw_media_type = raw_media_type 
    end 

    def assign_soundcloud_attributes 
    fetcher = SoundCloudFetcher.new(raw_link, raw_media_type).fetch 
    self.link = fetcher.link 
    self.media_type = fetcher.media_type 
    self.media_thumbnail = fetcher.media_thumbnail 
    self.media_iframe = fetcher.media_iframe 
    end 
end 

class SoundCloudFetcher 
    attr_accessor :link, :media_type, :media_thumbnail, :media_title, :media_iframe 

    def self.initialize(raw_link, raw_media_type) 
    @raw_link = raw_link 
    @raw_media_type = raw_media_type 
    end 

    def fetch 
    ...go get and set the data... 
    return self 
    end 
end 

所以上面的代碼是不完整的。它錯過了對#assign_soundcloud_attributes的實際調用。這種設計可以讓你在你想要打電話的地方移動。您可以將呼叫置於#new_from_link中,或者可以將其放置在before_validation或before_create回調中,具體取決於您的需要。

要澄清這一點的問題是你打算驗證傳入的raw_link,或者你想驗證從soundcloud api調用返回的鏈接。

如果您正在驗證原始鏈接,請將調用移至#assign_soundcloud_attributes以調用before_create回調。

如果您正在驗證從SoundCloud api調用檢索到的實際鏈接屬性,然後將其放入#new_from_link或#before_validation回調中。

0

您可以使用before_filter與rails_parms寶石。

https://github.com/nicolasblanco/rails_param

它的工作原理是這樣的:

param! :q,   String, required: true 
param! :categories, Array 
param! :sort,  String, default: "title" 
param! :order,  String, in: %w(asc desc), transform: :downcase, default: "asc" 
param! :price,  String, format: /[<\=>]\s*\$\d+/ 
相關問題