How to find the ids used by current user - ruby-on-rails

I have created a quiz and i displayed the items in one per page.. i want the values of question id that is visited by the current user . in this code i give next and it render the question i want the visited question id by current user
def next
#user = current_user
#student = Student.find_by_admission_no(#user.username)
#exam_group = ExamGroup.find_by_id(params[:exam_group_id])
#answer = Answer.new(params[:ans])
#answer.answer = params[:answer]
#answer.exam_group_id = #exam_group.id
#answer.user_id = #user.id
passed_question = params[:passed_question]
#answer.questions_id = passed_question
next_question = params[:next_question]
#question = Question.find_by_id(passed_question)
#module = Question.find_by_sql ["SELECT student_additional_field_id FROM questions WHERE id=#{passed_question}"]
student_additional_field_id = #module[0].student_additional_field_id
#questions = Question.find(:all, :conditions => [' exam_group_id=? && student_additional_field_id=? ',#exam_group,student_additional_field_id], :offset => #ans)
#ques = []
#questions.shuffle.each do |a|
#ques.push a.id unless a.id.nil?
end
a = #ques[0]
session[:ques_id] = a
#answer.modules_id = student_additional_field_id
if params[:answer] == #question.is_answer
#answer.marks = 1
else
#answer.marks = 0
end
if #answer.save
#ans = Question.find_by_id(a, :conditions => [' id not in (?) && exam_group_id=?',answered, #exam_group])
unless #ans.nil?
render(:update) do |page|
page.replace_html 'main', :partial => 'ans', :object => #ans
end
else
render(:update) do |page|
page.replace_html 'main', :partial => 'ans2'
end
end
end
end

It seems your problem is to do with Rails model associations:
Why do we need associations between models? Because they make common
operations simpler and easier in your code. For example, consider a
simple Rails application that includes a model for customers and a
model for orders. Each customer can have many orders
ActiveRecord Associations
ActiveRecord associations allow you to define a primary_key (typically an ID), which you can then reference on other tables through a foreign_key. The foreign key is typically a table column which will be called something like user_id, or another type of ID
You can associate your models using these functions:
belongs_to
has_one
has_many
has_many :through
has_one :through
has_and_belongs_to_many
To answer your question, you're obviously getting the current_user ID okay - so if you managed to get the relations set up correctly, you could literally call the data in this way:
#user = User.find(current_user.id)
#exam_group = #user.exams_groups
I would go through your code & put more info into it.... but I think you need to learn about ActiveRecord associations first

Related

Rich many-to-many assosiation. Only allow one record

