Trying to test my nested Rails 5 form (mintest) - ruby-on-rails

The actual nested form itself works fine, but i'd like to be able to have a test covering it to make sure I don't screw it up later. I also have more nested forms planned so I'd really like to figure this out.
I'm getting this failing test in my ListControllerTest:
"ListItem.count" didn't change by 1.
Expected: 1
Actual: 0
With this code:
https://pastebin.com/BRdtZW2T
Note that the "List.count" bit does pass. Again, this does actually work exactly as it's supposed to. I can create lists with lists items no problem when I actually submit forms on my app.
Lists are created with form_for
ListItems are created with fields_for

Figured it out. First off, I removed 'list_item_attributes' from the params being posted in my test. It seemed redundant, and I wasn't sure why I added it in there until I removed it, and my tests raised a different error:
TypeError: no implicit conversion of Symbol into Integer
app/controllers/lists_controller.rb:15:in `[]'
No idea what this was about, but some google searches turned up this:
http://billpatrianakos.me/blog/2013/09/29/rails-tricky-error-no-implicit-conversion-from-symbol-to-integer/
Which as it turns out is exactly my problem. So I added some extra square [] brackets to my params:[:list][:list_item], and presto it worked. See the revised pastebin as well as the article because that probably wasn't clear:
https://pastebin.com/uxRjsctK

Related

NoMethodError - Private method 'my_stats' called ... in rails console

Rails Console has been working fine until now. Suddenly I cannot call methods, neither class methods nor instance methods. But the app works fine.
Rails console
Catalog.my_stats
NoMethodError (private method `my_stats' called for #<Catalog:0x0000560a3796c9a8>)
If I try a method that does not exist it says "undefined method" instead of "private method", so it is able to see that the method exists. However - the method is NOT defined as private, and it has been working fine before. Built in Catalog.all works fine. Running on Ubuntu.
Example code for catalog.rb
def self.my_stats
puts "Hello!"
end
Update
I have another function in catalog.rb called string_to_array. This function responds well. And I can change it to a class function, and it works without problem. But if I create new functions they don't respond... also other, older functions responds well. Weird.
Short answer
The file had one "end" too much
Long answer I discovered that one of the functions above the troublesome ones had one "end" too much. Thanks to VS Code's vertical stripes I could identify that this particular "end" closed the class definition. This is why the functions were considered private, even without the word "private", because Rails gladly allowed them to be defined outside of the class. So the syntax checker did not consider this as an error. I also tried to add a lot of "end" words in the middle of the file, and in the end of the file, but the syntax was considered valid, still. This also explains why the GUI still worked, but the console had trouble accessing indirect "private" functions... maybe someone has a better name for these.. but now I've but them all inside the class where I think they belong. Thanks for your inputs.
Footnote
The stats code was tested temporarily in a particular branch that matched a spesific customer. The customer pasted this code into the catalog.rb file himself as a quick addon feature, and it worked for both of us. I then wanted this same code to be part of a new branch / version that was already in progress. I must have pasted it wrong, so that I did not get a fully functional checked-in version at my side - until now. Thats some time ago. So the "worked before - not now" was a little more tricky this time.

Rails 5 override dom_id helper method

