Fetching array of data from DB using Rails 3 - ruby

I want to access multiple columns using Rails 3.But it gave me the following error.
Error:
ArgumentError (wrong number of arguments (2 for 1)):
app/controllers/payments_controller.rb:13:in `check_type'
Check my below code.
payment_controller.rb:
class PaymentsController < ApplicationController
def payment
#payment=Vendor.new
respond_to do |format|
format.html
format.js
end
end
def check_type
if params[:commit]=="submit"
#vendor_type=PaymentVendor.where(:v_name => params[:v_name]).pluck(:type ,:Receipt_No)
#vendor_type.each do |vendor|
end
else
#v_name=Vendor.where(:s_catagory => params[:payment][:s_catagory] ).pluck(:v_name)
end
end
end
Actually i want to retrive data like below format.
#vendor_type=["Receipt_no":"type","Receipt_no":"type",.....]
Once these data will appear,I need how to access row values according to Receipt_No.Please help me to resolve this error.

Thanks to ActiveRecord >= 4 . pluck accepts multiple arguments so in
Rails 4: Your query will work
#vendor_type=PaymentVendor.where(:v_name => params[:v_name]).pluck(:type ,:Receipt_No)
Now as you are using Rails 3 which doesn't support multiple arguments to pluck then we can extend ActiveRecord::Relation itself like this:
put your file under config/initializers
# pluck_all.rb
module ActiveRecord
class Relation
def pluck_all(*args)
args.map! do |column_name|
if column_name.is_a?(Symbol) && column_names.include?(column_name.to_s)
"#{connection.quote_table_name(table_name)}.#{connection.quote_column_name(column_name)}"
else
column_name.to_s
end
end
relation = clone
relation.select_values = args
klass.connection.select_all(relation.arel).map! do |attributes|
initialized_attributes = klass.initialize_attributes(attributes)
attributes.each do |key, attribute|
attributes[key] = klass.type_cast_attribute(key, initialized_attributes)
end
end
end
end
end
Now in your controller you can pass multiple arguments to pluck like this:
# payment_controller.rb:
#vendor_type=PaymentVendor.where(:v_name => params[:v_name]).pluck_all(:type ,:Receipt_No)
Now you can use pluck_all in whole app. Hope this helps ;)
EDIT:
Try below code if plcuk_all not worked:
#vendor_type = PaymentVendor.where(:v_name => params[:v_name]).map{|v|[v.type ,v.Receipt_No]}
Reference for more info: http://meltingice.net/2013/06/11/pluck-multiple-columns-rails/

Your pluck(:type ,:Receipt_No) looks wrong,
pluck have only one argument.
Also your type of data #vendor_type is wrong, Array don't have key, value pair.
Use map like this,
#vendor_type=PaymentVendor.where(:v_name => params[:v_name]).map { |i| [i.Receipt_No] }

In terms of making a rails 3 method that behaves the same as the Rails 4 pluck with multiple columns. This outputs a similar array (rather than a hashed key value collection). This should save a bit of pain if you ever come to upgrade and want to clean up the code.
See this tutorial which outlines a similar method that outputs a hash.
config/initializers/pluck_all.rb
module ActiveRecord
class Relation
def pluck_all(*args)
args.map! do |column_name|
if column_name.is_a?(Symbol) && column_names.include?(column_name.to_s)
"#{connection.quote_table_name(table_name)}.#{connection.quote_column_name(column_name)}"
else
column_name.to_s
end
end
relation = clone
relation.select_values = args
klass.connection.select_all(relation.arel).map! do |attributes|
initialized_attributes = klass.initialize_attributes(attributes)
attributes.map do |key, attribute|
klass.type_cast_attribute(key, initialized_attributes)
end
end
end
end
end
Standing on the shoulders of giants and all

Related

How this ruby script using twitter api scrapes user ids?

Hello I have modified this older code to scrape twitter usernames, but for some reason it also scrapes user ids. I dont understand how it does that, since I dont see anywhere in the code "user_id" which you should use to get user ids according to twitter api documentation.
Here is the code
def my_usernames
"UHDTelevisions"
end
def my_userinfo(names)
#client.followers(names)
end
def my_userhash(users)
userhash = {}
users.each do |user|
userhash[user.screen_name] = user.id.to_s
end
return userhash
end
def my_users
my_userhash(my_userinfo(my_usernames))
end
def my_csv(my_users)
CSV.open('./my_users.csv','a+') do |csv|
my_users.each do |k,v|
csv << [k,v]
end
end
Here is the line that builds a hash {name ⇒ id}:
userhash[user.screen_name] = user.id.to_s
Here we already got the user object, that contains id amongst other user params. To return the list of names, one might simply:
#client.followers("UHDTelevisions").map &:screen_name
instead of all the code above.
If you wanted to keep a parallel structure you could change it to have my_userarray (since you only need values, not key-value pairs, I assume)
def my_userarray(users)
userarray = []
users.each do |user|
userarray << user.screen_name
end
return userarray
end
You would need to update the my_users method as well, of course, to reflect the new method name for my_userarray

Passing the parameter of an Object into an Object method

This a simplified version of what I am trying to solve:
In Ruby 2.0.0, Rails 4.0.0, Activerecord
Segment has_many Sales
Sale.find(1).bid = 1
Sale.find(1).ask = 2
Sale.find(2).bid = 10
Sale.find(2).ask = 20
etc
When I write this method:
class Segment
def add_stuff(param)
sales.map{ |s| s.param }.inject(:+)
end
end
Question: How to pass in bid or ask as param and interpolate that param properly within the block? Thanks.
Never use map on active record association, when you can use pluck or other querying method like, for example sum:
def add_staff(param)
sales.sum(param)
end
Just for the completeness, here is how to do it with map - note however that map is much slower and error prone than querying methods:
def add_staff(param)
sales.map {|s| s[param]} # if param is name of the column on sales model.
end
Or more general, where param is name of association or custom (non-column) method
def add_staff(param)
sales.map(&param) # Or map {|s| s.send(param) }
end

Rails 4 strong parameters ActiveModel::ForbiddenAttributesError

For some reason in my current controller I am getting ActiveModel::ForbiddenAttributesError even though I believe I am using strong parameters just fine. Albeit I am using permit! for the time being to permit all model attributes. See code below, what am I missing
class HeuristicsController < ApplicationController
def index
#heuristics = Heuristic.order(:name).page params[:page]
#heuristic = Heuristic.new
end
def create
#heuristic = Heuristic.new(params[:heuristic])
if #heuristic.save
redirect_to action: 'index', :flash => {:success => "New heuristic created!" }
else
render 'new'
end
end
def new
#title = "Heuristic"
#heuristic = Heuristic.new
end
private
def heuristic_params
params.require(:heuristic).permit!
end
end
i think you did not fully understand the way that strong-params work...
you have a method
def heuristic_params
params.require(:heuristic).permit!
end
and you are not using it
Heuristic.new(params[:heuristic])

Active Record to_json\as_json on Array of Models

First off, I am not using Rails. I am using Sinatra for this project with Active Record.
I want to be able to override either to_json or as_json on my Model class and have it define some 'default' options. For example I have the following:
class Vendor < ActiveRecord::Base
def to_json(options = {})
if options.empty?
super :only => [:id, :name]
else
super options
end
end
end
where Vendor has more attributes than just id and name. In my route I have something like the following:
#vendors = Vendor.where({})
#vendors.to_json
Here #vendors is an Array vendor objects (obviously). The returned json is, however, not invoking my to_json method and is returning all of the models attributes.
I don't really have the option of modifying the route because I am actually using a modified sinatra-rest gem (http://github.com/mikeycgto/sinatra-rest).
Any ideas on how to achieve this functionality? I could do something like the following in my sinatra-rest gem but this seems silly:
#PLURAL.collect! { |obj| obj.to_json }
Try overriding serializable_hash intead:
def serializable_hash(options = nil)
{ :id => id, :name => name }
end
More information here.
If you override as_json instead of to_json, each element in the array will format with as_json before the array is converted to JSON
I'm using the following to only expose only accessible attributes:
def as_json(options = {})
options[:only] ||= self.class.accessible_attributes.to_a
super(options)
end

getting active records to display as a plist

I'm trying to get a list of active record results to display as a plist for being consumed by the iphone. I'm using the plist gem v 3.0.
My model is called Post. And I want Post.all (or any array or Posts) to display correctly as a Plist.
I have it working fine for one Post instance:
[http://pastie.org/580902][1]
that is correct, what I would expect. To get that behavior I had to do this:
class Post < ActiveRecord::Base
def to_plist
attributes.to_plist
end
end
However, when I do a Post.all, I can't get it to display what I want. Here is what happens:
http://pastie.org/580909
I get marshalling. I want output more like this:
[http://pastie.org/580914][2]
I suppose I could just iterate the result set and append the plist strings. But seems ugly, I'm sure there is a more elegant way to do this.
I am rusty on Ruby right now, so the elegant way isn't obvious to me. Seems like I should be able to override ActiveRecord and make result-sets that pull back more than one record take the ActiveRecord::Base to_plist and make another to_plist implementation. In rails, this would go in environment.rb, right?
I took the easy way out:
private
# pass in posts resultset from finds
def posts_to_plist(posts)
plist_array = []
posts.each do |post|
plist_array << post.attributes
end
plist_array.to_plist
end
public
# GET /posts
# GET /posts.xml
def index
#posts = Post.all
##posts = [{:a=>"blah"}, {:b=>"blah2"}]
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => posts_to_plist(#posts) }
end
end
I found this page searching for the same answer. I think you have the right approach, though I'm also a newbie (on Rails) and not sure the right way to do it. I added this to application_helper.rb. Seems to work.
require 'plist'
module ApplicationHelper
class ActiveRecord::Base
public
include Plist::Emit
def to_plist
self.attribute_names.inject({}) do |attrs, name|
value = self.read_attribute(name)
if !value.nil?
attrs[name] = value
end
attrs
end
end
end
end
According to the plist project README, you should implement "to_plist_node", as opposed to "to_plist".
You should also mixin Plist::Emit to your ActiveRecord class.

Resources