rails wicked gem has_one association and nested form - ruby-on-rails

On my form on has_one association the fields do not appear for a singular form.
<%= f.fields_for :pack_social_media_sur_mesure, #commande.pack_social_media_sur_mesure do |ff| %>
remains empty
i think i missed something...
My Models :
Commande model :
class Commande < ApplicationRecord
belongs_to :user
validates_presence_of :user
has_one :pack_social_media_sur_mesure, dependent: :destroy
accepts_nested_attributes_for :pack_social_media_sur_mesure, allow_destroy: true
end
PackSocialMediaSurMesure model :
class PackSocialMediaSurMesure < ApplicationRecord
belongs_to :commande
...
end
My controller :
class CommandeStepsController < ApplicationController
...
def update
#user_id = current_user.id
#user = current_user
#commande = #user.commande
#commande.update(commande_params)
end
...
def commande_params
params.require(:commande).permit(:id,..., pack_social_media_sur_mesure_attributes: [:id, ...])
end
end
My form :
<%= form_for #commande, url: wizard_path, html: { class: "pack-slide" }, method: :put do |f| %>
<%= f.fields_for :pack_social_media_sur_mesure, #commande.pack_social_media_sur_mesure do |ff| %>
<%= ff.select :question1 %>
...
<% end %>
<%= f.submit %>
<% end %>
PS : I use wicked gem for this form, this why wizard_path.
Thx,
Théo

Ok I find.
The reason why the fields do not appear is that I had already created an 'commande' but not a 'pack_social_media_sur_mesure'. Or the "wicked gem" takes us to the edit path but we cannot edit it if it does not exist.
The solution was to create the pack_social_media_sur_mesure when creating the 'order' as bellow :
class CommandesController < ApplicationController
before_action :set_commande, only: [:show, :edit, :update, :destroy]
...
def create
#commande = current_user.create_commande(commande_params)
if #commande.save
if #commande.pack_social_media_sur_mesure == nil
#commande.create_pack_social_media_sur_mesure(...)
end
redirect_to ...
else
render :new
end
end
...
def set_commande
#commande = current_user.commande
end

Related

How to insert my association id into simple form for

