Rails nested with_option :if used in validation
You are right that when nesting two :if conditions, the inner one will replace the outer one and always be checked. A workaround to handle two levels of nesting is:
with_options :unless => !(outer condition) do
with_options :if => (inner condition) do
The if and unless conditions do not overwrite each other. I'm not sure I would call this a bug, but it would be nice if you could nest multiple :if conditions.
Send data from radio button to controller for validation of nested attribute value in Rails
- In your snippet, 'Check Answer' is merely a link. Since you want to send multiple attributes when clicking on it, you probably want to submit a form instead.
- The second parameter of
radio_button_tag
is the value that your controller will receive in the params. Instead ofp.is_answer
, you probably want to havep.id
.
Documentation for forms
Documentation for radio buttons
P.S. on why you should send the option's id instead: I'm not sure what your business use case is, but if you want to identify which option the user picked, you want to send an option identifier, i.e. the id
of the option. Furthermore, a user can send this param without knowing which option is correct. If this is school test, a student could then cheat :)
Error in custom uniqueness validation for rspec
I have a guess at what's happening. I think a fix would be to change your validation with the following line:
product.variants.reload.each do |v|
What I think is happing is that when you call variant1
in your test, it is running the validation for variant1, which calls variants
on the product object. This queries the database for related variants, and gets an empty result. However, since variant2 has the same actual product object, that product object will not re-query the database, and remembers (incorrectly) that its variants is an empty result.
Another change which might make your test run is to change your test as follows:
before do
@variant2 = FactoryBot.create(:variant, product_id: product.id, option_values: variant1.option_values)
end
It is subtle and I'd like to know if it works. This sets the product_id
field on variant2, but does not set the product
object for the association to be the actual same product
object that variant1 has. (In practice this is more likely to happen in your actual code, that the product object is not shared between variant objects.)
Another thing for your correct solution (if all this is right) is to do the reload but put all your save code (and your update code) in a transaction. That way there won't be a race condition of two variants which would conflict, because in a transaction the first must complete the validation and save before the second one does its validation, so it will be sure to detect the other one which just saved.
Some suggested debugging techniques:
- If possible, watch the log to see when queries are made. You might have caught that the second validation did not query for variants.
- Check the
object_id
. You might have caught that the product objects were in fact the same object. - Also check
new_record?
to make sure that variant1 saved before you tested variant2. I think it does save, but it would have be nice to know you checked that.
accessing data on a Model's associated Model to perform validations
You're getting that error because you're trying to call the #school
method within the context of your class instead of within an instance of your class, and #school
is an instance method.
To call instance methods when constructing your validation format Regexp, you can provide a lambda as the :with
option, as follows:
validates :email,
:message => "Must be a valid email",
:format => { :with => lambda {|user| /\A[\w+\-.]+@#{Regexp.quote(user.school.email_domain)}\z/i } }
This lambda will be invoked on your model instance, allowing you to call methods on your User
instance such as #school
. See the documentation for validates_format_of
for more details.
Modify error messages for validation with an option
I found these tags in my app. One of those should work for you!
equal_to: must be equal to %{count}
greater_than: must be greater than %{count}
greater_than_or_equal_to: must be greater or equal to %{count}
less_than: must be less than %{count}
less_than_or_equal_to: must be less or equal than %{count}
too_long:
one: 'is to short (max than: 1 character)'
other: 'is to long (max than: %{count} characteres)'
too_short:
one: 'is to short (min: 1 character)'
other: 'is to short (min: %{count} characteres)'
wrong_length:
one: doesn't have the right length (1 character)
other: doesn't have the right length (%{count} characteres)
other_than: must be different than %{count}
How do I refactor this object to lessen dependency on callbacks?
If they checked 'billing address same as shipping address', you shouldn't even try to validate or save a separate billing address, and therefore it shouldn't have any validation errors.
Since the form submit is creating multiple models, I'd suggest a separate OrderBuilder service object (there might be a better name) that you call from the controller. That way your order model doesn't need to be so concerned with clearing address errors. Your order builder can take care of creating the order and any address records, or copying over shipping address to billing address fields.
Also, your 'bill_to_shipping' should definitely be a boolean in the database. If you need to do any converting of the params to boolean, do it at the time you're saving the record, not every time you get it from the database.
Rails - grouped_options_for_select
The grouped_options_for_select
method indeed is the correct one.
Since you haven't provided code, this should result in the grouped options you want:
grouped_options_for_select [['Fruits', @fruits.collect {|v| [ v.name, v.id ] }],
['Veggies', @veggies.collect {|v| [ v.name, v.id ] }],
['Junk', @junk_food.collect {|v| [ v.name, v.id ] }]]
Which can be used to create the dropdown:
select_tag 'Food', grouped_options_for_select(...)
or with form_helper:
f.select :food_attribute, grouped_options_for_select(...)
Is there any way to keep validate field optional in rails?
You could use a conditional validation to achieve what you want:
See here: http://guides.rubyonrails.org/active_record_validations.html#conditional-validation
However, this can quickly get hard to manage. Depending on the condition you're switching on, it'd probably be a cleaner design to use a 'Form Object' which will give you more control and let you do validations without the messy conditional logic.
See section #3 of this blog post for more detail:
http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/
Using this pattern, you would check for your condition in the controller then determine which form object to send to the view.
Related Topics
How to Detect User Agent in Rails 3.1
Bundle Command Not Found Windows X64
Run Code Only If Script Called from the Command Line
Ruby: Remove Whitespace Chars at the Beginning of a String
Are There Any Good Mutation Testing Tools for Ruby 1.9 and Rspec2
Building Hash by Grouping Array of Objects Based on a Property of the Items
How to Get List of All Countries and Cities in Rails
How to Enable Ssl for a Standalone Sinatra App
How to Integrate Hoptoad with Delayedjob and Daemonspawn
How to Test Instance Variable Was Instantiated in Controller with Rspec
How to Negate a Scope in Rails
How to Escape a Single Quote in Ruby
Using Will_Paginate Without :Total_Entries to Improve a Lengthy Query
How to Make a Check Box Default to Being "Checked" in Rails 1.2.3
How to Get Generators Call Other Generators in Rails 3
How I Know My Document's Size Inside Mongodb with the Ruby Driver