Mongoid Document where class function value is true or false - ruby-on-rails-3

I'm trying to filter a feed of posts. A Post and User both have a Boolean field banned_from_feed.
Post has a function:
def banned
self.banned_from_feed or self.user.banned_from_feed
end
Running Post.all.excludes(:banned => true) doesn't filter out these documents, as banned is not a Mongoid Document field.

You probably want a scope:
scope :banned, lambda { any_of {:banned_from_feed => true}, {:user.banned_from_feed => true} }

Related

Rails: Search by custom instance method's value using tire gem & elasticsearch

For example, I have Article model like
class Article < ActiveRecord::Base
#Columns: id, title, status_number...etc
STATUSES = {1 => "SUCCESS", 2 => "REJECTED"}
include Tire::Model::Search
include Tire::Model::Callbacks
def display_status
STATUSES[status_number]
end
def self.search(params)
tire.search(load: true, page: params[:page], per_page: 2) do
query do
boolean do
must { string params[:query], default_operator: "AND" } if params[:query].present?
end
end
end
end
how to include display_status as "SUCCESS" by default in search method?
I tried
query do
boolean do
must { string params[:query], default_operator: "AND" } if params[:query].present?
must { term :display_status , "SUCCESS" }
end
end
But couldn't get result.
Please help to solve this problem. Thanks

Ruby integration with mailchimp-api gem

I'm trying to subscribe a single email to multiple lists with RoR and the official mailchimp-api gem. It works, but the last four values (double_optin, update_existing, replace_interests, and send_welcome) are not updating and I get an error that the email "already exists" even though I'm trying to pass the update_existing as true. I've written Mailchimp several times and they feel they've reached the end of their assistance. They have said they are not experts in the wrapper--even if it is the "official" gem--and cannot help me further. My code looks like this:
responses << mailchimp_lists.each do |ml|
mailchimp.lists.subscribe(
ml,
{ "email" => order.customer_email,
"euid" => order.customer_id,
"leid" => ""
},
{ "FNAME" => order.customer_first_name,
"LNAME" => order.customer_last_name,
"COMPANY" => order.company_name,
"ADDRESS1" => order.billing_address_1,
"ADDRESS2" => order.billing_address_2,
"CITY" => order.billing_city,
"STATE" => order.billing_state,
"POSTALCODE" => order.billing_zip,
"SALUTATION" => ""
},
"html",
false,
true,
false,
false
)
end
I've tried sending the last four params in several different ways such as:
"email_type" => "html",
"double_optin" => false,
Or:
{"email_type" => "html"},
{"double_optin" => false}
At times, Mailchimp can see the params arrive in such a way that it seems it should not be triggering an "email already exists" error, but it just won't work. Any help is appreciated.
The mailchimp-api gem's documentation describes the subscribe method as:
#subscribe(id, email, merge_vars = nil, email_type = 'html', double_optin = true, update_existing = false, replace_interests = true, send_welcome = false)
While the batch_subscribe shows:
#batch_subscribe(id, batch, double_optin = true, update_existing = false, replace_interests = true)
Note that the batch method does not include a "send_welcome" param. When I removed it from my list of params for the subscribe method--essentially sending three booleans instead of four as suggested, the update_existing worked perfectly. Seems like an error in the documentation here: http://www.rubydoc.info/gems/mailchimp-api/2.0.4/Mailchimp/Lists#subscribe-instance_method
Hopefully this helps someone else!

Not able to overwrite object properties in "create" method

