Using hstore and saving new values for user - ruby-on-rails-4

My user model contains values for things like:
name, email, phone, approved, etc..
The scope of the project I am working on includes custom user settings and for this reason I am using hstore (I dont want to create a user_settings table).
On the user edit view I want to create a checkbox called 'colors' and whether or not the checkbox is checked determines if that setting is set for the user or not.
I have already setup hstore as follows:
class AddHstore < ActiveRecord::Migration
def up
enable_extension :hstore
end
def down
disable_extension :hstore
end
end
And updated the User model as follows:
class AddSettingsToUser < ActiveRecord::Migration
def up
add_column :users, :settings, :hstore
end
def down
remove_column :users, :settings
end
end
This is essentially my user edit view:
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, :class => "form-horizontal user" }) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name, autofocus: true %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email %>
</div>
<div class="field">
<%= f.label :phone_number %><br />
<%= f.text_field :phone_number %>
</div>
<div class="actions">
<%= f.submit 'Update', :class => 'btn btn-primary' %>
</div>
<% end %>
At this point I am unsure as to how to actually implement this functionality. The user edit page allows the user to change their name, phone and other values but how would I include a new value for the hstore settings?

Inside the form_for from where you are creating users, add your hstore fileds like below :
<%= form_for resource, ...do |f| %>
#...
<%= f.fields_for :settings do |settings| %>
<%= settings.text_field :field1 %>
<%= settings.text_field :field2 %>
<% end %>
#....
<% end %>
Then update your controller strong parameter method like below to permit these new fields.:
def user_params
params.require(:user)
.permit(
:name,
:email,
settings: [ :field1, :field2 ]
)
end
Now, you are done. Open your rails console and try some sample data like
User.create(
settings: { field1: 'data1', field2: 'data2' }
)

Related

param is missing or the value is empty:

Here is booking controller:
class BookingsController < ApplicationController
before_action :logged_in_user, only: [:create]
def new
#booking = Booking.new
end
def index
#bookings = Booking.all
end
def create
#booking = current_user.bookings.build(booking_params)
if #booking.save
flash[:success] = "Booking created!"
redirect_to root_url
else
render 'static_pages/home'
end
end
def show
#booking = Booking.find(params[:id])
end
def destroy
#booking = Booking.find(params[:id])
#booking.destroy
redirect_to bookings_path
end
private
def booking_params
params.require(:booking).permit(:date, :hour, :game)
end
end
When I post after the utf8 and authenticity token I don't understand why "#<\Booking:0x000001061928a8>\" instead of simply "booking" then the nested hash contains date, hour and game which I permit in the controller.
Here is the view:
<%= form_for(#booking) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :day %>
<%= date_field(#booking, :date) %>
<%= f.label :hour %>
<%= number_field(#booking, :hour, in: 8..19) %>
<%= f.label :game %>
<%= select(#booking, :game, [['Singles', 1], ['Doubles', 2]]) %>
<%= f.submit "Book", class: "btn btn-primary" %>
<% end %>
Any help much appreciated.
Ok it was simply that I wasn't using the the f variable of the form builder for the select boxes, originally I was but I'd had problems rendering the select boxes so I'd taken it out. Must have been due to a syntax error.
Here's the working form_for with a date picker and other select boxes:
<div class="field">
<%= form_for(#booking) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :day %>
<%= f.date_field :day %>
<%= f.label :hour %>
<%= f.number_field :hour, in: 8..19 %>
<%= f.label :game %>
<%= f.select :game, [['Singles', 1], ['Doubles', 2]] %>
<%= f.submit "Book", class: "btn btn-primary" %>
<% end %>
</div>

Remove avatar - carrierwave and devise

I'm having an unbelievable amount of trouble getting the Carrierwave :remove_avatar checkbox to work in my Devise profile edit form. I've been following the carrierwave documentation and wiki.
I've mounted the uploader to the User model. I've added :avatar and :remove_avatar to in the ApplicationController sanitizer
application_controller.rb
def configure_permitted_parameters
devise_parameter_sanitizer.for(:account_update) do |u|
u.permit(:first_name, :last_name, :email,
:password, :password_confirmation, :avatar, :remove_avatar)
end
devise_parameter_sanitizer.for(:sign_up) do |u|
u.permit(:first_name, :last_name, :email,
:password, :password_confirmation)
end
end
I've added the :remove_avatar to the edit form
/devise/registrations/edit.html.erb
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, multipart: true }) do |f| %>
<%= f.label :avatar %><br />
<%= image_tag(resource.avatar_url(:thumb)) %>
<%= f.file_field :avatar, accept: 'image/jpeg,image/png' %>
<label>
<%= f.check_box :remove_avatar %>
Remove avatar
</label>
<%= f.label :first_name %><br />
<%= f.text_field :first_name, autofocus: true %>
<%= f.label :last_name %><br />
<%= f.text_field :last_name %>
<%= f.label :email %><br />
<%= f.email_field :email %>
<div><%= link_to 'Cancel', resource %> <%= f.submit "Update" %></div>
<% end %>
I'm not having any other problems with carrierwave except for removing the avatars. When I check the box and submit the form the picture is not removed.
I did a test where I used the users controller instead of devise's registrations controller and submitted the form to #user instead of resource and I was able to get it working. I'd rather stick to convention and use the registrations controller. What am I doing wrong or missing?
#user.remove_avatar!
#user.remove_avatar = true
#user.save
#user.reload
Try this, May help you.
Use this in your model:
after_commit :remove_avatar!, on: :destroy

rails simple_form using virtual attributes

I am trying to incorporate Simple_forms into my app using a virtual attributes. I am following http://railscasts.com/episodes/102-auto-complete-association-revised to get autocomplete to work as well. Simple_form works when i do not use a virtual attribute but when I do use the virtual attribute I get the error "Association :head_coach_name not found".
My Team Model is:
class Team < ActiveRecord::Base
attr_accessor :head_coach_name
belongs_to :user
validates :team_name, presence: true
belongs_to :head_coach, class_name: "User", :foreign_key => "head_coach_id"
def head_coach_name
user.try(:name)
end
def head_coach_name=(name)
self.user = User.find_by_name(name) if name.present?
end
end
My User model is:
class User < ActiveRecord::Base
has_many :teams, :class_name => "::Team", dependent: :destroy
end
My View:
<%= simple_form_for #team, html: {class: 'form-horizontal' }, url: teams_path, method: 'post' do |f| %>
<%= f.error_notification %>
<%= f.hidden_field :user_id %>
<div class="col-md-6">
<div class="row">
<div class="col-md-12">
<%= f.input :team_name, class: "form-control" %>
<%= f.input :year, collection: Date.today.year-90..Date.today.year %>
<%= f.input :season, as: :select, collection:
['Fall',
'Winter',
'Spring',
'Summer'] %>
<%= f.input :season_type, as: :select, collection:
['Outdoor',
'Indoor',
'Tournament'] %>
<%= f.input :awards %>
</div>
</div>
</div>
<div class="col-md-6">
<div class="row">
<div class="col-md-12">
<%= f.input :club %>
<%= f.input :division %>
<%= f.association :head_coach_name %>
<%= f.input :assistant_coach_id %>
<%= f.input :assistant_coach_two_id %>
</div>
</div>
</div>
<%= f.button :submit, label: "Add team", class: "btn btn-large btn-primary col-md-3 pull-right" %>
<% end %>
Everything works as long as i don't have the virtual association in there. I could put :head_coach and it would work with a drop down list but I want to use the autocomplete feature like in the railscast video. Also in rails console i can run these commands to show the virtual attribute works:
2.1.2 :003 > team.head_coach_name
User Load (0.6ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 100 LIMIT 1
=> "Miss Daisha Shanahan"
Any ideas on how I can get the virtual attribute to work correctly with simple_forms?
You are referencing an association that doesn't exist with f.association :head_coach_name. Try this instead:
f.association :head_coach, label_method: :head_coach_name
You have a few other oddities in your code, including your head_coach_name definition, which should rely on head_coach instead of user. Same concern for the head_coach_name= method.
Example. You have:
def head_coach_name
user.try(:name)
end
Seems like you should have:
def head_coach_name
head_coach.try(:name)
end

creating a record in a table automatically after saving the other record in tne other table rails4

I still novice with RoR. My mission is to add examplaries according to the number of exemplary inserted in the form of book, knowing that i have a book table and an examplary table and the relationship in between is a book has_many exemplaries and an exemplary belong_to a book.
This is my attempt:
in books_controller.rb
method create:
def create
#book= Book.new(book_params)
if #book.save
#book.nbr_exemplaires.times do |i|
#exemplaire= Exemplaire.create(book_id: #book.id, state: 0 )
end
flash[:notice]='goood'
redirect_to admin_manage_path
else
flash[:alert]='ouups'
redirect_to root_url
end
end
private
def book_params
params.require(:book).permit(:title, :pages, :resume,:nbr_exemplaires, :has_exemplaires, :author_ids =>[], :subject_ids =>[])
end
book/new.html.erb:
<h1>Add new book</h1>
<%= form_for(#book) do |form| %>
<div> <%= form.label :title %><br>
<%= form.text_field :title %>
</div>
<div>
<%= form.label :pages %><br>
<%= form.number_field :pages %>
</div>
<div>
<%= form.label :resume %><br>
<%= form.text_area :resume %>
</div>
<div>
<p>select author from existing list</p><br>
<%= form.collection_select :author_ids, #authors, :id, :l_name, {:selected => 1}, {:name => 'book[author_ids][]'} %>
</div>
<div>
<p> Select subject from existing list</p><br>
<%= form.collection_select :subject_ids, #subjects, :id, :name, {:selected =>1}, {:name => 'book[subject_ids][]'} %>
</div>
<div>
<%= form.label :has_exemplaires? %>
<%= form.check_box :has_exemplaires,{}, 'Yes', 'No'%>
<div id="expl_details" style="display:none;">
<%= form.label :nbr_exemplaires %> <%= form.number_field :nbr_exemplaires %>
</div>
</div>
<%= form.submit "Submit" %>
<% end %>
<script type="text/javascript">
var checkbox = document.getElementById('book_has_exemplaires');
var details_div = document.getElementById('expl_details');
checkbox.onchange = function() {
if(this.checked) {
details_div.style['display'] = 'block';
} else {
details_div.style['display'] = 'none';
}
};
</script>
Then I would suggest something like this:
class Book < ActiveRecord::Base
has_many :exemplaires
attr_accessor :nbr_exemplaires
after_save :create_exemplaires
private
def create_exemplaires
nbr_exemplaires.times do
self.exemplaires.create()
end
end
If you actually have a column name 'nbr_exemplaires' in your table, you don't need the attr_accessor line. That is only if you won't be saving that as separate value in the DB.
I would use nested attributes, that way rails will create them automatically for you through the same form:
class Book < ActiveRecord::Base
has_many :exemplaires
accepts_nested_attributes_for :exemplaires, allow_destroy: true
This would allow to use the nested form builder in your view:
<%= form_for(#book) do |form| %>
<div><%= form.label :title %><br>
<%= form.text_field :title %>
</div>
<%= form.fields_for :exemplaires do |f| %>
<%= f.text_field :name %>
... more fields
<% end %>
You could then add some javascript to create a multiple nested forms:
<%= link_to_add_fields "Add Exemplarie", f, :answers %>
With this kind of setup, rails will automatically create all the associated objects in the same action with no additional code on the controller/model side. Here is a great railscasts on it:
http://railscasts.com/episodes/196-nested-model-form-revised
If you haven't subscribed, I suggest you do. It's the most useful rails resource I ever used when starting out and it costs only a few $ a month. Good luck!

First argument cannot contain nil or be empty rails 4

I'm making a single page application based on Futureme.org for practice. The user goes to the home page, sees a form to put their email address, subject, and the body of their message and sends it.
The problem I am having is I get an error "First argument in form cannot contain nil or be empty". Here is my code;
Model;
class Letter < ActiveRecord::Base
VALID_EMAIL_REGEX = /\A[\w+\-,]+#[a-z\d\-.]+\.[a-z]+\z/i
validates_presence_of :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates_length_of :subject, presence: true, length: { maximum: 50 }
validates_presence_of :message
end
Controller;
class LettersController < ApplicationController
def new
#letter = Letter.new
end
def create
#letter = Letter.new(params[:letter])
if #letter.save
redirect_to letters_path, :notice => "Your letter was sent!"
else
render "new"
end
end
end
View form;
<%= form_for #letter, :html => {:class => 'form-horizontal'} do |f| %>
<% if #letter.errors.any? %>
<div class="error_messages">
<h2><%= pluralize(#letter.errors.count, "error")%>stopped this message from being saved</h2>
<ul>
<% #letter.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :subject %><br />
<%= f.text_field :subject %><br />
</div>
<div class="field">
<%= f.label :message, "Message" %><br />
<%= f.text_area :message, size: "60x10" %>
</div>
<div class="actions"><%= f.submit "Submit", class: "btn btn-small btn-primary" %></div>
<% end %>
The form is on the home page which is in the "Welcome Controller".
Any help would be great.
It looks like you build letter in action new when form is drawn on other view :)
You should move #letter = Letter.new to appropriate action
One of the variant is:
#WelcomeController
def home
#letter = Letter.new
end
#LettersController
def create
#letter = Letter.new(params[:letter])
if #letter.save
redirect_to letters_path, :notice => "Your letter was sent!"
else
render "welcome/home"
end
end
be careful if you prepare some data in action home you should care about initializing them for action create when validation failed because you render "welcome/home" view