Ruby on rails Rails:在控制器中处理参数之前验证参数?

Ruby on rails Rails:在控制器中处理参数之前验证参数?,ruby-on-rails,validation,ruby-on-rails-4,actioncontroller,Ruby On Rails,Validation,Ruby On Rails 4,Actioncontroller,我正在制作一个rails应用程序,用户可以将soundcloud链接粘贴到输入字段中。然后,该链接被发送到mypost_controller中的create操作,并用于获取该歌曲的JSON文件 # app/controllers/post_controller.rb def create require 'open-uri' raw_link = params[:post][:link] raw_link.downcase.include? "soundcloud.com/"

我正在制作一个rails应用程序,用户可以将soundcloud链接粘贴到输入字段中。然后,该链接被发送到my
post_controller
中的create操作,并用于获取该歌曲的JSON文件

# 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
,但问题是它似乎是在create操作中的所有代码之后完成的。我希望在创建操作中的所有代码之前完成验证。(因为如果没有有效的链接,创建操作中的代码将无法工作)

我如何才能做到这一点,或者有更好的做法吗?

class YourControllerclass 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
前\u过滤器:我的\u过滤器 在\u筛选器之前:我的\u筛选器2,:except=>[:index,:new,:create] def my_过滤器 #你的密码在这里 结束 def my_过滤器2 #你的密码在这里 结束 ........ 结束
您需要将json获取代码移出控制器并放入模型中。思考单一责任原则(SRP):

另外,这个问题有点让人困惑,因为您正在验证“link”属性,它是从soundcloud加载JSON的结果,所以这类问题使您的问题无法实现

也就是说,保持控制器倾斜

# 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 
#控制器。。。
def创建
@post=post.new_from_link(参数[:post][:link],参数[:post][:媒体类型])
@邮政储蓄
…渲染。。。
结束
#后模型。。。
类Post
所以上面的代码并不完整。它缺少对#assign_soundcloud_属性的实际调用。这种设计可以让你在想打电话的地方四处走动。您可以将调用放入#new_from_链接中,也可以根据需要将调用放入#验证前或#创建前回调中

要澄清这一点的问题是,您是想验证传入的原始链接,还是想验证从soundcloud api调用返回的链接

如果要验证原始链接,请将调用移动到#assign_soundcloud_attributes to a before_create回调


如果要验证从SoundCloud api调用中检索到的实际链接属性,请将其放入#new#u from_link或#before_validation回调中。

您可以将before_过滤器与rails_parmsgem一起使用

它的工作原理如下:

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+/
param!:q、 字符串,必填:true
param!:类别,数组
param!:排序,字符串,默认值:“标题”
param!:顺序,字符串,输入:%w(asc desc),转换::downcase,默认值:“asc”
param!:价格,字符串,格式:/[]\s*\$\d+/
检查此url:)[