How to Remove Validation Using Instance_Eval Clause in Rails

How to remove validation using instance_eval clause in Rails?

I found a solution, not sure how solid it is, but it works well in my case. @aVenger was actually close with his answer. It's just that the _validators accessor contains only information used for reflection, but not the actual validator callbacks! They are contained in the _validate_callbacks accessor, not to be confused with _validations_callbacks.

Dummy.class_eval do
_validators.reject!{ |key, _| key == :field }

_validate_callbacks.reject! do |callback|
callback.raw_filter.attributes == [:field]
end
end

This will remove all validators for :field. If you want to be more precise, you can reject the specific validator for _validators which is the same as the raw_filter accessor of validate callbacks.

How to change self in a block like instance_eval method do?

You can write a method that accepts a proc argument, and then pass that as a proc argument to instance_eval.

class Foo
def bar(&b)
# Do something here first.
instance_eval &b
# Do something else here afterward, call it again, etc.
end
end

Foo.new.bar { puts self }

Yields

#<Foo:0x100329f00>

Rails - Skipping one validation

You need to set that variable before hand, it can't be checked on valid. Likewise, when using a method with a question mark you need to put the question mark before the parentheses.

Model:

attr_accessor :skip_event_id

Controller:

new_lot.skip_event_id = true
if new_lot.valid?
# some stuff
end

How to raise validation errors from Rails Controller?

Look into before_filter, which can choose to render or redirect, or simply set some internal state (@captcha_failed = true) before your action is invoked.

You might want something like this:

class MyController < ApplicationController

before_filter :check_captcha

# ...

protected

def check_captcha
if params[:captcha] != request.env['recaptcha.valid']
redirect_to "index", notice: "Invalid captcha"
end
end

end

Devise - how to change setting so that email addresses don't need to be unique

Look in the config/initializers/devise.rb. You can change the default authentication key, which by default is :email to be anything you want, for example:

config.authentication_keys = [ :username ]

What do you call if: - { status_change? && finished? } in ruby?

Wow, there's a lot in your question...

Ruby allows you to put single line if statements at the end of a line. The preceding statement is only executed if the if statement returns true. These are often used for "guard clauses". But that's not exactly what's happening here...

Ruby also lets you drop the parentheses around method calls if it can infer exactly what the parameters are. Instead of typing sum(a, b) you can type sum a, b. It's one of the things that makes Ruby great for writing "Domain Specific Languages" like Rake and parts of ActiveRecord. Thoughtbot has a good article on them.

Because of this, that line could be rewritten:

before_validation(:start_at, if: -> { status_change? && finished? })

In this case, before_validation is an ActiveRecord callback. From that link, "Callbacks are methods that get called at certain moments of an object's life cycle. With callbacks it is possible to write code that will run whenever an Active Record object is created, saved, updated, deleted, validated, or loaded from the database."

In this case what you have is a "conditional callback". The start_at method (which you'll probably find defined at the bottom of the model file, or perhaps somewhere else, search the codebase for "def start_at") only gets called if the condition passes.

Regarding the condition itself, status_change? and finished? are also both methods. The question mark at the end is a Ruby convention to say this method returns a boolean. The && is Boolean logic to say that the whole conditional will return true if and only if both status_change? and finished? return true.

So, to state what this line of code does in plain English:

  • Before ActivRecord checks to see if the model is valid
  • run the start_at method...
  • ...but only if the status_change? method and finished? method both evaluate to true

Under the covers, the way this works is by passing a "lambda" as a parameter to the method. In this case it's using the "stabby lambda" syntax introduced back in Ruby 1.9. Check out The Ultimate Guide to Blocks, Procs and Lambdas and Using Lambdas in Ruby for more information.

Is it possible to directly save this file to ActiveStorage?

Looking at the gem documentation, looks like you don't need to use the write method but instead use to_s method which should create the xml string which you can then use Tempfile to upload with active storage:

Here's the to_s method

def to_s(update_time = true)
@time = Time.now if @time.nil? || update_time
doc = generate_xml_doc
doc.to_xml
end

#so assuming you have something like this:

bounds = GPX::Bounds.new(params)

file = Tempfile.new('foo')
file.path # => A unique filename in the OS's temp directory,
# e.g.: "/tmp/foo.24722.0"
# This filename contains 'foo' in its basename.
file.write bounds.to_s
file.rewind
@message.image.attach(io: file.read, filename: 'some_s3_file_name.xml')
file.close
file.unlink # deletes the temp file

UPDATED (thanks @Matthew):

But you may not even need the tempfile, this will probably work

bounds = GPX::Bounds.new(params)
@message.image.attach(io: StringIO.new(bounds.to_s), name: 'some_s3_file_name.xml')


Related Topics



Leave a reply



Submit