I have an app with the following tables:
Courses,
Exercises,
Answers, and
Users (with Devise).
class Answer < ActiveRecord::Base
belongs_to :exercise
belongs_to :user
end
Each exercise has an html answer box and a "submit" button, but I want to know if the data submitted by users through the answers in each exercise goes somewhere or what can I do to retrieve it?
What would I need to do to have the answers saved somewhere where they can reviewed, or even maybe sent by email?
I know like html forms that are sent by email when you hit submit, but would that indicate which user submitted the answer?
I appreciate your help!
For your current scenario you must have exercise_id and user_id column in your answers table.
When you submit a form for answer you must have exercise_id present. And you will easily get that from controller while you are showing exercise to answer.
Now for user_id, If you are using devise than you are getting current_user object every where in your application after login.
So to save answer you must write something like this:
current_user.answers.create(params_answer)
And params_answer should be something like:
def params_answer
params.require(:answer).permit(:exercise_id, :answer_text, :xxxx, :yyyy)
end
To get answer of any qustion that current user submitted:
curren_user.answers
To get answers of perticular exercise
curren_user.answers.where(:exercise_id, '##')
For more info go through http://guides.rubyonrails.org/association_basics.html and http://guides.rubyonrails.org/active_record_querying.html
Although I don't understand your words clearly.
Using session may help.
Related
This question already has answers here:
Rails: Prevent duplicate inserts due to pressing back button and save again
(8 answers)
Closed 3 years ago.
I have an issue where I have a form that creates an entity, let's say a survey. After submitting the form, the user is taken to an Edit form for the same entity, with more fields.
Some users press the BACK button, and end up resubmitting the same survey twice.
What's a good way to prevent this from happening?
Do I have to generate some kind of UID when the New form is generated, and then save that along with the survey. Then, if users hit back, the same UID will already be present in the form, and I can detect it.
Are there more straightforward solutions that don't require me to store a new piece of information on surveys?
You can use scoped validations on entity attributes, eg if a Survey would have_many Questions, they create some questions but then go Back and resubmit they would get validation errors as the questions already exist.
class Question < ApplicationRecord
belongs_to :survey
validates_uniqueness_of :name, scope: [ :survey_id ]
end
Of course this won't help much if they change the name of the question, like for instance if they forgot to add a question mark at the end... the validation will pass. For such instances you can have a custom validator:
class Question < ApplicationRecord
belongs_to :survey
validate no_similar_question
def no_similar_question
errors.add(:name, "You have already created a similar question in this survey!") if survey.questions.where("name like ?", "%#{name}%").count > 1
#
end
end
When that fails you can either just warn them "Question already created" or redirect them to edit the original input, maybe they just realized they made a mistake or want to double check before moving on. Helps improve the UX.
Good Day All!
Edited for better understanding.
First model is Inventory and in this model I have Product_Type, Product_Name and User_ID.
Second model I have Users which consist of First_Name, Last_Name and Pin_Number.
On my Inventories page I have a form for checking out said Product_Type and Product_Name, also a place for a user to put their Pin_Number in. On submit, it will check the Pin_Number they have typed in and validate it in the Users model and if the Pin_Number is correct it will create an entry with said Product_Type, Product_Name and User_ID (which is pulled from Pin_Number that was submitted.)
I am just trying to figure out how to validate that Pin_Number they submitted.
Thats why I thought I had to do some kind of validation and an if statement based on that validation. Not sure how to go about that.
I hope this clears up any confusion.
I am just trying to figure out how to validate that Pin_Number they submitted.
What constitutes a valid pin_number? Just that it allows you to successfully look up a User? What if a user enters another user's pin_number? Is that considered 'valid'? Something to think about...
It would be helpful if you would add to your question what your params look like upon form submission. But, we can do some guess work.
So, let's assume that params looks something like:
{..., "inventory"=>{"product_type"=>"foo", "product_name"=>"Bar"}, "pin_number"=>5, ...}
In your controller, you'll probably do something like:
if #user = User.find_by(pin_number: params[:pin_number])
#inventory = Inventory.new(inventory_params)
#inventory.user = #user
if #inventory.valid?
#inventory.save
# perhaps do some other stuff...
else
# handle the case where the `#inventory` is not valid
end
else
# handle the case where the `#user` was not found
end
This assumes you have something like:
private
def inventory_params
params.require(:inventory).permit(:product_type, :product_name)
end
In your Inventory model, you probably want to do something like (I apologize, I'm not on Rails 5 yet, so some of the syntax may be incorrect):
class Inventory < ActiveRecord::Base
validates :user_id,
:product_type,
:product_name,
presence: true
belongs_to :user
end
You probably also want to consider adding an index on User.pin_number if you're going to be doing a lot of finding by it.
Not sure if I got the question right, but sounds like a custom validator to me.
You can learn more about custom validators in the official Rails documentation under "Custom Validators"
Also, consider moving the class for the custom validator you'll build to a concern, which is a great way to make it reusable. You can find more information on this StackOverflow question and this nice tutorial.
I'm doing an ajax call to save data.Now the issue is that user might unknowingly submit the same data twice and it will become duplicate. Is there any shortcut or validation for abandoning the user from submitting or saving the same data twice?
Also please note that created_at,updated_at will not be same when the user submits the form for the second time. Also the only thing that can be unique in my table is ID :) .
If I have 10 form fields and until and Unless all the 10 fields of my form are same the validator will not reject the data.
You can use an attribute like 'title' and check if it's uniq for that user :
class SomeModel < AR
validates_uniqueness_of :title, :scope => [:user_id]
end
I do not think there's a reasonable solution of this problem on the server side.
Try a simple magic of javascript disable_with.
Alright so this is another try at asking my question. I did rather poorly the first time. I have a relationship set up in my models so that users have many submissions and submissions belong to a user. I have a reference column in my submissions table that references :user and an index:
add_index :submissions, :user_id
I am using omniauth so that people can sign in with twitter. I simply want to be able to have a signed-in user be able to submit a submission and then have rails understand that there is a relationship between the current_user and the submissions they just wrote. Problem is I can't seem to store current_user in an instance variable like so:
#user = current_user
which I would like to use in my submissions controller (create) like so:
#user = current_user
#submission = #user.submissions.create(params[:submission])
I need this so that I could have a user create a submission on views/submissions/index.html.rb page and rails would understand the relation. Thank you so much for looking at this. Also I apologize in advance if I just missed something really obvious or that is common knowledge.
Your post does not really contain a question or did I miss something? What seems strange to me is that you want to assign #user = current_user. There is no need to do so, current_user should be a user anyway, therefore you could just write #submission = current_user.submissions.create(params[:submission]).
Maybe you can edit your post and provide more details on your helper methods (current_user), the error message you get with the code above. What do you get if you add Rails.logger.info current_user (or current_user.name if you have this field)?
If you want you can follow the link in my profile here on Stack Overflow, I have a couple of Rails tutorials there, including one with Omniauth.
Ugh - not sure why I'm having so much trouble with this.
Writing a simple question and answer app (see Rails - Where should this code go to stay true to MVC design? for some details)
Trying to stick to MVC principles and proper design - this app is simply a learning experience, so I want to make sure I'm doing things in a generally accepted way
The referenced question gave me advice to split up my functionality into the different models. However, trying to implement this, I find myself passing parameters all over the place and I just get a feeling that I'm not doing something right. So, here's the basic layout of the app and the tasks I am trying to accomplish - if someone could let me know if I'm on the right track...
Question Model: contains id(pkey), question_number(int), question_text(string), answer_text(string)
User Model: contains: id(pkey), uid(string), current_question(int), name(string)
I created both of the above with scaffold so they have all the default routes, controller actions, etc...
I created a gateway controller and set it to be my default page through routes.rb
The idea is, user browses to localhost:3000/?uid="whatever" and the index page displays the current question (Question.find_by_question_number(#user.current_question))
User enters answer in a form, which POSTs it to an action. In my first draft, this called an action in the gateway controller which checked if the answer was correct.
Now, I am trying to take vadim's advice in my last question and keep the user login in user and the question logic in question. So now my form POSTs to the users controller.
Here's where I get mixed up. The logic code shouldn't be in the controller, right? So I call a method in the model, passing it stuff like the user's answer and the question id since I can't read the session in the model. This works fine, I can now take care of the logic in the user model - so now the user model calls a method in the question model to actually check the answer. That means I have to instantiate my question object using the ID I passed, then call another method, passing (again!) the answer. Etc...etc...
See what I mean? I definitely understand the value of MVC in theory, but whenever I try and implement it I wind up with a mess like this. It this correct, and it just seems like overcomplicating things because my program is so simple?
Can someone walk me through how you would split the logic up? You don't need to post actual code, just what you would put where, like:
Gateway Controller:
-display question to user
-take answer and pass to XXX controller
XXX controller:
-call method Foo in XXX model, passing X and Y
The basic flow should be, user is shown a question, user answers question, answer is compared to the correct answer in the question model, message is returned based on result, and it answer was correct, user's current_question is incremented.
Thanks so much for the help, I have books and Google and have been reading my a$$ off, just lost in the sauce here. This is my first attempt to venture outside the safety of pre-written example code, so please be gentle!!
Thanks!!
In most cases in a Q&A app, you would have a Question Model, an Answer Model, and a User model. Your actions are:
displaying answers (the show method for the Questions controller)
Showing the new answer form
Posting to the create method on the Answers controller.
Some code:
class Question
has_many :answers
end
class Answer
belongs_to :question
has_many :users
validates_presence_of :user
validates_presence_of :question
validates_uniqueness_of :question_id, :scope => :user_id
end
class User
has_many :answers
end
Routes
resources :questions do
resources :answers
end
answers_controller
class AnswersController < ApplicationController
def create
#answer = Answer.new(params[:answer])
#answer.user = current_user
#answer.question = Question.find(params[:question_id])
if #answer.save
flash[:success] = "Saved!"
redirect_top #answer.question
else
render :new
end
end
end
The basic flow should be:
a method in the controller selects the question and displays a view with a form in it
the users submits this form
this is a POST to the controller
in the controller you check the result and display it to the user in another/the same view.
Now to the model. You can put methods in there that check certain things. Still, the controller handles the work, it calls the method and processes the results in the controller.