Use :order with find_by_id - ruby-on-rails-2

In my Rails application I have a Device and a DevicePort class with a one to many relationship between them.
In my device controller I get a list of all the ports belonging to that device but I can't seem to order them:
#device_ports = Device.find_by_id(params[:id], :order => 'id ASC').device_ports
This doesn't seem to work and doesn't give any syntax errors either.
In the view I am simply doing:
<% #device_ports.each do |device_port| %>
...
<% end %>
Is anyone able to explain why the ports aren't being sorted by id?

If you want to order device_ports, I'd do something like this:
#device_ports = Device.find(params[:id]).device_ports.all(:order => 'id ASC')

Well, you are ordering just the devices, the ports are randomly being fetched. You can eager load your association and order the ports with this:
Device.includes(:device_ports).where('devices.id = ?', params[:id]).order('device_ports.id')
Make note about the query that is generated. You have access to the ports table when you join them.
UPDATE:
If you want the other way around:
DevicePort.includes(:device).where('devices.id = ?', params[:id]).order('device_ports.id')
Only the association inside the includes is changed.

#device_ports = Device.exists?(params[:id]) ? Device.find_by_id(params[:id]).device_ports : []
if you want order on device sports do following
#device_ports = Device.exists?(params[:id]) ? Device.find_by_id(params[:id]).device_ports.order('id ASC') : []
For rails 2.x.x use following
#device_ports = DeviceSport.find(:all, :conditions => ["device_id = ?", params[:id]], :order => 'id ASC' )

Related

ActiveRecord conditions across multiple tables.

I'm trying to retrieve cars from my database where each car has a manufacturer, and can have multiple styles.
For example, a ford fiesta is a coupe, sedan and hatch.
I've got my relationships set-up in my models, but now I want to create a query to return the results. The query construction will depend on what parameters are supplied.
This is what I've got so far
conditions = {}
conditions[:manufacturer_id] = params[:manufacturer_id] unless params[:manufacturer_id].blank? # this works!
conditions[:style_id] = "style_id IN (?)", params[:style_ids] unless params[:style_ids].blank? #this breaks it :(
cars = Car.find(:all, :conditions=> conditions)
return render :json => cars
The error getting returned is
PG::Error: ERROR: column cars.style_ids does not exit of course this is because the style_id is in a join table called cars_styles. Is there a way to tell ActiveRecord which table to look for within the condition?
The key thing here is that I want to only have one controller method which takes the params in existence and then creates the right query. So if I don't have a manufacturer_id, it will only query the styles, or if vice versa. Of course, I'll be adding other params later too.
I ended up doing this with scoped queries like this
scope :from_manufacturer, lambda{|manu|{:joins => :manufacturer, :conditions => "manufacturers.id = #{manu}" }}
scope :from_style, lambda{|style|{:joins => :style, :conditions => "styles.id = #{style}"}}
def self.get_cars(params)
scope = self
[:manufacturer,:style].each do |s|
scope = scope.send("from_#{s}", params[s]) if params[s].present?
end
scope
end
Works great!

Simply extracting multiple records from multiple other records...(Rails/Ruby)

I think this is a simple problem, but i just cant get my head round the solution. If i have a collection of records (reports in this case):
#reports = Report.all, :conditions => ["score > 10"]
and then i try to find the associated collection of other type of records (users in this case) i, naively, try this - but know from the offset that it wont work:
#users = User.find :all, :conditions => ["id IN (?)", #results.user_id]
So, how do i efficiently extract the #users collection of records?
Assuming that User has_many :reports
#users = User.joins(:reports) # all users that have reports
If you only want all users for some specific reports
#users = User.joins(:reports).where("reports.id IN (?)", #reports.map(&:id))

Better way to query an LDAP users via ruby net-ldap?

Is there a better way to search for users and computers specifically using the Net-ldap gem?
Here is what I am currently having to do to get only users.
results = search :base => #base, :filter => Net::LDAP::Filter.eq("cn", "*")
#results = Array.new
results.each do |result|
#results.push result if result[:objectclass].include? "person" unless result[:objectclass].include? "computer"
Seems like there would be a better way. I can't see anything obvious in the documentation.
You can use the Join filter functionality of net-ldap:
filter = Net::LDAP::Filter.eq("sAMAccountName", "*")
filter2 = Net::LDAP::Filter.eq("objectCategory", "organizationalPerson")
joined_filter = Net::LDAP::Filter.join(filter, filter2)
ldap.search(:base => treebase, :filter => joined_filter) do |entry|
puts entry.sAMAccountName
end
If you know the objectClass that is used for persons, you could use the filter '(objectClass=person)', replacing 'person' with the objectClass. Most implementations will use 'person' or an objectClass that inherits from 'person' such as 'inetOrgPerson'. Using the filter '(cn=*)' will most likely get entries that are not persons.
Try using Filter.eq("objectClass","person")