I need to limit my rich many-to-many association table to only one association per unique par. (rails).
That means i want terminals (model 1) and subscriptions (model 2) to have one custom_price (rich join) not any more than that.
How is this done most elegantly?
So far i have done:
def new_custom_price
#terminal_id = params[:terminal_id]
#subscription_id = params[:subscription_id]
#custom_price = CustomPrice.find_or_initialize_by_terminal_id_and_subscription_id( #terminal_id, #subscription_id)
render action: 'custom_price'
end
def create_custom_price
#terminal_id = params[:terminal_id]
#subscription_id = params[:subscription_id]
#custom_price = CustomPrice.new(custom_price_params.merge( :terminal_id => #terminal_id, :subscription_id => #subscription_id))
respond_to do |format|
if #custom_price.save
format.js { render action: 'add_custom_price' }
else
format.js { }
end
end
end
Two things you can do to handle this: (This is assuming "price" is the unique part of the many to many relationships)
1) Validation in CustomPrice
validates :price, uniqueness: {scope: [:terminal_id, :subscription_id]}
Unique Price on CustomPrice with a scope of Terminal and Subscription IDs
http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates
2) Use helpers
CustomPrice.find_or_create_by(custom_price_params.merge( :terminal_id => #terminal_id, :subscription_id => #subscription_id))
Similar to the one used in your new action
http://api.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-find_or_create_by

Rails checking db for already existing user and add comment without creating a new user

I have a landlord and comment class.
Landlord has 1:N comments.
When a landlord is created it creates a comment on the same form (nested).
When the form is submitted, users_controller#create is called.
I want to check the database if the landlord with the same name, city and state already exists and add the comment to that landlord instead of creating a new one.
def create
#check if a landlord of the same name already exists and add comments to that
if Landlord.find_by_name(params[:name]) && Landlord.find_by_city(params[:city])&& Landlord.find_by_province(params[:province])
#landlord_exists = Landlord.find_by_name(params[:name]) && Landlord.find_by_city(params[:city])&& Landlord.find_by_province(params[:province])
#landlord_exists.comments.build
#landlord_exists.comments[0].setIP request.remote_ip
#landlord_exists.save
else
#landlord = Landlord.new(params[:landlord])
#landlord.comments[0].setIP request.remote_ip
if #landlord.save
flash[:success] = "Thank you for submitting a Landlord"
redirect_to landlords_path
else
end
end
end
update # 1 down to
def create
#landlord = Landlord.where(:name => params[:name], :city => params[:city], :province => params[:province]).first_or_create!
#landlord.comments[0].setIP request.remote_ip
if #landlord.save
redirect_to landlords_path
else
end
end
The line
#landlord = Landlord.where(:name => params[:name], :city => params[:city], :province => params[:province]).first_or_create!
Seems to be returning a nil object thus throwing errors when setIP is called.
What would be causing this? I have tried it in the terminal and it worked fine although I was using hardcoded values.
The simplest way to do it would be to use ActiveRecord::Relation's first_or_create! method. This will perform a query based on the params entered in the form, and create a record if no matches are found, meaning you can get of the if ... else conditionals:
#landlord = Landlord.where(params[:landlord]).first_or_create!
#landlord.comments.build
# etc ...

How to specify a record with a date greater than another date?

I have a record called Feeds that contains the field 'last_visited' and 'last_modified', both are timestamps.
I'm trying to render a list in a view of alls Feeds where last_modified > last_visited.
I currently have this:
Controller
#feeds = #user.feeds
#feeds_hot = #feeds.where(['#feeds.last_modified > ?', #feeds.last_visited])
Have a feeling I'm way off track here. Should I also being using a model class to do this?
Any helps is greatly appreciated.
Edit:
Here's my model
class Feed < ActiveRecord::Base
attr_accessible :feed_id, :feed_url, :last_modified, :title, :url, :last_visited, :user_id
belongs_to :user
scope :hottest, lambda {where('last_modified > ?', :last_visited)}
def fetch_feed!
feed = Feedzirra::Feed.fetch_and_parse(feed_url) # probably want some eror handling here
self.title = feed.title
self.url = feed.url
self.last_modified = feed.last_modified
self.last_visited = feed.last_modified
self #or nil if you like
end
def self.check_for_update(feed)
fetched_feed = Feedzirra::Feed.fetch_and_parse(feed.feed_url)
entry = fetched_feed.entries.first
feed.last_modified = entry.published
end
def update_visit_date!
date = Time.now
update_attribute(:last_visited, date)
self
end
end
Edit
Updated code
Controller
def home
#user = current_user
#feeds = #user.feeds
#feeds_hot = #feeds.hottest
end
Model
attr_accessible :feed_id, :feed_url, :last_modified, :title, :url, :last_visited, :user_id
belongs_to :user
scope :hottest, lambda {where("'last_modified' > ?", 'last_visited')}
View
%ol.feeds.feeds_hot
- #feeds_hot.each do |feed|
%li.feed.hot[feed]
= render :partial => 'feeds/feed_link', :locals => {:feed => feed}
Unfortunately it's still not rendering the hot feeds in the view when I have a feed with the following data:
Last Modified 2013-06-14 23:49:07 UTC
Last Visited 2013-06-14 23:47:55 UTC
Last Modified is a few hours > than Last Visited
If you're looking to get a list of all feeds that have been modified more recently than the most recent visit on any feed, the following will work:
last_visit = Feed.order("last_visited").last.last_visited
#feeds = #user.feeds
#hot_feeds = Feed.where("last_modified > ?", last_visited)
EDIT:
Based on your comments and a re-reading of your question, the code posted above will not accomplish what you're trying to do. Since you're trying to get a list of all invites where each has been modified since it was last visited, you'll want to create a model scope to do the lookup with ActiveRecord. The following code should work:
# app/models/feed.rb
class Feed < ActiveRecord::Base
scope :hottest, lambda {where('last_modified > ?', :last_visited)}
end
Then, you can run the following in a console, controller, or view:
#user.invites.hottest
#=> array of all the user's invites that have been modified more recently than they have been viewed

ruby on rails can i use something like Model.find(params[:id]).where()

Hi, I am still a student and I'm taking a software engineering course and we have this big project (web design) and we're using rails so my question is I have a table Users and a table Groups and another association table GroupUsers where it has two foreign keys user_id and group_id. Whenever a user creates or join an already created group his id and the group_id are added to GroupUsers table
module GroupUsersHelper
def join
#group_id = params[:id]
#user_id = params[:user_id]
#newuser= GroupUser.new(:group_id => #group_id, :user_id => #user_id)
#newuser.save
redirect_to(:controller => 'groups', :action => 'show', :id => #group_id)
end
end
Now I have to create method leave group where I'll have to destroy the record from GroupUsers, so I wrote this code also in GroupUsersHelper
def leave
#group_id = params[:group_id]
#user_id = params[:user_id]
#group_user_id = params[:group_user_id]
#newuser= GroupUser.find(#group_user_id).where(:group_id => #group_id, :user_id =>
#user_id)
#newuser.destroy
redirect_to(:controller => 'groups', :action => 'show', :id => params[:id])
end
but I get this error
ActiveRecord::RecordNotFound in GroupsController#leave
Couldn't find GroupUser without an ID
If you need more info about the code please let me know.
The other answers addressed your code example, but not the question in the title. You cannot use Model.find(params[:id]).where() in ActiveRecord (Rails' default ORM). Model.find returns a single record (an instance of your Model class) but Model.where returns a Model::ActiveRecord_Relation object (an array-like object). The .where method is only available on your Model class directly (i.e. Model.where) or on an ActiveRecord_Relation. If you are chaining methods, you need to make sure each method returns an ActiveRecord_Relation. For example:
Model.where("name = ?", "max")
.order(created_at: :desc)
.reorder(created_at: :asc)
.includes(:sent_comments)
Model.find(params[:id]) will generate such kind of query
*Lets take an example : GroupUser.find(params[:id]) will generate sql equivalent*
select * from group_users where id = params[:id]
If you want to add where condition do something like this
GroupUser.where("# id ={params[:id]} and someColumn = #{somevariable}")
You are not passing the groupuser_id in the params hash. Instead of storing it in the #group_id and #user_id, just try this:
#newuser= GroupUser.find_by_group_id_and_user_id(params[:group_id],params[:user_id])
Can you additionally post your params dump so we can figure out how to make a good redirect since i hence that will be a problem also.
Just do:
group = Group.find(params[:group_id])
user = User.find(params[:user_id])
group.users.delete(user)
group.save
This will remove the user from the users association, and will automatically destroy the GroupUser record when the group is saved. See the collection.delete method.
#max pleaner is right, you should not use Model.find().where().
It is incorrect, and if you think about it, you will see that it is redundant. To find the association you wish to destroy, you either need params[:group_id] and params[:user_id], or just params[:group_user_id].
If you have passed the params[:group_user_id] to the leave method, you already have all the information needed to find the association:
def leave
#newuser= GroupUser.find(params[:group_user_id])
#newuser.destroy
redirect_to(:controller => 'groups', :action => 'show', :id => params[:group_id])
end
Or alternatively, If you have passed the params[:group_id] and params[:user_id] to the leave method:
def leave
#newuser= GroupUser.find_by_group_id_and_user_id(params[:group_id], params[:user_id])
#newuser.destroy
redirect_to(:controller => 'groups', :action => 'show', :id => params[:group_id])
end
Also, there are a few other redundancies in your code that you will notice I omitted above. There is no need to assign each parameter to an instance variable before passing the parameter to the find() method:
#model_id = params[:model_id]
#model= Model.find(#model_id)
#can be simplified to:
#model = Model.find(params[:model_id])
Generally, you only want to create instances variables for a record or collection of records you will need to access in a view (such as a Group in the context of your application).

How to copy or clone model?

I have a model Book with attributes id, name, price. I have an instance of Book:
b1 = Book.new
b1.name = "Blah"
b1.price = 12.5
b1.save
I would like to copy b1, create another instance of the Product model. I'm tryid p1=b1.clone then p1.save but it didn't work. Any idea?
And my environment is:
Netbeans 6.9 RC2
JRuby 1.5.0
EDITED:
My TemporaryProduct model:
class Admin::TemporaryProduct < ActiveRecord::Base
def self.update_from_web_service(web_service_url)
response = HTTParty.get(web_service_url)
response["webServiceResult"]["product"].each do|element|
unless exists? :orignal_product_id => element['id']
create!(
:name => element['name'],
:price => element['price'],
:amount => element['amount'],
:description => element['description'],
:orignal_product_id => element['id'],
:image => element['image'],
:shop_account_number => element['shopAccountNumber'],
:unit => element['unit']
)
end
end
end
end
Product is create action:
def create
#temporary_products = Admin::TemporaryProduct.find_all_by_orignal_product_id(params[:product])
#product = Admin::Product.new(#temporary_products.attributes)
# #product = #temporary_products.clone
respond_to do |format|
format.html { redirect_to(admin_products_url, :notice => 'Admin::Product was successfully created.') }
end
end
I want to clone all b1's attributes to p1 model.
I think you want:
b2 = Book.create(b1.attributes)
Edit:
Given your create action above, I think what you want to do is change the line which starts #product to
#temporary_products.each {|tp| Admin::Product.create(tp.attributes)}
That will create a new Product object for each TemporaryProduct object, using the same attributes as the TemporaryProduct. If that's not what you want, let me know.
You can make duplicate record using dup in rails For Example,
b1 = Book.create(name: "example", price: 120)
b1.save
duplicate_record = b1.dup
duplicate_record.save!
or you can create first new record and then make a duplicate
Hope this is useful for you.
If by didn't work you mean that there is no new record in the database then you probably want to set the id of p1 to null before you save. If the clone has the same id as the original then it would appear to represent the same object.

Resources