how to mark as checked for associated values in Rails 4 checkbox with many to many association - ruby-on-rails

i am creating a user ACL i have 2 models one is users_group and another is access_sections.
Now let's supouse I have 2 access_sections (pages, users)
I wanted to associate both access_sections with users_group,
Now here what i have already did
I created many to many association, added new join table access_sections_user_groups
Whenever i add new user group I pass instance variable to get all available access_sections the I show them as a checkbox in a new user group form, once i check any of access section I loop through in array and insert all elements in 'table access_sections_user_groups' with users_group id and access_sections id everything is working now i wanted to do that when I edit usergroup my checkbox should be checked if the specific access_sections is associated with user_group
user_group_controller.rb
def create
#user_group = UserGroup.new(group_params)
if #user_group.save
flash[:notice] = "User group added !"
flash[:type] = "success"
if params[:user_group][:access_sections].present?
params[:user_group][:access_sections].each do |f|
UserGroup.find(#user_group.id).access_sections << AccessSection.find(f)
end
end
redirect_to(:action => "index")
else
flash[:notice] = "error while adding new group!"
flash[:type] = "danger"
render("add_new")
end
end
user_group/_form.html.erb
<%= f.label("Add section to Access Control ") %>
<% #acl_sections.each do |k| %>
<%= f.check_box(:access_sections, { :multiple => true }, k.id, nil) %>
<% end %>

Should work
f.check_box(:access_section_ids, { :multiple => true }, k.id, nil)
Hence you need to update your model like this way:
def create
if #user_group.create(user_group_params)
# ...
end
end
def user_group_params
params.require(:user_group).permit(access_section_ids: [])
end

Related

rails undefined method `each' for #<Field

I have a form that allows user to register for a tournament. In the process of building the registration form I hae dynamic nested fields with so far field_type of basic. When I load the participants new form I am trying to load all the fields from the Fields table with field_type of basic. It will find them and if I just try <%= #basic.name %> from the new form it will give the name of the last field in the database with that field_type, but if I try:
<% #basic.each do |b| %>
<%= b.name %>
<% end
I get the error undefined method `each' for #<Field.
Here is the new action from the participants_controller:
def new
#participant = #event.participants.new
#user = User.find(current_user.id)
#children = #user.children
#basic = Field.find_by(event_id: #event.id, field_type: 'basic')
end
Fields belong to events but do I have to connect them to participants to make this work?
Thanks
find_by only returns a single record (or nil if the criteria aren't matched) use where to return a collection.
#basic = Field.where(event_id: #event.id, field_type: 'basic')
However assuming you have the association has_many :fields defined in Event you could also use:
#basic = #event.fields.where(field_type: 'basic')
And if you have the scope :basic, -> { where(field_type: 'basic') } defined in Field you can further simplify to:
#basic = #event.fields.basic

Saving arrays in Rails 4.2.3

I am having some trouble saving arrays in Rails.
Rails version: 4.2.3 | Ruby version: 2.2.1 | DB: PostgreSQL
In my view, I have a collection of check boxes that shows the conferences that my member attended.
<%= f.fields_for :conferences_member do |conference| %>
<%= collection_check_boxes(:conferences_member, :conference_id, #all_conferences, :id, :name)%>
<% end %>
I put a break point (binding.pry) after the create action in my MembersController, and surprisingly, it shows the selected check boxes:
Processing by Database::MembersController#create as HTML
Parameters: {"utf8"=>"✓","authenticity_token"=>"XYZ==",
[...] "conferences_member"=> {"conference_id"=>["3", "5", ""]}, [...]
Now, if I go to rails c, and type ConferencesMember.last to check what was saved, I get:
pry(main)> ConferencesMember.last
ConferencesMember Load (0.5ms) SELECT "conferences_members".* FROM
"conferences_members" ORDER BY "conferences_members"."id" DESC LIMIT 1
=> nil
These are my associations:
#=> member.rb
has_one :conferences_member
accepts_nested_attributes_for :conferences_member, allow_destroy: true, reject_if: :all_blank
#=> conferences_member.rb
serialize :conference_id, Array
belongs_to :member
#=> members_controller.rb
params.require(:member).permit( [...]
:conference_member_attributes => [:id, :member_id, :conference_id => []],
[...])
I want to thank you in advance. I've tried almost everything here on StackOverflow, but I don't see my error.
Thank you again.
EDIT:
More of my MembersController:
def new
#member = Member.new
#member.build_conferences_member
end
def create
#member = Member.new(member_params)
binding.pry
end
The log doesn't show any error, it just shows that conferences were not saved at all.
First, your field needs to be renamed to nest the :conference_id in :conferences_member_attributes (not in :conferences_member as you do now). Take advantage of the form object yielded by fields_for:
<%= f.fields_for :conferences_member do |conference| %>
<%= conference.collection_check_boxes :conference_id, #all_conferences, :id, :name %>
<% end %>
You also need to actually save the record in the create action: Member.new builds the record but does not save it. Typically, the create action branches based on whether the record saved or did not (due to validations). So you might rewrite this method like so:
def create
#member = Member.new(member_params)
# when #member.save returns true, it saved to the db successfully
if #member.save
redirect_to members_path, notice: "Member #{#member.id} saved!"
# otherwise, it didn't save because of a validation error, so we render the error
# to the user and give them a chance to fix it
else
flash[:error] = "Member didn't save: #{#member.errors.full_messages.to_sentence}"
render :new
end
end
Lastly, to make sure your data gets through your strong parameters, check your logs for any messages that parameters were filtered out. The messages look like:
Unpermitted parameters: your_favorite_attribute

Rails how to use f.select with virtual attributes

I have a user model that contains 2 booleans in the database - admin, and readonly. Basically this allows me to have 3 levels of access (readonly, editable, and admin).
I have a screen that allows admins to edit other users permissions. Instead of having 2 checkboxes for the boolean values of admin and readonly, i created a dropdown using f.select and i created a virtual attribute called "permission".
Everything works fine when saving a user as far as permissions go, the only thing is that when you go to the edit page for a particiular user, it does not load the page with the user's actual permission in the dropdown. It just loads the first value in the dropdown as the default value.
How can i make it so this dropdown shows the users actual permission when first loading the user edit page?
Here's my virtual attribute code for my User model:
# get the permission
def permission
if self.read_only
#permission = 'readonly'
elsif self.admin
#permission = 'admin'
else
#permission = 'editable'
end
end
# Set the permission.
def permission=(value)
p "VALUE = #{value}"
if value == 'readonly'
self.read_only = true
self.admin = false
#permission = 'readonly'
elsif value == 'admin'
p "INSIDE admin"
self.read_only = false
p "before #{self.admin}"
self.admin = true
p "after #{self.admin}"
#permission = 'admin'
elsif value == 'editable'
self.read_only = false
self.admin = false
#permission = 'editable'
end
end
and here's my f.select in my form view:
<%= f.select :permission, options_for_select([['Admin', 'admin'], ['Read Only', 'readonly'], ['Editable', 'editable']], {:disabled => #permissions_disabled}) %>
I tried using collection_select, but couldn't figure out how to populate the list.
as stated in Rails f.select trying to disable a dropdown from being changed, you dont need the options_for_select. If you remove it and pass the fourth parameter a selected option, you should be set.
<%= f.select :permission, [['admin', 'Admin'], ['readonly', 'Read Only'], ['editable', 'Editable']], { selected: 'readonly' }, { disabled: #permissions_disabled } %>
but given the code above, even without the selected option, as long as f.object.permission returns the right value, you should be fine.
Try adding this to your last options hash: :selected => #user.permission
For example:
<%= f.select :permission, options_for_select([['Admin', 'admin'], ['Read Only', 'readonly'], ['Editable', 'editable']], {:disabled => #permissions_disabled, :selected => #user.permission}) %>

Rails error with where clause in update_attributes

I have a table without primary key with three columns - Player_ID, Season and Amount. When I want to update my current table I have this error message: ActiveRecord::StatementInvalid (Mysql2::Error: Unknown column 'salaries.' in 'where clause': UPDATE salaries SET Season = 20192, Amount = 3232.0 WHERE salaries.`` IS NULL)
Update method in my controller:
def new
#salary = Salary.new
#players = Player.all
#title = "Add salary"
end
def create
#players = Player.all
#salary = Salary.new(params[:salary])
if #salary.save
flash[:success] = "Successfully added salary"
redirect_to salaries_path
else
#title = "Add salary"
render 'new'
end
end
def edit
#player_id = params[:player_id]
#season = params[:season]
#salary = Salary.find_by_Player_ID_and_Season(params[:player_id], params[:season])
#players = Player.all
#title = "Edit salary"
end
def update
#players = Player.all
#player_id = params[:player_id]
#season = params[:season]
#salary = Salary.find_by_Player_ID_and_Season(params[:player_id], params[:season])
if #salary.update_attributes(params[:salary])
flash[:success] = "Successfully edited salary"
redirect_to salaries_path
else
render 'edit'
end
end
_form.html.erb
<%= form_for(#salary, :url => salary_path(:player_id => #player_id, :season => #season)) do |f| %>
<%= f.collection_select :Player_ID, #players, :ID, :Name %>
<%= f.text_field :Season %>
<%= f.text_field :Amount %>
<%= f.submit "Add" %>
<% end %>
Active Record models have to have a primary key or rows can't be updated or delete.
There is a composite_primary_keys gem if you really don't want to add an ID column to your table (although adding that primary key is certainly the path of least resistance)
Your table has already primary key! It's the id attribute.
The params[:season] ... i think it's params[:salary][:season], right?
I think you should write in downcase season, player_id, amount. After that, if it still has problem, post new code here^^
I know the reason for your error, although the root cause isn't immediately clear to me. Your failing query is this:
ActiveRecord::StatementInvalid (Mysql2::Error: Unknown column 'salaries.' in 'where clause': UPDATE salaries SET Season = 20192, Amount = 3232.0 WHERE salaries.`` IS NULL)
The important part is this:
WHERE salaries.`` IS NULL
It would make a certain amount of sense if it were WHERE salaries.foo IS NULL or WHERE salaries.bar IS NULL, but you just have empty space where a column name would normally be. So I guess MySQL (for some weird reason) is interpreting that to mean that you're talking about a column called salaries (i.e. salaries.salaries), which doesn't exist.
I don't even know why the WHERE clause is in there in the first place.
Does your create action work?
Update: the problem is almost certainly this line:
if #salary.update_attributes(params[:salary])
I believe what you want instead is:
if #salary.update_attributes(:amount => params[:amount])
See if that does anything.

Passing IDs through a new Form

This question is about a different approach I'm trying to the one asked here:
Passing IDs through a new Form
I have a group#view page, that is accessed by a Person. In this page, the Person can see the members of the group via methods I developed. The problem is that I need to create the model Honors using the Id from the group, the id from the person accessing the page, and the id from a member of this group.
In my Honors controller I have:
def create
#person = Person.find(current_person)
#asked_groupmembership = #person.owned_group_memberships.find_all_by_status(true,:include => [:group, :member])
#asked_groupmembership.each do |agm|
#honor = Honor.create(:group => Group.find(params[:group_id]),
:person => Person.find(current_person), :honored => Person.find(agm.member.id))
end
if #honor.save
...
end
In my view I have a link that directs the person to the form in order to create a new honor:
<% #asked_groupmembership.each do |agm| %>
<%= link_to "Create Honor", new_honor_path(:group_id => #group.id, :person => current_person.id,
:honored => agm.member.id) %>
But in my forms I can't get the ids and stuff
<% form_for(:honor, :url => honors_path(:group_id, :person,
:honored)) do |f| %>
The error I get is that I can't find Group without an Id.
Any ideas? Thanks.
##Edited2##
Changed my crontroller
def new
##person = Person.find(params[:person])
##honored = Person.find(params[:honored])
##group = Group.find(params[:group_id])
#honor = Honor.new
end
def create
#person = Person.find(current_person)
#honor = Honor.create(:group => Group.find(params[:group_id]),
:person => Person.find(params[:person]),
:honored => Person.find(params[:honored]))
if #honor.save
...
end
First, it seems like you are missing a controller method. Along with every form that creates a new object there are typically two controller methods
new
Gathers up any data that the form needs to render itself
Renders the form
create
Collects the data from the form
Creates the new object
It looks to me like you are missing the new method. In the new method you would gather up all the hidden data that the form needs (e.g. the information that the user is not going to type in directly, like the #person info). Then, I would put this information in your form using hidden form parameters (rather then trying to put it in the form URL).
Objective: From the group#view, loop through and create and "Add Honor" link for each member of the group, while keeping track of the specific member being honored, group in which said member is honored, and the person who is honoring.
The following accomplishes that objective.
Route:
match "honors/:group/:person/:honored" => "honors#create", :as=>"my_custom_new_honor"
Group view:
<% #asked_groupmembership.each do |agm| %>
<%= link_to "Create Honor", my_custom_new_honor_path(:group=> #group.id, :person => current_person.id,:honored => agm.member.id) %>
Honor Controller, Create Method
#honor = Honor.create(:group => Group.find(params[:group_id]),
:person => Person.find(params[:person]),
:honored => Person.find(params[:honored]))
In this scenario you do not need the honor#new method, you're going directly to the create method. This assumes all the relationships are established correctly.

Resources