I have an model that belongs to different models (game belongs to field and organiser), but when I fill the form to create the game, my creation method is not catching up the field reference
class Game < ApplicationRecord
belongs_to :organiser
belongs_to :field
end
class Organiser < ApplicationRecord
has_many :games, dependent: :destroy
end
class Field < ApplicationRecord
has_many :games, dependent: :destroy
end
Controller
class GamesController < ApplicationController
before_action :set_game, only: [:show, :edit, :update, :destroy]
def new
#organiser = Organiser.find(params[:organiser_id])
#game = Game.new
end
def create
#game = Game.new(game_params)
organiser_id = current_organiser.id
#organiser = Organiser.find(organiser_id)
#game.organiser = #organiser
#game.save
redirect_to organiser_games_path(#organiser)
end
def edit
organiser_id = current_organiser.id
#organiser = Organiser.find(params[:organiser_id])
end
def update
organiser_id = current_organiser.id
#organiser = Organiser.find(organiser_id)
#game.update(game_params)
redirect_to organiser_games_path(#organiser)
end
private
def game_params
params.require(:game).permit(:field_id, :total_players)
end
def set_game
#game = Game.find(params[:id])
end
_form parcel for new and edit view
<%= simple_form_for [#organiser, #game] do |f| %>
<div class="form-inputs">
<%= f.input :field_id, as: :select, collection: Field.all.collect(&:location) %>
<%= f.input :total_players %>
</div>
<div class="form-actions">
<%= f.button :submit, "Create", class: "btn btn-primary" %>
</div>
<% end %>
I am a beginner, and if you guys can help me with basic solutions that will help me to understand the complex bit, I will appreciate
I received no message, it looked like it went trough but it did not
collection: Field.all.collect(&:location)
Your collection has to be an array with the relation's id and the displayed value. Here, you only collect the value of location for each Field.
this code should do the trick:
<%= f.input :field_id, as: :select, collection: Field.all.map { |field| [field.id, field.location] } %>
field.id will be the value of your select option (currently, there's no value so it can't works), and field.location will be the text of your select option. :)

How to get UsersPublisher join model working

I have three models: User, Publisher and Interest all with many to many relationships linked through three join models but only 2 out of 3 join models record the id's of their 2 parent models. my UsersPublisher model does not link User to Publisher.
My Interestscontroller proccesses a form (see code) through which I ask the user to provide Interest and Publisher. The latter gets processed via the fields_for method which allows you to pass Publisher attributes via the InterestsController. the UsersPublisher join model records the user_id but the publisher_id is nil.
I've tried putting #users_publishers in both the new and create methods of Publishers- and InterestsController. My latest attempt of using after_action in the InterestsController (see code) has also failed. I've also tried the after_action way in the PublishersController
Your helped is highly appreciated!
The UsersPublisher join model
class UsersPublisher < ActiveRecord::Base
belongs_to :user
belongs_to :publisher
end
InterestsController
class InterestsController < ApplicationController
before_action :find_user
after_action :upublisher, only: [:new]
def index
#interests = policy_scope(Interest)
end
def show
#interest = Interest.find(params[:id])
end
def new
#interest = Interest.new
#interest.publishers.build
authorize #interest
end
def create
#interest = Interest.new(interest_params)
#users_interests = UsersInterest.create(user: current_user, interest: #interest)
authorize #interest
if #interest.save
respond_to do |format|
format.js
format.html {redirect_to root_path}
end
flash[:notice] = 'Thank you, we will be in touch soon'
else
respond_to do |format|
format.js { render }
format.html { render :new }
end
end
end
def edit
#interest = Interest.find(params[:id])
authorize #interest
end
def update
#interest = Interest.find(params[:id])
#interest.update(interest_params)
if #interest.save
flash[:notice] = 'Your interest has been added'
else
flash[:notice] = 'Oops something went wrong'
end
end
private
def interest_params
params.require(:interest).permit(:name, publishers_attributes: [:publisher,:id, :feed])
end
def find_user
#user = current_user
end
def upublisher
#users_publishers = UsersPublisher.create(publisher: #publisher, user: current_user)
end
end
Form
<%= form_for [#user, #interest] do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.fields_for :publishers do |ff| %>
<%= ff.label :publisher %>
<%= ff.text_field :publisher %>
<%= ff.label :feed %>
<%= ff.text_field :feed %>
<%end%>
<%= f.submit "Submit" %>
<%end%>
Since you're using fields_for, you'll want to make sure you have accepts_nested_attributes_for:
class UsersPublisher < ActiveRecord::Base
belongs_to :user
belongs_to :publisher
accepts_nested_attributes_for :publisher
end
This should fix your issue (if it's as you outlined).
Your question is pretty broad, so I don't know whether the above will work. Below are my notes...
From the looks of it, your structure is very complicated; you should work to make it as simple as possible. In the case of creating "interests", you may wish to get rid of the form completely:
#config/routes.rb
resources :publishers do
resources :interests, path: "interest", only: [:create, :destroy] #-> url.com/publishers/:publisher_id/interest
end
#app/controllers/interests_controller.rb
class InterestsController < ApplicationController
before_action :set_publisher
def create
current_user.interests.create publisher: #publisher
end
def destroy
#interest = current_user.interests.find_by publisher_id: #publisher.id
current_user.interests.delete #interest
end
private
def set_publisher
#publisher = UserPublisher.find params[:publisher_id]
end
end
You'd be able to use the above as follows:
<%= link_to "Add Interest", publisher_interest_path(#publisher), method: :post %>
<%= link_to "Remove Interest", publisher_interest_path(#publisher), method: :delete %>
Thinking about it properly, you've got a pretty bad structure.
I'd do something like this:
#app/models/user.rb
class User < ActiveRecord::Base
has_many :interests
has_many :publishers, through: :interests
end
#app/models/interest.rb
class Interest < ActiveRecord::Base
belongs_to :user
belongs_to :publisher
accepts_nested_attributes_for :publisher
end
#app/models/publisher.rb
class Publisher < ActiveRecord::Base
has_many :interests,
has_many :users, through: :interests
end
This should give you the ability to create interests for any number of users and publishers. If you create a publisher for a specific user, you can use accepts_nested_attributes_for to pass the appropriate data:
#config/routes.rb
resources :users do
resources :interest, only: [:new, :create, :destroy] #-> url.com/users/:user_id/interests/new
end
#app/controllers/interests_controller.rb
class InterestsController < ApplicationController
def new
#user = User.find params[:user_id]
#interest = #user.interests.new
#interest.publisher.build
end
def create
#user = User.find params[:user_id]
#interest = #user.interests.new interest_params
end
private
def interest_params
params.require(:interest).permit(:user, :publisher)
end
end
#app/views/interests/new.html.erb
<%= form_for [#user, #interest] do |f| %>
<%= f.fields_for :publisher do |p| %>
<%= p.text_field :name %>
<% end %>
<%= f.submit %>
<% end %>

Association :patient not found, rails 4

I'm trying to associate a relation betwen 1 patient with a consultation, but I'm getting a error:
Association :patient not found
In the model I have:
class Patient < ActiveRecord::Base
belongs_to :user
has_many :consultums, through: :patients
end
class Consultum < ActiveRecord::Base
belongs_to :patients
belongs_to :user
has_one :recetum
end
in the controller I have:
class ConsultationController < ApplicationController
before_action :authenticate_user!
before_action :set_consultum, only: [:show, :edit, :update, :destroy]
respond_to :html
def index
#consultation = Consultum.all
respond_with(#consultation)
end
def show
respond_with(#consultum)
end
## when I try to create a new consultation, throw me the error ##
def new
#consultum = Consultum.new
# patient_id
respond_with(#consultum)
end
def edit
end
def create
#consultum = Consultum.new(consultum_params)
#consultum.save
respond_with(#consultum)
end
def update
#consultum.update(consultum_params)
respond_with(#consultum)
end
def destroy
#consultum.destroy
respond_with(#consultum)
end
# def patient_id
# patient = Patient.find(params[:id])
# # patient = #patient.id
# #consultum.patient_id = patient
# end
private
def set_consultum
#consultum = Consultum.find(params[:id])
end
def consultum_params
params.require(:consultum).permit(:Reason_Consultation, :Diagnostic, :TX, :Labs, :Observations, :patient_id)
end
end
so, as you can see I create the function patient_id, and I'm trying to retrieve the id from the 'patient' and put into patient_id in 'consultum' table, but seems not work...
if I uncomment patient_id function throw me this error:
Couldn't find Patient without an ID
I'm stuck, any idea?
Thanks in advance
EDIT
in my view I have:
consultation/new.html.erb
<div class="page-header">
<%= link_to consultation_path, class: 'btn btn-default' do %>
<span class="glyphicon glyphicon-list-alt"></span>
Back
<% end %>
<h1>New consultum</h1>
</div>
<%= render 'form' %>
_form.html.erb
<%= simple_form_for(#consultum) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :Reason_Consultation %>
<%= f.input :Diagnostic %>
<%= f.input :TX, placeholder: "optional" %>
<%= f.input :Labs, placeholder: "optional" %>
<%= f.input :Observations, placeholder: "optional" %>
<%= f.association :patient %>
</div>
<div class="form-actions">
<%= f.button :submit, "Save Consultation" %>
</div>
<% end %>
When creating associations in rails pay super close attention to the pluralization!
class Patient < ActiveRecord::Base
belongs_to :user
has_many :consultums, through: :patients
end
class Consultum < ActiveRecord::Base
belongs_to :patients
belongs_to :user
has_one :recetum
end
You will notice that your Consultum class does not have a patient relation. It has belongs_to :patients.
class Consultum < ActiveRecord::Base
belongs_to :patient
belongs_to :user
has_one :recetum
end
Also your attribute naming should follow the Ruby conventions!
Ruby uses snake_case for naming attributes and methods and will automatically treat any identifier which begins with an UPPERCASE letter as a constant!
This is not just a stylistic issue - MRI Ruby will let you reassign constants with a warning. Other versions or future versions may be less lenient.
Bad Good
.Reason_Consultation .reason_consultation
.Diagnostic .diagnostic
.TX .tx
.Lab .lab
.Observations .observations
https://github.com/bbatsov/ruby-style-guide
To call an action you can pass parameters as follow:
link_to "New Consultum", new_consultum_path(:id => here, yo have to put the paciente id)
Hope this helps!

Rails polymorphic posts associations and form_for in views

I've been having trouble setting up the form for a polymorphic "department" post in the department view. I followed the rails-cast tutorial for polymorphic associations here
Models:
class Course < ActiveRecord::Base
belongs_to :department, inverse_of: :courses
has_and_belongs_to_many :users, -> { uniq }
has_many :posts, as: :postable #allows polymorphic posts
end
class Department < ActiveRecord::Base
has_many :courses, inverse_of: :department
has_many :posts, as: :postable #allows polymorphic posts
has_and_belongs_to_many :users, -> {uniq}
end
class Post < ActiveRecord::Base
belongs_to :user, touch: true #updates the updated_at timestamp whenever post is saved
belongs_to :postable, polymorphic: true #http://guides.rubyonrails.org/association_basics.html#polymorphic-associations
belongs_to :department, counter_cache: true #for counting number of posts in department
belongs_to :course, counter_cache: true
validates :department_id, :course_id, presence: true
end
config/routes
devise_for :users
devise_scope :users do
match '/users/:id', to: "users#show", via: 'get'
end
resources :departments do
resources :courses
resources :posts
end
resources :courses do
resources :posts
end
views/departments/show.html.erb
<div class="tab-pane" id="posts"><br>
<center><h3>Posts:</h3></center>
<%= render "posts/form", postable: #department %>
</div>
views/posts/_form.html.erb
<%= render "posts/wysihtml5" %>
<center><h3>Create New Post:</h3></center>
<%= form_for [#postable, Post.new] do |f| %>
<%= f.label :title %>
<%= f.text_field :title, class: "form-control" %>
<%= f.label :description %>
<%= f.text_area :description, :rows => 3, class: "form-control" %>
<%= f.text_area :content, :rows => 5, placeholder: 'Enter Content Here', class: "wysihtml5" %>
<span class="pull-left"><%= f.submit "Create Post", class: "btn btn-medium btn-primary" %></span>
<% end %>
controllers/post_controller.rb
class PostsController < ApplicationController
before_filter :find_postable
load_and_authorize_resource
def new
#postable = find_postable
#post = #postable.posts.new
end
def create
#postable = find_postable
#post = #postable.posts.build(post_params)
if #post.save
flash[:success] = "#{#post.title} was sucessfully created!"
redirect_to department_post_path#id: nil #redirects back to the current index action
else
render action: 'new'
end
end
def show
#post = Post.find(params[:id])
end
def index
#postable = find_postable
#posts = #postable.posts
end
...
private
def post_params
params.require(:post).permit(:title, :description, :content)
end
def find_postable #gets the type of post to create
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
controllers/departments_controller.rb
def show
id = params[:id]
#department = Department.find(id)
#course = Course.new
#course.department_id = #department
end
The error is "undefined method `posts_path' for #<#:0x0000010d1dab10>"
I think the error has something to do with the path in the form, but I don't know what. I've tried [#postable, #postable.posts.build] as well but that just gives me undefined method: PostsController.
Anybody know what's going on and how I can fix it?
#department is passed into the form partial as a local variable, but the form calls an instance variable:
# views/departments/show.html.erb
<%= render "posts/form", postable: #department %> # <------ postable
# views/posts/_form.html.erb
<%= form_for [#postable, Post.new] do |f| %> # <------ #postable
Thus, the namespaced route is not properly determined
[#postable, Post.new] # => departments_posts_path
[ nil , Post.new] # => posts_path
Checking your routes, posts are only accessible via nested routes. posts_path is not a valid route, it's method does not exist, and the error is correct: undefined method `posts_path'
Fix:
Set a #postable instance variable in the departments controller so that the form helper can use it:
def show
id = params[:id]
#postable, #department = Department.find(id) # <-- add #postable
#course = Course.new
#course.department_id = #department
end
Then you can simply call render in the view:
<%= render "posts/form" %>

Add model/database association upon create

I have a model named Entry, which has many Categories. The page where I create/edit the Entry has checkboxes for every Category.
When I am editing an Entry, everything works okay. When I create the Entry, I get as an error for the #entry:
:entry_categories=>["is invalid"]
My thinking is that rails can't create the entry_categories because it doesn't know the id of the Entry ( which it shouldn't, it hasn't been assigned an id yet ).
I feel like this is a very common thing to try to do. I haven't been able to find an answer though. Here comes the code spamming, there must be something I am missing and hopefully some more experienced eyes can see it.
entry.rb
class Entry < ActiveRecord::Base
validates_presence_of :contents
validates_presence_of :title
has_many :entry_categories, dependent: :destroy
has_many :categories, through: :entry_categories
belongs_to :book
validates_presence_of :book
end
entry_category.rb
class EntryCategory < ActiveRecord::Base
belongs_to :entry
belongs_to :category
validates_presence_of :entry
validates_presence_of :category
end
category.rb
class Category < ActiveRecord::Base
validates_presence_of :name
validates_uniqueness_of :name
has_many :entry_categories, dependent: :destroy
has_many :entries, through: :entry_categories
end
entries_controller.rb
class EntriesController < ApplicationController
before_action :find_entry, only: [ :show, :edit, :update, :destroy ]
before_action :find_book, only: [ :new, :create, :index ]
before_action :authenticate_admin!, only: [:new, :create, :edit, :update, :destroy ]
def new
#entry = Entry.new
end
def create
#entry = #book.entries.new( entry_params )
if #entry.save
redirect_to entry_path( #entry ), notice: 'Entry Created'
else
render :new
end
end
def show
#categories = Category.joins( :entry_categories ).where( "entry_categories.entry_id = #{#entry.id} " ).select( "name, categories.id " )
#category_class = #categories.first.name.downcase.gsub( / /, '_' ) if #categories.any?
end
def index
#entries = #book ? #book.entries : Entry.all
end
def edit
end
def update
if #entry.update( entry_params )
redirect_to entry_path( #entry ), notice: 'Entry Updated'
else
render :edit
end
end
def destroy
#book = #entry.book
#entry.destroy
redirect_to book_path( #book ) , notice: 'Entry Destroyed'
end
protected
def entry_params
params.require(:entry).permit( :title, :contents, :year, :month, :day, category_ids: [] )
end
def find_entry
#entry = Entry.find( params[:id] )
end
def find_book
#book = Book.find( params[ :book_id ] )
rescue
#book = nil
end
end
_form.html.erb
<%= form_for [ #book, #entry ] do | form | %>
<%= content_tag :p, title %>
<%= form.text_field :title, placeholder: 'Title', required: true %>
<%= form.number_field :year, placeholder: 'Year' %>
<%= form.number_field :month, placeholder: 'Month' %>
<%= form.number_field :day, placeholder: 'Day' %>
<%= form.text_area :contents %>
<fieldset>
<legend>Categories</legend>
<%= form.collection_check_boxes(:category_ids, Category.all, :id, :name ) %>
</fieldset>
<%= form.submit %>
<% end %>
So again, the entry_categories are invalid in the create method, in the update they are fine. It's the same html file.
There must be some way to tell rails to save the Entry before trying to save the EntryCategory?
Thanks.
I managed to get this working by taking the validations out of EntryCategory:
class EntryCategory < ActiveRecord::Base
belongs_to :entry
belongs_to :category
validates_presence_of :category
end
I'm not particularity happy about this solution, and would still appreciate other thoughts.
I think you can use any of the following approach:
You can use autosave functionality of Active Record association. By this, when you will save EntryCategory, it will automatically save Entry as well.
class EntryCategory < ActiveRecord::Base
belongs_to :entry , autosave: true
#rest of the code
end
You can also use before_save callback of active record. by this, whenever you will save EntryCategory, it will first call a specified method, than proceed with saving.
class EntryCategory < ActiveRecord::Base
before_save :save_associated_entries
#rest of the code
def save_associated_entries
# code to save associated entries here
end
end
Try this:
replace this code:
<%= form.collection_check_boxes(:category_ids, Category.all, :id, :name ) %>
with:
<% Category.all.order(name: :asc).each do |category| %>
<div>
<%= check_box_tag "entry[category_ids][]", category.id %>
<%= category.name %>
</div>
you can format it with fieldset instead of div

Resources