Trick when dynamically appending GET attributes - url

When dynamically building SQL queries you often see something like this:
WHEN 1=1 AND title="Example" AND ...
The purpose of the 1=1 is to be able to keep appending AND-statements without having to check if any previous statements exist. Thereby avoiding something like this happening:
WHEN AND title="Example" AND ...
I quite often come across a related issue when building the the attributes/search-query for a GET request. I don't want to keep checking if I need to prepend the attribute with '?' or '&'.
So my question is, is there any 'safe' way for me to add an initial attribute that won't interfere with any potential software on the server side. Assuming I do not have full knowledge of the backend.
Something like:
http://example.com?1=1&title=example
http://example.com?null&title=example
http://example.com?i-am-useless&title=example
Or is this allowed?
http://example.com?&title=example
Is there perhaps a simpler way to solve this?

Make sure the URI-string you want to add parameters to already ends in a '?'. Then for every key-value pair, add 'key=value&' to it. Optionally you can then in the end delete the last character from the resulting string. - Reddit user omepiet

Related

How to implement Object.try! in Ruby on Rails?

I'd like to shorten code like the following:
content = content.join("\n") if content.respond_to? :join
into this:
content.try!(:join, "\n")
Is this a good idea, and can it be implemented in terms of the existing Object.try?
If I understand correctly, you want a version of try that modifies the object in-place, as in the difference between x = x.reverse and x.reverse!
To answer your questions...
Is this a good idea
No, it's not, it's actually impossible.
Can it be implemented in terms o the existing Object.try?
No, it can't, either with or without Object.try, it cannot be implemented at all. You cannot change an object's type in-place.
Using .join on an array produces a string. You cannot change an array in-place to become a string. This is why there is no join! method in the first place. Many of the methods on Array and Enumerable have versions with and without !. Many other methods do not have a ! version. This is because the ! version cannot be implemented.
In general, if you have a method like reverse and it's in-place equivalent reverse! you can already use try just fine:
content.try(:reverse!)
If the ! method doesn't already exist, such as join and the non-existent join!, it's because it cannot work, and you cannot make it work with a hypothetical try!.
Note that you can make something like this work with a proxy object, but this is a horrible overwrought solution to a nonexistent problem.
Just use content = content.join("\n") if content and be done with it.

How to return untranslated keys

For an API, I want to return the actual keyified string.
So:
User.errors.messages[:name]
#=> activerecord.errors.models.user.attrributes.blank
Instead of
Can't be blank
I know I can override this by creating an actual translation, or by setting custom errors in the validates methods in my Models, but I was wondering if there is a lower level, simpler way to make rails return the "keyified" string instead of parsing it through the translation-layers.
I answered some similar questions on SO, but could not find them right now...
I think that this is not possible right now because the ActiveModel::Errors::add method does not store the Key to the message, but just the derived message.
It's also not trivial to reverse get the key from translation files or the like.
I think it would be a valuable addition to rails to actually store the key of the error-message instead of just the message itself.

How to access a scope if its name is being used as a query column

