Rails 3: displaying error full messages in flash message - ruby-on-rails-3

Here is my CreditCard model:
validate :name_is_split_properly
private
def name_is_split_properly
if last_name.blank?
self.errors[:base] << "Last Name is required"
end
end
When a user submits a CreditCard, the validation takes place and this is how I am setting the error(s) in a flash message:
flash[:error] = current_order.errors.full_messages.join('\n')
redirect_to new_order_path(:client_id => params[:client_id])
But for some reason when the flash[error] is displayed in the view, this is how its displayed: Credit card base Last Name is required... how do I get rid of the key?

Try errors.add(:base, "Last Name is required")

Related

How to return the correct fields in Rails API?

I have these two tables - User, Accounts.
User contains an authentication key,
Accounts contains the list of accounts.
I am trying to get the list of accounts for the user if the authentication key is correct.
So in the controller I have -
def show
#user = User.where(authentication_token: params[:authentication_token])
render json: #user.as_json(
only: [:email, :id, :authentication_token]
),
status: :created
end
This would just return the user details. How can i edit it so it first checks if the user exists with that Authentication_token, and then uses the UserID, in the accounts table to get the list of accounts ?
Your question is a little unclear: What is the desired behaviour if the authentication_token is not correct? Raise an exception? Redirect somewhere? Display a flash message? ...
You could, for example, do something like this:
def show
if authenticated_user
render json: authenticated_user.accounts.as_json(
only: [:id, :foo, :bar]
),
status: :ok
else
render json: { errors: { authentication_token: 'Invalid' } },
status: :unauthorized
end
end
private
def authenticated_user
#authenticated_user ||= User.find_by(
authentication_token: params[:authentication_token]
)
end

Process form data before creating table entry

