Why doesn't this associated create call work? - ruby-on-rails

I've got a User model that has many Items. A Rating belongs to a User and an Item.
In the DB, I have set ratings.user_id to be not NULL.
when I am creating an Item, I would like to do this:
def create
current_user.items.create(params[:item]).ratings.create(params[:rating]
redirect_to items_path
end
However, this balks with an SQL error "user_id cannot be nil"
so I rewrote the create method as
def create
current_user.items.create(params[:item]).ratings.create(params[:rating].merge({:user_id => current_user}))
redirect_to items_path
end
which works fine.
However, I had thought that chaining the create methods off the current user's receiver would have populated the rating's user_id. Anyone know why not?
TIA.

I'd recommend you normalize this if possible in the database. Maybe take out the user_id attribute from the ratings table and if you need it in your model get it through a join using a :through method
class Rating
has_many :items
has_one :user, :through=>:items

If you created and saved the Item, then made a Rating from that item, it wouldn't pass the user along to the Rating, right? You'd just refer to it as #rating.item.user, right?
When you think about it like that, you wouldn't expect the Item created via the current_user to pass the user information along to the rating.
Make me wonder if you really need the user has_many ratings relationship.

Because Item has many Ratings and that association does not know about the user id. Given that association chain Item would have a user id because it belongs to a user. And Rating would have an item id because it belongs to an item. But the Item to Rating assocation doesn't know anything about a user unless you tell it.

Related

Specify table for rails .where

Can't find same question. How can I specify select.where for model?
I need to select from different tables by one model and want to get something like this in controller:
params[:id] = 1248 // here is example of request params
id=params[:id] // this id goes to message SQL like table name with prefix:
Message(id).all => select * from messages_1248
How can I get something like this?
Thanks for answers!
UPD:
I have one table with users and many tables with messages (each table is for one pair of users). In users table there is 'messages' column with messages tables id's. And inside user_controller I need to run a query like in my question. Maybe anybody can share an example?
how about little bit change the design, with just 2 tables (user and message) just idea with details below
user table (id,name)
messages table(user_id,message_text)
you setup the relation user has_many messages (please see this link for more guide http://guides.rubyonrails.org/association_basics.html#the-has-many-association
user.rb
has_many :memberships
message.rb
belongs_to :user
for example you need to access user with specific id and the messages for this user
inside users_controller.rb
def show
#user = User.find(params[:id])
# this find user
#messages = #user.messages
# get all the messages for specific users
end

Rails, after a record is created, how to automatically create an associated record?

I have a Ratings model where a user can rate an object... After a rating takes place I want to then automatically create a RatingLog record so the user can see a list of all the ratings.
Models: Rating.rb and RatingLog.rb
I see RatingLog including a list of events other than just Ratings, like Badges etc... VERY similar to StackOverflow.
What is the right way with Rails 5, to populate RatingLog.rb after a Rating is created... Should I use after_create in Rating.rb? Should I create some other type of callback? Would love to hear what is the right way to implement the above in Rails 5.
Thank you
I assume that you have models:
class Rating
has_one :rating_blogs
end
class RatingBlog
belongs_to :rating
end
so, to create a rating blog afer rating is created, you can do:
#rating = Rating.new
#rating.build_rating_blog(some_message: 'Message')
#rating.save
So when #rating is created, a rating blog will be created and associated with #rating.
I don't know if this is considered okay... But I do this right inside of the create action, in your case I'll guess:
RatingController
def create
...
#ratinglog = RatingLog.create
#ratinglog.user = current_user
#ratinglog.rating = #rating.id
#ratinglog.comment_type = "server generated"
#ratinglog.comment = "#{current_user.fname} #{current_user.lname} submitted a rating of #{#rating.content}"
#ratinglog.save!
...
end
Another option is an after_commit callback which will only run when the Rating object is saved.
after_create will work too, but if you have an error when you try to save your RatingLog then the Rating record you created will also not save (checkout this answer).
So depending on the behavior you want, choose one:
after_commit RatingLog errors don't effect Rating saves
after_create RatingLog errors rollback Rating saves
Also:
It's not totally clear from your post, but it sounds like Rating and RatingLog are holding very similar data?? or if RatingLog will hold logs of other events, maybe name it something else.
Check out this answer on naming conventions -- the convention for model file naming is rating.rb and rating_log.rb

How to implement a last_modified_by (person) attribute on two unrelated models - Rails

I have a Record model and in order to edit this model, you must be logged in as an instance of Admin. I would like to have a column called last_modified_by which points to the Admin who last modified the Record. In the database, I was thinking it would be good in the records table to add a column that holds the Admin's id; however, the only way I know how to do that is with an association. These two models are not associated with each other so an association doesn't make a lot of sense. Is there any other way I might be able to accomplish this task without resorting to associations? Any advice would be much appreciated!
Hmm, I think the association is a good tool here. You might want to try to hack it somehow but I think nothing you can conjure up will ever be as good as an association via a foreign_key(also so fast). But perhaps you would like to name your association and do something like:
class Record < ActiveRecord::Base
belongs_to :culprit, :class_name => 'Admin', :foreign_key => 'last_modified_by'
end
or give it some more senseful naming?
You could create an Active Record before_save callback. The callback would save the admin's id into the last_modified_column. This would make sure the admin id is saved/updated each time there is a change to the model.
For example, assuming admin is #admin:
class Record < ActiveRecord::Base
before_save :save_last_modified
def save_last_modified
self.last_modified_column = #admin.id
end
As for getting #admin, you could employ a method similar to this, and set #admin = Admin.current (like User.current in the link) somewhere in the Record model.

whats the difference between these create methods

Hey I am stuck with my orientation in rails.
I got a User model, a Course Model and a CourseEnrollment Model.
When I want to add a link in my Course Index View like
link_to 'join' CourseEnrollment.create(:course_id => course.id, :user_id => current_user)
Does this create method belong to my Model? I am confused because in my User Model I defined a method that uses role_assignments.create(.....). What is the difference between these 2 create methods? I cant use course_enrollments.create by the way. Thx for your time
I'm a bit confused as to what you're asking, but I'll try my best.
(First of all, in your example, current_user should probably be current_user.id.)
When you call CourseEnrollment.create, you are simply creating a new CourseEntrollment model with the specified attributes.
Assuming that your User model has_many :role_assignments:
When you call #role_assignments.create from within your User model, Rails automatically creates the association for you (e.g. sets the user_id to the id of the user). This doesn't have to be done within the model itself, though:
current_user.role_assignments.create(...) # automatically sets the association
Assuming that your User model also has_many :course_enrollments, the following will create a CourseEnrollment model and automatically associate it with the current user:
current_user.course_enrollments.create(...)

How do I implement this code without needing to access current_user.id from a model in RoR?

I have a note model, with the following association
note.rb
has_many :note_categories, :dependent => :destroy
has_many :categories, :through => :note_categories
The NoteCategory model was created to function as a join table between notes and categories.
I need to implement the following:
A user removes a category from a note. This can be done by either removing one category from a note (deletes one entry in the note_categories table), or by deleting the note entirely (deletes all entries in the note_categories table relating to the note)
Before the row/s in note_categories is/are deleted, I need to determine if the user who is deleting the category from a note is the same user who initially created the category (creator field in the category model)
If it is the same user, the category entry itself is to be deleted
Obviously to do this, I need to access the id of the user, to check against the creator field of the Category. I am already using a before_destroy method in the NoteCategory model to do some other things, but I can't access current_user.id in there because it's a model, and current_user is a method in the Application Controller. From the questions I've read here on SO, it seems that accessing the id of the current user from a model is bad form.
I don't think I can use the controller in this circumstance because when a note is deleted, the :dependent => :destroy line means that the associated rows in note_categories are deleted as well. I need to do the creator check in this situation as well, but the note_categories rows are removed via the destroy method in the model, not the controller, which is the behavior specified by :dependent => :destroy.
So how should I go about doing it? Thanks for reading!
One way of doing this could be to add an attr_accessor to the Note model like so:
# in Note.rb
attr_accessor :destroyed_by
and set it before destroying the record:
# NotesController#destroy
#note.destroyed_by = current_user.id
#note.destroy
Then in your Note.rb before_destroy call, you can check the Category's creator id against the destroyed_by id.
You say
Before the row/s in note_categories is/are deleted, I need to determine if the user who is deleting the category from a note is the same user who initially created the category (creator field in the category model)
If it is the same user, the category entry itself is to be deleted
Are you sure you wan't to do such a thing? What if a user has used the same category for many notes, and he wants to delete it form one of them? You sure would want to delete an entry from note_categories, but should you also delete the category itself?
A common implementation for such a scenario is to check while deleting a note_category (through perhaps a before_destroy) whether this one is the last note_categories for the category, and delete it if it is. This also means that if a note is deleted, only the related note_categories should be deleted, and not the categories themselves.
I think that you want to maintain a log of who created the post and who is deleting it. The before_destroy method does the part of deleting associations and I think it is working fine for you. as of maintaining record of whether the user who created the note is deleting the note or not comes under logging part. I hope this helps you around this problem
http://rohitsharma9889.wordpress.com/2010/08/19/logging-in-ruby-on-rails/
EDIT:
You can also try reading this article. I would recommend you to prefer this one on the above one
Environment variables in Model

Resources