I've a piece of code in my product model where I assign values to columns by fetching from s3. The column names includes a counter "i" as well -
The 3 sample column names are -
pic1_file_name
pic2_file_name
pic3_file_name
The problematic code is -
prod = Product.find(id)
i=1
s3 = AWS::S3.new
bucket=s3.buckets['bucket_name']
bucket.objects.each do |obj|
prod.("pic"+"#{i}".to_s+"_file_name")=obj.key[45..1]
# the above line give a syntax error, unexpected '=', expecting end-of-input
prod.("pic"+"#{i}".to_s+"_file_name").to_sym = obj.key[45..-1]
# The above line gives an error undefined method `call' for #<Product:0x7773f18>
prod.send("pic"+"#{i}".to_s+"_file_name")=obj.key[45..-1]
# The above gives syntax error, unexpected '=', expecting end-of-input
i+=1
end
prod.save
Could you please advise as to how should I structure my column name with a variable so that I can assign a value to it without having to type 15 separate columns every time.
Any pointers will be appreciated.
Thanks in advance!
You almost got the last one right. You see, when doing
obj.pic1_file_name = 'foo'
you're actually calling method pic1_file_name=, not pic1_file_name. That line is equivalent to this:
obj.pic1_file_name=('foo')
With that in mind, your last line becomes
prod.send("pic#{i}_file_name=", obj.key[45..-1])
You can use the send method to call a method from a string:
prod.send("pic#{i}_file_name") # to read
prod.send("pic#{i}_file_name=", obj.key[45..-1]) # to assign
Related
I have one variable with number and text concatenated (e.g. "[79511]Rocket"). If this variable does contains numbers inside the brackets, I must store then (numbers only) in one column of my table. I'm validating this with the below code:
enterprise_id = "[79511]Rocket".split(/[\[\]]/x)[1].match(/^(\d)+$/) rescue nil
When I test in with Puts, it works as 79511, fine.
But then when I run the code to insert into database like below:
enterprise_id = "[79511]Rocket".split(/[\[\]]/x)[1].match(/^(\d)+$/) rescue nil
insert_ds = DB["INSERT INTO pd_deals ( enterprise_id ) VALUES (?)", enterprise_id]
insert_ds.insert
The target column is Integer type in table.
It throws an error:
/home/bm93/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/sequel-4.34.0/lib/sequel/dataset/sql.rb:1252:in `literal_other_append': can't express #<MatchData "79511" 1:"1"> as a SQL literal (Sequel::Error)
from /home/bm93/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/sequel-4.34.0/lib/sequel/dataset/sql.rb:108:in `literal_append'
from /home/bm93/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/sequel-4.34.0/lib/sequel/dataset/sql.rb:673:in `block in placeholder_literal_string_sql_append'
from /home/bm93/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/sequel-4.34.0/lib/sequel/dataset/sql.rb:670:in `loop'
from /home/bm93/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/sequel-4.34.0/lib/sequel/dataset/sql.rb:670:in `placeholder_literal_string_sql_append'
from /home/bm93/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/sequel-4.34.0/lib/sequel/sql.rb:109:in `to_s_append'
from /home/bm93/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/sequel-4.34.0/lib/sequel/dataset/sql.rb:1214:in `literal_expression_append'
from /home/bm93/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/sequel-4.34.0/lib/sequel/dataset/sql.rb:86:in `literal_append'
from /home/bm93/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/sequel-4.34.0/lib/sequel/dataset/sql.rb:345:in `literal'
from /home/bm93/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/sequel-4.34.0/lib/sequel/dataset/sql.rb:1534:in `static_sql'
from /home/bm93/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/sequel-4.34.0/lib/sequel/dataset/sql.rb:23:in `insert_sql'
from /home/bm93/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/sequel-4.34.0/lib/sequel/dataset/actions.rb:334:in `insert'
from /home/bm93/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/sequel-4.34.0/lib/sequel/adapters/shared/postgres.rb:1355:in `insert'
from tt.rb:12:in `<main>'
I'm doing this way because I need to extract a number from a string. Any hint there? Is there any way better?
If you execute:
"[79511]Rocket".split(/[\[\]]/x)[1].match(/^(\d)+$/)
in irb, you'll see:
=> #<MatchData "79511" 1:"1">
because String#match returns a MatchData instance and calling inspect on a MatchData gives you #<MatchData ...>. If you puts that value:
puts "[79511]Rocket".split(/[\[\]]/x)[1].match(/^(\d)+$/)
you'll see 79511 because puts calls to_s on its arguments to convert them to strings.
Sequel won't call to_s, it will try to figure out how to translate the argument to something the database understands on its own and it doesn't know what to do with a MatchData instance, hence the:
can't express #<MatchData "79511" 1:"1"> as a SQL literal
error.
You could call to_s yourself:
DB["INSERT INTO pd_deals ( enterprise_id ) VALUES (?)", enterprise_id.to_s.presence]
or use the MatchData#[] method:
DB["...", enterprise_id ? enterise_id[0] : nil]
or even use String#[] as Cary Swoveland suggests:
enterprise_id = "[79511]Rocket"[/(?<=\[)\d+(?=\])/]
DB["...", enterprise_id.presence]
I'm not that familiar with Sequel so you might need some to_i calls in there to convert the '79511' strings to 79511 numbers.
[{"Id"=>1015765, "Date"=>"/Date(1468062000000+0100)/", "EventGroupName"=>"Electric Daisy Carnival", "VenueName"=>"Milton Keynes Bowl", "Town"=>"Milton Keynes", "Country"=>"UK", "TicketCount"=>35, "Currency"=>"GBP", "MinPrice"=>79.75, "LayoutId"=>3932, "EventGroupId"=>32347, "VenueId"=>3596}]
I'm getting this response form an api im calling
How do i go about getting the id to use elsewhere in the controller???
Heres my controller
api = HTTParty.get("url here").parsed_response
id = api["Events"]
I have tried sticking [Id] on the end of the id call but that didnt work.
Sam
Additional
Heres what i tried :)
id = api["Events"].first["Id"]
results = HTTParty.get("partoneofurl" + id + "parttwoofurl")
syntax error, unexpected tIDENTIFIER, expecting ')'
syntax error, unexpected ')', expecting keyword_end
The result of the HTTParty call is an array that contains a hash table with the response elements. To access the these values you need first to access the hash table, that is the array's first element and then you can access the values in the hash table. You can do that in this way:
$ api.first["Key"]
I'm getting this error:
TypeError in Properties#show
At line #67 in /Users/taylor/Pro/rentroll_analysis/app/views/properties/show.html.erb, where this exception is raised:
can't convert Array into Integer
This is the extracted source around line #67:
64: <td><%=u.unit_number%></td>
65: <td><%=u.unit_type%></td>
66: <td><%=number_to_currency(u.market_rent - u.current_rent)%></td>
67: <td><%=number_to_currency(u.market_rent - u.current_rent)*(session[:assumptions]= [:spread_x])%></td>
68:
69: </tr>
70: <%end%>
When running this:
def setup_assumptions
if session[:assumptions].nil?
session[:assumptions]=[:min_spread=>400,:spread_x=>10]
end
end
I'm sure it's relatively simple but I can't figure it out.
If you're trying to set it to a map, use a map (curly braces) not an array (square brackets):
session[:assumptions] = { :min_spread => 400, :spread_x => 10 }
Otherwise you're setting session[:assumptions] to an array with a hash in it.
Also, what is your goal here?
number_to_currency(u.market_rent - u.current_rent) * (session[:assumptions]= [:spread_x])
I think you mean:
number_to_currency(u.market_rent - u.current_rent) * session[:assumptions][:spread_x]
When you save something to your session it saves it as a string, so when you're pulling something back from the session and want to perform Integer methods on it, you'll likely have to specify that it's an integer.
Doing something like: session[:assumptions][:spread_x].to_i to use your session content as an integer. Also, please note I think you have an errant = in your original code.
Lastly, you might not run into this, but I've sometimes had trouble using nested symbols in session variables. As in session[:assumptions][:spread_x]. I've sometimes had to change this to something like session[:assumptions]['spread_x'] and call the nested variable with a string instead.
Good luck!
When I attempt to run my script, I get an error returning on a variable assignment. I've re-checked my syntax many times and it doesn't seem to be a mistake I made there--I even had somebody else look at it just in case. However, the error that returns continuously points me to the syntax, and I can't seem to find a solution to this problem.
Here is the whole troublesome function:
function registerquestlines()
if player["testline"] == nil then
player["testline"] = {"prog" = {true,false,false}, "quests" = {"testline1", "testline2", "testline3"}, "prog#" = 1}
end
end
Again, the error I get is: '}' expected near '=' on the line in which I assign values to player["testline"].
A table initializer uses either an unquoted name or a bracketed expression, not a quoted name.
{prog = {true,false,false}}
{["prog"] = {true,false,false}}
I have an array of hashes. Each entry looks like this:
- !map:Hashie::Mash
name: Connor H Peters
id: "506253404"
I'm trying to create a second array, which contains just the id values.
["506253404"]
This is how I'm doing it
second_array = first_array.map { |hash| hash[:id] }
But I'm getting this error
TypeError in PagesController#home
can't convert Symbol into Integer
If I try
second_array = first_array.map { |hash| hash["id"] }
I get
TypeError in PagesController#home
can't convert String into Integer
What am I doing wrong? Thanks for reading.
You're using Hashie, which isn't the same as Hash from ruby core. Looking at the Hashie github repo, it seems that you can access hash keys as methods:
first_array.map { |hash| hash.id }
Try this out and see if that works--make sure that it doesn't return the object_id. As such, you may want to double-check by doing first_array.map { |hash| hash.name } to see if you're really accessing the right data.
Then, provided it's correct, you can use a proc to get the id (but with a bit more brevity):
first_array.map(&:id)
This sounds like inside the map block that hash is not actually a hashie - it's an array for some reason.
The result is that the [] method is actually an array accessor method and requires an integer. Eg. hash[0] would be valid, but not hash["id"].
You could try:
first_array.flatten.map{|hash| hash.id}
which would ensure that if you do have any nested arrays that nesting is removed.
Or perhaps
first_array.map{|hash| hash.id if hash.respond_to?(:id)}
But either way you may end up with unexpected behaviour.