Rails, can't load data from fixtures that have HABTM relationshionship - ruby-on-rails

I'm new to rails and testing and have a problem with loading my fixtures.
payment.yml
payment:
name: something
amount: 1.5
event: some_event
user: some_user
description: long text
users: some_user, some_user2
users.yml
some_user:
email: test#test.com
nick: name
some_user2:
email: test#test.com
nick: name
okey, so the problem is that when I'm doing the functionaltest for creating a payment
test "should create payment" do
assert_difference('Payment.count') do
post :create, :payment => #payment.attributes
end
it just sends
< Payment id: nil, name: "something", amount: 1.5, event_id: 972288058, user_id: 63246679, created_at: "2010-11-05 19:56:53", updated_at: "2010-11-05 19:56:53", description: "long text" >
and not the users array with multiple users. I use the "user" to define who owns the payment and users (in a seperate join table) as a list of users sharing the payment.
Any idea what I'm doing wrong?
here is the model for payments
class Payment < ActiveRecord::Base
has_many :comments, :as => :commentable, :dependent => :destroy
belongs_to :event
belongs_to :user
has_and_belongs_to_many :users
end

Can you put the model for payment? I had something similar and the problem was that the model was different. For example, if it's a ActiveRecord class, you have to check how it and its relationships. For example, if the event is actually an "event_id" that belongs_to an "event" class, then you should put something similar to this:
payment.yml
payment:
name: something
amount: 1.5
event_id: 1
user_id: 1
...
user.yml
id: 1
name: David Smith
status: Branch Manager
...
event.yml
id: 1
name: overdraft charge

Related

Dealing with has_one and has_many associations with one user model

I currently have a User model
class User < ApplicationRecord
has_one :leases
end
a Lease model
class Lease < ApplicationRecord
belongs_to :tenant, class_name: 'User'
belongs_to :landlord, class_name: 'User'
end
and a Rental model
class Rental < ApplicationRecord
has_one :lease, dependent: :destroy
end
and I only have one user model supporting tenants and landlords.
The problem I'm facing is that a landlord can have multiple leases with many different tenants, but tenants can only have one lease at a time.
I'm somewhat confused on how I should structure this properly. Should I have a has_many relation with the User model and the Lease model instead of the has_one and then just a method say lease on the User model to get the lease for a tenant?
What I would like to have is something like
tenant.lease
and
landlord.leases
Could I just do?
class User < ApplicationRecord
has_one :lease, foreign_key: "tenant_id"
has_many :leases, foreign_key: "landlord_id"
end
this seems to work, but I'm not sure if its the right way to go.
Using STI, you could have the following models
==> user.rb <==
class User < ApplicationRecord
end
==> landlord.rb <==
class Landlord < User
has_many :leases
end
==> tenant.rb <==
class Tenant < User
has_one :lease
end
==> lease.rb <==
class Lease < ApplicationRecord
belongs_to :tenant
belongs_to :landlord
end
Then you can do things like
irb(main):003:0> landlord = Landlord.create(name: 'the landlord')
=> #<Landlord id: 5, name: "the landlord", type: "Landlord", created_at: "2022-01-03 22:16:56", updated_at: "2022-01-03 22:16:56">
irb(main):004:0> tenant = Tenant.create(name: 'the tenant')
=> #<Tenant id: 6, name: "the tenant", type: "Tenant", created_at: "2022-01-03 22:17:09", updated_at: "2022-01-03 22:17:09">
irb(main):005:0> lease = Lease.create(tenant: tenant, landlord: landlord)
=> #<Lease id: 3, tenant_id: 6, landlord_id: 5, created_at: "2022-01-03 22:17:28", updated_at: "2022-01-03 22:17:28">
irb(main):006:0> tenant.lease
=> #<Lease id: 3, tenant_id: 6, landlord_id: 5, created_at: "2022-01-03 22:17:28", updated_at: "2022-01-03 22:17:28">
irb(main):007:0> landlord.leases
=> #<ActiveRecord::Associations::CollectionProxy [#<Lease id: 3, tenant_id: 6, landlord_id: 5, created_at: "2022-01-03 22:17:28", updated_at: "2022-01-03 22:17:28">]>
To accomplish this, you only need to add a type column to your User model and Rails will take care of the rest.
In my opinion, you should go with has_many approach. As landlord and tenant both are users. in place of using tenant_id and landlord_id, you have to use 'user_id' and to identify user, use user_type i.e. tenant and lanlord.
Just an opinion !!

