I cannot solve the following problem
Any help or suggestion is appreciated
Agent collects orders for Product on a paper going from one Shop to another in his Region.
At the end of the day, he inserts the quantity of each Product to each Shop.
Each Shop orders more than 4 types of products.
I need to design to be able to bulk insert.
<table>
<tr>
<td>Shop1</td>
<td>Product1</td>
<td>Product2</td>
<td>Product3</td>
<td>Product4</td>
etc...
</tr>
<tr>
<td>Shop2</td>
<td>Product1</td>
<td>Product2</td>
<td>Product3</td>
<td>Product4</td>
etc...
</tr>
etc...
</table>
In the browser it needs to look as below
One approach could be to use a custom form model. This is a pretty good guide on the subject. This may not be perfect, but should get you on the right track at least. All credit to the following (slightly modified for your question) code goes to Sam Slotsky from the blog linked above. Read the post for more detail about each piece.
Here's the custom form model:
class ProductForm
include ActiveModel::Model
attr_accessor :products
def products_attributes=(attributes)
#products ||= []
attributes.each do |i, product_params|
#products.push(Product.new(product_params))
end
end
end
Here's the controller:
class ProductsController < ApplicationController
def new
#product_Form = ProductForm.new(products: [Product.new])
end
def create
#product_form = ProductForm.new(params[:product_form])
if #product_form.save
flash[:notice] = "Created products"
redirect_to root_path
else
flash[:notice] = "There were errors"
render :new
end
end
end
Here's the view:
<div>
<%= form_for #product_form, url: products_path, method: :post do |f| %>
<%= f.fields_for :products do |c| %>
<%= c.text_field :attr_1 %>
<%= c.text_field :attr_2
<%- # ... etc ... %>
<% end %>
<p>
<%= f.submit "Submit" %>
</p>
<% end %>
</div>
Related
Im trying to get all the Posts from the the Users. I'm following using the act_as_follower gem. The User follows a profile model, and Posts belong to a User.
My User model:
acts_as_follower
My Profile model the user follows:
belongs_to :user
acts_as_followable
Post model:
belongs_to :user
My Post Controller.rb:
def follow
#profile = Profile.find(params[:id])
current_user.follow(#profile)
redirect_to :back
end
def unfollow
#profile = Profile.find(params[:id])
current_user.stop_following(#profile)
redirect_to :back
end
Im trying to implement something like this using follows_by_type method provided:
#posts = current_user.follows_by_type('Post').order("created_at DESC")
But the thing is the User follows the Profile model, but here I'm looking for a type 'Post'.
EDIT
In my index controller i'v set up the following:
#favoritePost = Post.where(user_id: current_user.all_follows.pluck(:id))
And in the view iv implemented this:
<% if user_signed_in? %>
<%#favoritePost.each do |post| %>
<%= post.title %>
<% end %>
<% end %>
The gem lets you follow multiple models and follows_by_type('Post') filters the Posts you follow.
What you're looking to do is to return the posts from the users you follow.
Controller
#posts = Post.where(user_id: current_user.all_following.pluck(:id))
View
<% #posts.each do |post| %>
<%= post.title %>
<% end %>
I worked out this solution, might not be the best, but it works as required.
In my controller i set this up:
#following = current_user.all_following
#followposts = #following.each do |f|
f.user.id
end
And in my view I have set this up:
<% #followposts.each do |f| %>
<% f.user.posts.each do |g| %>
<%= g.title %>
<% end %>
<% end %>
I have stripe subscriptions on my site. yesterday i created a basic way for the user to view their payment history and cards used. i now want to break this up into two views so that the payment history is on one page and the card(s) used is on another page. I feel like i must be missing something but when i tried to do this nothing is showing on the page. I am pretty new to rails so the whole stripe subscriptions thing has been a bit of a challenge but getting there. This is the original code could someone offer some guidance as to the steps i need to follow. I tried literally splitting this into two different view file but that didn't work so i have gone back to where i was originally now!
subcriptions/show.html.erb
<h1>View your payment history and cards</h1>
<h4><%= #charges.data.length %> Charges! </h4>
<% #charges.data.each do |charge| %>
<%= charge.statement_description %>
£<%= charge.amount %>
<%= Time.at(charge.created).strftime("%d/%m/%y") %>
<% end %>
<h4><%= #charges.data.length %> Cards! </h4>
<% #cards.each do |card| %>
<%= card.brand %>
**** **** **** <%= card.last4 %>
<%= card.exp_month %>/<%= card.exp_year %>
<% end %>
subscriptions controller:
class SubscriptionsController < ApplicationController
def new
#subscription = Subscription.new
end
def create
# raise 'a'
#subscription = Subscription.new(params[:subscription].permit(:stripe_card_token))
#subscription.user = current_user
if #subscription.save_with_payment(params[:plan]) #(current_user)
redirect_to #subscription, :notice => "Thank you for subscribing!"
else
render :new
end
end
def destroy
end
def show
customer_token = current_user.subscription.try(:stripe_customer_token)
#charges = customer_token ? Stripe::Charge.all(customer: customer_token) : []
#cards = customer_token ? Stripe::Customer.retrieve(customer_token).cards : []
end
end
subscriptions model
class Subscription < ActiveRecord::Base
belongs_to :user
validates_presence_of :user_id #it should be always compulsary
# attr_accessible :plan
attr_accessor :stripe_card_token
def save_with_payment(plan)
if valid?
customer = Stripe::Customer.create(description: 'subscription', plan: plan, card: stripe_card_token)
self.stripe_customer_token = customer.id
save!
end
rescue Stripe::InvalidRequestError => e
logger.error "Stripe error while creating customer: #{e.message}"
errors.add :base, "There was a problem with your credit card."
false
end
end
The most simple way to achieve it, is to create 2 methods in controller (for example payments and cards):
def payments
customer_token = current_user.subscription.try(:stripe_customer_token)
#charges = customer_token ? Stripe::Charge.all(customer: customer_token) : []
end
def cards
customer_token = current_user.subscription.try(:stripe_customer_token)
#cards = customer_token ? Stripe::Customer.retrieve(customer_token).cards : []
end
create 2 views for these (payments.html.erb and cards.html.erb under /views/subscriptions/ directory):
payments.html.erb:
<h1>View your payment history</h1>
<h4><%= #charges.data.length %> Charges! </h4>
<% #charges.data.each do |charge| %>
<%= charge.statement_description %>
£<%= charge.amount %>
<%= Time.at(charge.created).strftime("%d/%m/%y") %>
<% end %>
cards.html.erb:
<h1>View your cards</h1>
<h4><%= #charges.data.length %> Cards! </h4>
<% #cards.each do |card| %>
<%= card.brand %>
**** **** **** <%= card.last4 %>
<%= card.exp_month %>/<%= card.exp_year %>
<% end %>
and edit routes by:
resources :subscriptions do
get '/payments', to: 'subscriptions#payments' # or get 'subscriptions/payments', to: 'subscriptions#payments' (depending on which link you would like to see)
get '/cards', to: 'subscriptions#cards'
end
This would be pretty much it. Run rake routes to see generated routes to use it correctly and you're good to go. Please check for spelling mistakes in case you'll copy something - not sure if I didn't make any.
I have an app where users can create courses, and each course has_one syllabus. How could I go about configuring my courses and syllabuses (I know it's Syllabi but apparently Rails doesn't) controller, and my routes, so on a course's page there is a link to create or show the course's syllabus, and a link back to the course from the show syllabus page?
In my routes I have:
resources :courses do
resources :syllabuses
member do
put :enroll #this is so users can enroll in the course
end
end
Currently , so the course_id will be saved in the syllabus table in my courses_controller, I have:
def create_syllabus
#course = Course.find(params[:id])
#syllabus = #course.build_syllabus(params[:syllabus])
if #syllabus.save
redirect_to #syllabus, notice: "Successfully created syllabus."
else
render :new
end
end
then in my courses show page I have:
<section>
<% if (current_user.courses.includes(#course) ||
current_user.coursegroups.find_by_course_id_and_role(#course.id, "admin")) %>
<%= render 'create_syllabus' %>
<% end %>
</section>
then in my create_syllabus form (in my courses views folder) I have tried starting it off with:
# I have #course = Course.find(params[:id]) defined in show in the
#courses_controller
<%= form_for #course.create_syllabus do |f| %>
<%= form_for #course.syllabus.create_syllabus do |f| %>
<%= form_for #course.syllabus.create do |f| %>
and I get an undefined method error for each of those.
If you want to create a new syllabus in your show action of a specific course, you can add this to your controllers and views:
courses_controller.rb
#course = Course.find(params[:id])
# Build a new #syllabus object, only if there is none for the current course
unless #course.syllabus
#syllabus = #course.build_syllabus
end
views/courses/show.html.erb
# Show the syllabus name if there is one, or show the form to create a new one
<% if #course.syllabus.name %>
<p>Syllabus: <%= #course.syllabus.name %></p>
<% else %>
<p>Create Syllabus:</p>
<%= form_for([#course, #syllabus]) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<% end %>
syllabuses_controller.rb
def create
#course = Course.find(params[:course_id])
# Build new syllabus object based on form input
#syllabus = #course.build_syllabus(params[:syllabus])
if #syllabus.save
# redirect to /course/:id
redirect_to #course, notice: 'Syllabus was successfully created.' }
end
end
course.rb
class Course < ActiveRecord::Base
attr_accessible :name
has_one :syllabus
end
syllabus.rb
class Syllabus < ActiveRecord::Base
belongs_to :course
attr_accessible :name, :course_id
end
Some things that I left out but you should still include:
validations
rerendering form if something goes wrong
pulling things out into partials
fixing bad code like if #course.syllabus.name
pull out if/else logic into a helper
…
I am building an app with voting (a post has many votes, a user has many votes). It was working when I didn't limit the number of votes per user, but after adding a validation, it gets the following error when I try to vote up a post that the same user voted up previously:
>undefined method `model_name' for NilClass:Class
>Extracted source (around line #28):
>25: <% end %>
>26:
>27: <table class="posts" summary="User posts">
>28: <%= render #posts %>
>29: </table>
>Trace:
>app/views/posts/index.html.erb:28:in `_app_views_posts_index_html_erb__978098650233580665_2485618500'
>app/controllers/votes_controller.rb:23:in `create'
It works when voting for a post which the user has not voted up previously. How do I get rails to flash the error when the user has already voted for the post, but then redirect without an error? I'm sure I've just missed something obvious. The validation works when I try to add a vote through the rails console (ie, rails doesn't add the new vote to the database if that user has already voted for it). Thanks -
The related code in vote.rb:
class Vote < ActiveRecord::Base
attr_accessible :user_id, :post_id
validate :only_one_user_per_post
belongs_to :user
belongs_to :post, :counter_cache => true
private
def only_one_user_per_post
if Vote.where("user_id = ? AND post_id = ?", self.user_id, self.post_id).all.any?
errors.add(:user_id, "Can only post once per post!")
end
end
end
the create from VotesController.rb
def create
#vote = Vote.new(params[:vote])
post = params[:vote][:post_id]
uid = params[:vote][:user_id]
if #vote.save
flash[:success] = "You voted for the article"
redirect_to root_path
else
flash[:failure] = "You did not vote"
render 'posts/index'
end
relevant code from index.html.erb:
<% flash.each do |key, value| %>
<div class="flash <%= key %>"><%= value %></div>
<% end %>
<table class="posts" summary="User posts">
<%= render #posts %>
</table>
And here's the relevant snippet from _post.html.erb:
<%= form_for #vote do |f| %>
<div class="right"> <%= image_submit_tag "plus32.png", :size => "16x16", :class => "squareicon" %>
<span class="label success"><%= post.votes_count %></span>
</div>
In your controller, in the else-branch you have the following code:
else
flash[:failure] = "You did not vote"
render 'posts/index'
end
You also will need to retrieve the #posts there to alleviate the error. Or use redirect_to posts_path instead.
Hope this helps.
I have a table of venues and I'm adding offers to each venue using a nested form on the venues edit page. However, each time I add a new offer the fields_for form saves the text entered and creates a new blank form for another offer record to be added.
I just want the one 'add new offer' form not one for each record added.
no offers added - this is fine:
one offer added - now theres 2 'add new offer' forms and an unwanted blank offer partial:
This is what I want it look like after adding one offer:
The number of new blank offer forms and blank partials changes with the number being built in the controller (at the minute its 1)
venues controller
class VenuesController < ApplicationController
def edit
#venue = Venue.find(params[:id])
1.times { #venue.offers.build }
end
def update
#venue = Venue.find(params[:id])
if #venue.update_attributes(params[:venue])
flash[:notice] = 'Venue updated successfully'
redirect_to :back
end
end
end
venues model
class Venue < ActiveRecord::Base
has_many :offers
accepts_nested_attributes_for :offers
end
venues edit.html.erb
<%= form_for #venue do |f| %>
<h2 class="venue_show_orange">Offers</h2>
<div class="edit_venue_details">
<% if #venue.offers.count.zero? %>
<div class="no_offers">
No offers added yet.
</div>
<% else %>
<%= render :partial => 'offers/offer', :collection => #venue.offers %>
<% end %>
<div class="clearall"></div>
<h2 class="edit_venue_sub_header">Add a new offer</h2>
<%= f.fields_for :offers do |offer| %>
<p class="edit_venue">title: <br>
<%= offer.text_field :title, :class => "edit_venue_input" %></p>
<% end %>
</div>
<button class="submit_button" type="submit"> Save changes</button>
<% end %>
So how can I have just the one add new offer form on the venues edit page, which lets me add a new offer then blanks the form so it can be used again? Also, is there any way to prevent the blank offer partials being created?
Thanks very much for any help its much appreciated!
class VenuesController < ApplicationController
def edit
#venue = Venue.find(params[:id])
end
...
end
venues edit.html.erb
<%= f.fields_for :offers, #venue.offers.build do |offer| %>
<p class="edit_venue">title: <br>
<%= offer.text_field :title, :class => "edit_venue_input" %></p>
<% end %>
I'm not sure if this will work, but have you tried the following?
<%= f.fields_for #venue.offers.last do |offer| %>
I think the problem is that you pass it the symbol :offers, which cause fields for to create fields for all the offers, but you should be able to pass only a specific object to the fields_for method as well.