Argument error in collect object Rails 3 - html

Guys I'm using a select() tag in .html.erb file as follows
<%= select(:hfi_id, b.beneficiaryloans.collect { |h| [User.find(h.hfi_id).firstname, h.hfi_id] }) %>
what's wrong in this statement? actually it is giving an error called
wrong number of arguments (2 for 3) - error for above line
But same thing I executed in irb console, it's working fine like
irb(main):012:0> me=Beneficiary.find(1)
=> #<Beneficiary id: 1, firstname: "Mohan", lastname: "Bairwa", address: "1399 m.k.b jagatpira", age: 24, sex: "Male", total_members: 1, cso_id: 123, project_id: 17, remarks: nil, status_id: 4, created_at: "2011-11-07 09:39:24", updated_at: "2011-11-07 09:55:07">
irb(main):018:0> me.beneficiaryloans.collect {|h|User.find(h.hfi_id).firstname,h.hfi_id]}
=> [["Gruh", 117]]
using irb console I'm getting correct result
=> [["Gruh", 117]]
but when I put it in .html.erb file, It's giving argument error. How to solve this?

Look at this. select method has 3 obligatory parameters and you provide only two..

Related

Write ecto schema to csv file in elixir?

Hi I have Person schema in elixir like this
[
%Texting.Contact.Person{
__meta__: #Ecto.Schema.Metadata<:loaded, "people">,
email: nil,
name: "John",
phone_number: "13334445555",
phonebook: #Ecto.Association.NotLoaded<association :phonebook is not loaded>,
phonebook_id: 60,
previous_phonebook_id: 60,
subscribed: true,
updated_at: ~N[2018-09-22 14:36:04.788163],
user: #Ecto.Association.NotLoaded<association :user is not loaded>,
user_id: 54
},
%Texting.Contact.Person{
__meta__: #Ecto.Schema.Metadata<:loaded, "people">,
email: nil,
name: "Rhee",
phone_number: "14443335555",
phonebook: #Ecto.Association.NotLoaded<association :phonebook is not loaded>,
phonebook_id: 60,
previous_phonebook_id: 60,
subscribed: true,
updated_at: ~N[2018-09-22 14:36:13.671479],
user: #Ecto.Association.NotLoaded<association :user is not loaded>,
user_id: 54
}
]
And I want to save this to csv file format.So I did this
def write!(people) do
file = File.open("contacts.csv", [:write, :utf8])
people
|> Enum.map(&Map.from_struct(&1))
|> Enum.map(&CSV.encode(&1, headers: [:name, :phone_number]))
|> Enum.map(&IO.write(file, &1))
end
but I got an error like this
** (Protocol.UndefinedError) protocol String.Chars not implemented for #Function<62.51129937/2 in Stream.transform/3>. This protocol is implemented for: Atom, BitString, Date, DateTime, Decimal, Ecto.Date, Ecto.DateTime, Ecto.Time, Float, Floki.Selector, Floki.Selector.AttributeSelector, Floki.Selector.Combinator, Floki.Selector.Functional, Floki.Selector.PseudoClass, Integer, List, NaiveDateTime, Postgrex.Copy, Postgrex.Query, Postgrex.Stream, Time, URI, Version, Version.Requirement
(elixir) /home/ubuntu/bob/tmp/0a92cc555e2418d1b56e3b10e5321a85/elixir/lib/elixir/lib/string/chars.ex:3: String.Chars.impl_for!/1
(elixir) /home/ubuntu/bob/tmp/0a92cc555e2418d1b56e3b10e5321a85/elixir/lib/elixir/lib/string/chars.ex:22: String.Chars.to_string/1
(elixir) lib/io.ex:553: IO.write/2
(elixir) lib/enum.ex:1314: Enum."-map/2-lists^map/1-0-"/2
What I want to do is save only name and phone_number field to csv file format.
How can I do this?
According to the documentation, CSV.encode/2 takes a list of list of strings and doesn't have the option you tried to use.
Here's how I'd do it:
def write!(people) do
people
|> Stream.map(&[&1.name, &1.phone_number])
|> CSV.encode()
|> Enum.into(File.stream!("contacts.csv"))
end
The Enum.map creates a list of list of strings which is then encoded and streamed into contacts.csv.
To add a header line at the top, you can use Stream.concat/2 to prepend the header line:
def write!(people) do
[["name", "phone_number"]]
|> Stream.concat(people |> Stream.map(&[&1.name, &1.phone_number]))
|> CSV.encode()
|> Enum.into(File.stream!("contacts.csv"))
end

How to use Jbuilder to display parent info with child information nested underneath