Return a matching result in the view across three models in Rails app

I'm inheriting a codebase for a Rails app that uses a blog engine -- and I am not making sense of how the models interact.
What I want to do is show the author who is associated with a specific article.
There is a table for articles called LinesArticle. An example entry:
<LinesArticle id: 2, title: "Example Article", sub_title: "Example Title",
content: "Example Content", published: true, published_at: "2017-08-22 00:00:00",
created_at: "2017-08-23 06:15:33", updated_at: "2017-08-23 06:15:36", slug: "whatever",
featured: false, document: nil, short_hero_image: "", teaser: "">
Next, there is a table for Authors called LinesAuthor. An example entry that should be associated:
#<LinesAuthor id: 1, name: "John Doe", email: "jd#examplesitedotcom", created_at: "2017-08-19 07:46:04", updated_at: "2017-08-19 07:46:04">
So if I compare these two tables, there isn't a connection between the data that would make sense for the models. So then I found LinesAuthorable that I think connects them. An entry:
<LinesAuthorable id: 2, author_id: 1, article_id: 2,
created_at: "2017-08-23 06:15:33", updated_at: "2017-08-23 06:15:33">
So my thinking is, if my controller calls an article like #articles = LinesArticle.last and I want to show the author who wrote that article by matching article_id to the matching result in LinesAuthorable and then query LinesAuthor for the matching author_id.
Reading through the documentation, I have now created models where an Article model belongs_to :lines_authorable and Author has_many :Lines_Authorable. If that is the right approach, how would you call that in the view to actually show the Author?
The LinesAuthorable table is acting as a through table, you can use a has_many through relationship to connect the data, something like:
class LinesArticle < ApplicationRecord
has_many :lines_authorables, foreign_key: :article_id
has_many :lines_authors, through: :lines_authorables
end
class LinesAuthor < ApplicationRecord
has_many :lines_authorables, foreign_key: :author_id
has_many :lines_articles, through: :lines_authorables
end
class LinesAuthorable < ApplicationRecord
belongs_to :line_article, foreign_key: :article_id
belongs_to :line_author, foreign_key: :author_id
end
You can then access an article's authors, and likewise an author's articles directly through the relationship:
#article = LinesArticle.first
#article.lines_authors #=> #<LinesAuthor::ActiveRecord_Relation...>
#author = LinesAuthor.first
#author.lines_articles #=> #<LinesArticle::ActiveRecord_Relation...>

Properly modeling monetary transactions in Rails 4

I am making a toy application to learn Rails 4 (without just cloning a tutorial).
Users sign up (I'm using the Devise gem to take care of user authentication), and a BTC pub/prv keypair is generated, and an address is computed and displayed to the user (in a flash message), so they can top off their account. Other Users sign up, and anyone can search for anyone and a dropdown is dynamically populated with every single user, but filters down names as a User types the name of their friend/associate, whoever they want to send Bitcoin to. I am only using testnet for this idea at the moment, no real BTC (don't worry!).
Anyways, here is my idea for modeling this application:
class User < ActiveRecord::Base
has_many :account
end
class Tx < ActiveRecord::Base
has_one :receiver, class => "account"
belongs_to :user, through :account
end
class Account < ActiveRecord::Base
belongs_to :user
has_many :tx
end
The reason why I don't like the above is because in my mind it seems that a Tx (short for transaction since transaction is a reserved word in Rails) actually belongs to two users, but my readings seem to indicate that I can't have something like this:
class User < ActiveRecord::Base
has_many :tx
end
class Tx < ActiveRecord::Base
has_one :receiver, class => "user"
has_one :sender, class => "user
end
Which of these implementations is better? I appreciate any insight into this model.
I'd go with the second method. I went with "transfers" instead of "tx", for readability - but you can name it as you please.
class User < ActiveRecord::Base
has_many :transfers
has_many :received_transfers, :class_name => "Transfer", :foreign_key => "receiver_id"
end
class Transfer < ActiveRecord::Base
belongs_to :user # Sender
belongs_to :receiver, :class => "User"
end
Testing it:
>> Transfer.create(:user_id => 1, :receiver_id => 2, :amount => 4.00)
=> #<Transfer id: 1, user_id: 1, receiver_id: 2, amount: #<BigDecimal:7fb3bd9ba668,'0.4E1',9(36)>, created_at: "2014-09-03 04:35:47", updated_at: "2014-09-03 04:35:47">
>> User.first.transfers
=> #<ActiveRecord::Associations::CollectionProxy [#<Transfer id: 1, user_id: 1, receiver_id: 2, amount: #<BigDecimal:7fb3c10682f0,'0.4E1',9(18)>, created_at: "2014-09-03 04:35:47", updated_at: "2014-09-03 04:35:47">]>
>> User.last.received_transfers
=> #<ActiveRecord::Associations::CollectionProxy [#<Transfer id: 1, user_id: 1, receiver_id: 2, amount: #<BigDecimal:7fb3bdabace8,'0.4E1',9(18)>, created_at: "2014-09-03 04:35:47", updated_at: "2014-09-03 04:35:47">]>
Happy coding!