I have a simple table for storing users accounts information (emails and passwords) with two additional columns:
is_active - says if user account is enable or disabled - the column
type is boolean and in the context of DB2 it is mapped with
decimal(1)
registration_date - says when the user was created - the column
type is datetime and in the context ofDB2 it is mapped with
datetime
As this fields will not be set by the user, I have deleted their inputs from the users _form.
I want to populated this fields in my users controller as follows:
def create
#security_user = SecurityUser.new(params[:security_user])
#security_user.is_active = 0
#security_user.registration_date = DateTime.now
...
end
But I can not pass the validations that I have in the model. They looks like:
class SecurityUser < ActiveRecord::Base
# Loading custom validators
require 'lib/date_format_validator'
...
# Accessible columns
...
# Relationships
...
# Validations
validates :is_active, inclusion: { in: 0..1, message: "only '0' and '1' allowed"}, presence: true
validates :registration_date, date_format:true , presence: true
end
where the 'lib/date_format_validator' looks like follows:
class DateFormatValidator < ActiveModel::EachValidator
def validate_each(object, attribute, value)
if (DateTime.parse(value) rescue ArgumentError) == ArgumentError
object.errors[attribute] << (options[:message] || "is not valid datetime")
end
end
end
What I am doing wrong?
EDIT: The screenshot below displays the errors:
EDIT2: Sam Ruby's answer helps me to finish with something like this for my custom validator method:
class DateFormatValidator < ActiveModel::EachValidator
def validate_each(object, attribute, value)
unless value.kind_of? DateTime || (DateTime.parse(value) rescue ArgumentError) != ArgumentError
object.errors[attribute] << (options[:message] || "is not valid datetime")
end
end
end
and to transform the validates method for the is_active column as follows:
validates :is_active, inclusion: { in: [ true, false ], message: "only 'true' and 'false' allowed"}
because as it is said in the official documentation:
Since false.blank? is true, if you want to validate the presence of a boolean field you should use validates :field_name, :inclusion => { :in => [true, false] }.
The problem is that you are trying to validate the ActiveRecord object as if the columns are of type String. But since you have defined your columns as boolean and datetime, what you will be validating will be of type TrueClass, FalseClass or ActiveSupport::TimeWithZone.
In other words, the values are already parsed.
true is never 0 or 1.
DateTime.parse(DateTime.now) will always raise ArgumentError
If you want to validate the unparsed values, do so in the controller.

rails 3 validations uniqueness on attributes of an association

i have a model called Fund and a model called Company .. where fund belongs_to a company.
i have this validation in my Fund table:
validates :name, presence: true, uniqueness: true
This works both on server side and client side using client_side_validations. But i want my fund names to be unique across both fund.name values and fund.company.name values. And i want to do it in a way it would work with client_side_validations too.
Suggestions?
Ended up creating a very specific validator and adding it to client-side-validation. Here'z the breakdown
In models/fund.rb
validates_fund_name_not_company_name :name
new file in config/initializers/validators .. called fund_name_not_company_name_validator.rb
class FundNameNotCompanyNameValidator < ActiveModel::EachValidator
def validate_each(record, attr_name, value)
if ::Company.exists?(name: value)
record.errors.add(attr_name, :fund_name_not_company_name, options.merge(:value => value))
end
end
end
# This allows us to assign the validator in the model
module ActiveModel::Validations::HelperMethods
def validates_fund_name_not_company_name(*attr_names)
validates_with FundNameNotCompanyNameValidator, _merge_attributes(attr_names)
end
end
module ClientSideValidations::Middleware
class FundNameNotCompanyName < ClientSideValidations::Middleware::Base
def response
if ::Company.exists?(name: request.params[:name])
self.status = 404
else
self.status = 200
end
super
end
end
end
then in app/assets/javascripts/rails.validations.custom.js
clientSideValidations.validators.remote['fund_name_not_company_name'] = function(element, options) {
if ($.ajax({
url: '/validators/fund_name_not_company_name',
data: { name: element.val() },
// async must be false
async: false
}).status == 404) { return options.message; }
}
This helped a great deal

Sphinx Scope Returning Nothing

I'm trying to create a simple scope that sphinx will index (Ruby on Rails). The normal scope returns what it should, the sphinx scope returns no results.
define_index do
# fields
indexes :name
indexes author
indexes description
indexes list_of_tags
indexes approved
# attributes
has created_at, updated_at, downloads
# delta indexing
set_property :delta => true
# weighting fields
set_property :field_weights => {
:name => 10,
list_of_tags => 6,
author => 5,
description => 4,
}
end
normal scope:
scope :approved, where(:approved => true)
sphinx scope:
sphinx_scope(:approval_scope) {
{:conditions => {:approved => "true"}}
}
Approved is a boolean field, however, since I'm indexing it as a field, I believe its value is treated as a String. Regardless, letting the value of the sphinx scope be "true" or true makes no difference - Theme.approval_score still returns 0 results unlike Theme.approval. I hope I'm missing something simple..
make the approved with has
define_index do
# fields
...
has approved
...
end
then
sphinx_scope(:approval_scope) {
{:with => {:approved => true}}
}