validates using Proc - ruby

If I remove the || statement below this will work. Any ideas why?
I want it to validate only on categories other than "social" and "news"
validates :image, presence: true, if: Proc.new { |a| a.category != "social" || a.category != "news" }

To validate on categories that's not 'social' and not 'news', you will need
validates :image, presence: true, if: Proc.new { |a| a.category != "social" && a.category != "news" }

SeanLi has given you a correct revision, but allow me to supplement it with some deeper logical understanding.
The confusion here would probably be cleared up by a quick study of DeMorgan's Laws. These are the rules for distributing negations (NOTs) over conjunctions (ANDs) and disjunctions (ORs). Using Ruby syntax:
"Neither p nor q" can be written, equivalently, as either !(p || q) or !p && !q.
Meanwhile, "Not both p and q" / "Either not-p or not-q" can be written, equivalently, as either !(p && q) or !p || !q.
However, as their English renderings make clear, the first pair means something different (is logically distinct from) the second pair.
To risk belaboring the obvious, this fact can be applied to your case by recognizing the equivalence of !(p == q) and p != q.

Related

Compare attributes with `value == nil`

I want to compare two object attributes with:
if object1.attribute1 != object2.attribute1
I'm also trying:
if (object1.attribute1 || object2.attribute1) && object1.attribute1 != object2.attribute1
When both attributes are nil, I would like to say they are equal, and not satisfy the if condition. But the codes above satisfy the if condition when both attribute1 are nil.
How can I do it?
Unfortunely I can't add comment because my reputation < 50.
I read your comment. You can bang-bang you're boolean in this case.
What it means:
!!nil
#=> false
!!''
#=> true
If it's not helpful, write me and I will delete the answer.

ruby conditions using && and ||

