Rails 4:将属性的值传递给模型以进行动态防病毒

时间:2016-07-10 13:23:19

标签: ruby-on-rails validation model controller attributes

在我的“入门”模式中......

class Entry < ActiveRecord::Base

...我试图将属性的值直接传递给下面的数据验证(动态更新的属性是':wpu',值是基于用户表单提交的整数。有三个用户从下拉菜单中选项将提交':wpu'的值;为了进行此对话,请考虑“5”,“10”或“20”的值。

validates :text, length: { is: DYNAMIC_VALUE_WOULD_GO_HERE,
    tokenizer: lambda { |str| str.squish.gsub('&'){''}.scan(/\w+/) }
    }

当字符串属性的字数':text'等于前面提到的另一个属性':wpu'的整数时,这将验证。如果我用'5','10'或'20'替换'DYNAMIC_VALUE_WOULD_GO_HERE',上面的代码是完美的,但我没有成功根据用户的输入在那里放置动态值。

我已经做了这件事 - 可能有一个简单的答案 - 现在已经3天了,但没有成功。

我尝试过的事情:

1)使用attr_reader并调用属性值 2)将控制器方法参数传递给模型

我对任何建议和其他方法持开放态度。我是红宝石和铁轨的初学者。

这是我的完整型号代码。它目前不起作用,因为我无法通过'params'。否则,如果我删除下面的随机实验方法,不试图使这个动态,一切正常。

    class Entry < ActiveRecord::Base
    belongs_to :story
    attr_reader :wpu

    #method used to generate 'wpu' | which is words per user in Story
    def self.storywpu

        #story ID from EntriesController
        current_entry_story_id = Entry.find(params[:id]).story_id

        #returns 'wpu' | which is words per user in Story
        storywpu = Story.find(current_entry_story_id).wpu

        return storywpu
    end

    #strips ALL white space before form submission
    auto_strip_attributes :text, :nullify => false, :squish => true

    #validates each field has been filled out
    validates :user_id, presence: true
    validates :story_id, presence: true
    validates :text, presence: true, autocomplete: false

    #validates word count is exactly 'wpu' | which is words per user in Story
    validates :text, length: { is: self.storywpu,
        tokenizer: lambda { |str| str.squish.gsub('&'){''}.scan(/\w+/) }
        }
end

这是我的控制器的一个相关部分供参考......

class EntriesController < ApplicationController
   before_action :set_entry, only: [:show, :edit, :update, :destroy]

def create 

    #New text entry
    @entry = Entry.create(entry_params)
    #Related story params
    @story = Story.find(@entry.story_id)
    @storyWPU = Story.find(@entry.story_id).wpu
    @word_count = @entry.text.squish.gsub('&'){''}.scan(/\w+/).size.to_i
    @wordsLeft = @storyWPU - @word_count


    if @word_count.nil?
        @response = 'enter ' + @wordsLeft.to_s + ' words'
    elsif @wordsLeft == 1
        @response = 'enter ' + @wordsLeft.to_s + ' word'
    elsif @wordsLeft < 0
        @response = @wordsLeft.abs.to_s + ' too many!'
    else
        @response = 'enter ' + @wordsLeft.to_s + ' words'
    end

    respond_to do |format|

        if @entry.save
            format.html { redirect_to edit_story_path(@story), notice: 'Nice!' }
            format.json { render :show, status: :created, location: @entry }
        else
            format.html { redirect_to edit_story_path(@story), notice: @response }
            format.json { render json: @entry.errors, status: :unprocessable_entity }
        end
    end
end

    private    
    def set_entry
      @entry = Entry.find(params[:id])
    end

    private
    def entry_params
      params.require(:entry).permit(:text, :user_id, :story_id, :wpu)
    end
end

1 个答案:

答案 0 :(得分:0)

我认为这一切都错了。我通过将动态验证虚拟地移动到控制器中来解决这个问题。基本上,如果在文本字段中提交的单词数量与属性值之一不匹配,我试图避免保存到数据库。

现在一切正常。这是我的控制器&#39;创建&#39;代码供参考......

def create 

    #New entry
    @entry = Entry.new(entry_params)

    #story variables
    @story = Story.find(@entry.story_id)
    @storyWPU = Story.find(@entry.story_id).wpu
    @word_count = @entry.text.squish.gsub('&'){''}.scan(/\w+/).size.to_i
    @wordsLeft = @storyWPU - @word_count

    if @word_count.nil?
        @response = 'enter ' + @wordsLeft.to_s + ' words'
    elsif @wordsLeft == 1
        @response = 'enter ' + @wordsLeft.to_s + ' word'
    elsif @wordsLeft < 0
        @response = @wordsLeft.abs.to_s + ' too many!'
    else
        @response = 'enter ' + @wordsLeft.to_s + ' words'
    end

    respond_to do |format|

        if @wordsLeft == 0 && @entry.save
            format.html { redirect_to edit_story_path(@story), notice: 'Nice!' }
            format.json { render :show, status: :created, location: @entry }
        else
            format.html { redirect_to edit_story_path(@story), notice: @response }
            format.json { render json: @entry.errors, status: :unprocessable_entity }
        end
    end
end