I have a Rails 3.2 app that uses a legacy database so most tables and ids aren't in the Rails format. The whole app uses set_table_name and set_primary_key, and as we've recently migrated to 3.2 from 3.0, we're getting a whole bunch of deprecation warning.
The suggestion is to use self.primary_key = 'another_key', however for some reason this approach is not working.
I'm using FactoryGirl to build and save the models, and when it tries to save the model it gives me the following error: (on an Oracle database)
ActiveRecord::StatementInvalid:
OCIError: ORA-01400: cannot insert NULL into (sql string)
Basically from what I understood, the custom primary_key is not being correctly set, and ends up as being nil, which obviously will raise this error. The SQL string has the correct custom PK, but it seems that the value being passed to it is null.
Is there any fix for that? If I keep the deprecated set_primary_key it works flawlessly, but I know it's depreceted and I don't want to keep using it.
I found the problem. Turns out that in some files I was doing
self.primary_key = :some_key
This was failing because I'm passing a symbol, and not a string. Changing :some_key to string everywhere solved the issue.
Related
I am struggling with an issue with a Rails 5.2.4.1 app.
Configuration is the following:
Ruby 2.6.5
Rails 5.2.4.1
attr_encrypted 3.1.0
I have a model called Chicken that has 2 attributes: name - which is attr_encrypted and number - which is a normal integer field. Whenever I perform queries to retrieve any other fields except the attr_encrypted one, that still gets attached to the result and it's alway nil:
Chicken.select(:number) => #<ActiveRecord::Relation [#<Chicken id: nil, number: nil, name: nil>]>
Please keep in mind that this is just a test application and the queries that I am trying to execute on the actual app where I have encountered this initially, are more complex.
Is there a way to prevent attr_encrypted from attaching encrypted fields to queries results? Since the current results mean that I have to re-write all the existing queries in the app or add a filter for these types of fields somehow
This problem was caused by this change to attr_encrypted. As far as I can tell, there isn't any easy way to remove this attribute without modifications to the library but no one actively works on it so that seems unlikely.
The only options as far as I can see are to:
Use another library
Override the models attributes method to exclude the value (may produce undesirable results). It will still show in other methods active record provides.
Deal with it
Something else I haven't been able to find
A few ways you can deal with it:
Use a library to generate JSON responses for the frontend to only include attributes you want
redefine serializable_hash like devise does to remove attributes. (A lot safer than redefining the attributes method itself.
I'm using the active_model_serializers gem for a RoR API. Versions:
Rails: 4.2.8
Ruby: 2.2.5
active_model_serializers: 0.10.0
I'm using a virtual attribute in a serializer. I get it by using a sub query when I retrieve the objects from the database.
You can find the code here: Github Gist
This is the error I'm getting:
undefined method 'number_of_reservations' for DiscountSchedule...
This field isn't defined in the table nor in the model (attr_accessor)
I'm not sure why it doesn't work, I have a very similar serializer and it's working OK.
Any help will be appreciated.
EDIT:
I have another serializer where the virtual/calculated field is working OK. My guess on this is that since AR is making a bunch of LEFT OUTER JOINS and the SELECT list of the query is very big at some point something is getting broke.
The link won't work for me as I don't have access at my work place, however, from the error I can recommend you to check if you have defined the attributes like this in your serializer attributes :number_of_reservations and have an action in the serializer that says
def number_of_reservations
// Your logic goes here.
end
I suspect this question has to be about ActiveRecord, rather than AMS. You're trying to use select and alias to collect some computed (aggregate) attribute along with objects themselves. This, unfortunately, won't work in ActiveRecord, at least not in versions below 4.2.X. And this is why you're observing this behavior, there is no number_of_reservations in your models.
To see what's going on, try to inspect #objects here: https://gist.github.com/LuisDeHaro/ebf92781b449aa1ee7b85f8f552dd672#file-some_controller-rb-L17
Indeed: the issue was by the big amount of LEFT JOINS that the includes(:table_name) is generating. The serializer then does not know what to do.
I found a monkey-patch gem that works for AR (Rails 4 & 5) that fix this.
https://github.com/alekseyl/rails_select_on_includes
So, the virtual field number_of_reservations is picked up by the serializer like a charm.
And, you might be wondering: why do you want to retrieve a field that is not in the table definition in the database. A: well, in some scenarios you will need a calculated field for EVERY row you are retrieving. A SQL sub query is one of the most efficient ways to do so.
It's working now for me.
I am trying to overwrite a record in rails 4.0.
old_p.update_attributes(new_p.attributes)
old_p is the record pulled from the database, new_p is the record the user has created that will replace the record from the database. new_p actually has its own record in the database, but is only stored there temporarily.
This seems to work some of the times, but most of the time it comes back with
ActiveRecord::RecordNotUnique in Controller#overwrite
PG::UniqueViolation: ERROR: duplicate key value violates unique constraint
This is an upgrade from rails 2, and seemed to have been working as expected when it was a rails 2 app. There seems to be little documentation on update_attributes, but it seems as if it is copying the id of the object as well.
I have also tried assign_attributes with .save later, but to the same effect.
If it is copying the id of the object as well, is there a way to easily leave out the id? As the record has some 20+ attributes I would have to manually enter and they could change often. Or is there something else that I am missing?
You can use
old_p.update_attributes(new_p.attributes.tap { |h| h.delete('id')})
We have a field in our mongodb database called "failed?", including the question mark. Sometimes when I access that field, I get the value in the database, and sometimes I get null. I'm looking to understand what should happen a little bit more in order to debug this. So, can you have a question mark in a field name in a model, like so:
field :failed?, :type => Boolean, :default => nil
or am I in for a world of trouble. Assuming I already have this in the database and have to work with it, how should I get the fields out.
Environment: Rails 3.1, JRuby, Mongoid.
It's most likely a Mongoid bug as question marks in field names are valid in MongoDB. If I had to take a guess, it could be a weird conflict with the automatic <field>? that are created by Mongoid.
The easiest way to work around this would be to try accessing it through the raw hash that is pulled out from MongoDB, you can access it with model.attributes["failed?"]. If you still have issues, then likely it's a MongoDB driver problem.
I generated a scaffold against a legacy SQL Server database view that has a text primary key with no id column. I have set_primary_key "Gift_ID" in the model but Im getting an error on the show method.
I can list the records okay but when I click on the show link, it errors out. It appears to be using id to look up the record even though I have set_primary_key in the model. Here is the complete text of the error displayed;
NoMethodError in PledgesController#show
undefined method `eq' for nil:NilClass
Rails.root: /home/steve/RubymineProjects/otatest
Application Trace | Framework Trace | Full Trace
app/controllers/pledges_controller.rb:16:in `show'
Request
Parameters:
{"id"=>"PL-24681"}
Show session dump
Show env dump
Response
Headers:
None
Can anyone shed some light on why it is still trying to use "id" as the key?
Thanks for any help!
I solved my problem, so I thought I'd answer my own question in case it helps someone else;
I gave up on using the set_primary_key option in the model and added an "id" field to the view in my legacy system (SQL Server) using a key field in the data. That solved the id problem.
I also found that the generated scaffolding field names are case sensitive. So I used the view to set all field names to lowercase. You could make sure your scaffolding case matches the legacy field names, but I found that it's easier to just set them all to lower case.
One more thing; I had a few legacy boolean fields that had a "?" on the end of the field name, the scaffolding did not like that either, so I removed the "?" in the view.
Bottom line, building a Rails app on top of a legacy system has it's challenges. I discovered most my problems by migrating the table to the legacy database and examining the way it created the fields then modifying my view to match.