How to build select cmd on rails active model? - ruby-on-rails-4

User Table
id| name | email | invited_by_id
1 | jhon | jhon#mail.com | null
2 | sarah | sarah#mail.com | 1
3 | baby | baby#mail.com | 2
As User table you'll see sarah's invited by jhon and baby's invited by sarah
Expect Result
id| name | email | invited_by_id | invited_by_name
1 | jhon | jhon#mail.com | null | null
2 | sarah | sarah#mail.com| 1 | jhon
3 | baby | baby#mail.com | 2 | sarah
How to create select cmd or best way to get the result as my expect on rails active model ?

user.rb
def inviter_name
if self.invited_by_id.nil?
nil
else
User.find(self.invited_by_id).name
end
end
or you can use belongs_to
belongs_to :inviter, class_name: "User", foreign_key: 'invited_by_id'
and the inviter name can be got like below:
#user.inviter.name

#Zoker is correct, you should add a 'belongs_to' clause to your model definition:
belongs_to :invited_by, class_name: "User"
Once done, the request could be as simple as this:
User.all.each do |user|
puts [user.name, user.email, user.invited_by_id.to_s, user.invited_by.name].join(", ")
end
This will print out a (very) basic CSV list of the results you require. This makes most sense in a console session - if you put this code in a controller you'd end up with it getting lost in the server output.
For large lists you will get a performance hit using this look-up. For each row, a separate request will be made to the database to find the 'invited by' user so we can read the name.
Better is to do this:
User.includes(:invited_by).each do |user|
puts [user.name, user.email, user.invited_by_id.to_s, user.invited_by.name].join(", ")
end
This tells Rails to make one more query, which gets all the included 'invited_by' users in one go. This means that instead of making (number_of_rows + 1) queries you're now making just 2.
(Code untested at time of writing.)

Related

Compare fields within relationship on Django ORM