Dealing with some legacy code we came across a rather annoying situation. We are looping through a query with the <cfoutput query="x"> tag. That query has a column named 'url'. Within that loop we need to check if a key exists within the url scope. Since CF puts a priority on what's in the query over general page scopes I can't use a structKeyExists(url,"key") since as far as CF is concerned at this point, url is a string with the value from the current row of the query.
How can I break out of the query scope and inspect what's in my url?
As a temporary we are using isDefined("url.key"), but I would still like to know if there is a way to break out of the query scope.
Also can't really change the column, or even the column name in the query without a few hours of work tracking down an changing all references to it, so we're going to avoid that if at all possible.
EDIT:
There seems to be some confusion as to how this code is set up, and why the simple solutions don't apply. It would be hard for me to give a thorough example but I will try to clarify the situation.
There are many pages that would count as 'pageA' for the following example. Enough that changing how things work would require a change in scope and investment in time that's just not going to happen in the time allotted.
PageA runs a query with one of the columns being named url, then starts an output loop via cfoutput, inside that loop PageB is included. One PageA may have different variables in the URL scope than another PageA, actually they are the same, but may be named differently(varID=x in one case vid=x in another). Inside of PageB I need to use the value from that url scope, so I want to run through the different possible names (if key 'varID' exists in url, use it, otherwise use 'vid').
This is why I want to "punch through" the query scope to get the url structure, and not the url column from the query. Any other method seems to require modifying the many PageAs.
So the question is not how to solve this problem specifically, as there are many ways to do it, I would just really like to avoid them as they all add a lot of time in implementation and testing. The question remains, is there a way to access the url scope as a variable if url exists as a query column and you are in the query scope.
I thought it might work to create a function that returned the url scope, but upon testing it, even with a local-scoped query (which prevents the function using the query itself) the use of url inside the function is still corrupted:
<cffunction name="getUrlScope"><cfreturn Url /></cffunction>
...
<cfoutput query="x">
<cfif StructKeyExists( getUrlScope() , 'key' )>
<!--- still fails :( --->
There is however an undocumented (meaning unsupported and liable to change) option. If you dump getPageContext() you will see a bunch of functions that do interesting things, including dealing with scopes.
You can use getPageContext().SymTab_findBuiltinScope('URL') to get at the URL scope.
You can also use getPageContext().getCfScopes() to get an array of scopes. I'm not sure if the order is guaranteed fixed but it seems to be [cgi,?,url,form,cookie,?] checking on both CF10 and cflive (CF9), so possibly is.
(In CF8 there was the method getBuiltinScopes, which returned a struct instead of an array - this no longer appears to exist, reinforcing the whole unsupported and changeable nature of these methods.)
On Railo those don't work, but there is getPageContext.UrlScope() and similarly-named functions for the other scopes.
One solution would be to assign the url struct to a new variable outside of the cfoutput tag and then reference that variable instead of url. Example:
<cfset urlScope = url>
<cfoutput query="x">
<cfset keyExists = structKeyExists(urlScope, "key")>
</cfoutput>
My solution for this is always to alias the url column in the query as int
SELECT URL as qURL FROM myTable ...
IF you don't have access to the query (it's a stored precedure or used elswhere etc) you can always use query of a query to reselect it with your alias.
I don't care for the idea of creating a separate reference to URL outside the output - but that would also work. I just want to KNOW what is user input (i.e. comes from the URL or FORM) and what is generated internally (i.e. comes from a query).
Couldn't you move structKeyExists(url,"key") outside of the cfoutput block, and store that into a variable? Or do a structAppend to copy the url struct into another struct named something else?
Another approach is to replace your cfoutput block with a cfloop block.
<cfloop from="1' to = "#YourQuery.recordcount#" index = "idx">
<cfif StructKeyExits(url,"key")>
<cfoutput>
#url.key# is not the same as #YourQuery.url[idx]#
which can also be referenced like this #YourQuery["url"][idx]
etc

How can I most efficiently iterate over a hash of hashes in order based on key value in inner hash?

I've got a JSON hash of hashes returned by a website API that I want to parse and display based on a specific key's value within the internal hashes.
I can think of solutions that would achieve this, but they would take a number of lines of code and don't seem efficient. Surely there must be a way to natively in Rails, given the focus on convention over configuration. I've googled around a bit, but found nothing that covers this issue.
Sample Response from API:
[{"banner":"01197271","birthday":"1991-01-11","committee_id":1,"created_at":"2012-08-08T01:56:02-05:00","email":"me#example.com","first_name":"Dan","graduation_date":"May 2013","hometown":"San Antonio","hours_enrolled":15,"id":2,"image":{"url":null,"thumb":{"url":null},"large":{"url":null}},"invitation_accepted_at":null,"invitation_limit":null,"invitation_sent_at":null,"invitation_token":null,"invited_by_id":null,"invited_by_type":null,"last_name":"Tester","local_apt":"","local_city":"San Antonio","local_state":"Texas","local_street":"One UTSA Circle","local_zip":"78249","major":"Computer Science","permanent_apt":"","permanent_city":"","permanent_state":"","permanent_street":"One UTSA Circle","permanent_zip":"","phone":"5558813284","same_address":true,"tour_trained":false,"updated_at":"2012-08-17T03:35:26-05:00","utsa_id":"uoi431"},
{"banner":"","birthday":"1990-10-25","committee_id":null,"created_at":"2012-08-03T16:19:23-05:00","email":"you#example.com","first_name":"Test","graduation_date":null,"hometown":null,"hours_enrolled":null,"id":1,"image":{"url":null,"thumb":{"url":null},"large":{"url":null}},"invitation_accepted_at":null,"invitation_limit":null,"invitation_sent_at":null,"invitation_token":null,"invited_by_id":null,"invited_by_type":null,"last_name":"User","local_apt":"","local_city":"","local_state":"","local_street":"","local_zip":"","major":null,"permanent_apt":"","permanent_city":"","permanent_state":"","permanent_street":"","permanent_zip":"","phone":"","same_address":false,"tour_trained":false,"updated_at":"2012-08-15T10:05:54-05:00","utsa_id":""}]
Potential solution would be to go through each internal hash, determining value of relevant key value, then store, based on where the key value places it compared to already tested hashes. When complete, return.
Ok so if you have objects that are set up to parse this information, those objects can build themselves based off the parameters of your hash. So you could do something like this
object = MyObject.create(your_hash_parameters)
Where your_hash_parameters are the parameters that you presented in your example.
I'm not sure what would happen if there were more paramaters than your object knew what to do with, if it would still build itself or not. If that is the case, you could use the delete_if method to exclude attributes that are unwanted.
One more note, if this isn't something that you want saved to your database, and its only to display temporary information. I would set up a model with attr_accessors that represent the attributes that you are displaying.
As told in comment, I'd create an ActiveResource object and add relevant methods to it.