Difference between has_one and belongs_to on a 1 to many relationship in Ruby on Rails

The idea is that i have a table users and a table customers. Each user has many customers that are related only to them. Actually Im using this model. So every customer that will be created will also get the related user_id in the customers table.
class Customer
belongs_to :user
end
class User
has_many :customers
end
After some SO question it was stated to me that I should use this model, for the same result.
class Customer
has_one :user
end
class User
belongs_to :customer
end
But i dont get the difference. Any easy explaination wether Im right with my way or what is wrong.
regards
denym
It won't actually be the same result...
The first one:
class Customer
belongs_to :user
end
class User
has_many :customers
end
Will set a user_id in the Customer and nothing in the User. That means that a customer can only be related to one user. In terms of reflections you can do stuff like this:
user = User.create(name: 'John Snow')
customer = user.customers.build(name: 'Tywin Lannister')
customer.save
user.inspect
=> #<User id: 8, name: "John Snow">
customer.inspect
=> #<Customer id: 12, user_id: 8, name: "Tywin Lannister">
user.customers.inspect
=> [#<Customer id: 12, user_id: 8, name: "Tywin Lannister">]
customer.user
=> #<User id: 8, name: "John Snow">
The second one:
class Customer
has_one :user
end
class User
belongs_to :customer
end
Will set a customer_id in the user. You can do stuff like this:
customer = Customer.create(name: 'Tywin Lannister')
user = customer.build_user(name: 'John Snow')
user.inspect
=> #<User id: 8, customer_id: 12, name: "John Snow">
customer.inspect
=> #<Customer id: 12, name: "Tywin Lannister">
user.customer
=> #<Customer id: 12, name: "Tywin Lannister">
customer.user
=> #<User id: 8, customer_id: 12, name: "John Snow">
So in your case
Well you need the first one.
From the documentation:
A belongs_to association sets up a one-to-one connection with another model, such that each instance of the declaring model “belongs to” one instance of the other model.
A has_one association also sets up a one-to-one connection with another model, but with somewhat different semantics (and consequences). This association indicates that each instance of a model contains or possesses one instance of another model.

creating instance of belongs_to model not showing up in it's associated objects list

I've created two models with the below associations
class User < ActiveRecord::Base
has_many :roles, :dependent => :destroy
end
class Role < ActiveRecord::Base
belongs_to :user
end
class Student < Role
end
class Tutor < Role
end
However when I create a new child role, I assume it would get associated to the model it has the belongs to for.
Such as:
Tutor.create(:user_id => user_id)
I would expect:
#some user #user
#user.roles
to have an array containing a Tutor. However, it doesn't seem to be working. Any ideas what I'm doing wrong?
Once you start using Single Table Inheritance, than the Tutor that you created isn't a role, as far as active-record is concerned for this type of query.
class User < ActiveRecord::Base
has_many :roles
has_many :tutors
end
#user = User.first
#user.roles
=> []
#user.tutors
=> [#<Tutor id: 1, user_id: 1, type: "Tutor", created_at: "2012-10-26 18:15:16", updated_at: "2012-10-26 18:15:16">]
If you want to get a list of all roles that your users may have:
Role.where(user_id: #user.id).all
[#<Tutor id: 1, user_id: 1, type: "Tutor", created_at: "2012-10-26 18:15:16", updated_at: "2012-10-26 18:15:16">, #<Student id: 2, user_id: 1, type: "Student", created_at: "2012-10-26 18:18:32", updated_at: "2012-10-26 18:18:32">]

Resources