I have encountered a strange problem. We have a project, in which - for security reasons - we wanted to avoid displaying the id for most of the models. So, instead of having a dom id user_12, we wanted to use the serial (id="user_adsi94zurew"). First we gave it all manually (like in these two haml lines):
.user_line{id: "user_#{#user.serial}"}
= form_for #user, url: user_path(#user), id: {"edit_user_#{#user.serial}"}
It is just not nice, we didn't like it. Then I found the helper method dom_id, which I overrode in the application_helper the following way:
def dom_id(record, prefix = nil)
if record.respond_to?(:serial)
"#{dom_class(record, prefix)}_#{record.serial}"
else
super
end
end
It just worked fine for most of the situations, though I didn't have the time for a thorough testing, because - as our application grew larger - we needed to rewrite it. We changed to Rails 5.0.0.1 and started to sort our controllers in modules (folders). I copied the code to our new application_helper.rb, and I found it was not working (it returned the good old user_12). And then I found, it WAS working, and then again, it wasn't. And that was it: it was almost totally random, when or where it worked. I made some tests and found that, when not working, my code was not even run (so it was not that the condition evaluated to false), the method went straight into the original dom_id, as if mine hadn't existed at all!
Then I found some rules against my theory of random, but these were even stranger:
1.) In the file /app/views/company_manager/companies/edit.html.haml, as well as in the new.html.haml (same folder) it never works. My first thought was that it is due to the module CompanyManager.
2.) In the root (/app/views/landings/landing_page.html.haml) it worked. Then it didn't! But if I made any change in the helper method (adding a p 'here', or even an empty new line(!)), it worked again!
3.) In the partial /app/views/company_manager/regions/_region.html.haml (.region_line{id: dom_id(region)}) it didn't work, but in the ajax response update.js.erb (same folder) it did (at least occasionally). I had some tough ten minutes due to that, because I tried to update region line in the DOM with the following jQuery code: $('#<%= dom_id(#region) %>').replaceWith('<%= j(render #region) %>');, and since the dom_id returned region_6 first and region_hd5j8g6 second, jQuery couldn't find the line to update.
4.) Lastly, we use the old way to access helper methods from controllers (which means include ApplicationHelper in the ApplicationController). When the method returned company_31, I tried to reference it from the controller, and it raised a NoMethodError, whereas other helper methods from ApplicationHelper were still accessible.
Conclusion: it seems to me that as Rails merges the helper methods it is sometimes my method that overrides the original, and sometimes it is vice versa. If the server is already running, and I make some changes in my method, Rails seems to reload just application_helper.rb, so it is my method that is above the original (though it still has no effect on companies/edit or regions/_region)...
Any ideas? Other explanations? Something, I missed? Any hints?
(Note: With alternatives, thank you, I am well equipped. If there is no solution, I will rename my method to dom_id_serial and try to convince form_for to use it instead of dom_id, or anything. So I am interested in anything that overrides dom_id and works, or any reason why it does not, and nothing else.)
Thanks in advance!

Can access ActiveRecord object, but not its attributes

I'm rendering a view in Rails using form_for and nested_form_fields. Here, #procedure_step is a record that has_many :procedure_step_actions, each of which belongs_to :error, which is a ProcedureError that has (among some relations to other models) an integer :code that I'm trying to access and print out to the page. Here's my template:
<%= form_for #procedure_step do |f| %>
<%= f.nested_fields_for :procedure_step_actions do |act| %>
<%= act.object.error.code %>
<% end %>
<% end %>
When I run this, I get undefined method 'code' for nil:NilClass. Okay, so my relations are messed up and I can't access act.object.error, right? Changing my template to display that instead yields #<ProcedureError:0x0000000ece02a8>, which is what one would expect of a functioning relation. Dumping its contents to the screen using debug shows all the attributes of the record, including code, but I still can't access it with the original template! Clearly act.object.error is not nil, so Rails telling me that act.object.error is nil doesn't make any sense to me.
Frustrated, I tried to work around the problem by using act.object.error.to_json. This printed the correct JSON for the record with all its attributes. Using JSON.load() on this gave me a correct Hash of all the attributes, but using [:code] to try to access the code gives me undefined method '[]' for nil:NilClass. Again, I know that object isn't nil, but Rails still refuses to allow me to access it.
Running out of ideas, I tried to use regular expressions to pull the code out of the raw JSON string. /"code":([0-9]+)/.match(act.object.error.to_json) returned #<MatchData "\"code\":69" 1:"69">, which is right. I used [1] to try to access the code number that was matched, but again I got undefined method '[]' for nil:NilClass.
Enough with ActiveRecord, I thought to myself. I decided to turn to raw SQL queries. I got the ID of the error in question using act.object.error_id, then printed that to the screen first to make sure I could access it. Luckily, I could. Then I inserted it into my SQL query with "... WHERE id = #{act.object.error_id}". I refreshed the page again and was greeted with a SQL error. It showed the final SQL query string I had generated, but it ended with WHERE id =. The ID of the error didn't get added to the string. ProcedureError.find(action.object.error_id) gave a similar error.
I'm totally out of ideas. What could possibly be preventing me from accessing one simple integer in so many different ways?
There are at least a couple of issues here. The first is that you probably want to be using fields_for, rather than nested_fields_for, if you're using 4.x.
The second is similar to what the first answer has indicated. You have a nested fields form, which allows you to nest one level in, but you are trying to nest two levels in. By addressing your law of demeter violation you should be able to make some more progress.
Debugging things like this you can get more information by throwing in a binding.pry or byebug right in your erb.
<%- binding.pry %>
Then reload the page. Your server will be stopped at that point in your code and you can play with variable values to learn more about what's going on.
One thing I can see right off the bat is you are violating Law of Demeter here
act.object.error.code
The form object obviously has to stay but you can delegate access to the subobjects by making a method on the procedure_step which can help with handling nulls, and other error cases.
Try delegating that first as I'm not sure if the scope that is created by nested_forms_for will allow the ActiveRecord::Relation object to perform properly. I'll double check locally.
A delegation might look like the following
class ProcedureStepActions
belongs_to :error
def error_code
#error.code
end
end
EDIT:
Other things that might be helpful are the version of Ruby and Rails you are using and any other additional gems or libraries.

