I want to set up some has_many, :through objects using fixtures for testing in rails 3.1.
If you look at the documentation on the association as an example, I want to know how to assign assemblies to parts. The only way I've found to do it is to explicitly create the manifest object in it's own file, but if I'm happy with the defaults on that model and all I want to specify are the part/assembly id's then is there a way to do it directly?
http://guides.rubyonrails.org/association_basics.html#choosing-between-has_many-through-and-has_and_belongs_to_many
I want something like:
my_assembly:
parts: my_first_part, my_second_part
This works if you do HABTM, but not when you have the explicit join model.
Assuming you want or have to stick with fixtures, then if you switch from an HABTM to a has_many :through relationship, then you can no longer use the short inline lists. You must create a separate fixture file for the :through model.
Never, ever, use Rails fixtures for anything.
I'll repeat: Never, ever, use Rails fixtures for anything.
They are dangerous, cumbersome and make your tests leak state. They are unsuitable for writing proper tests. At best, you get tests that look as if they are properly written, but have hidden dependencies. The Rails team got this feature 100% wrong, and I wish they'd remove it from Rails so people wouldn't be tempted to use it.
Instead, install factory_girl_rails and use factories to create your testing records on demand:
Factory :assembly, :parts => [Factory(:part, :name => 'first'), Factory(:part, :name => 'second')]
Related
Sorry if this has been asked already, but I can't find any questions similar.
Using rails 5.
I have a double-nested resource
resources :users do
resources :checklists do
resources :checklist_items do
member do
patch :completed
end
end
end
end
And I have
user.rb
user has_one :checklist
checklist.rb
checklist belongs_to :user
And I know how to create a new checklist for one user in the commandline:
User.checklist.create
Now I want to create a new checklist for all the existing users in the database via the commandline. Sort of like this imaginary command:
User.all.checklist_create
so that every user gets a checklist. How do I accomplish this?
This worked for me, but maybe there is a shorter way to achieve it?
User.all.each do |user|
user.create_checklist
end
Rails and Ruby are filled with lots of metaprogramming and I won't be surprise if a method like what you are suggesting actually exist. However, from a design perspective, I think that would be an overkill. Imagine if you had 10K+ users and you want to use that single command to create tickets for all 10k users? How about their fields for each ticket.
So to solve your problem here are few options you can consider to have it your way.
Factory Girl
With factory girl, you have methods like create_list, build list, check out their documentation for more. From their names, they seem intuitive enough. These methods help you to create list of several objects and based on how you structure your factories, you can have what you desire in just one line.
Seed.rb
Rails provides a seed.rb file where you can add ruby script that should be for seeding your database with some default value. By default, you have an example script in the seed.rb file and you can use that as a reference to setup the structure you want.
However you will only want to use this option, if all you want is test/dummy data to play with alas, your use case may be different. But if you do require this data all for the sake of testing, I will recommend you follow a TDD approach. Hope this helps you.
Trying to find the definitive answer on whether active record associations should be in the list of attr_accessible attributes.
I've seen
class Foo
attr_accessible :name
attr_accessible :bars
belongs_to :bar
end
also seen
attr_accessible :bars_id
want to know the proper way to be able to do Foo.new(name: 'name' bar: barvar)
As often the definitive answer is: "It depends™"
Only the attributes you want to mass-assign should be made accessible.
So if you want or need to do…
Foo.new(name: 'name', bar: barvar)
…then you simply have to make bar accessible.
In the end assign_attributes is called which does a simple send("#{attribute_name}=", attribute_value) after checking the accessibility of the attribute.
Some coding style aspects:
Often mass assignment happens when processing the param hash. At least that's where the security problems are lurking. There you rarely have a Bar object but more often a bar_id.
However if you work with model instances, most people prefer using the association methods (as #Andrew Nesbitt wrote) because that often has some advantages (automatic saving, automatic update of the association counterpart, cleaner code, …)
So there are reasons to have one or the other or both.
My personal opinion: One should not waste a lot of time on this topic since Rails 4.0 will have a better solution for parameter sanitizing. (See strong_parameters if you want it in Rails 3, too)
You can avoid needing to make bar_id accessible by using the association builder:
# singular (has_one)
foo = bar.build_foo(name: 'name')
# plural (has_many)
foo = bar.foos.build(name: 'name')
The only time you would need to make an association accessible is if you are using accepts_nested_attributes.
While you can avoid making bars_id (shouldn't that be bar_id?) accessible in your example, the question is if parts of your application still needs access to it. Using active_admin, I had to make the whatever_id accessible to make things work with relations.
Category has many products, videos, music etc.
When category in question will be destroyed, all stuff, associated with it, will be broken.
Sure, I can manually implement #before_destroy method of ActiveRecord, but, this is not good solution, i think.
Is there any Rails gem, that checks declared association of models with Category and prevent deletion, if something is associated with it?
This functionality comes standard with rails.
Use :dependent => :restrict when declaring your association.
See the doc here for more:
http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_many
Option
:dependent => :restrict
does exactly this.
Thanks
This question relates to using Ruby on Rails 3 with MongoMapper and EmbeddedDocument. Also, the ManyAssociation.
http://mongomapper.com/documentation/embedded-document.html
The MongoMapper examples (in the link above) show two separate classes:
class Order
include MongoMapper::Document
many :line_items
timestamps!
end
class LineItem
include MongoMapper::EmbeddedDocument
key :name, String
key :quantity, Integer
end
But this pollutes the global namespace with LineItem. Out of context, LineItem for what? And what if I want another model, say WishList, to also have a LineItem set?
So it is possible to embed the LineItem class inside Order, like this:
class Order
include MongoMapper::Document
many :line_items, :class_name => "Order::LineItem"
timestamps!
class LineItem
include MongoMapper::EmbeddedDocument
key :name, String
key :quantity, Integer
end
end
While this may be technically fine (yes?), will I run into design issues later on? Does it just make the code too ugly? Too complex?
Presumably, the existence of this in the Ruby language means someone thinks it's an ok idea?
One thing I always liked about Django is how it uses "apps" to group related model classes (and separate the namespaces). So my code above is also achieving that in Rails.
I don't see any technical problems to either approach. The problem I've run into is that when a class is embedded in it's parent and is also in the same file, I'll forget it's there. So if your namespaces it as Order::LineItem you can make an "order" folder in your "models" folder and put "line_item.rb" in there.
The other trouble is if you want to have a controller for Order::LineItem, you also have to namespace it and put it in a folder, and in the router it will look like:
resource :orders do
resources :line_items, :controller => "order/line_items"
end
Unless you know your app is going to have multiple types of line_items, I'd recommend not namespacing it—you could be over-coding if you did. For example, if you were later to need two types of line_items you might even find that some of your code could be re-used between models—and if you namespaced your first line_item you may find yourself de-namespacing it.
In Python, namespaces are considered a great thing that there should be more of. But when you think about the global namespace of your Rails app, it's not that cluttered. Gem authors are pretty good about keeping all of their classes namespaced in their one gem module, so in your Rails app you're going to have one namespace for each gem you're using (Rails itself is 5 gems, not sure how many global constants though), plus and a bunch of files included by Rails (e.g. SecureRandom). It turns out to be really nice to have those files "just there" and I've found in practice that namespace collisions are rare and you can easily work around them. I've only run into a namespace issue maybe once, but several times I've accidentally defined a "send" method on a model—a much more common problem with similar repercussions.
Should I write unit tests for my associations?
I haven't found many good resources on how and whether to do the testing. I also see/hear some opinion that it is okay to not test your associations (belongs_to and has_many) as they are already tested in rails. And there is another view that says, if it code you write, it is code you test.
So if you say I should, please tell me few good ways of doing this.
Currently, I'm writing tests using Test::Unit and I'm not using Shoulda (I don't have any macros). So for testing each association, I am creating a bunch of objects and then doing asserts on them. Somewhat like this -
For a Post model that has_many comments, my test logic goes this way -
p = Post.create(:title => 'dummy_title', :content => 'lorem ...')
3.times{ Comment.create(:post_id :=> p.id, :commentor => 'jack')}
assert_equal(3, p.comments.size, "post doesn't have correct no of comments")
To me, testing the association borders on testing the language (or in this case, testing the framework).
I'd reserve it for circumstances where you're doing something nonstandard with the association. For example, if every time you create a comment it changes something in the parent post, test that.