I have a checkout button on my product page show view which accepts the offer. Each offer belongs_to a user. I don't want the user who created the offer to be able to accept it themselves so if it is the current user on the page I want to hide the button. I can't figure out why this code doesn't work:
<% unless current_user.id == #offer.sender_id %> #sender_id is a foreign key in the offer model that makes each offer belong_to a user.
<div id="accept_offer">
<%= button_to 'Accept Offer', etc %>
</div>
<% end %>
current_user is a devise gem method I believe.
Any help appreciated.
your code seems correct, you maybe need to look into your Offer.sender_id attribute in the model to see if it contains the right user id (of the creator of the offer). You could check that by creating a new offer throught your application (in the browser) then, in the console you type:
Offer.last.sender_id
And check if it corresponds to your current_user id
Just saw the error and got the reason.
You tried the page without sign in so unless current_user works, this means you have not signed in. Your original code doesn't considered this case.
Generally you should see an error as current_user is not defined but you may have disabled that.
Two ways to fix:
Change current_user, assign an object in any case
class ApplicationController
def current_user
super || User.new
end
end
Change the logic
<% if current_user && current_user != #obj.sender %>
# Button code
# Only signed in user with different id can see it
Related
I am struggling with a college project course, and I have been stuck with this error for weeks now, despite the suggestions provided by colleagues and tutors.
In my create method for a given table. I am trying to have the page containing the forms for new record entries redirect back to the index page after saving. Instead, I get redirected to this error instead, highlighting #courier=Courier.new(courier_new_path) with the error stating that it is not a hash, and would not redirect me back into index. However, when manually searching the index, I see that the data string would indeed get updated.
I have tried renaming the path label, but Rubymine prompt suggestions appear limited, and any further deviation would cause a different error
The following is the create method in the controller page (courier_controller.rb):
def create
#courier=Courier.new(params.require(:courier).permit(:courier_name,:courier_email))
#courier.save
redirect_to courier_path(#courier)
#courier=Courier.new(courier_new_path)
if #courier.save
redirect_to(:controller=>'courier' ,:action=>'index')
else
render('new')
end
end
Here is the code for the form page (courier/new/html.erb):
<h1>Courier#new</h1>
<p>Find me in app/views/courier/new.html.erb</p>
<%= form_with scope: :courier, :url => {:action => 'create'}, local: true do |f| %>
<p>
<%= f.label :courier_name %><br/>
<%= f.text_field :courier_name %>
</p>
<p>
<%= f.label :courier_email %><br/>
<%= f.text_field :courier_email %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
I have tried renaming #courier as Courier.new(courier_create_path) or Courier.nww(courier_path), I have tried looking for arguments using a hash form, but none seemed equivocal nor translatable as a solution to my problem.
Any suggestions would help. This is part of a college project, and as a multimedia student not as savvy in programming compared to fellow peers, I would highly appreciate suggestions that I can try out.
Many thanks in advance.
Has anyone tried to explain what is actually going on in your create method? I've added comments after each line to say what that line is doing.
def create
#courier=Courier.new(params.require(:courier).permit(:courier_name,:courier_email))
# use the params to build a new courier record (the permit part is usually in a separate method that other methods can access but it works this way)
#courier.save
# Save the new courier record to the database
redirect_to courier_path(#courier)
# Send the user back to the "show" page of the courier record (not index!)
#courier=Courier.new(courier_new_path)
# this makes no sense, you are trying to create a new courier object using a path method
# Basically you are saying: #courier = Courier.new('/courier/new')
if #courier.save
#you are trying to save this record that will fail because you can't create a courier by passing it a url
redirect_to(:controller=>'courier' ,:action=>'index')
#send the user to the index page of the courier views.
else
render('new')
#something went wrong so go back to the new courier form.
end
end
When your program gets to line 4 redirect_to courier_path(#courier) it is going to exit the create method and send the user to http://my_app:3000/couriers/1 where the number 1 would be the ID in the database of the record you just created. This would relate to the file in your app in app/views/couriers/show.html.erb. It sounds like you want to get to http://my_app:3000/couriers which presents the user with the file app/views/couriers/index.html.erb Not sure why you are doing anything after that line.
Also it is unclear what error you are getting. You need to look at your webserver console, the place where you run "rails s" that shows all the communications between the browser and your app. find the stack trace that starts with the actual error, and add that to your question above (don't paste it in a comment, it will be too long and impossible to read).
I think you just need:
def create
#courier=Courier.new(params.require(:courier).permit(:courier_name,:courier_email))
if #courier.save
redirect_to #courier #if you want to redirect to their 'show" page
else
render('new')
#something went wrong so go back to the new courier form.
end
end
What might be confusing to a new programmer is that Rails is doing so much "magic" behind the scenes it gets very confusing if you don't already know the underlying concepts happening behind the scenes. You are saying redirect_to(:controller=>'courier' ,:action=>'index') which specifically says "go to the index page of the couriers" but you can say redirect_to #courier and it will assume that you want to go to the page that shows the record of the courier you just created. If you really want to go the table that shows all of the couriers you would replace that with redirect_to :couriers The symbol :couriers tells it to go to the index method of the couriers controller.
So I tried to add this code to first the views and then the controller. It didn't work and gave me an error : undefined method save for 4:Fixnum.
Code:
<% unless location.user.interests.blank? %>
<% #merged_array = location.user.interests.split(',').uniq +
current_user.interests.split(',').uniq %>
<% location.score = #merged_array.length - #merged_array.uniq.length %>
<% location.score.save %>
<% else %>
<% location.score = 0 %>
<% location.score.save %>
<% end %>
But then I removed it from both controller and views..... Now the index page isn't showing the locations at all I checked and the show page is working and records still exist
This is really not the way it should work.
Just read a bit about the MVC pattern - it's worth it!
You shouldn't check in production credentials into your repository - especially not if it is public.
Checkout https://github.com/bkeepers/dotenv to keep your keys and passwords privately.
You should change your passwords immediately!
The error you got is because location.score is an integer not an object - location.save! will save the object with its new score.
PS: You don't want to be the guy who let production creds into the guide for new employees. https://www.reddit.com/r/cscareerquestions/comments/6ez8ag/accidentally_destroyed_production_database_on/
Beside of that, Keep going!
Sorry forgot that it only displays locations within a 50 mile radius and i was travelling...... Silly me :)
I had a model named b_page I wanted to create another column , so I ran a migration:
rails g migration add_status_to_b_page status:string
so migration was successful. Users should be able to update their status so I put this on the _form.html.erb:
<div class="field">
<%= f.label :status %><br>
<%= f.text_field :status %>
</div>
was successful but then i added it to the show.html.erb
<%= #b_page.status %>
but everytime i make a new b_page or edit the current one I dont see it on show.html.erb
Without seeing your code I guess you have to whitelist the new parameter (status) in your BPageController (at the very bottom, in something like def bh_pages_params).
You can check the logs whether the parameter that comes into your controller (via the form) actually arrives at the data (ActiveRecord Model), this whitelisting approach (called Strong Parameters) is in place to safe guard your data.
thx I fixed my problem I forgot to add status in
params.require(:b_page).permit(:Bpage_name, :banner_img, :profile_img, :status) in my controller
I want to add a column in a mysql table from a controller. The user completes a form, and when he sends it, it creates a new column (not row) with the information in the form. How can I do this?
it create new column
Don't.
Your database is sacrosanct, dynamically altering it is like dynamically changing a car based on some user's request. A car has four wheels, engine and seats. You can change the colour, tyres, etc... but not the fundamentals.
It's the same with web apps - you should not be changing the fundamental structure of your system. Sure, you'll be able to change various aspects of it (User Avatar etc), but the underlying basis of the system (the db schema) should be kept above any changes.
What you should be doing is maintaining your database fidelity through a tight set of Models, allowing you to create a dynamic experience around the data you've been provided.
For example...
The user complete a form and when he send it, it create new column
A better way to explain this will be to use a user story.
I'll surmise the following in your case:
A user wants to add a new project to his portfolio. He fills out the form to explain what the project will be and adds a number of extra fields specific for that project.
I think you're asking about the "extra fields" part...
You have to remember Rails is built on top of a relational database:
This means that you have the flexibility provided by your models to grant your users the capacity to add and manipulate as many pieces of associated data as they need.
The data they add to the system can have any name & any structure, so long as you provide that functionality within the system itself...
#app/models/user.rb
class User < ActiveRecord::Base
has_many :projects
has_many :specialized_fields, through: :projects
end
#app/models/project.rb
class Project < ActiveRecord::Base
belongs_to :user
belongs_to :specialized_field
accepts_nested_attributes_for :specialized_field
end
#app/models/specialized_field.rb
class SpecializedField < ActiveRecord::Base
has_many :projects
has_many :users, through: :projects
end
According to my example above,
User can make a Project
Project can have specialized fields (above the standard fields)
User can add specialized fields to the model
Thus you can do the following:
#app/controllers/projects_controller.rb
class ProjectsController < ApplicationController
def new
#project = current_user.projects.new #-> assuming you're using Devise
#specialized_field = #project.build_specialized_field
end
def create
#project = Project.save project_params
#project.save
end
private
def project_params
params.require(:project).permit(:name, :start_time, :end_time, specialized_field_attributes: [:name, :value])
end
end
The form could be as follows:
#app/views/projects/new.html.erb
<%= form_for #project do |f| %>
<%= f.text_field :name %>
<%= f.fields_for :specialized_field do |s| %>
<%= s.text_field :name %>
<%= s.text_field :value %>
<% end %>
<%= f.submit %>
<% end %>
Why would you like to add new columns to the database via the controller? This shouldn't be the case - and in general I couldnt' think of a single reason why this should ever be required. It sounds unconventional and against design principles.
If you add more information of what is required and what you are tyring to do I am pretty sure we can work out an alternative solution. (I bet what you are trying to do can be achieved with a many-to-many relationship, or similar, somehow). Post more information and see what we can do.
But as answer and solution I'd say it shouldn't be required.
Why do you want to do this? Database design is part of the application development, so you are the one deciding the rows. When the user inputs data, there are a gazillion things that can go wrong (hacks, invalid values...), which can affect your entire database. It's not worth risking that.
If you want a flexible schema, you can store hashes in a specific field.
For example you have a extra_data field which is a hash. Then in your form you can have to inputs, input_name and input_value which will go to the hash. This way you will have more flexible values for the same column and you don't need to change your database schema.
I've been struggling for a while on this (been reading a lot of the ruby on rail guides to try and understand this), but I'm not sure how user inputs work.
I am trying to search for a restaurant in my database with a list of fields the user specifies (cuisine, zipcode, review score). I have created a html.erb page that has the options for all of these.
Here is my controller.
class WelcomeController < ApplicationController
def home
#my_search = Restaurant.joins(:inspection).where(cuisine: c, zipcode: z, totalscore: 1..h)
end
My models for restaurant and inspection also have relations between them (the foreign keys).
How would you go about letting the user give inputs for c (cuisine), z (zipcode) and 1..h (score range)?
I know that people have answered this question in the past, but I think I need a concrete example to actually understand how to do this. As in, what would you put in the html.erb code so that when an option is selected, that value is passed to the method?
Thank you
First you need to create a form in the view. The simplest way to do this is with form_tag:
<%= form_tag(home_path) do %>
<%= text_field_tag 'cuisine' %>
...other inputs
<% end %>
Next, make sure you have a route defined for your controller action in config/routes.rb
post 'home' => 'welcome#home'
Most likely your routes will look different but this is the bare minimum you need.
And in your controller you can access the submitted data using the params object
class WelcomeController < ApplicationController
def home
#restaurants = Restaurant.joins(:inspection).where(
cuisine: params[:cuisine],
# ...other params
)
end
end