Mass Assignment warning when using association methods - ruby-on-rails

I have a very odd mass assignment error that shows up when I use association methods to create new objects.
I have a user model that looks like this:
class User < ActiveRecord::Base
has_many :posts, :dependent => :destroy
end
I also have a posts model that looks like this:
class Post < ActiveRecord::Base
belongs_to :user
attr_accessible :body, :title
end
If I do the following in console, I get a mass assignment warning:
> user = User.create(:name => "Daniel");
> user.posts.create(:title => "Hello World")
=> #<Post id: 1, body: nil, title: "Hello World", created_at: "2011-11-03
18:24:06", updated_at "2011-11-03 18:24:06", user_id = 1>
> user.posts
=> WARNING: Can't mass-assign attributes: created_at, updated_at, user_id
When I run user.posts again, however, I get:
> user.posts
=> [#<Post id: 1, body: nil, title: "Hello World", created_at: "2011-11-03
18:24:06", updated_at "2011-11-03 18:24:06", user_id = 1>]
There are a couple of other tricks I can do to avoid the mass assignment error, such as calling user.posts before I do users.posts.create.
Why is this happening and how can I prevent it?
I'm using Rails 3.0.7.

How about changing your user model to include attr_accessible for posts association
class User < ActiveRecord::Base
has_many :posts, :dependent => :destroy
attr_accessible :posts
end

Related

How do i select an association record that has yet to be saved in Rails?

I have the following models and relationships. I'm building a form and am wanting to initialize terms of the proposal for the form. How can I select a specific ProposalTerm by it's term_type_id to pass on to my fields_for block?
Proposal
class Proposal < ApplicationRecord
after_initialize :add_terms
has_many :terms, class_name: "ProposalTerm", dependent: :destroy
accepts_nested_attributes_for :terms
def add_terms
terms << ProposalTerm.first_or_initialize(type: TermType.signing_bonus)
end
end
ProposalTerm
class ProposalTerm < ApplicationRecord
include DisableInheritance
belongs_to :proposal
belongs_to :type, class_name: "TermType", foreign_key: "term_type_id"
def self.signing_bonus
find_by(type: TermType.signing_bonus)
end
end
My Attempt
>> #proposal.terms
=> #<ActiveRecord::Associations::CollectionProxy [#<ProposalTerm id: nil, season: nil, value: nil, is_guaranteed: false, term_type_id: 2, proposal_id: nil, created_at: nil, updated_at: nil>]>
>> #proposal.terms.where(term_type_id: 2)
=> #<ActiveRecord::AssociationRelation []>
I was able to figure out an answer. I had tried "select" but I was doing it incorrectly.
I had tried the following,
#proposal.terms.select(term_type_id: 2)
but that wasn't returning anything. I then did the following...
#proposal.terms.select { |t| t.term_type_id = 2 }
If you want to return just the first instance use "detect" ...
#proposal.terms.detect { |t| t.term_type_id = 2 } }

Activerecord enum doesn't generate helpers

I have created an active record enum field: role. Added it to the model and the table. But it doesn't generate the helpers?
Membership model
enum role: [:employee, :admin, :owner]
after_initialize :set_default_membership_role, :if => :new_record?
def set_default_membership_role
self.role ||= :employee
end
pry output
=> [#<Membership id: 1, company_id: 1, user_id: 1, created_at: "2014-11-25 16:06:03", updated_at: "2014-11-25 16:06:03", role: 0>]
[3] pry(main)> #membership.role
from /Users/gtheys/.rbenv/versions/2.1.2/gemsets/worke_rs/gems/activerecord-4.1.5/lib/active_record/relation/delegation.rb:136:in `method_missing'
Is it because because Membership is a join model for user and companies?
model/User.rb
has_many :companies, :through => :memberships, dependent: :destroy
model/Companies.rb
has_many :users, :through => :memberships
Or is there another problem why the enum helpers are not created?
Are you sure you are calling .role on the actual membership model?
In your example (pry output) it looks like #membership is an active_record/relation.
Try #membership.first.role

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!

unknown attribute errror when implementing rails multiple table inheritance

I followed the post http://techspry.com/ruby_and_rails/multiple-table-inheritance-in-rails-3/ to implement the multiple table inheritance with Rail 4. I have three models: user, applicant and tutor. Here is my code:
class User < ActiveRecord::Base
belongs_to :student, :polymorphic => true
end
class Tutor < ActiveRecord::Base
acts_as_student
end
class Applicant < ActiveRecord::Base
acts_as_student
end
# in the /lib/student_module.rb
module Student
def acts_as_student
include InstanceMethods
has_one :user, :as => :student, :autosave => true, :dependent => :destroy
alias_method_chain :user, :build
user_attributes = User.content_columns.map(&:name) #<-- gives access to all columns of Business
# define the attribute accessor method
def student_attr_accessor(*attribute_array)
attribute_array.each do |att|
define_method(att) do
user.send(att)
end
define_method("#{att}=") do |val|
user.send("#{att}=",val)
end
end
end
student_attr_accessor *user_attributes #<- delegating the attributes
end
module InstanceMethods
def user_with_build
user_without_build || build_user
end
end
end
The User Table has username, email attributes.The Tutor table has first_name,last_name,intro,program,entry_year attributes.
In the rails console, I got
tutor = Tutor.new => #<Tutor id: nil, first_name: nil, last_name: nil, intro: nil, created_at: nil, updated_at: nil, entry_year: nil, program: nil>
tutor.username
=> ActiveRecord::UnknownAttributeError: unknown attribute: student_id
I found the error was from the student_attr_accessor method. How should I fix it? Thanks!
I found I forgot to declare a foreign key column and a type column in the User Model. To fix this, just run a migration like:
def change
add_column :users, :student_id,:integer
add_column :users, :student_type,:string
end

rails basic polymorphism

i'm trying to create a polymorphic relationship between votes can be submitted by users and apply to articles. my code
class Vote < ActiveRecord::Base
attr_accessible :value, :voteable_id, :voteable_type
belongs_to :voteable, :polymorphic => true
end
class User < ActiveRecord::Base
has_many :votes, :as => :voteable
end
class Article < ActiveRecord::Base
has_many :votes, :as => :voteable
end
<Vote id: 1, value: 1, created_at: "2012-07-27 03:13:14", updated_at: "2012-07-27 03:13:14", voteable_id: nil, voteable_type: nil>
From looking at the rails documentation via http://guides.rubyonrails.org/association_basics.html#polymorphic-associations
I feel that my code is set correctly but i'm having a bit of trouble triggering it correctly, ie, how do I actually create a vote object with a properly define relationship to either an article or user?
Is votable_type is string?
Next example should work correctly..
#user.votes.new :value => 1
#user.save
.
I was able to make this work, I was setting the voteable_type attribute incorrectly.

Resources