ActiveRecord changing position on memory

I have a rather odd situation here.
My OrdersController has an edit method and at some point I have the following statement:
order_item.item = item
As you can guess, order_item.item expects a reference to an Item object, which is exactly what item is. Here comes the mistery. The first time I send a request to orders/{some_order_id}/edit, I receive the expected response. But if I send a new request (even if I just press F5) the application crashes and I receive the following error message:
ActiveRecord::AssociationTypeMismatch in OrdersController#edit
Item(#177601092) expected, got Item(#67520280)
What have I discovered so far? I have put an puts "#{Item.object_id}" just before the order_item.item = item and found out that Item.object_id changes from a request to another, which means that the Item ActiveRecord is changing its position on memory. (For instance, in the above example, during the first request Item.object_id is 67520280, while in the second it changes to 177601092.)
My question is: What can be causing the Item ActiveRecord to change its position on memory?
Useful info: I'm using rails 3.0.20
Update:
I found out that this change of ID is pretty common. But I still can't figure out why the expectation doesn't change as the Item.object_id does.
Despite the fact that I am not using Factory Girl, this answer and this discussion helped me a lot.
tl;dr
The problem was solved when I set cached_classes to true in my environment.

fullcalendar with rails - limit results to a range

I've got fullcalendar working with a small rails app (yeah) but it's sluggish because the find in my controller is finding ALL the records before it renders the calendar. I'm using a JSON approach. The field names I'm using are starts_at and ends_at. This (in the index method of the assignments_controller) works:
#assignments = Assignment.find(:all, :conditions => "starts_at IS NOT NULL")
But, as I said, it's pokey, and will only get worse as more records get added.
So this is clearly more of a rails question than a fullcalendar question: I can't figure out how to get fullcalendar to initially display the current week (when no parameters have been sent) and then accept parameters from next/previous buttons while, in either case, only looking up the relevant items from the database.
Oh - this is rails 2.x, NOT 3.
Thanks for any pointers.
Please ignore this question.
It turned out to be an issue with Date format inconsistencies between JavaScript (Epoch) and Ruby. At least that's what I think at the moment.
I'm still scratching my head, trying to figure out how exactly I "fixed" it, but it seems to be working.
I was aware of this project: http://github.com/bansalakhil/fullcalendar
but it took me ages to get the nuance of Time.at figured out.
I must say, Time is a tricky thing.
In real life as well as in code.
Thanks to everyone who gave my (misguided, as it turned out) question a glance.

Resources