How to get result of the previous action - ruby-on-rails

Hi Inside rails console you can get the result of the previous operation with _ Is there any way to do such a thing inside ruby program?

everything in Ruby is an object, so think about it, if any returned object is not assigned a reference then it will be marked for garbage collection, so no there is no way other than to assign a returned object to a variable!

You can do this with irb (and programs that improve on irb) - it's not specific to Rails. But apart from that, I'm not aware of being able to do what you want.

Related

Ruby on Rails - using a block parameter as a method call

I'm having trouble with a little Ruby on Rails I'm building and need some help.
I have a Table with 20+ Columns and a corresponding XML File which can be parsed as some sort of hash with a gem. Every key would be mapped to a column and every value would be a data record in said column.
The way I access a specific value in the already parsed XML file is:
filename["crs","inputkeyhere"]
which returns the value, for example "52" or whatever.
What I am trying to do is upload the file, parse it with the gem and give each column the corresponding value.
My table (or model) is called "Attributeset" and I already know how I can access every column:
#attributeset = Attributeset.new
#attributeset.attributes.keys
So my thought process was:
Iterate over all the keys
Pass every key into a block called |a|
Use the rails possibilty to set attributes by calling the corresponding #attributeset.
Set colum attribute to the corresponding xml key
So my code would go something like this:
#attributeset.attributes.keys.each do |a|
#attributeset.a=filename["crs",a]
end
But my problem is, that ruby thinks ".a" is a method and apparently does not evaluate "a" to the block parameter.
I've read through lambdas and procs and whatnot but didn't really understand how they could work for my specific situation.
Coming from bash scripting maybe my thinking might be wrong but I thought that the .a might get evaluated.
I know I can run the block with yield, but this only works in methods as far as I know..
Any help is appreciated.
Thanks and stay healthy,
Alex
Thanks for the input!
I wanted to make it as clean as possible, and not using any temporary hashes to pass arguments.
I've found the method
write_attribute
which can be used like this:
#attributeset.write_attribute(a, xmp["crs",a])
worked perfectly for me.
You can use []= method to set values dynamically:
#attributeset.attribute_names.each do |attribute|
#attributeset[attribute] = filename["crs", attribute]
end

Is there a way to directly access and/or manipulate the `locals` hash from inside of a `partial` Rails ERB template?

