I have been building a Rails application that performs accounting functionality. As part of this, I have a model with the class name Transaction. So far so good, I have been building this functionality for a month or so, and everything is working as expected.
Until now...
I have just discovered some older reporting functionality that was developed months ago using the Ruport library has stopped working. It appears that Ruport, when generating PDFs, requires a library that also has a class/module named Transaction.
TypeError in Admin/team reportsController#generate
Transaction is not a module
...
This error occurred while loading the following files:
pdf/writer
transaction/simple
So, I'm looking for a quick fix here. One that hopefully doesn't involve renaming my Transaction model and refactoring the last few weeks worth of code.
Looking forward to some clever suggestions :)
Already answered and old, but I came here with the same problem, but solved it in a different way.
I have two Models named Pull and Query.
Trying to reference Query.some_static_method() within a method in Pull resulted in Query resolving to ActiveRecord::AttributeMethods::Query:Module.
Solved it by putting the empty namespace in front of it with ::Query.some_static_method()
I believe the issue is down to Ruport requiring the PDF::Writer gem, which in turn requires the Transaction::Simple gem which defines the module Transaction.
There is certainly a #transaction method in ActiveRecord, but I do not think there is a Transaction module or class within Rails. I'll be happy to be corrected on that one.
Namespacing is usually the best practice for avoiding naming conflicts like this. E.g.
module Account
class Transaction < ActiveRecord::Base
....
end
end
However, namespacing ActiveRecord models may throw up other issues.
As time consuming as it may be, renaming your Transaction model may be the best bet.
You can still keep your existing transactions database table if you wanted, so your migrations don't need to change, by putting self.table_name = "transactions" inside your model.
Your associations with other models can also still be named "transaction(s)" by specifying the class_name in your association call. E.g.
class User < ActiveRecord::Base
has_many :transactions, :class_name => "AccountTransaction"
end
Those two suggestions may or may not save you some time.
Your problem may come from the fact that Transaction is also a reserved word in Rails…
Related
What are the implications of having a object_id / object_type on a model (for a polymorphic association) in regards to Object itself containing an object_id and that overriding it (http://ruby-doc.org/core-2.3.1/Object.html#method-i-object_id)?
class Event
belongs_to :object, polymorphic: true # object_id/object_type
end
When I search for object_id through the whole codebase of one of my rails projects (including all gems), I can see over 200 hits. In Rails only, this is about 50 hits.
I'd expect problems with records comparison, using them as hash keys, putting them to sets, perhaps also duplicating them with dup. In Rails, record.object_id is referenced in caching, has_many_through associations, AREL, pretty printing the record, minitest expectations, also in pry debugger,
But just from quick-looking trough the code it is very hard to guess if it will cause problems or not and I generally tend to be very defensive about such potential problems - you'll never know for sure if your next usage of the object will not break things in a way that is both very hard to debug and perhaps impossible to fix.
As I said above, I'd be very curious if you tried, but myself would rather name it belongs_to :thing, polymorphic: true or better yet something even more specific.
If you attempt to define object_id on a class you'll find that you get the following angry warning from the Ruby interpreter warning: redefining 'object_id' may cause serious problems (try it from IRB). That sounds scary - and the incidents may be tied to specific versions of Ruby (and vary based on the version used). I'd recommend fixing this.
I believe you can belong_to object, while defining the foreign_key to something else, like foreign_key: :object_identifier. That way you dont have to worry about object_id.
I think the best to follow this documentation Active Record Associations, I think defining another object_id will make you sustain the relation manually in your code and you will lose Active Record features for doing that.
I am only looking for answers from senior/more experienced Ruby/Rails developers on this one, since I think this is a bit more advanced of a question.
I have a gem I am working on that adds some behavior to AR models. I have to test it for a lot of different associations (has_many, habtm, has_one etc), and I also have to test behavior when different options are passed for the associations (e.g. :foreign_key). Now with all these different models, I can use the same table in the database because the fields themselves do not need to change, only behavior specified through has_many, belongs_to and so on.
Keep in mind there are a lot of different options, so the number of models is quite large.
First I don't think it would be bad practice to have the definition of the models next to / in the test itself, for readability purposes (if I have multiple tests that use the same model then I would group them together and use the before method). So this is one of my goals, and you can comment on this if you don't agree.
The second thing I am not sure of is I wanted to keep the simple/same name of the model in all the tests, for example "Task", instead of TaskWithManySubtasksAndForeignKey or something ugly like that. The problem is there are so many models it's hard to come up with meaningful and simple names. I'm not quite sure about this - using the same name, since it's a constant, is a little problematic. I have a solution with a proxy class but I don't think this is the optimal solution. I was considering using variables (with the let method) like "taskModel", but it seemed a little verbose and unusual.
One other option that comes to mind, but I am not sure is possible to do easily, is to remove an existing association and then define a new one. So e.g. add a has_many and then remove it, add a habtm...
How would you go about doing this?
Defining unique models in the spec files is not necessarily a bad idea since it makes it easy to see exactly how each model is defined. The obvious problem with this approach is if you want to reuse the models in other test files. The Rails approach to this is to define all the models in separate files and then just require them in the tests that need it.
I think it really just depends on how many models you have and how much you want to reuse. In one of my gems, I took the approach of defining the models in the spec file, in another gem, I defined them in the spec helper, and in yet another I took the Rails approach and used a separate directory for them. If you asked me which one I preferred, I'd probably go with the spec that also contains the models because it's all in one place. Definitely a subjective problem though.
Another approach I've taken on occasion is to create an anonymous class that's guaranteed to only be around for the life of that test:
describe 'my test' do
let(:my_class) do
Class.new(Task) do
has_many :things
belongs_to :something_else
end
end
it 'should have many things' do
my_class.should have(100).things
end
end
I am starting to implement an MTI solution and have a basic question. I have 3 physical models - SMSNotifications, EmailNotifications, TwitterNotifications and they are subclasses of notification. At times in my code, I want to say Notifications.find(:all)so that I can get a set of results sorted by their creation time. Then I want to do things based on their subclass. What is the way to write Notifications.find(:all) and have Rails look through the subclass tables and combine the results? Right now Rails still thinks I have a physical Notifications table which goes against my MTI design.
I am also considering the possibility that I should be using STI instead. I would probably have 10 empty columns per row but if getting all notifications requires a query for each type of notification, then I feel like this could be a big issue.
Thanks!
Yes, you will need separate queries for each type. If this is a dealbreaker, then you should go with either STI or the mixed model approach advocated in your previous question.
If you use https://github.com/hzamani/acts_as_relation:
rails g model notification notification_type:string notification_id:integer <other columns>
rails g model email_notification <columns>
class EmailNotification < ActiveRecord::Base
acts_as :notification
end
....
then the code you want might be something like this:
Notification.all.each do |n|
case n.notification_type
when "EmailNotification"
...
when "SMSNotification"
...
end
end
For this purpose, you can make the subclasses have a polymorphic association with some specific model (X). You can edit the callback after_initialize to associate one entry of this specific model X with each of your subclasses on creation. In this way, you can perform find on the target (X) of the mentioned polymorphic association.
I recently forked a promising project to implement multiple table inheritance and class inheritance in Rails. I have spent a few days subjecting it to rapid development, fixes, commenting and documentation and have re-released it as CITIER Class Inheritance and Table Inheritance Embeddings for Rails.
I think it should allow you to do what you needed by asking for all notifications, it will still return the correct models. If you were to do something like
Notification.all().each do |n|
if n.class == 'EmailNotification'
#Do something
end
end
Or even define a function in the root Notification class and overload it in subclasses to return something different.
Consider giving it a look: http://peterhamilton.github.com/citier
I am finding it so useful! I would (by the way) welcome any help for the community in issues and testing, code cleanup etc! I know this is something many people would appreciate.
Please make sure you update regularly however because like I said, it has been improving/evolving by the day.
I think there are a lot of places where my design may be screwing this up. I have very limited experience with Rails though. This is happening in Rails 2.3.2 with Postgres 8.3.
We've got two tables in our DB. One called "survey" and one called "survey_timepoint". A survey can have multiple time points so in the survey_timepoint table there is a column called "survey_id" with an fk constraint on it.
I also think I should mention that the tables were not created with a rails migration although they do follow the rails naming conventions. I suspect AR isn't anticipating a constraint on that column and it doesn't know how to handle the situation.
In my rails models I have:
has_many :survey_timepoint
and
belongs_to :survey
If I do something like:
s = Survey.new
s.survey_timepoint.push SurveyTimepoint.new
s.save!
I get:
ActiveRecord::StatementInvalid: PGError: ERROR: insert or update on table "survey_timepoints" violates foreign key constraint "survey_timepoints_fk"
DETAIL: Key (survey_id)=(59) is not present in table "surveys"
I'm assuming that if I delete that fk constraint on survey_timepoint.survey_id it'll work ok. It seems like I shouldn't have too though. Am I going to be stuck creating and saving each of the objects separately and wrapping the whole process in a transaction? It seems rather un-railsy. Apologies for any necessary information that I may have omitted.
You might want to check the SQL commands being sent. It looks like it is adding the survey_timepoint record before the survey record. Note that you are already dealing with two database changes — the survey and the survey_timepoint — so you should be using a transaction.
You can fix the immediate problem by doing s.save! before adding the timepoint (and then calling it again). My knowledge of Rails functionality is not deep enough to know if there is a more "railsy" way of doing this then wrapping it in a transaction.
I just experimented and found that this works with MySQL:
s = Survey.new()
s.survey_timepoints << SurveyTimepoint.new # Note "survey_timepoints" (plural)
s.save!
I think it would work equally well with PostgreSQL.
It does two inserts, first the Survey, then the timepoint, and wraps them in a transaction.
You can also do it all on one line:
Survey.create!({:name=>'New Survey', :survey_timepoints => [SurveyTimepoint.new]})
Incidentally, for ActiveRecord to work right you have to make sure of your singulars and plurals. (If you want to break the expected forms, you'll need to tell AR you're doing that -- a whole other topic.)
Your tables should be:
surveys
-------
# ...
survey_timepoints
-----------------
survey_id
# ...
And in your models you'd have:
class Survey < ActiveRecord::Base
has_many :survey_timepoints
# etc...
end
class SurveyTimepoint < ActiveRecord::Base
belongs_to :survey
end
I'm currently using the awesome attachment-fu plugin for a Rails app, but as a novice developer, I've never encountered a scenario like the one I've found myself in.
Essentially, I'm using the attachment-fu plugin on two levels.
Is for user avatars in the user class.
Is to allow file attachments (PDFs, etc) in a messaging system.
My question is what the best use practice would be in these situations to remain DRY, clear, and consistent.
Clearly it would make no sense to define and execute the plugin in both classes, but there's something deeply strange to me (possibly unfounded) about just going ahead and setting it all up in the godly Application class.
Is there something in between, or is the parent class the way to go?
Thanks!
What's the DRY issue with defining the attachment_fu settings twice?
Unless the files are of the same type and being stored in the same place, you're not going to be repeating anything in the configuration.
Sure, you'll have two has_attachment declarations, but the options will mostly differ (one declaration for your avatars and the other for your pdf's etc.
99.99% of the code to handle attachment will be buried in the attachment_fu libs, your configuration code should be pretty DRY by default =)
Is "outsourcing" avatar support entirely to Gravatar an option? There are some Rails plugins that will display avatars hosted by Gravatar. You might not need to re-invent the wheel there.
What wfarr is describing would be single table inheritance, which is what I currently do in this situation. I have one table for Assets which contains all the necessary attachment_fu columns, plus an extra column called type, which will hold the actual model name. I have a model for assets and additional models for specific upload types that inherit from assets:
asset.rb:
class Asset < ActiveRecord::Base
... attachment_fu logic ...
end
avatar.rb:
class Avatar < Asset
... avatar specific attachment_fu logic ...
end
pdf.rb:
class PDF < Asset
... PDF specific attachment_fu logic ...
end
I would lean towards using a parent class, with subclassing for the different ways you intend to actually use the attachments in your application. It may not be the DRYest solution available, however, it lends itself to a logical pattern rather well.
Couldn't you use Polymorphic Associations?
I'm about to hit this in my app with attachment_fu, so I'm not exactly sure on attachment_fu, but for the old school File Column plugin, I would use Polymorphic Associations.
My "file" model would be:
class FileUpload < ActiveRecord::Base
belongs_to :fileable, :polymorphic => true
file_column :name
end
and then any models that needed a file attachment would be like:
class Company < ActiveRecord::Base
has_many :file_uploads, :as => :fileable
end
File Column is no good anymore as it borks on Safari 3.x and is no longer maintained. It was nice and simple though... Ah, the good old days...
For what it's worth, I think Patrick Berkeley has done a good job with handling multiple attachments through the Paperclip plugin. He's outlined his work here:
http://gist.github.com/33011