im following ryan bates screen cast on how http://railscasts.com/episodes/219-active-model on how to validate a form without a database
but i keep getting an undefined method valid?
heres my controller
def create
#contacts = FreshDeskApiWrapper.new().post_tickets(params[:contacts])
if #contacts.valid?
redirect_to new_contact_path
else
flash[:notice] = "OOps"
render action: 'new'
end
end
I can seem to call
$ FreshDeskApiWrapper.new().valid?
just fine in the console but it does not seem to like it when i tack on the
$ FreshDeskApiWrapper.new().post_tickets(params[email: 'user#example.com']).valid?
i get an undefined method valid?
There is something im not understanding about this
heres my fresh_desk_api_wrapper.rb file i created in my models folder
class FreshDeskApiWrapper
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :config, :client, :subject, :email, :custom_field_phone_number_50754, :custom_field_company_50754, :description
validates :subject, presence: true
validates :email, presence: true
validates_format_of :email, :with => /^[-a-z0-9_+\.]+\#([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
self.config = YAML.load_file("#{Rails.root}/config/fresh_desk.yml")[Rails.env]
self.client = Freshdesk.new(config[:url], config[:api_key], config[:password])
end
def post_tickets(params)
client.post_tickets(params)
end
def persisted?
false
end
end
post_tickets is something im defining in there
You can call valid? on an single instance of an object, not multiple. #contacts would imply that your post_tickets method is returning multiple objects.
try something like this:
#contacts = FreshDeskApiWrapper.new(post_tickets(params[:contacts])
what seems to be the problem is that the method you are adding dosnt return a active record object, so the method valid? is not available
Edit:
maybe this:
#contacts = FreshDeskApiWrapper.new(FreshDeskApiWrapper.post_tickets(params[:contacts])
omg im so dumb so what i did was
def create
#contacts = FreshDeskApiWrapper.new(params[:contacts])
#contacts.post_tickets(params[:contacts])
if #contacts.valid?
redirect_to new_contact_path
else
flash[:notice] = "OOps"
render action: 'new'
end
end
and it works!
Im still struggling to learn all this.....thanks for your guy's guidance it really helped
Related
Watching Railscasts, more specifically Form Objects. Here is the code.
Controller code:
def create
#signup_form = SignupForm.new
if #signup_form.submit(params[:user])
session[:user_id] = #signup_form.user.id
redirect_to #signup_form.user, notice: "Thank you for signing up!"
else
render "new"
end
end
Method found on form object:
class SignupForm
def submit(params)
user.attributes = params.slice(:username, :email, :password, :password_confirmation)
profile.attributes = params.slice(:twitter_name, :github_name, :bio)
self.subscribed = params[:subscribed]
if valid?
generate_token
user.save!
profile.save!
true
else
false
end
end
end
I understand most of the code, but what I don't understand is how .valid? can run without an object written directly in front of it (i.e.: object.valid?)? I tried replicating this with Ruby, but Ruby requires an object to be directly written in front of the method, which leads me to believe this is some sort of Rails magic.
Can someone explain how .valid? runs without an object in front of it , and which object it picks up?
I tried using the following Ruby code and did not work:
array = [1,2,3,4]
def meth
if is_a?
puts "is array"
else
puts "not array"
end
end
array.meth => error: wrong number of arguments (given 0, expected 1)
In the Railscast #416 in question, Ryan includes (among others) the ActiveModel::Validations module into the SignupForm class. This module implements the valid? method for the class.
Now, in Ruby you can always call methods on the current object (i.e. self) without explicitly naming the receiver. If the receiver is unnamed, self is always assumed. Thus, in your submit method, valid? in called on the same instance of the SubmitForm where you originally called submit on.
class SignupForm
def submit(params)
user.attributes = params.slice(:username, :email, :password, :password_confirmation)
profile.attributes = params.slice(:twitter_name, :github_name, :bio)
self.subscribed = params[:subscribed]
if valid?
generate_token
user.save!
profile.save!
true
else
false
end
end
def valid? // <--- this is what they are calling.
return true // this is made up... i am sure it does something
end
end
I've been trying to push the input data from my form to the database using the create function, but the instance variable in create function keeps returning 'nil' and after the 'begin transaction', it does 'rollback transaction'
The model function works fine as I get the desired parsed data, and so does the timetables_params function. But timetables_params[:start_time] always returns 'nil' even though the timetables_params returns all the start_time values and end_time values.
How can I fix this?
Here is my controller
def index
#user = current_user
#timetables = #user.timetable.all
end
def new
#timetable = Timetable.new
end
def create
timetables_params[:start_time] = Timetable.parse_timetable_time(timetables_params, 'start')
timetables_params[:end_time] = Timetable.parse_timetable_time(timetables_params, 'end')
#timetable = Timetable.create(timetables_params)
if #timetable.save
flash[:success] = "Done"
else
render 'new'
end
end
private
def timetables_params
params.require(:timetable).permit(:user_id, :start_time, :end_time)
end
end
Here is my model
belongs_to :user
attr_accessor :user, :start_time, :end_time
def self.parse_timetable_time(hash, type)
date_string = hash["#{type}_time(1i)"].to_s + "=" + hash["#{type}_time(2i)"].to_s + "=" + hash["#{type}_time(3i)"]
Time.parse(date_string)
end
You probably have not set the user since its belongs_to :user and i dont see it anywhere in your code. That's why its rolling back and you probably required user_id in your Timetable model. My suggestion is below
Instead of:
#timetable = Timetable.create(timetables_params)
Use build:
#timetable = current_user.timetables.build(timetables_params)
Thanks for all the help above, but turns out that I just had to add the following lines in the model and modify the controller create function:
model
validates :user_id, presence: true
validates :start_time, :end_time, presence: true
controller
def create
#timetable = current_user.timetables.build(timetables_params)
if #timetable.save
flash[:success] = "Done"
else
render 'new'
end
And, I don't necessarily need to parse the datetime values, Rails does do it automatically
I have a modified copy of https://github.com/talho/openphin/blob/master/app/controllers/admin/invitations_controller.rb
The main code is primarily the same, however our system was upgraded a few months back to Rails 4.x and the invitation system no longer works.
The method with the issue is create. I have tried swapping out:
#invitation = Invitation.new(params[:invitation])
with
#invitation = Invitation.create(invitation_params)
And creating
def invitation_params
params.require(:invitation).permit!
end
However, here is what I have:
invitation_params = {"name":"Test","subject":"test","body":"test","organization_id":"","author_id":24448}
#invitation = {"id":null,"name":null,"body":null,"organization_id":null,"author_id":null,"subject":null,"created_at":null,"updated_at":null,"lock_version":0}
Also, if I use create!, then my output error is:
E, [2015-12-14T13:03:38.664099 #24385] ERROR -- : Validation failed: Author can't be blank (ActiveRecord::RecordInvalid)
I could use any guidance/help on why everything ends up as null.
You call return what leaved the method, before you call save! in the record. Furthermore you might want to read about Strong Parameters. You might want to change your code to:
#invitation = Invitation.new(
params.require(:invitation).permit(
:name, :subject, :body, :organization_id, :author_id
)
)
#invitation.save!
render :json => { :invitation => #invitation }.as_json
return
Please note that you usually do not need to call return in controller method. And when you call save! immediately after new then create! might be an better option:
def create
invitation = Invitation.create!(invitation_params)
render json: { invitation: invitation }.as_json
end
private
def invitation_params
params.require(:invitation).permit(
:name, :subject, :body, :organization_id, :author_id
)
end
How do I get the parameters of datetime_select to save?
Error parameters:
{"utf8"=>"✓",
"authenticity_token"=>"/Tu18E4ubxp0XWcoLTdrm2B4Ho80PDH86dWwm9fvEMs=",
"post"=>{"title"=>"asdf",
"event_date(1i)"=>"2015",
"event_date(2i)"=>"8",
"event_date(3i)"=>"7",
"event_date(4i)"=>"15",
"event_date(5i)"=>"26",
"description"=>"asdf",
"published"=>"0"},
"button"=>""}
The model:
class Spree::Post < ActiveRecord::Base
validates_presence_of :title, :description, :event_date
def event_date
end
scope :published, lambda { where(:published => true) }
scope :latest, order("created_at DESC").limit(3)
end
Relavent controller code:
def create
#post = Spree::Post.new(post_params)
if #post.save
flash[:notice] = "Post saved successfully"
redirect_to admin_posts_path
else
flash[:alert] = "There was an error saving your post"
redirect_to :back
end
end
And the view:
<p><%= f.label :event_date, Spree::Post.human_attribute_name(:event_date) %></p>
<p><%= f.datetime_select :event_date %></p>
The problem seems to be that it's trying to store multiple values. I'm guessing that the fix will be by adding to the model file, right?
Have you permitted event_date in your post_params? (We don't know, because you didn't include your entire posts controller file.) If you haven't already permitted them, you might want to try editing your post_params to look like:
class Spree::PostsController < ActionController::Base
private
def post_params
params.require(:post).permit(:event_date)
end
end
See http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html for more information.
EDIT: Actually, given the snippet of your error message you provided, I'm less confident you have a strong parameters problem. I'll still keep this answer up, though.
You have to explicitly permit each parameter part
def post_params
params.require(:post).permit("event_date(1i)","event_date(2i)","event_date(3i)","event_date(4i"),"event_date(5i)",:any,:other,:post,:fields)
end
You should ensure that your field is a datetime in your database. If it is a string it will throw this error message when you try to save the datetime_select.
New to rails, and I think i found my problem but I'm not sure if this is the case
def additional_info
#user = User.find params[:id]
end
def update
#user = User.find(params[:id])
if #user.update(user_addinfo)
render user_path
else
render action: 'additional_info'
end
end
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
def user_addinfo
params.require(:user).permit(:years_business, :years_relationships, :years_careers, :years_lifeoutlook)
end
end
A user suggested that i change the
if #user.update(user_addinfo) to -> if#user.update!(user_addinfo)
the result was an error page saying my password is too short! I went back reread Michael Hartl's guide and rails api on the params. section and i believe this is causing an issue? I've tried changing to
params.permit(:years_business, :years_relationships, :years_careers, :years_lifeoutlook)
only and it still gives a password too short error.... what am i doing wrong? or am i totally misunderstanding the params?
There's probably a length validation in the User model that checks for the length of the given password.
Open the app/models/user.rb file and look for a line like this:
validates :password, length: { minimum: 4 }
or:
validates_length_of :password