I am currently splitting some code out to make it more reusable, and other code more succinct.
I realize I am passing a good bit of options into the locals hash, besides just the form variable, and all of these seem to only apply directly to the input object I am creating.
I was thinking of merging the locals hash into another that contains some defaults, and passing that to the input creation function.
After some researching API docs like these:
Ruby on Rails - API - ActionView::Renderer
Ruby on Rails - API - ActionView::PartialRenderer
and digging around to find these last 2 methods in the stack trace:
From: .../.rvm/gems/ruby-2.1.5#ux-rails3.2/gems/actionpack-3.2.22.5/lib/action_view/template.rb # line 145 ActionView::Template#render_without_mini_profiler: ... 2.1.5 (#<ActionView::Template:0x007fa41e138cc8>):0 >
From: .../app/views/shared/_checkbox_group.html.erb # line 3 ActionView::CompiledTemplates#_app_views_shared__checkbox_group_html_erb___4197967411385159258_70171427980900: ... 2.1.5 (#<#<Class:0x007fa40f30fec0>:0x007fa40fe71c50>):0 >
RVM, Ruby, Rails, Formtastic, Pry, Byebug, & Pry-Byebug.
Old, not-so-helpful workaround answer
As it may be convenient from the question's phrasing, one method is to not spend time diving into the Rails template rendering framework code and documentaion, and instead simply provide the options I mentioned for the locals hash, inside of a single property containing a new hash containing them, and pass that into the template.
Later I use that hash to merge with the default hash I had inside of the template and pass that to the input function as normal.
I could leave the Q&A here in case there might still me reasons people would want to directly access the locals hash, or could even develop an alternative approach that would be possible as well.
Update
So I dove into the Rail template rendering framework...
Exposition
I started simply taking this:
2.1.5 (#<#<Class:0x007fc01d352e08>:0x007fc018879698>):0 > self.class
=> #<Class:0x007fc01d352e08>
That wasn't much helpful, then went up into actionpack-3.2.22.5/lib/action_view/template.rb:145 to find this:
2.1.5 (#<ActionView::Template:0x007fc011e90510>):0 > method_name
=> "_app_views_shared__adrad_index_html_erb___3381877171036202789_70231455466120"
2.1.5 (#<ActionView::Template:0x007fc011e90510>):0 > view.method(method_name.to_sym)
=> #<Method: #<Class:0x007fc01d352e08>(ActionView::CompiledTemplates)#_app_views_shared__adrad_index_html_erb___3381877171036202789_70231455466120>
2.1.5 (#<ActionView::Template:0x007fc011e90510>):0 > view.method(method_name.to_sym).source_location
=> ["<our project_path>/app/views/shared/some.html.erb", 0]
Where the last point wasn't great, but then I started looking for ActionView::CompiledTemplates, which unfortunately, you cannot use source_location to find, or instance variable declarations for that matter (different issue :) ).
I decided to randomly search the actionpack-.../lib/action_view/ directory to find a reference or so in context.rb, but instead of looking inside of template.rb, I skipped straight to searching for locals in that gem's files now.
resolver.rb did not help much, and neither did template_renderer.rb.
Once I delved into template.rb and found the familiar above stack frame for render that my answer had to be between that and my actual page with the included locals properties,
I followed compile! to its definition,
saw a familiar ActionView::CompiledTemplates,
then a compile,
found an interesting arbitrary, literal, meta source manipulation, as I was sort of expecting with the lack of more stack frames in-between to scour, and the callback-esque naming scheme, I found this curious variable, as a parameter to the dynamically-generated template function: local_assigns.
I quickly jump around to locals_code's definition since it is also used and verify this is source variable enumeration I was looking for!
Answer
local_assigns!
Also, I currently don't believe the hash provides any properties I would want to avoid, such as any information specific to only the current partial template page that I wouldn't want to be propagated to the child partial template page.
Update
I am starting to do more with this variable, and I wonder if I am limited.
I want to mix-in some default values, which might involve using binding.local_variable_set, but it is not able to create new local variables (How to dynamically create a local variable?), so I might just have to use my own nested data structure now..

How is this method memory intense?

I found the following method to be a HEAVY memory user on Ruby 1.8.7 and return absolutely no results (when there should be lots). The method also works like a charm on Ruby 1.9.2, returning all the wanted results while consuming no memory at all (or so!). I guess that's because a local variable has the same name as the containing method, but anyone have a clear answer for that?
def contact_of
contact_of = Circle.joins(:ties).where('ties.contact_id' => self.guid).map { |circle| circle.owner } || []
return contact_of.uniq!
end
By the way, I'm running Rails 3.1.1.
Thanks!
UPDATE : There's a part of the question that is erroneous. The fact that no contacts are returned when there should be is my misunderstading of 'uniq!' instead of 'uniq'. The first one does return 'nil' when no duplicates are found.
Still trying to figure out the memory problem...
Yeah, contact_of.uniq! would make a recursive call to the same function. I'm surprised it works in Ruby 1.9, actually.
Also, your DB query is terrible, because it retrieves a lot of unnecessary records and then does further select logic on the Ruby side. You probably want to start the find from Owner, not Circle.

Iterating through array of Models in rails

Yet another ruby question but this is a bunch of questions in one. I'm really starting to like rails but there are some questions that I'd just like to ask straight out.
Right now, I'm implementing a queue in sqlite. I already have a scaffold setup with this working OK. The purpose is for a web crawler to read through the array and determine which links he should crawl next.
The architecture in the program is 2 controllers. one for Job and one for crawler. The Jobs has the standard Crud interface supplied by scaffold. Where I'm falling down is I'm still trying to understand how these things communicate with eachother.
The Job is formatted as a url:string and depth:decimal. The table is already populated with about 4 objects.
#sitesToCrawl = Job.all
#sitesToCrawl.each {|x|puts Job.url}
I have a bunch of questions about the above.
At the moment, this was supposed to display all the jobs and I foolishly thought it would display plain text but its actually a hexidecimal pointer to the object itself. What Im trying to do is iterate through the #sitesToCrawl and put out each Jobs url.
Questions start here:
1: I know ruby is dynamically typed. Will #sitesToCrawl become an array like i want it to be with each slot containing a job.
2: #sitesToCrawl.each is pretty straighforward and I'm assuming its an iterator.
is X the name od the method or what is the purpose of the symbol or string between |*|
3: Puts and print are more or less the same yes? if i say #x = puts 3 then would x be 3?
4: Job.url. Can objects be referenced this way or should I be using
##sitesToCrawl = db.execute("SELECT url FROM jobs;")
where db is a new database
As Rubish Gupta pointed out, in your block, you should do x.url, otherwise you're trying to access the url method on the class Job, not on instances of Job. In other words, in blocks, the items in the pipes are the arguments of the block, and each will iterate through your array, passing in one item at a time to your block. Check out the doc here.
Just to extend this idea, each on Hashes (associative arrays, maps, whatever you know them as) will pass two variables to your block: a key and a value, like this:
a_hash.each {|key_var, val_var| puts "#{key_var} is associated with #{val_var}"}
Also, it's been a bit since I've done plain ActiveRecord models, but you might look into doing
#sitesToCrawl = Job.all.to_a
since Job.all is a lazy finder in that it's building a query in potentia: you've essentially built a query string saying SELECT * FROM jobs, but it might not be executed until you try to access the items. each might do that, I can't remember off the top of my head, but if you're using a debugger to look at it, I know you need to_a to get it to run the query.
You should absolutely be using job_instance.url - that's the beauty of ActiveRecord, it makes database access easy, provided everything gets set up right :)
Finally, puts and print are almost the same - the difference is that puts "string" is essentialy print "sting"; STDOUT.flush - it flushes at the end of the statement.

How do I find where a ruby method is declared?

I have a ruby method (deactivate!) that is on an activeRecord class. However, I can't seem to find where that method is declared.
There have been numerous developers on this project, so it could be anywhere. There is a deactivate! on an unrelated class, but it doesn't seem to get called.
Any ideas how to find all the superclasses for an instace, or where to find the code for deactivate!?
First question would be: is it an actual method? Does obj.method(:deactivate!) raise an error?
If it doesn't, then you can use Method#source_location(in Ruby 1.9 only, and backports can't support it):
obj.method(:deactivate!).source_location
If it does raise a NoMethodError, it is handled via method_missing. This makes it hard to track. If it accepts arguments, I'd try sending the wrong type and using the backtrace of the raised exception.
Are you using state_machine? If you have an event transition called :deactivate, the model will have the method #deactivate! created automatically.
When I need to find where a method is declared on some class, say 'Model', I do
Model.ancestors.find {|c| c.instance_methods(false).include? :deactivate! }
This searches the ancestor tree in the same order that ruby does for the first that has the method in instance_methods(false), which only includes non-inherited methods.
Note: before ruby 1.9, the methods were listed as strings not symbols, so it would be
Model.ancestors.find {|c| c.instance_methods(false).include?('deactivate!') }
As a first stab, try the Jump to Declaration feature of your IDE. Depending on how good your IDE's static type inference is, it should take you right there.
If that doesn't work, set a breakpoint on that call, fire up the debugger and step into the method.

Resources