Backstory: I'm building a site that takes in a Soundcloud URL as part of a post. Currently, I store the link they provide and, when a user loads their feed view, I retrieve the associated image / title / favorite count etc. via my post_helper. I have quickly come to realize that this is not scalable and is hurting load times.
So, what I think I should do (feel free to tell me that there is a better way), is to retrieve the SC/YT metadata on form submit and store it along with the other post data (id, user, content etc.) in the posts' table entry. How would I go about calling the helper methods to retrieve such on form submit and include the metadata in the submitted params?
post_helper.rb excerpt:
def soundcloud_info(soundcloud_url, type)
begin
resolve = scClient.get('/resolve', :url => soundcloud_url)
track_info = scClient.get("/tracks/#{resolve.id}")
rescue Soundcloud::ResponseError => e
%Q{ Error: #{e.message}, Status Code: #{e.response.code} }
end
if type == "title"
%Q{#{track_info['title']}}
elsif type == "image"
%Q{#{track_info['artwork_url']}}
elsif type == "favCount"
%Q{Favorite count: #{track_info['favoritings_count']}}
end
end
post_controler.rb excerpt:
def create
#post = current_user.posts.build(params[:post])
if #post.save
flash[:success] = "Your post was successful!"
redirect_to root_url
else
#feed_items = current_user.feed.paginate(page: params[:page])
render 'static_pages/home'
end
end
So apparently it's pretty straight forward... all I need to do is modify the parameters in the controller before I call #post = current_user.posts.build(params[:post]). My issue was that I was trying to do so in the helper.
I haven't quite adapted the whole thing to get all my required fields, but here's an example of how I have adapted the create method to pull the api URL out if someone submits SoundCloud's embed iframe.
micropost_controller.rb excerpt:
def create
#url = params[:post][:link_html]
if #url[/^.*src="(https|http):\/\/w.soundcloud.com\/player\/\?url=(.*)">/]
params[:post][:link_html] = CGI::unescape($2)
end
#post = current_user.posts.build(params[:post])
if #post.save
flash[:success] = "Your post was successful!"
redirect_to root_url
else
#feed_items = current_user.feed.paginate(page: params[:page])
render 'static_pages/home'
end
end

Destroy method failing in controller test

I'm experiencing a bizarre issue testing a destroy method. I'm using FactoryGirl and Rspec.
Here's a look at the method in question. As you can see, it doesn't actually destroy the dealer, just set it and it's dependent object's active attributes to false:
dealers_controller.rb
def destroy
#dealer = Dealer.find(params[:id])
#dealer.active = false
#dealer.save!
#dealer.leads.each { |lead|
lead.active = false
lead.save!
}
#dealer.users.each { |user|
user.active = false
user.save!
}
redirect_to dealers_path
end
When I run this method in the application it does exactly what it should do. Now, on to the test.
dealers_controller_spec.rb
describe "#destroy" do
context "when deleting a valid record" do
let(:dealer) { FactoryGirl.create(:dealer_with_stuff) }
before do
#user = FactoryGirl.build(:admin_user)
login_user
delete :destroy, :id => dealer.id
end
it { should assign_to(:dealer).with(dealer) }
it { should redirect_to(dealers_path) }
it { should set_the_flash }
it "is no longer active" do
dealer.active.should be_false
end
it "has no active users" do
dealer.users.each do |user|
user.active.should be_false
end
end
it "has no active leads" do
dealer.leads.each do |lead|
lead.active.should be_false
end
end
end
end
The first 3 tests pass, but the last 3 all fail (weirdly, the user.active.should be_false test only fails if I put a sleep(10) after delete :destroy up above, but let's not get into that issue now). So when I check the test log, it goes through the entire destroy process, but then does a ROLLBACK, so for some reason it doesn't save any of the records; but it doesn't give me any more information than that.
Does anyone have any thoughts on this? I've tried everything I can possibly think of.
What if you reload the dealer? The dealer in your tests is different from the #dealer object in the controller (ActiveRecord doesn't do identity maps).
before do
#user = FactoryGirl.build(:admin_user)
login_user
delete :destroy, :id => dealer.id
dealer.reload # << add this
end

validates_acceptance_of still saves the record

I am using ruby 1.9.2-p180, rails 3.0.7. I have used validates_acceptance_of since the user has to agree to our terms and conditions. We don't have a column for this, but I understand that "If the database column does not exist, the terms_of_service attribute is entirely virtual. " from http://ar.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#M000082
Anyway, I double checked this by smoke testing the app manually and I see from the logs that the record is still inserted into the db, which is weird because upon submitting the form, I am redirected back to the form with the error: "Must agree to terms and conditions"(which made me think it worked before)
Am I doing something wrong here?
_form.haml:
%label.checkbox-label{:for => "operator_terms_and_conditions"}
= f.check_box :terms_and_conditions
I agree to
= link_to "Terms and Conditions", operator_terms_path, :target => "_blank"
operators_controller:
def create
user_params = params[:operator][:user]
user_params.merge!(:login => user_params[:email])
#password = params[:operator][:user][:password]
Operator.transaction do # don't save User if operator is invalid
#operator = Operator.create(params[:operator])
end
respond_to do |format|
unless #operator.new_record?
UserMailer.operator_confirmation_email(#operator, #password).deliver
UserMailer.operator_registration_admin_notification_email(#operator).deliver
UserSession.create(#operator.user)
format.html {redirect_to new_operator_aircraft_path}
else
format.html { render :action => "new" }
end
end
end
and in the model:
validates_acceptance_of :terms_and_conditions
Found the answer. The problem was not with validates_acceptance_of but rather with how I was saving the data. When an operator was created, a user was also created that was tied to it and it was this user that was being inserted into the db.
This happens because although the operator was being rolled back(because it wasn't valid) the user was still created(because it was not in a transaction).
I solved this by using nested_transactions:
operator model:
...
User.transaction(:requires_new => true) do
create_user
raise ActiveRecord::Rollback unless self.valid?
end
...

how to check if email exists from object errors array Rails

I am creating users from emails.
If an email exists I want to skip creating that user.
Here is my model method:
def invite_users(emails, board)
invalid_emails =[]
emails.each do |email|
user = User.new(:email => email)
user.save ? Participant.make(user, board) : invalid_emails << email unless user.errors.each {|key, msg| msg == "has already been taken"}
end
invalid_emails if invalid_emails.any?
end
I want to check if the error generated from user.save is a duplicate email error. If so I don't want to put that email in the invalid_emails array.
How can I do this?
validates_uniqueness_of is useless for such purposes.
The canonical thing to do is to add a unique index on email to the users table, and use code like:
begin
-- do stuff that creates records --
rescue ActiveRecord::StatementInvalid => e
raise unless /Mysql::Error: Duplicate entry/.match(e)
end
if you want to emulate create or find, you do something like
result = nil
begin
result = User.create(:email => xxxx)
rescue ActiveRecord::StatementInvalid => e
if /Mysql::Error: Duplicate entry/.match(e)
user = User.find_by_email(xxx)
else
raise
end
end
just change
user = User.new(:email => email)
user.save ? Participant.make(user, board) : invalid_emails << email unless user.errors.each {|key, msg| msg == "has already been taken"}
to
user = User.new(:email => email)
if User.find_by_email( email ).blank?
Participant.make(user, board)
else
invalid_emails << email
end
Since errors is basically an array you could just change each to any to get a boolean value for your condition.