Does this Rails 3 Controller method make me look fat?

This is a new application, and I have an index method on a Search controller. This also serves as the home page for the application, and I'm trying to decide if I am headed down the wrong path from a design pattern perspective.
The method is already 35 lines long. Here is what the method does:
3 lines of setting variables to determine what "level" of hierarchical data is being searched.
Another 10 lines to populate some view variables based on whether a subdomain was in the request or not.
A 10 line section to redirect to one of two pages based on:
1) If the user does not have access, and is signed in, and has not yet requested access, tell them "click here to request access to this brand".
2) If the user does not have access, is signed in, and has already requested access, tell them "so and so is reviewing your request".
Another 10 lines to build the dynamic arel.
I can't get it straight in my head how to separate these concerns, or even if they should be separated. I appreciate any help you can offer!
Summarizing what you've said in something codelike (sorry, don't know ruby; consider it pseudocode):
void index() {
establishHierarchyLevel();
if (requestIncludedSubdomain())
fillSubdomainFields();
else
fillNonsubdomainFields();
if (user.isSignedIn() && !user.hasAccess()) {
if (user.hasRequestedAccess())
letUserIn();
else
adviseUserOfRequestUnderReview();
}
buildDynamicArelWhateverThatIs();
}
14 lines instead of 35 (of course, the bodies of the extracted methods will lengthen the overall code, but you can look at this and know what it's doing). Is it worth doing? That really depends on whether it's clearer to you or subsequent programmers. My guess is it's worth doing, that splitting out little code blocks into their own method will make the code easier to maintain.
That's a lot of variables being set. Maybe this is a good opportunity for a module of some kind? Perhaps your module can make a lot of these decisions for you, as well as acting as a wrapper for a lot of these variables. Sorry I don't have a more specific answer.
Without your code it's somewhat difficult to suggest actual fixes, but it definitely sounds like a really wrong approach and that you're making things much harder than they need to be:
3 lines of setting variables to
determine what "level" of hierarchical
data is being searched
if there is a search form, I would think you would want to pass those straight from the params hash into scopes or Model.where() calls. Setup scopes on your model as appropriate.
Another 10 lines to populate some view variables based on whether a subdomain was in the request or not.
This seems to me like it should be at most 1 line. or that in your view, you should use if statements to change what you'd like your output to be depending on your subdomain.
A 10 line section to redirect to one of two pages based on:
the only thing different in your explanation of the 2 views is "whether the user has requested access" surely this is just a boolean variable? You only need 1 view. Wrap the differences into 2 partials and then in your view and write one if statement to choose between them.
Another 10 lines to build the dynamic arel.
It might be necessary to go into Arel, but I highly highly doubt it. Your actual search call can in most cases (and should aim to be) 1 line, done through the standard ActiveRecord query interface. You want to setup strong scopes in your models that take care of joining to other models/narrowing conditions, etc. through the ActiveRecord Query interface.

Resources