Preventing SQL Injection/Good Ruby method

What is a good method in Ruby to prevent SQL Injection?
in straight up ruby? use prepared statements:
require 'mysql'
db = Mysql.new('localhost', 'user', 'password', 'database')
statement = db.prepare "SELECT * FROM table WHERE field = ?"
statement.execute 'value'
statement.fetch
statement.close
Not just in Ruby - bind your parameters (be it in the database, or in your client code).
Check out the guide they have up on this: http://guides.rubyonrails.org/security.html#injection
Basically, you want to use bind variables in your models to find data, rather than inline parameters..
Model.find(:first, :conditions => ["login = ? AND password = ?", entered_user_name, entered_password])
According to http://ruby.railstutorial.org/ you can prevent Cross Site Request Forgery by inserting the
<%= csrf_meta_tags %>
tag in the header of app/views/layouts/application.html.erb.
Direct link of example
This thread references:
http://www.ruby-forum.com/topic/90258#new
http://www.ruby-forum.com/topic/82349#143790
ActiveRecord's find() method has built in ways to avoid SQL injection by
using the format
> :conditions => [ "user_name = ?", user_name]
Is there any such system for escaping injection in order? It seems to
only take a string and feed it to the SQL statement. This causes a
vulnerability when using params to set : order as in this function:
def list
sort_by = params[:sort_by]
#book_pages, #books = paginate :books,
:order => sort_by,
:per_page => 10
end
We've tried a few methods to sanitize sort_by such as order => ['?',
sort_by] but it just passes that to the SQL statement like a flattened
array. The 'escaping magic' does not work for order. Should I use
gsub! to sanitize params[:sort_by]?

ROR- Cannot use Find in a 1-many relationship

In Ruby on rails, our model includes orders and payments.
There's 1-many relationship between order and payments.
In the orders model we specify:
has_many :payments, :as => :payable
And a payment record has payable_id that is set to order.id.
In a report, I want to select all payments that belong to orders of a given type.
Using:
payments = Payment.find(:all, :conditions => conditions)
and adding 'payable.type="a" ' to the conditions doesn't work.
It seems that ActiveRecord doesn't develop this into a correct join statement (payable_id=order.id and orders.type='a').
I cannot use explicit SQL here, as the condition contains other things that are inserted there earlier in the code.
Thanks,
Raffi Lipkin
Your conditions clause is wrong.
You state that an Order
has_many :payments, :as => :payable
This tells me that a Payment
belongs_to :payable, :polymorphic => true
This means that the payments table has two columns of note: payable_id and payable_type. This also means that Payments can be applied not just to Orders, but also to other models as well (CreditCardBalances, who knows).
If you want to query for payments of a specific type, i.e. belonging to any instance of a particular class, you need to be querying the field payments.payable_type. This works fine:
Payment.find(:all, :conditions => "payable_type = 'Order'")
Here's a gist that shows what I did to test this. The models created are set up just like described above.
Don't forget that you can extract that into named scopes if it's easier:
named_scope :on_orders, :conditions => "payable_type = 'Order'"
Which makes it
Payment.on_orders
Or dynamically:
named_scope :on, lambda { |type| { :conditions => "payable_type = '#{type.to_s}'" } }
Which then makes it
Payment.on(Order) # or Payment.on(CreditCardBalance) or Payment.on("Order")
Try incliding and reference the actual table id name in the condition, rather than the association alias:
find(:include => "payments", :conditions => ["payment.type = ?", "x"]
You mention 'payment type'. If they're fairly static, have you considered using single table inheritance (STI) to subclass your different payment types? Then Rails will do all the magic to filter on type.
E.g.
class CreditCardPayment < Payment
...
end
It doesn't even need to exhibit different behaviour initially; however you'll probably find that it turns out to be really useful to have different data and polymorphic behaviour around payments.

Resources