I am using jbuilder in rails to generate some JSON in a rails app.
In my models, 'od_items' belong to 'od', and 'ods' belong to 'sophead'.
I want to display each 'od' of the 'sophead', and then nested under each of these, I want to display each of the 'od_items' that belong to the 'od'.
Here is my code so far:
json.ods #sophead.ods do |od|
json.od od
json.od_items od.od_items do |od_item|
json.od_item od_item
end
end
This is outputting the following JSON:
ods: [
{
od: {
id: 51,
sophead_id: 386,
created_at: "2018-03-21T15:28:48.802Z",
updated_at: "2018-03-21T15:28:48.802Z",
status: "Open"
},
od_items: [
{
od_item: {
id: 285,
od_id: 51,
qty: "1.0",
part: "CARRIAGE CHARGE",
description: "Simpson Carriage Charge",
created_at: "2018-03-21T15:28:48.823Z",
updated_at: "2018-03-21T15:28:48.823Z"
}
},
{
od_item: {
id: 284,
od_id: 51,
qty: "1.0",
part: "MISCELLANEOUS",
description: "Split Box Charge",
created_at: "2018-03-21T15:28:48.816Z",
updated_at: "2018-03-21T15:28:48.816Z"
}
}
]
}
],
The problem is that I want 'od_items' to be nested inside the 'od' that it relates to, instead it appears next to it.
This should be pretty simple to sort out, but I cant find anything online.
(First question on Stack overflow - Thanks very much in advance)
If your #sophead.ods is a collection of hashes, you can easily achieve it merging the od element with its od_items:
json.ods #sophead.ods do |od|
json.od od.merge(od_items: od.od_items)
end
Since it seems that these are ActiveRecords:
json.ods #sophead.ods do |od|
json.od od.as_json.merge(od_items: od.od_items.map(&:as_json))
end
According to the README, another way to obtain the same result is to use json.merge!:
json.ods #sophead.ods do |od|
json.od do
json.id od.id
json.sophead_id od.sophead_id
json.created_at od.created_at
json.updated_at od.updated_at
json.status od.status
json.merge! { od_items: od.od_items.as_json}
end
Another approach which assures better performances would be to use ActiveModelSerializer instead.
class OdSerializer < ActiveModelSerializers::Model
attributes :id, :sophead_id, :created_at, :updated_at, :status
has_many :od_items, serializer: OdItemSerializer
end
class OdItemSerializer < ActiveModelSerializers::Model
attributes :id, :od_id, :qty, :part, :description, :created_at, :updated_at
end
# And in the controller
render json: #sophead.ods, each_serializer: OdSerializer

Elixir decode with Poison

I'm getting this string as query result from my database:
"%Sample.Struct{list: [], total: \"0.00\", day: 6, id: \"8vfts6\"}"
Is there any way to convert this one back to map?
I'm getting this error decoding it with poison
** (Poison.SyntaxError) Unexpected token: %
(poison) lib/poison/parser.ex:56: Poison.Parser.parse!/2
(poison) lib/poison.ex:83: Poison.decode!/2
I can't fix the way data is being added to database, i must find a proper way for a key/value route to easily retrive data from that. (this is just a sample for a more complex result)
As it was mentioned in comments, you should not use Code.eval_string. But, there is a way to safely convert your code to Elixir struct, using Code module:
ex(1)> encoded = "%Sample.Struct{list: [], total: \"0.00\", day: 6, id: \"8vfts6\"}"
"%Sample.Struct{list: [], total: \"0.00\", day: 6, id: \"8vfts6\"}"
First, get the AST from the string, but use the pattern matching to ensure it is a struct you are looking for ({:__aliases__, _, [:Sample, :Struct]}). All other (potentially malicious) code will fail this match:
iex(2)> {:ok, {:%, _, [{:__aliases__, _, [:Sample, :Struct]}, {:%{}, _, keymap}]} = ast} = Code.string_to_quoted(encoded)
{:ok,
{:%, [line: 1],
[{:__aliases__, [line: 1], [:Sample, :Struct]},
{:%{}, [line: 1], [list: [], total: "0.00", day: 6, id: "8vfts6"]}]}}
Here you have the full ast for you struct, and the keymap. You may now be tempted to use eval_quoted with the AST, to get the struct you needed:
iex(3)> {struct, _} = Code.eval_quoted(ast)
{%Sample.Struct{day: 6, id: "8vfts6", list: [], total: "0.00"}, []}
iex(4)> struct
%Sample.Struct{day: 6, id: "8vfts6", list: [], total: "0.00"}
But it is still not safe! Someone may put a function causing side effect into the string, like "%Sample.Struct{list: IO.puts \"Something\"}", which will be executed during the evaluation. So you will need to check the keymap firsts, if it contain safe data.
Or you may just use keymap directly, without evaluating anyting:
iex(5)> struct(Sample.Struct, keymap)
%Sample.Struct{day: 6, id: "8vfts6", list: [], total: "0.00"}