I have two models, route and stop.
A route can have several stop, each stop have a name and a number. On same route, stop.number are unique.
The problem:
I need to search which route has two different stops and one stop.number is less than the other stop.number
Consider the following models:
class Route(models.Model):
name = models.CharField(max_length=20)
class Stop(models.Model):
route = models.ForeignKey(Route)
number = models.PositiveSmallIntegerField()
location = models.CharField(max_length=45)
And the following data:
Stop table
| id | route_id | number | location |
|----|----------|--------|----------|
| 1 | 1 | 1 | 'A' |
| 2 | 1 | 2 | 'B' |
| 3 | 1 | 3 | 'C' |
| 4 | 2 | 1 | 'C' |
| 5 | 2 | 2 | 'B' |
| 6 | 2 | 3 | 'A' |
In example:
Given two locations 'A' and 'B', search which routes have both location and A.number is less than B.number
With the previous data, it should match route id 1 and not route id 2
On raw SQL, this works with a single query:
SELECT
`route`.id
FROM
`route`
LEFT JOIN `stop` stop_from ON stop_from.`route_id` = `route`.`id`
LEFT JOIN `stop` stop_to ON stop_to.`route_id` = `route`.`id`
WHERE
stop_from.`stop_location_id` = 'A'
AND stop_to.`stop_location_id` = 'B'
AND stop_from.stop_number < stop_to.stop_number
Is this possible to do with one single query on Django ORM as well?
Generally ORM frameworks like Django ORM, SQLAlchemy and even Hibernate is not design to autogenerate most efficient query. There is a way to write this query only using Model objects, however, since I had similar issue, I would suggest to use raw query for more complex queries. Following is link for Django raw query:
[https://docs.djangoproject.com/en/1.11/topics/db/sql/]
Although, you can write your query in many ways but something like following could help.
from django.db import connection
def my_custom_sql(self):
with connection.cursor() as cursor:
cursor.execute("SELECT
`route`.id
FROM
`route`
LEFT JOIN `stop` stop_from ON stop_from.`route_id` = `route`.`id`
LEFT JOIN `stop` stop_to ON stop_to.`route_id` = `route`.`id`
WHERE
stop_from.`stop_location_id` = %s
AND stop_to.`stop_location_id` = %s
AND stop_from.stop_number < stop_to.stop_number", ['A', 'B'])
row = cursor.fetchone()
return row
hope this helps.

cucumber Repeat steps

I am learing cucumber and trying to write a feature file.
Following is my feature file.
Feature: Doctors handover Notes Module
Scenario: Search for patients on the bases of filter criteria
Given I am on website login page
When I put username, password and select database:
| Field | Value |
| username | test |
| password | pass |
| database | test|
Then I login to eoasis
Then I click on doctors hand over notes link
And I am on doctors handover notes page
Then I select sites, wards, onCallTeam, grades,potential Discharge, outstanding task,High priority:
| siteList | wardsList | onCallTeamList | gradesList | potentialDischargeCB | outstandingTasksCB | highPriorityCB |
| THE INFIRMARY | INFIRMARY WARD 9 - ASSESSMENT | null | null | null | null | null |
| THE INFIRMARY | INFIRMARY WARD 9 - ASSESSMENT | GENERAL MEDICINE | null | null | null | null |
| THE INFIRMARY | INFIRMARY WARD 9 - ASSESSMENT | GENERAL MEDICINE | CONSULTANT | null | null | null |
| THE INFIRMARY | INFIRMARY WARD 9 - ASSESSMENT | GENERAL MEDICINE | CONSULTANT | true | null | null |
| THE INFIRMARY | INFIRMARY WARD 9 - ASSESSMENT | GENERAL MEDICINE | CONSULTANT | true | true | null |
| THE INFIRMARY | INFIRMARY WARD 9 - ASSESSMENT | GENERAL MEDICINE | CONSULTANT | true | true | true |
Then I click on search button
Then I should see search results
I want to repeat last three steps like I select the search criteria then click on search button and then check search result. So how should I break this feature file. if I use scenario outline then there would be two different scenarios One for login and one for search criteria. Is that fine? Will the session will maintain in that case? Whats the best way to write such feature file.
Or is this a right way to write?
I don't think we can have multiple example sets in a Scenario Outline.
Most of the scenario steps in the example is too procedural to have its own step.
The first three steps could be reduced to something like.
Given I am logged into eoasis as a <user>
Code in the step definition, which could make calls to a separate login method that could take care of updating entering the username, password and selecting database.
Another rule is to avoid statements like "When I click the doctor's handover link". The keyword to avoid here being click. Today its a click, tomorrow it could be drop down or a button. So the focus should be on the functional expectation of the user, which is viewing the handover notes. So we modify this to
When I view the doctor's handover notes link
To summarize, this is how I would write this test.
Scenario Outline: Search for patients on the basis of filter criteria
Given I am logged into eoasis as a <user>
When I view the doctor's handover notes link
And I select sites, wards, onCallTeam, grades, potential Discharge, outstanding task, High priority
And perform a search
Then I should see the search results
Examples:
|sites |wards |onCallTeam |grades |potential Discharge |outstanding task |High priority|
| THE INFIRMARY | INFIRMARY WARD 9 - ASSESSMENT | null | null | null | null | null |
This really is the wrong way to write features. This feature is very declarative, its all about HOW you do something. What a feature should do is explain WHY you are doing something.
Another bad thing this feature does is mix up the details of two different operations, signing in, and searching for patients. Write a feature for each one e.g.
Feature: Signing in
As a doctor
I want my patients data to only be available if I sign in
So I ensure their confidentiality
Scenario: Sign in
Given I am a doctor
When I sign in
Then I should be signed in
Feature: Search for patients
Explain why searching for patients gives value to the doctor
...
You should focus on the name of the feature and the bit at the top that explains why this has value first. If you do that well then the scenarios are much easier to write (look how simple my sign in scenario is).
The art of writing features is doing this bit well, so that you end up with simple scenarios.

rails ordering by has many relation

I'm trying to order my concerts by the number of reviews each has. Concert has_many reviews. Tried doing this
<% #concerts = Concert.all %>
<% #concerts.order(reviews.size).each do |concert| %>
-
-
-
<% end %>
but I get this error
undefined method `review' for
ActiveRecord::Relation::ActiveRecord_Relation_Concert:0xb5540398>
Any suggestions how I would reference the number of reviews each has to order the concerts?
Not the best, but the simplest solution is
#concerts = Concert.all.includes(:reviews).sort_by{|concert| concert.reviews.size}.reverse
An alternative to the other answer which will ultimately give you the same result set, but will have slightly different side effects:
Concert.select("concerts.*, count(reviews.id) review_count")
.joins("LEFT JOIN reviews ON concerts.id = reviews.concert_id")
.group("concerts.id")
.order("review_count")
The main difference is that this query will not immediately execute until it is used; you'll receive an active record relation, just as you normally would when using any of the active record query methods, which means you can further refine or add to the query (hypothetically speaking).
Another difference is that this query does not require eager loading of reviews. Depending on your needs, if you don't require any information from the related reviews, this query will run considerably faster.
As far as timing / performance goes, using a database of 50 concerts and 43867 reviews (index exists on FK), both versions seem to execute in approximately the same time (with eager loading). Here's a table of my benchmarking results (all results are in seconds):
| # | Sory_by Query | Pure AR Query | No eager loading |
--------------------------------------------------------
| 1 | 2.899806 | 2.840702 | 0.02164 |
| 2 | 3.150556 | 2.818374 | 0.21612 |
| 3 | 2.812867 | 3.025921 | 0.016368 |
| 4 | 3.069562 | 3.055307 | 0.016884 |
| 5 | 2.862722 | 2.680357 | 0.021316 |
|---|---------------|---------------|------------------|
AVG: 2.9591026 | 2.8841322 | 0.0584836 |
As you can see, there's no significant difference between the two queries using eager loading, and a major difference using my query above without eager loading. Obviously, the exact results will be different for you, but this should give you an idea of the relative differences.
Side note:
From what you posted in the question, it seems you are/were wanting to write this query in the ERB view. I would strongly advice moving this query to a method in the Concert model, and creating an instance variable from the return of that method in the controller which the view can then use. That way you keep everything nice and separated.
Edit
To illustrate my recommendation, I would place the query in a class method of the Concert model, like so:
def self.ordered_by_reviews
return select("concerts.*, count(reviews.id) review_count")
.joins("LEFT JOIN reviews ON concerts.id = reviews.concert_id")
.group("concerts.id")
.order("review_count")
end
Which you can call from your controller (doesn't matter which controller):
... other controller code:
#concerts = Concert.ordered_by_reviews
... and so on
You can then use #concerts as you need and can remove any stuff like #concerts = Concert.all and such.
Alternatively, you can also use scopes to do the same thing (which I believe would be considered more Rails-y anyways):
class Concert < ActiveRecord::Base
scope :ordered_by_review, -> { select("concerts.*, count(reviews.id) review_count").joins("LEFT JOIN reviews ON concerts.id = reviews.concert_id").group("concerts.id").order("review_count") }
... rest of class

ASP Membership Profile in ColdFusion

I am trying to replicate the ASP Membership Profile functionality in ColdFusion. Basically I want to be able to get and save the property values.
To understand my basic need, I have the following:
table: aspnet_Profile
UserID | PropertyNames | PropertyValuesString |...| LastUpdatedDate
xyzxyz | FirstName:S:0:5:LastName:S:5:1: | SollyM |...| 2013-01-01 00:00:00.000
Now using ASP.net, using profile.GetPropertyValue("FirstName") will return Solly and profile.GetPropertyValue("LastName") will return M.
The interpretation of the PropertyNames is:
LastName => PropertyName
S => String
5 => Starting Position
1 => Length
To save the new LastName you use profile.SetPropertyValue("LastName","de Mots") and the table will be as below:
table: aspnet_Profile
UserID | PropertyNames | PropertyValuesString |...| LastUpdatedDate
xyzxyz | FirstName:S:0:5:LastName:S:5:7: | Sollyde Mots |...| 2013-01-02 00:00:00.000
How can I replicate this in ColdFusion?
I have been trying this for over 2 days.
I finally wrote my own CFC and can be downloaded from http://collabedit.com/7xmca
There are 3 functions:
PasswordEncrypt => This is one if the queries I had to deal with when Hashing the Password in CFM to match that of Membership.
ProfileGet("UserId","PropertyName") => returns the value of the property name.
ProfileSet("UserId","PropertyName","NewPropertyValue") => updates the PropertyName with the NewPropertyValue.
Note that the ProfileGet and ProfileSet only deals with the PropertyValuesString and not the PropertyValuesBinary of the Profile. You can extend this to get that much.

Django dynamic form with additional meta data

I want to make an form for purchasing tickets. The problem is that for every event there can be diferent types of ticket with diferent price.
For every kind of ticket I will have to create an edit box where user can select how much tickets he wants.
Then in view class I will just display the dynamicly created form ... the only problem that I see now is that I don't know where to save an information for each ticket price so I can easy display it in the the same row where the edit box is?
P.S. I'm also not sure how can I dynamicly create a form using Django ... but this have to be easy ;)
P.S. Form have to be something like this:
--------------------------------------------------------
| Tiket Type | Price | How much? | Price |
--------------------------------------------------------
| Tiket Type Name | Price $1.00 | [ ] | Price... | [tiketkind.id = 1]
| Tiket Type Name | Price $2.00 | [ ] | Price... | [tiketkind.id = 12]
| Tiket Type Name | Price $3.00 | [ ] | Price... | [tiketkind.id = 18]
| Tiket Type Name | Price $4.00 | [ ] | Price... | [tiketkind.id = 21]
--------------------------------------------------------
| TOTAL PRICE: | ... |
--------------------------------------------------------
| Email: [ ] |
--------------------------------------------------------
This is pretty easy. Instead of thinking about making dynamic forms, think about making dynamic fields.
You'll have one form. When you initialize it, you'll pass it information about the tickets available. In the init of your form you will dynamically add field objects to the form by appending to self.fields.
Example:
self.fields['this_field_I_just_made_up'] = forms.CharField()
Notes:
The first thing you'll need to do in your init is to pop off your custom values.
The second thing you'll need to do in your init is to call the init of the superclass with *args and **kwargs.
If you don't do those two things, in that order, you will get errors.
Shawn
Source: http://groups.google.com/group/django-users/browse_thread/thread/3629184ceb11aeef
First of all, you're thinking in PHP. Don't do that. There's no need for array-like HTML element names.
I'm not entirely sure I understand your requirements, but it sounds like a formset will do what you want.