I can't figure how to correctly write the rule
I want express the following rule:
If conclusion is 'negative' one of the premises must be negative.
Here's how I tried to write this.
def test4b
if (#conclusion.getQuality == 'negative' && (#major.getQuality != 'negative' || #minor.getQuality != 'negative'))
validity = "invalid (4b) Negative conclusion without a negative premise"
else
validity = "pass"
end
end
But this isn't working. It seems to exclude every syllogism with a negative premise. Again, I only want to exclude syllogisms where which have a negative conclusion without any negative premises.
It should be:
if (#conclusion.getQuality == 'negative' && (#major.getQuality != 'negative' && #minor.getQuality != 'negative'))
Both of #major and #minor are not to be 'negative'.
Your method is to retrun the logical value of !conclusion => (!major || !minor). The negation of this expression would be:
!conclusion && !(!major || !minor) <=> !conclusion && major && major
(DeMorgan's law). This is the condition youa re lloking for, note there are no || here.
Also note that it would be more readable though if you do:
if (#conclusion.getQuality == 'negative' && [#major, #minor].all? {|m| m.getQuality != 'negative'})
or
if (#conclusion.getQuality == 'negative' && ![#major, #minor].any? {|m| m.getQuality == 'negative'})

Why can procs be invoked with === in ruby 1.9?

This article mentions 4 ways to invoke procs in ruby 1.9, and === is one of them. I don't understand why this would be done this way at all. Does it have any relationship to the normal meaning of === (asking if the two objects are the same object)?
irb(main):010:0> f =-> n {[:hello, n]}
=> #
irb(main):011:0> f.call(:hello)
=> [:hello, :hello]
irb(main):012:0> f === :hello
=> [:hello, :hello]
irb(main):013:0> Object.new === Object.new
=> false
irb(main):014:0> f === f
=> [:hello, #]
Note that === in Ruby is NOT about equality, unlike JavaScript. It is specifically used for case expressions:
case cats.length
when 42 # Uses 42 === cats.length
puts :uh
when /cool/i # Uses /cool/i === cats.length
puts :oh
when ->(n){ n.odd? || n/3==6 } # Passes cats.length to the proc
puts :my
end
This is what the docs have to say:
It is to allow a proc object to be a target of when clause in the
case statement.
This is a, perhaps contrived, example:
even = proc { |x| x % 2 == 0 }
n = 3
case n
when even
puts "even!"
else
puts "odd!"
end
It works because the case/when is basically executed like this:
if even === n
puts "even!"
else
puts "odd!"
end
The case/when checks which branch to execute by calling === on the arguments to when clauses, picking the first that returns a truthy value.
Despite its similarity to the equality operator (==) it not a stronger or weaker form of it. I try to think of the === operator as the "belongs to" operator. Class defines it so that you can check if an object belongs to the class (i.e. is an instance of the class or a subclass of the class), Range defines it as to check if the argument belongs to the range (i.e. is included in the range), and so on. This doesn't really make the Proc case make more sense, but think of it as a tool for making your own belongs to operators, like my example above; I defined an object that can determine if something belongs to the set of even numbers.
This feature is useful in case construction, when you need to calculate something at the comparing.
is_odd =-> n { n%2 != 0 }
is_even =-> n { n%2 == 0 }
case 5
when is_even
puts "the number is even"
when is_odd
puts "the number is odd"
end
=> the number is odd
Does it have any relationship to the normal meaning of === (asking if the two objects are the same object)?
Actually, that's a common misconception about === in Ruby. It's actually not strictly for Object#object_id comparison (although that is its behavior in many common invocations). In Ruby, === is case subsumption.
Here's the description of === from Object: "Case Equality -- For class Object, effectively the same
as calling #==, but typically overridden by descendants
to provide meaningful semantics in case statements."
Sadly, even though it is comprised of three =, it doesn't have anything even remotely to do with equality :-D

Why does this method for pluralizing category names not work in all cases?

PLURALIZATION_EXCEPTIONS = "hardware",'memory'
def pluralize_category_name(name)
category = name.split(' and ')
exceptions_to_exp = ""
category.map! { |e|
if e.match(/^[A-Z]+$/) and !e.match(/^[A-Z]+S$/)
e = e.pluralize
end
(PLURALIZATION_EXCEPTIONS.include?(e.downcase) || e.match(/^[A-Z]+S$/) ||
e.match(/[memory|hardware]/) )? e : e.pluralize
}.join(' and ')
end
The test should and expectation should be as follows:
it "properly pluralizes hardware as hardware" do
pluralize_category_name("hardware").should == "hardware"
end
it "properly pluralizes UPS as UPS" do
pluralize_category_name("UPS").should == "UPS"
end
it "properly pluralizes PDA and Portable Hardware as PDAs and Portable Hardware" do
pluralize_category_name("PDA and Portable Hardware").should == "PDAs and Portable Hardware"
end
it "properly pluralizes perfume and cologne as perfumes and colognes" do
pluralize_category_name("perfume and cologne").should == "perfumes and colognes"
end
The last test fails :(
HELP!
I think your problem is that in your condition
(PLURALIZATION_EXCEPTIONS.include?(e.downcase) || e.match(/^[A-Z]+S$/) ||
e.match(/[memory|hardware]/) )? e : e.pluralize
"perfume" matches /[memory|hardware]/.
[memory|hardware] is a character class that matches any of m, e, m, o, r, etc..
Perhaps you meant e.match(/(memory|hardware)]/i) instead? This alternative pattern would pass your tests but it doesn't make use of your PLURALIZATION_EXCEPTIONS constant so would need updating if you added any other exceptions.

Problems with Ruby "||" "or"?

Beginning Ruby Question:
I'm trying to see if a string variable's contents is either "personal" "email" or "password".
I'm trying:
if params[:action] == "password" || "email" || "personal"
foo
else
don't foo
end
But that doesn't work and returns strange results, and using IRB to play around with "or" statements I have no idea why the following happens:
irb(main):040:0> a = "email"
=> "email"
irb(main):041:0> a == "password" || "email"
=> "email"
irb(main):042:0> a == "email" || "password"
=> true
I just want something that if any of the 3 variables are true no matter what order they are in it returns true, if not it returns false. Anyone want to help this n00b out?
This specific problem will have many good solutions, but instead I will concentrate on the boolean logic for educational purpose
You'll want to do this:
(a == "password") || (a == "email) || (a == "password")
Programming languages aren't like English: it has a strict grammatical rule, and instead of saying:
"if x is 3 or 5"
in most programming languages, you have to say:
if x is 3 or x is 5
Similarly, where as it's common in mathematical notation to say:
"if a < b < c"
in most programming languages, you have to say:
if a < b and b < c
Let's see what happens with your experiment:
a == "password" || "email"
Due to what is called "operator precedence", this is parsed as:
(a == "password") || "email"
Now, since a == "email", this essentially evaluates to:
false || "email"
which is why this expression evaluates to "email".
Similarly, with:
a == "email" || "password"
This is essentially
true || "password"
and that's why it evaluates to true.
The case statement is also good for matching this or that or ...
case email
when "password", "email", "whatever"
puts "found a match: #{email}"
else
puts "no match"
end
Sometimes I use this version:
if ["password","email","personal"].include?(params[:action])
foo
else
don't foo
end

Resources