0

Je fais une application rails où l'utilisateur peut coller un lien soundcloud dans un champ de saisie. Ensuite, ce lien est envoyé à l'action de création dans mon post_controller et utilisé pour obtenir le fichier JSON pour cette chanson.Rails: Valider les paramètres avant qu'ils ne soient gérés dans le contrôleur?

# 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 

Dans le modèle Post, je suis en train de courir validates :link, presence: true, mais le problème est qu'il semble être fait après tout le code dans l'action create. Je veux que la validation soit faite avant tout le code dans l'action create. (Puisque s'il n'y a pas de lien valide, le code de l'action create ne fonctionnera pas).

Comment puis-je faire cela ou existe-t-il une meilleure pratique?

+0

Cocher cette url :) [http://coverhound.com/blog/post/better-conditional-validations-in-rails] –

Répondre

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

Vous devez déplacer le code de récupération json du contrôleur vers un modèle. Think Single Responsibility Principle (SRP): http://en.wikipedia.org/wiki/Single_responsibility_principle

En outre, cette question est légèrement déroutante car vous validez l'attribut "link" qui est le résultat de la charge JSON de soundcloud, ce qui rend votre question impossible à réaliser .

Cela dit, gardez le contrôleur maigre

# 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 

Ainsi, le code ci-dessus n'est pas complète. Il manque l'appel réel à #assign_soundcloud_attributes. Cette conception vous permet de vous déplacer où vous voulez faire l'appel. Vous pouvez placer l'appel dans #new_from_link, ou vous pouvez le placer dans un rappel before_validation ou before_create, selon vos besoins. La question à résoudre est la suivante: avez-vous l'intention de valider le raw_link transmis, ou souhaitez-vous valider le lien renvoyé par l'appel api soundcloud?

Si vous validez le lien brut, déplacez l'appel vers #assign_soundcloud_attributes vers un rappel before_create.

Si vous validez l'attribut de lien réel qui est extrait de l'appel API SoundCloud, placez-le dans le rappel #new_from_link ou #before_validation.

0

Vous pouvez utiliser un before_filter avec rails_parms gem.

Voir https://github.com/nicolasblanco/rails_param

Il fonctionne comme ceci:

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+/ 
Questions connexes