SQL LIKE search error only on one row of table

This is weird, it never happens to me before
Im on the rails console, because my search form is not working, for some reason when i do a search using the row called 'nombre', the search doesnt work, this is the output data:
First, I will show you my table data:
2.3.0 :035 > Item.all
Item Load (0.6ms) SELECT "items".* FROM "items"
=> #<ActiveRecord::Relation [#<Item id: 1, nombre: "Melamina Blanca", espesor: 18, material: "MDF", quantity: 14, created_at: "2016-08-04 00:56:13", updated_at: "2016-08-30 00:05:01">, #<Item id: 2, nombre: "Melamina Gris Grafito", espesor: 15, material: "Aglo", quantity: 9, created_at: "2016-08-04 00:56:13", updated_at: "2016-08-30 00:05:01">, #<Item id: 3, nombre: "Melamina Azul", espesor: 18, material: "MDF", quantity: 26, created_at: "2016-08-04 00:56:13", updated_at: "2016-08-30 00:05:01">, #<Item id: 4, nombre: "Melamina Rojs", espesor: 18, material: "MDF", quantity: 5, created_at: "2016-08-04 00:56:13", updated_at: "2016-08-30 00:05:01">]>
2.3.0 :036 >
So as you can see, the first item, the name (nombre) is 'Melamina Blanca'
If I do the search, I get the following:
item = Item.where("nombre LIKE ?", "Blanca")
Item Load (0.8ms) SELECT "items".* FROM "items" WHERE (nombre LIKE 'Blanca')
=> #<ActiveRecord::Relation []>
So I tried to search by another row, on this case called 'Material'
item = Item.where("material LIKE ?", "Aglo")
Item Load (0.5ms) SELECT "items".* FROM "items" WHERE (material LIKE 'Aglo')
=> #<ActiveRecord::Relation [#<Item id: 2, nombre: "Melamina Gris Grafito", espesor: 15, material: "Aglo", quantity: 9, created_at: "2016-08-04 00:56:13", updated_at: "2016-08-30 00:05:01">]>
I get a correct search, I tried with the other rows and all of them work, except the one I need, which is 'nombre'
Any ideas why?
I think the problem is you are searching for an exact match. To search for a pattern string, you have to use % which defines wildcards.
Try
Item.where("nombre LIKE ?", "%Blanca%")
This will look for records with names that contain "Blanca" in it.
If you want to search for names that start with "Blanca", use
Item.where("nombre LIKE ?", "Blanca%")
Or for names ending with "Blanca", use
Item.where("nombre LIKE ?", "%Blanca")
Note: Your search across material "Aglo" was successful because the material field in the record contained the exact string "Aglo".
Hope this helps!

Is .create method adding nil value if it fails to recognize an integer in Rails 4

In my controller, I need to pluck a single, matching integer value and then create a record with that value in another table. In action, it looks like this:
if Participation.where(ranking: "1")
first = PointsAllocation.where(game_id: params[:game_id]).where(place: "1").pluck(:points)
Stack.create(game_id: params[:game_id], user_id: current_user.id, chips: first)
else
end
I have tested in the console that the first variable is definable. If I run PointsAllocation.where(game_id: "1").where(place: "1").pluck(:points), it will return:
SELECT "points_allocations"."points" FROM "points_allocations" WHERE "points_allocations"."game_id" = 1 AND "points_allocations"."place" = 1
=> [10]
Ok, so it is correctly plucking what looks like an integer value for Points. I then want to use this points value and send it to the Chips column in the Stack table. When I run this, it will add a nil record even though first is defined, like so:
<Stack id: 1, game_id: 1, user_id: 1, chips: nil>
In troubleshooting, I thought maybe the issue here is that even though it looks like an integer (and Chips, I should add, is a t.integer attribute), maybe it's accidentally a string or something from pluck. So let's map this to an integer to be safe by adding map(&:to_i) after the pluck.
When I do that, it gets weirder, as it now returns:
<Stack id: 9, game_id: 1, user_id: 1, chips: 0>
So when I convert it to an integer, it changes 10 to a 0 and adds it to the table.
Where am I going wrong?
You may resolve it loading only one object instead ActiveRecord::Association:
first = PointsAllocation.where(game_id: params[:game_id]).where(place: "1").first
points = first.points
Stack.create(game_id: params[:game_id], user_id: current_user.id, chips: points)
Problem is that AR trying convert incorrect values if they type different with column type:
Stack.create(chips: 10)
#=> <Stack id: ..., chips: 10>
Stack.create(chips: [10])
#=> <Stack id: ..., chips: nil>
Stack.create(chips: "10")
#=> <Stack id: ..., chips: 10>
Stack.create(chips: "first")
#=> <Stack id: ..., chips: 0>