using "AND" operator in rails - ruby

I have something like this:
#photos = Photo.where(:user_id => #user.id)
I want something like:
#photos = Photo.where(:user_id => #user.id, :public => 1)
However this does not work. I cannot find how to use the "AND" operator

Your solution should work:
Photo.where(user_id: #user.id, public: 1)
Generates a query like this (assuming MySQL and a #user.id of 5):
SELECT `photos`.* FROM `photos` WHERE ((`photos`.`user_id` = 5 AND `photos`.`public` = 1))
I suspect that public is a boolean field and depending on your database adapter, true and false can either be stored as 1 and 0 or as t and f.
Try to pass a boolean value instead and let Rails handle the conversion:
Photo.where(user_id: #user.id, public: true)
It's even easier if you set up associations and some scopes:
class User < ActiveRecord::Base
has_many :photos
end
class Photo < ActiveRecord::Base
belongs_to :user
scope :public, -> { where(public: true) }
scope :private, -> { where(public: false) }
end
Now you can fetch a user's photos with:
#user.photos.public # user's public photos
#user.photos.private # user's private photos

Databases do not always store boolean values as 1 or 0.
So ActiveRecord normalizes that and only recognizes true and false (or nil) when using hash conditions.
All these queries are equivalent:
#photos = Photo.where("user_id = ? AND public = ?", #user.id, 1)
#photos = Photo.where(user_id: #user.id, public: true)
#photos = Photo.where(user: #user, public: true)
But it is generally preferred to write it like that:
#photos = #user.photos.where(public: true)

Try
#photos = Photo.where("user_id = ? AND public = ?", #user_id, 1)
Active record documentation will help you.

Related

How to pass complex types as arguments in graphene Python

I'm trying to create a query that accepts a complex argument object like so:
class Pair(graphene.ObjectType):
x = graphene.Int()
y = graphene.Int()
class Pairs(graphene.ObjectType):
pairs = graphene.List(graphene.NonNull(graphene.Field(Pair, required=True)), required=True)
class Query(graphene.ObjectType):
endpoint = graphene.Field(ResultType, pairs=graphene.Argument(Pairs, required=True))
I'm invoking it as follows in testing:
client = graphene.test.Client(graphene.Schema(query=Query))
executed = client.execute(
"""query($pairs: Pairs!) {
endpoint(pairs: $pairs) {
[result type goes here]
}
}"""
Any thoughts on what may be wrong with this approach?
I was able to do with the code below
class SomeFilter(graphene.InputObjectType):
name = graphene.String()
class Query(graphene.ObjectType):
all_somes = graphene.List(Some, options=SomeFilter())
def resolve_all_somes(self, info, options=None):
if options:
if name := options.get('name'):

Class Initialization with Faker Gem

I have created a class that will automatically fill with data using the faker gem when an instance of the class is created. I am having trouble getting the Person object to populate. It is probably a clumsy syntax mistake.
require 'rubygems'
require 'faker'
class Person
attr_accessor :firstname , :lastname, :phonenumber, :workaddress, :bio, :email
def initialize(firstname = Faker::Name.first_name ,
lastname = Faker::Name.last_name,
phonenumber = Faker::PhoneNumber.phone_number,
workaddress = "#{Faker::Address.street_name},
#{Faker::Address.city}, #{Faker::Address.state_abbr}, #{Faker::Address.zip}",
bio = 'bla bla bla',
email = Faker::Internet.email)
end
end
I ran the code above in a ruby interpreter but I could not get the Class attributes to initialize, The following yields nillClass instead of String.
p = Person.new
puts p.firstname.class
Working Solution:
def initialize(firstname = Faker::Name.first_name ,lastname =Faker::Name.last_name,phonenumber = Faker::PhoneNumber.phone_number,workaddress = "# {Faker::Address.street_name}, #{Faker::Address.city}, #{Faker::Address.state_abbr}, #{Faker::Address.zip}",bio = "#{Lolem.new.words(7)}", email = Faker::Internet.email)
#firstname = firstname
#lastname = lastname
#phonenumber = phonenumber
#workaddress = workaddress
#bio = bio
#email = email
end
You have to have code in your initialize method initializating your attributes like:
def initialize(firstname = Faker::Name.first_name, ...)
#firstname = firstname
# ...
end
You are just initializating the parameters in the initialize method and doing nothing with them.

Ruby Quick Class Instance Scope

I have a quick problem that probably comes down to something stupid. I have a class that extends OAuth::AccessToken and uses instance variables (#) so that each time it constructs an object, those variables will be unique that instance. However, when I try to return the final object from this class, I get an error. A quick example:
require 'oauth'
class OauthFigshare < OAuth::AccessToken
def initialize (consumerkey, consumersecret, accesstoken, accesstokensecret)
#consumerkey = consumerkey
#consumersecret = consumersecret
#accesstoken = accesstoken
#accesstokensecret = accesstokensecret
#apiurl = "http://api.figshare.com"
#consumer = OAuth::Consumer.new(#consumerkey,#consumersecret,{:site=> #apiurl})
#token = { :oauth_token => #accesstoken, :oauth_token_secret => #accesstokensecret}
puts #consumer.class
puts #token
#client = OAuth::AccessToken.from_hash(#consumer, #token)
puts #client
puts #client.get('/v1/my_data/articles')
return #client
end
end
The problem is that when I check inside the class to see if the token is working, it does. However, when I check against the constructed object outside the class, it doesn't work.
#client.get(url) returns Net::HTTPOk calling from in the class
auth = OauthFigshare.new(inputs)
auth.get(url)
This returns Net::HTTPUnauthorized
What am I not getting about scope here?
Edit to include actual class
The return value of the initialize method is not used. It seems like you actually want to override self.new instead.

How to share a validation.Constraint across multiple Forms?

I'm using Constraints on my web forms and I've noticed that several forms have similar validations, for instance I have several types of form with a start date and an end date. In each case, I want to validate that the start date is before the end date. Here's the case class I'm creating from my form:
case class OrderSearchForm(orderId: Option[Int], startDate:Option[Long], endDate:Option[Long])
and my validation (Let's ignore the .get() for now):
def validateSearchDate = Constraint[OrderSearchForm]{
osf: OrderSearchForm => {
if (!osf.startDate.isEmpty && !osf.endDate.isEmpty && osf.startDate.get.compareTo(osf.endDate.get) > 0 )
Invalid("Begin Date is after End Date.")
else
Valid
}
}
Now, since I have lots of forms with a start date and an end date, I'd like to re-write my validation to work with all of the case classes representing these forms. I'm wondering whether the typeclass pattern can help me with this:
trait TwoDates[T] {
def twoDatesTuple(t: T): (Option[Long], Option[Long])
}
trait TwoDatesOSF extends TwoDates[OrderSearchForm] {
def twoDatesTuple(t: OrderSearchForm) = (t.startDate, t.endDate)
}
implicit object TwoDatesOSF extends trait TwoDatesOSF
def validateSearchDate = Constraint[TwoDates[_]] { t: TwoDates[_] => ... (as above)}
but applying does not work:
validateSearchDate(OrderSearchForm(None, None, None))
yields:
error: type mismatch; found : OrderSearchForm required:
TwoDates[_]
betweenDates(osf)
1) Can I write generic validations using typeclasses? If so, what am I doing wrong?
2) Can I write generic validations while AVOIDING using super-classes (i.e.
abstract class TwoDates(start: Option[Long], end:Option[Long])
case class OrderSearchForm(orderId: Option[String], startDate:Option[Long], endDate:Option[Long]) extends TwoDates(startDate, endDate)
which seems awkward once multiple validations are in play)
Thanks!
I think you can use structural types:
private type TwoDates = { def startDate: Option[Date]; def endDate: Option[Date] }
def validateTwoDates = Constraint[TwoDates] { osf: TwoDates =>
if (!osf.startDate.isEmpty &&
!osf.endDate.isEmpty &&
osf.startDate.get.compareTo(osf.endDate.get) > 0) {
Invalid("Begin Date is after End Date.")
} else Valid
}
case class Something(
startDate: Option[Date],
endDate: Option[Date],
name: String)
private val form = Form(mapping(
"startDate" -> optional(date),
"endDate" -> optional(date),
"name" -> text)
(Something.apply)(Something.unapply).verifying(validateTwoDates))

Gmaps4rails Polygon not displaying [duplicate]

Ruby noob here. Trying to display a list of points as a polygon on a google map using the gmaps4rails gem (awesome gem by the way). Any suggestions based on code sample below would be much appreciated! I can see the outline for the map, but no map and no polygon. Update: this code has been updated and the problem is solved.
Class Schoolpoint is a list of lat/long pairs that belong to School
In my controller:
#polyjson = []
schoolpoints = []
Schoolpoint.where(:school_id => params[:id]).each do |point|
schoolpoints << { :lng => point.longitude, :lat => point.latitude}
end
#polyjson = [schoolpoints]
#polyjson = #polyjson.to_json
Then in the view:
<%= gmaps({"polygons" => { "data" => #polyjson }})
in Schoolpoint model:
class Point < ActiveRecord::Base
belongs_to :place
acts_as_gmappable :process_geocoding => false
def gmaps4rails_address
"#{longitude}, #{latitude}"
end
end
Update: This error now longer exists, but I've left it in case its helpful to someone dealing with similar problem. Finally, here is the resulting js with an uncaught Syntaxerror => unexpected token.
Gmaps.map = new Gmaps4RailsGoogle();
Gmaps.load_map = function() {
Gmaps.map.initialize();
Gmaps.map.polygons = [[{"lng"=>-80.190262, "lat"=>25.774252, "strokeColor"=>"#FF0000", "strokeOpacity"=>0.3, "strokeWeight"=>1, "fillColor"=>"#FF0000", "fillOpacity"=>0.7}, {"lng"=>-87.6245284080505, "lat"=>41.8868315803506}, {"lng"=>-87.6241636276245, "lat"=>41.8674515900783}, {"lng"=>-87.6203870773315, "lat"=>41.8674835487326}, {"lng"=>-87.6167392730712, "lat"=>41.8579591627635}, {"lng"=>-87.6348495483398, "lat"=>41.8577034549953}, {"lng"=>-87.6342701911926, "lat"=>41.8588701133785}, {"lng"=>-87.6341199874878, "lat"=>41.858946025344}, {"lng"=>-87.6341146230697, "lat"=>41.8590858629394}, {"lng"=>-87.6341199874878, "lat"=>41.8600767034266}, {"lng"=>-87.6342219114303, "lat"=>41.8612433185139}, {"lng"=>-87.634157538414, "lat"=>41.8613112372298}, {"lng"=>-87.6342540979385, "lat"=>41.8621502271823}, {"lng"=>-87.6341950893402, "lat"=>41.8622580965204}, {"lng"=>-87.6342433691024, "lat"=>41.8626336402037}, {"lng"=>-87.6341092586517, "lat"=>41.8630930789441}, {"lng"=>-87.6342326402664, "lat"=>41.8631010691539}, {"lng"=>-87.6342862844467, "lat"=>41.8651984646832}, {"lng"=>-87.6342165470123, "lat"=>41.865314318812}, {"lng"=>-87.6342540979385, "lat"=>41.865929540668}, {"lng"=>-87.6343238353729, "lat"=>41.8661652409794}, {"lng"=>-87.6343667507171, "lat"=>41.8664728485533}, {"lng"=>-87.6342701911926, "lat"=>41.866564731048}, {"lng"=>-87.6343882083892, "lat"=>41.8673317449823}, {"lng"=>-87.6344525814056, "lat"=>41.8680388278011}, {"lng"=>-87.6346457004547, "lat"=>41.8691693450993}, {"lng"=>-87.6346671581268, "lat"=>41.8696886572982}, {"lng"=>-87.6345813274383, "lat"=>41.8698804022745}, {"lng"=>-87.6347583532333, "lat"=>41.869992253245}, {"lng"=>-87.634892463684, "lat"=>41.8706873227465}, {"lng"=>-87.6353269815445, "lat"=>41.8726167002032}, {"lng"=>-87.6352626085281, "lat"=>41.8728443868687}, {"lng"=>-87.6354557275772, "lat"=>41.8730081609862}, {"lng"=>-87.6353698968887, "lat"=>41.8732797854267}, {"lng"=>-87.6356971263885, "lat"=>41.8740227522642}, {"lng"=>-87.6356971263885, "lat"=>41.8746458790817}, {"lng"=>-87.6359224319458, "lat"=>41.87509724279}, {"lng"=>-87.6361316442489, "lat"=>41.8754088017203}, {"lng"=>-87.6364105939865, "lat"=>41.8754727110567}, {"lng"=>-87.6364642381668, "lat"=>41.8757642965932}, {"lng"=>-87.6371240615844, "lat"=>41.876678987795}, {"lng"=>-87.637939453125, "lat"=>41.8801059676767}, {"lng"=>-87.6379930973053, "lat"=>41.8806172030015}, {"lng"=>-87.6378536224365, "lat"=>41.8829017358812}, {"lng"=>-87.6375961303711, "lat"=>41.8844593251054}, {"lng"=>-87.6372849941253, "lat"=>41.8857213439117}, {"lng"=>-87.6371347904205, "lat"=>41.8860408383893}, {"lng"=>-87.6355576515197, "lat"=>41.8870552227663}, {"lng"=>-87.6282513141632, "lat"=>41.8870951588295}, {"lng"=>-87.6281654834747, "lat"=>41.8868076186168}]];
153:2439 Uncaught SyntaxError: Unexpected token >
Gmaps.map.create_polygons();
Gmaps.map.adjustMapToBounds();
Gmaps.map.callback();
};
window.onload = function() { Gmaps.loadMaps(); };
I passed their base tutorial (from screen cast) and markers works fine. But I had problem with polylines (as you with polygons). At the end I resolved my problem (it can help you with polygons).
So, view is the same as they gave :
<%= gmaps({
"polylines" => { "data" => #bemap_polylines }
})
%>
The model is also the same as their.
class Character < ActiveRecord::Base
belongs_to :bemap
acts_as_gmappable
def gmaps4rails_address
#describe how to retrieve the address from your model, if you use directly a db column, you can dry your code, see wiki
address
logger.info address
end
end
So, the main problem was into controller. Here is mine :
def show
#bemap = Bemap.find(params[:id])
#bemap_polylines = []
#bemap_characters = []
#bemap.characters.each do |v|
#bemap_characters << { :lng => v[:longitude], :lat => v[:latitude]}
end
#bemap_polylines << #bemap_characters
#bemap_polylines = #bemap_polylines.to_json
respond_to do |format|
format.html # show.html.erb
format.json { render json: #bemap }
end
end
Gmaps4rails doesn't provide any builtin method to create the js for polygons.
The one you use is malformed, see doc: https://github.com/apneadiving/Google-Maps-for-Rails/wiki/Polygons.

Resources