Rails little loop error - ruby-on-rails

I have a job model which has_many offers, User could accept or reject these offers, but how can I do that when User accept an offer, the more offers cannot be created? I try to do this in that way, it works but it duplicates input boxes. So what I'm doing wrong or how can I do it in another way?
#show.html.haml
- if #job.offers.blank?
= render 'offers/form'
- #job.offers.each do |f|
- if #job.offers.find(f).status == false || #job.offers.find(f).status == nil
= render 'offers/form'
- else
cannot do that
#offers/_form.html.haml
= simple_form_for([#job, #job.offers.build]) do |f|
= f.input :pirce_offer
= f.button :submit

You need to equate yourself with scoping in programming; whenever you create a "block" in Ruby, it's essentially like invoking a function, with its own local scope:
- #job.offers.each do |f|
- if f.status == false || f.status == nil
= render 'offers/form'
- else
cannot do that
As an aside to this, I don't get the purpose of calling a form that builds a new offer?
You're looping through an offer of a job, using the status conditional to determine whether the user should create an offer or not.... yet, surely if the offer exists, the user has already posted an offer?
Also, you're using a completely fresh set of data for the form:
= simple_form_for([#job, #job.offers.build]) do |f|
= f.input :pirce_offer
= f.button :submit
Shouldn't you be using something like the following:
= simple_form_for([#job, f]) do |f|
= f.input :pirce_offer
= f.button :submit
Okay I get it -- you have a sort of "auction" system where offers are accepted/declined. This would give you the ability to make a new offer if the previous was rejected........... it's still sketchy as hell.
how can I do that when User accept an offer, the more offers cannot be created
You'll need to use some validation in your view and model.
Something like this:
#app/models/offer.rb
class Offer < ActiveRecord::Base
validates :user_id, uniqueness: { scope: :job, message: "Only one offer per job" }
end
I could create a much more complete answer if you describe how you want the jobs/offers to work.

Related

How to set field automatically in Rails

I have a simple feedback form to allow the Users send the feedback. Controller for it:
class FeedbacksController < ApplicationController
expose(:feedback, attributes: :feedback_params)
def create
ApplicationMailer.customer_feedback(feedback).deliver_now if feedback.save
respond_with(feedback, location: root_path)
end
private
def feedback_params
params.require(:feedback).permit(:email, :message, :name, :phone)
end
end
Here I'm using expose gem.
And the view for it:
= simple_form_for(feedback, url: feedback_path) do |f|
legend
= t(".any_questions")
.form-inputs
= f.input :name
= f.input :email
= f.input :phone
= f.input :message, as: :text
.form-actions
= f.button :submit, t(".submit")
I want the next: to check somewhere if current user present(logged in to application) If yes = then set the email field using user.email (when he visit the feedback form -> email should be already filled in. If user not logged in to site then this field should be empty. Where should I put this logic? Thanks!
The simple form documentation explains how simple form is very easy to customize according to your needs. Assuming you are using devise for user authentication (if you're not, simple_form is designed to work with devise so you should check it out), then you can user current_user to access the currently logged in user.
I think simple_form's input_html would help you here:
= f.input :email, input_html: { value: "#{current_user.email if current_user}"}

ActionMailer delivering email even if checkbox is not checked

I have a checkbox (:notify) for Post, and I want to send emails when I create a new post, only if it is checked. However, ActionMailer is delivering the emails even if it is not checked. Here is the code snippet:
if #post.save
unless params[:post][:notify].nil?
PostMailer.notify_new(#post).deliver
end
.........
..............
Form:
= bootstrap_form_for #post, remote: true do |f|
= f.text_area :body
= f.check_box :notify, label: ""
= f.submit "Send", class: "button"
How do I fix it such that emails are delivered only when the notify checkbox is checked?
Thanks!
You should move all this into the Post model...
class Post
attr_accessor_with_default :notify, false
after_create :deliver, :if => Proc.new {|p| p.notify}
def deliver
PostMailer.notify_new(self).deliver
end
end
Then, notify will be treated as a boolean. Don't forget to permit :notify attribute in your controller.
I'd double check that params[:post][:notify] is the correct parameter to be looking for. If those parameters are always showing up, I'd look at your view logic. Also, if you're going to use this method of checking, change you condition to an if. For example:
if params[:post][:notify].present?
PostMailer.notify_new(#post).deliver
end

Submitting multiple forms in Rails

I have to submit multiple forms, I followed the advice of this post: How to submit multiple, duplicate forms from same page in Rails - preferably with one button
Note I'm still quite new to Rails/programming and some of my ways of doing things might not be ideal.
Here's my view:
= form_tag ([#event, #registration]) do
- x.times do
= render 'multi_form'
= submit_tag "Submit registrations"
The form (note that there are more fields):
- hidden_field_tag :event_id, :value => #event.id
.control-group
= label_tag :title
.controls
= select("registrations[][title]", :registration, Registration::TITLE)
.control-group
= label_tag :first_name
.controls
= text_field_tag "registrations[][first_name]"
.control-group
= label_tag :last_name
.controls
= text_field_tag "registrations[][last_name]"
.control-group
= label_tag :email
.controls
= text_field_tag "registrations[][email]"
The controller:
def create
array_number = 0
x.times do
#registration = Registration.new(params[:registrations][array_number])
#registration.save
UserMailer.registration_user_notify(#event, #registration).deliver
array_number = array_number + 1
end
respond_to do |format|
format.html {redirect_to thank_you_event_registrations_path(#event)}
end
end
When submitting it seems, to an extent, to be doing the right thing, for one it fires off an email to x unique email addresses, which makes me think that #registration contains the correct details in each loop - it's not saving to the database however. I can see that all the params are there in the log file, except that :title seems to be doing something bad (see below: but I'll focus on that later), the main thing I want it to do now is run though each array and save it as a new entry.
The log:
Parameters: {"utf8"=>"รข", "authenticity_token"=>"BQXm5fngW27z/3Wxy9qEzu6D8/g9YQIfBL+mFKVplgE=", "event_id"=>"7", "registrations"=>[{"title"=>{"registration"=>"Mrs"}, "first_name"=>"Person", "last_name"=>"One", "email"=>"charl#privatelabel.co.za"...
I'm hoping the info I provided is enough, any advice will be appreciated.
Thanks!
EDIT:
#iblue
It did the trick! It was a validation error and it's saving everything into different rows. Thank you very much!
One more thing if I may, any idea how the :title form part should be formatted in order to return paramater:
"title"=>"Mrs",
as opposed to:
"registrations"=>[{"title"=>{"registration"=>"Mrs"},
Thanks again!
You are not checking if #registration.save actually saves the record. It can return true or false. I guess it just silently fails.
If you use #registration.save!, it wile raise an exception when anything goes wrong. I guess there is some kind of validation error there.

Accept Rails model attribute only if it was previously blank

I have a Rails model (persisted with Mongoid) that can be collaboratively edited by any registered user. However, I want to allow editing any particular attribute only if it was previously blank or nil.
For example, say someone created an object, and set its title attribute to "Test Product". Then another user comes along and wants to add a value for price, which until now has been nil.
What's the best way to do this, while locking an attribute that has previously been entered?
Look into the ActiveRecord::Dirty module for some nice utility methods you can use to do something like this:
NON_UPDATABLE_ATTRIBUTES = [:name, :title, :price]
before_validation :check_for_previously_set_attributes
private
def check_for_previously_set_attributes
NON_UPDATABLE_ATTRIBUTES.each do |att|
att = att.to_s
# changes[att] will be an array of [prev_value, new_value] if the attribute has been changed
errors.add(att, "cannot be updated because it has previously been set") if changes[att] && changes[att].first.present?
end
end
The easiest way, i think, is by checking for it in the form itself.
Just say add :disabled => true to the input field if the person cannot edit it.
<% if #my_object.name %>
<%= f.text_field :name, :disabled => true %>
<% else %>
<%= f.text_field :name, :disabled => true %>
<% end %>
(i think there is a prettier way to write this code)
But by using this the user has a visual feed back that he can't do something, it is always better to not allor something than to give an error message

Retain Search Form Data Ruby On Rails

Trying to build a search on my homepage with simple_form (Pretty much same as formtastic). The search works fine and im getting my results but after submission I want to retain the vales with what the user submitted.
I am using a namespace for my form so how can I retain the data for the form. Here is some code which may help.
Controller
def index
#results = Property.search(params[:search])
end
View
%h1 Search Form
= simple_form_for(:search) do |f|
= f.input :location, :as => :select, :collection => Location.all.asc(:name)
= f.input :type, :collection => PropertyType.all.asc(:name)
= f.input :bedrooms, :collection => 1..10,
%p.box
= f.button :submit
-if #results
%h1 Search Results
.results
- #results.each do |property|
.result
%h1= property.title
Within the Index controller I have tried all sorts of things ie
#search = params[:search]
But each time I try something the search breaks.
What am I doing wrong ?
Hope you can advise
One approach is to do as Xavier Holt suggested, and pass in values to each input. The simpleform doco suggests:
= f.input :remember_me, :input_html => { :value => '1' }
The other approach is to have simpleform do it for you. SimpleForm will automatically populate the fields with values if you give it something like an activerecord object.
In this case, that means creating a model object:
class PropertySearchCriteria
attr_accessor :location, :type, :bedrooms
def initialize(options)
self.location = options[:location]
self.type = options[:bedrooms]
self.bedrooms = options[:bedrooms]
end
end
Then, change your controller:
def index
#property_search_criteria = PropertySearchCriteria.new(params[:search])
#results = Property.search(#property_search_criteria)
end
(you'll have to change the Property.search method as well)
Then, change your simple_form_for:
= simple_form_for(:search, #property_search_criteria) do |f|
And if you do all that, and get the stars to align just right, then simpleform will pre-populate the form fields all by itself. You may have to add some stuff to PropertySearchCriteria to get simpleform to be properly happy.
This is a lot of stuffing around just to get the values showing up, but it'll keep you sane if you need to add validations.
I'm doing something similar in the app I'm working on (I'm not using formtastic, but this should be at least very close to something that works for you). I got around it by making sure #search was a hash in the controller:
#search = params[:search] || {}
And then using #search[:key] as the :value option in all my search inputs (There's a chance you'll need to set #search.default = '' to get this working):
<%= text_field_tag :name, :value => #search[:name] %>
And that's all it took. As my app is getting more complicated and AJAXy, I've been thinking of moving the search parameters into the session information, which you might want to do now to stay ahead, but if you're just looking for a simple solution, this worked great for me.
Hope this helps!
you can try storing your parameters in session like so:
def index
#results = Property.search(params[:search])
store_search
end
def store_search
session[:search] = params[:search]
end
just be sure when you are done with the parameters that you clean them up
...
clear_search if session[:search]
def clear_search
session[:search] = nil
end

Resources