Referencing Table Entries in Rails - ruby-on-rails

I'm working on a project in rails where I have a database of products, and I'm looking to use forms to manipulate them.
However, I'm having a great deal of difficulty figuring out how to do this.
I tried to use the standard:
<%= form_for(#product) %>
...
<% end %>
to send an entry to my product controller, but that returns a nil/empty field error.
My method to remove products from inventory is below. I strongly suspect this to be highly incorrect, but I have yet to figure out how to get far enough to even receive an error with that:
def ship
#products.where(#products.code = params[:code]).quantity -= 1
end
If there is any way that anybody could guide me in the right direction, I would be highly grateful. I've been trying to figure this out for a while now.

Try like this, let me know what else do you need.
def ship
#product = Product.find_by(code: params[:code]) # or you can use :code => params[:code], but not an equal sign
#product.quantity -= 1
if #product.save
respond_to do |format|
format.html {}
format.json {}
end
end
end
where returns an array or objects.
You after negating the quantity you should save it or update product on the go
You should respond back or else you'll get template missing error, OR you can redirect to some page

Related

how to copy a object with rails

I would like to use deep_dup to duplicate the parent and child objects and save as a new record using rails 5. I have been searching to see some example code to implement it on my project but so far i could not find anything.
so far i did this but it does not work.
def copy
#product = Product.find(params[:id])
#newproduct = #product.clone :include => :productlines
success = #newproduct.save
if success && #newproduct.errors.empty?
redirect_to (edit_product_path(#newproduct))
flash[:danger] = "Procut copied"
else
flash[:danger] = "Procut cannot be copied"
end
end
<%= link_to "Clone", copy_product_path(#product), :method => :put %>
the gem deep_cloneable is available but i could not understand the documantation, no idea how to use it.
Can anyone just show me a way to implement this on my project?
Would be really appreciated if someone can help.
It looks like you'll need to use the deep_clone method to include the productlines association (Also make sure it's not supposed to be product_lines).
#new_product = #product.deep_clone include: :productlines

Inserting into a Postgres Array from Rails

I am very new to Rails, I want to be able to insert names into an array attached to my user.
I added an empty array called 'subscribed_tasks' to my 'schema.rb'
And I wondered how I can push data into that array.
My first attempt was:
Having '= link_to "Subscribe", subscribe_task_path, class: "btn btn-default"' in my show.haml and then having this within my route.rb:
resources :tasks do
member do
get :subscribe
end
end
& then adding this to my Tasks_Controller:
def subscribe
#user = current_user
#user.subscribed_tasks << #task.title
redirect_to #task, notice: "Subscribed to "+ #task.title
end
The problems I'm facing are:
How do I pass the task they're subscribing to's parameters to the controller so then the correct data can be pushed into the array. Also, I don't think I'm finding the array correctly.
All in all, what I'm programming is a mess, am I missing something fundamental about Rails and is there an entirely better way to solve this problem?

Rails link_to new with parameters not saving parameters

So, I have two objects, Floor, which has_many FloorMonsters, and FloorMonster which belongs_to Floor.
I have a link_to new_floor_monster_path in the show page on Floor, and I intend to pass the Floor id as a parameter. The link_to currently looks like this:
= link_to "Add a Monster to this Floor", new_floor_monster_path(floor_id: #floor.id)
In the controller for FloorMonster, the new method is this:
def new
#floor_monster = FloorMonster.new(floor_id: params[:floor_id])
respond_to do |format|
format.html # new.html.erb
format.json { render json: #floor_monster }
end
end
When I click the link, the URL shows the parameters:
http://.../floor_monsters/new?floor_id=4
But when I save, the floor_id is nil and the program crashes. What am I missing here? I've tracked down sources that do exactly what I did, but I am getting no succes. The accepted answer here and this blog post are doing exactly what I am doing as far as I can tell, but they managed to get it to work.
I assume that you are exposing the new FloorMonster in a form to allow setting other attributes and then saving it. In order to pass the floor_id attribute along to the create action, you will need to add a field to your form for it. If you don't want it to be seen or to be editable, use a hidden_field. In your form, add:
= f.hidden_field :floor_id

Display duplicate record when uniquenss validation fails?

When my Rails uniqueness validation fails, I would like to display the duplicate record using a partial in the form view when the user is sent back.
How do I accomplish this? Right now I only know how to alter the error message that is displayed.
There isn't a built-in way to do this in Rails, and there's probably a dozen ways to do it. Here's one approach, while not elegant, should get you what you want.
1) Check if there's a uniqueness validation error. Unfortunately there isn't an easy way to do this, so you'll have to check the name of the error in your controller. If there's an error, search for the existing record, and store it in an instance variable:
def create
#new_model = Model.new(params[:model])
if #new_model.save
# success...
else
if #new_model.errors[:field].index("has already been taken")
#existing_record = Model.where(field: model.field).first
end
render :new
end
end
2) Render the existing record in a partial in your view
<%= render partial: 'partial_name', locals: {existing_record: #existing_record} %>

How to require a value is entered in a search form

I built a basic search form that queries one column in one table of my app. I followed episode 37 Railscast: http://railscasts.com/episodes/37-simple-search-form. Note I just posted another search related question, but it's on a completely different issue.
In my app, the search queries the zip code column of my profile table, and returns a list of profiles that contain the right zip code.
Here's my problem. Currently, when a user leaves the input blank and hits the submit button, the search displays all profiles on the site. I don't want this to happen. If the field is blank, I don't want the search to go through. I'd like to either do a flash notice or throw an error, explaining that the user needs to enter a zip code to proceed.
Here's my setup:
PROFILES CONTROLLER
def index
#profiles = Profile.search(params[:search])
end
PROFILE MODEL
def self.search(search)
if search
find(:all, :conditions => ['zip LIKE ?', "%#{search}%"])
else
find(:all)
end
end
PROFILE/INDEX.HTML.ERB
<% form_tag ('/profiles', :method => :get) do %>
<%= text_field_tag :search, params[:search], :maxlength => 5 %>
<%= submit_tag "Go", :name => nil %>
<% end %>
Thanks!
def index
#profiles = Profile.search(params[:search]) unless params[:search].blank?
end
You probably don't want to throw an error if the search field is blank, because the user will see that error the first time he comes to the index page. To properly handle that type of error message, you'll need to do one of several things.
Split the form generation and the actual search into two separate actions. In a RESTful app, this would typically be a new and create action. (new for the form, create for the actual search).
Add a check for a post, as opposed to a get. Only attempt the search, or throw the error, if it's a post. Otherwise, just show the form. You'll typically see this in older Rails examples (like pre- 2.0 tutorials).
Add some hidden field that says "Hey, I'm submitting a search." This is the same idea as checking for a post, but would still work if you wanted all gets for some reason.
My choice would be the first one. It'd roughly look like this.
def new
end
def create
if params[:search].blank?
flash.now[:error] = "Please enter a zip code to search for."
render :new
else
#profiles = Profile.search(params[:search])
render :show
end
end
In your views, new.html.erb (or .haml or whatever) would contain your search form and show.html.erb would contain your search results. Usually there's a search form partial that both of them would share.
You just need to check if it's blank before you do your search.
def index
if params[:search].blank?
flash[:error] = "Doh! You forgot the zip code."
else
#profiles = Profile.search(params[:search])
end
end
If returning all results is never a use case then you might want to remove that code from your model as well. Also if you're checking for a blank search in more than this one controller action you should move the logic into the model.
I actually found an answer to this that doesn't require me to make any changes to my current setup.
If you look in the search model above, which I copied from the Railscast, you see that Ryan included wildcards on both sides of the search query:
find(:all, :conditions => ['zip LIKE ?', "%#{search}%"])
I'm not familiar with sql syntax at all, so I missed that. It was those wildcards that was letting through the blank search and returning all results in the database. When I removed the "%'s" from that sql statement, the blank search now returns the same result as a search where we don't have a record matching the zip queried, which is the result I wanted.
Just wanted to share so others might catch this in the future.

Resources