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 andfinished?
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
Ruby Strftime: Month Without Leading Zero
Why Should I Use Rspec or Shoulda with Rails
Rails: Ensure Only One Boolean Field Is Set to True at a Time
How to Reflect in the Database a New Belongs_To and Has_Many Relationship in Ruby on Rails
How to Get Searchlogic to Work with Rails 3
How to Export a Ruby Array from My Heroku Console into CSV
Gem Dependencies Versions Meaning
Testing Actionmailer Multipart Emails(Text and HTML Version) with Rspec
How to Fire and Forget a Subprocess
Namespacing Thor Commands in a Standalone Ruby Executable
Can't Convert Fixnum to String During Rake Db:Create
Sidekiq List All Jobs [Queued + Running]