Rails adding method, action to controller? - ruby-on-rails

Rails... pretty hard to learn from 0
Im making project about autosop.
1 user makes advertisement, sets, where he is going, and other users can join him.
I have problem adding action, since i just dont know how to make it.
I have made already authorization, autentification.
Where things get tricky - i have 2 scaffolds - Advertisement (user fills form with data). And AdvertisementCommitment(dont even need scaffold imho, but.. ok). In Database - it is user_id and advertisement_id.
At the moment, User can make advertisement.
If i go to /advertisements index page, i get all advertisements listed nicely. I want to add a link to each advertisement - to commit.
Question - where and what i need to do, to make this action work ? How to pass that advertisement to advertisement_commitment ?
SOLVED
<%= link_to "Join", { :controller => 'advertisement_commitments',
:user_id => current_user.id, :advertisement_id => advertisement.id},
:method => :post %>
maybe it will be useful for someone :)

have a look at http://ruby.railstutorial.org/
You will then have a better idea of how Rails works, and how you can get Rails to do what you want...

Related

link_to 'new' action in a different controller?

I want to have a link at the bottom of my show.html.erb that links to the new action in a different controller.
class Sample < ActiveRecord::Base
belongs_to :song
end
class Song < ActiveRecord::Base
has_many :samples
end
So, at the bottom of the show action for songs, I want to link to new for samples. This seems pretty easy, but I'm struggling to figure this out. I would also like to pass the id from the song to the form as :song_id
Fiddy, because you're new, let me explain how this works...
Routes
Your problem is that you don't understand the Rails routing structure - I'll hopefully explain it for you.
Rails, since it's an MVC framework, builds a series of "routes" for you. These "routes" are stored in the file available at config/routes.rb.
Routes, as described by the Rails documentation are as follows:
The Rails router recognizes URLs and dispatches them to a controller's
action. It can also generate paths and URLs, avoiding the need to
hardcode strings in your views.
The most important thing you should consider here is the way the routes generate paths for you. These paths are simply Rails "helper" methods, which you can call from your views. The reason these exist is two-fold -
They provide you with a DRY (don't repeat yourself) way of accessing / manipulating data
They are constructed around objects, helping maintain the object-orientated nature of Rails
These will likely mean nothing to you. However, what you need to realize that if set up your routes correctly, it seriously helps your app's infrastructure immensely.
--
Rails
This leads us quite nicely onto appreciating the way in which Rails works
Rails is an MVC (model view controller) framework. This might seem somewhat trivial, but in reality, it's one of the most important aspects to learn about Rails development, and here's why:
The Rails software system works by taking "requests" (user input) and then routing them to specific controller#actions. Those controllers then build model data from the database, and will translate that into either variables or objects, which you can use in your view.
The reason I mention this is that this type of development takes a lot of getting used-to, in that your program's flow is not about logic / functionality, but the accessibility of data. Therefore, when you ask about the routes or other parts of your app, you need to firstly remember what data you wish to show, and also how you want that data to be shown - this will give you the ability to construct & use the routes / controller actions which will get it to work properly
--
Fix
In terms of what you're saying, the way you'd go about achieving the result you want will be to use a nested route:
#config/routes.rb
resources :songs do
resources :samples #-> domain.com/songs/:song_id/samples/new
end
This will create a new route for you (which you can check by firing rake routes in your rails c (console). This will give you a path to use for your samples#new action:
#app/views/songs/show.html.erb
<%= link_to #song.name, new_song_sample_path(#song) %>
The above link will take you to the samples#show action, which you'll be able to populate with as much data as you require from the samples controller. The important thing to note is this action will have params[:song_id] available for you to either build an object from, or otherwise
<%= link_to "New Sample", new_sample_path(:song_id => #song_id) %>
Where #song_id is the variable that has that id in it.
Set paths in link_to tag which you can get by running rake_routes in terminal.
Ex
link_to "New song", new_sample_path(#song)
In the example given above #song is the instance variable of your current page.
You can also get some idea from here:
link_to Base URL Randomly Changed
Song Model:
accepts_nested_attributes_for :sample, allow_destroy: true
Route:
resources :songs do
resources :samples
end
Song's Show file:
<%= link_to "New Sample", new_song_sample_path(#song) %>
in url it will be:
/songs/:song_id/sample/new
Try this and let me know it works or not... I hope this helps you

Use multiple checkboxes to change one field - rails controller change params

I've got articles that can be shown in lots of different sites. They can either be visible or not.
I've ended up going for a single bitmasked permission field in the article, rather than lots of has_many permissions separate records.
I'm not sure how best to set this field. What I've done so far is write two methods in the article model - one gives you a hash of {1 => 'true', 2 => 'true', 3 => 'false'} - visible or not on site 1, 2, 3. The second method takes a similar hash and sets the permission field correctly.
I can send the permission hash to my view through the controller, and I can make checkboxes that show if the article is visible or not. These appear on a pop up dialog using jquery. I haven't done it yet, but I think I can use javascript to make a hash to send back.
But I don't know how to make the update controller take the hash from the params, send it to my make permission method and then put that into the params again to update my article.
How would I go about doing this? Or am I barking up the wrong tree entirely.
Any ideas?
I would suggest you to create a Site model which reproduces the different sites. This is especially a good thing if there might come up more websites! Then you could build a has_and_belongs_to_many association between the Site and the Article model to commit on which site an article should be displayed!

Braintree "shopping cart"-like implementation in rails app / finding previous params[:id]?

I'm trying to integrate Braintree into my rails app which already has a deposits controller, model, and view. Right now basically you can specify an amount but I have its status set to "Pending". I would like it so that the user can make such a deposit but then pay for it at any time using Braintree (ala shopping cart). Would I have to create another controller and/or model to do this? (For example all the Braintree examples I've seen want the payment immediately).
Specifically, I've been trying to just work with the 'deposits' I already have. I put the form for the user's name, credit card info, etc. on the deposits "show" page and a confirm button. This seems to work fine if all fields satisfy validation, however it doesn't when there is an error and renders the show page again.
In DepositsController.rb:
def confirm
#deposit = Deposit.find(params[:id])
#result = Braintree::TransparentRedirect.confirm(request.query_string)
if #result.success?
render :action => "confirm"
else
render :action => "show"
end
end
The problem is that :id now is the Braintree transaction ID, rather than the deposits id (primary key). So of course Deposit.find(params[:id]) can't be found.
What is the best way to implement this? Should I store the previous id somehow or get it another way? Should I be using another controller? Thanks!
Short answer is you should be using a Cart model, connected to this Deposit model from what i can gather here. Based on other questions, however, that feeling could change.
So, solely based on what you wrote above:
If we follow a RESTful approach, you should be creating a Deposit#new for all new deposits.
In your Deposit#create, you would then put all of your logic into the deposit.rb model file. this logic includes, going to Braintree and such.
You say you are working with the deposits you already have, in that case, they should be handled in the Deposit#edit method.
Further questions I would ask of you in this regard, are you using ActiveMerchant? If not, why not?

custom action for a nested resource without adding to routes

This is probably really simple but I have a nested resource lets say:
map. resources :book, :has_many => :pages
I write an action called "turn" that increases page.count by 1. How do I call this action using a link_to? Thanks a lot in advance.
It's hard to tell where your page.count comes in. In Railish, you would find pages.count (note the 's'). Further, count (and also size) is a read-only attribute on arrays and hashes et.al. provided by ruby that returns the number of elements. You don't set count.
Next, I'm not sure where your turn action is supposed to live, on the Book or the Page? And what is supposed to happen after it does what it does? Finally, a route is what makes an action an action -- without it, it's just a function.
For a moment, we'll assume you are trying to store the number of times a Page in a Book has been visited. It would be a better idea to have an instance variable called reads or times_viewed etc. in your Page model. Assuming your Book model is using restful routing, in Book's show action, you create an instance variable of the Page model being viewed and increment its reads attribute before rendering the view.
If you are trying to make a link sort of how 'Like' works in Facebook, meaning you want to update a record in a table without sending the user to a different page, you'll need to use link_to_remote* and some javascript. In that case, I'd just refer you to the Railscasts on that subject.
*I think as of Rails 3, link_to_remote became just link_to with :remote => true.

How do controller actions know which REST operation to perform?

When I'm at /profile/new, for example, and I submit a form to create a profile, Rails knows to perform a POST operation; and when I update that profile from /profile/edit/1, Rails knows to perform a PUT operation... My question is, how does it know to do that?
I can't understand how this works past the controller. What exactly is going on in the background? I've dug around a little bit and I know ActiveRecord and ActiveResource? are involved, but I'd like to know the details. I've only been around since Rails 2.2 and every resource I find seems to teach by example. I'm interested in understanding how things work at a lower level, but there's nothing to guide me through learning by reading apis & source code.
You know how a view page of new page or edit page in a user's scaffold looks right?
form_for(#user) # something like that
So this is a helper method which you can find inside action_view/helper .. file
Basically the form rendering for new and edit will be decided by this form_for method, what this form_for method will do is (I just made some bullet points)
1) It will check what type of input you gave in your form_for
(check api for different ways of using form_for helper)
2) It will decide the the html options based on the below code
if object.respond_to?(:new_record?) && object.new_record?
{ :class => dom_class(object, :new), :id => dom_id(object), :method => :post } # for new
else
{ :class => dom_class(object, :edit), :id => dom_id(object, :edit), :method => :put } # for edit
end
3) It will do one more thing for edit page it will add a hidden field which will have user's id value in it.
Please let me know if you need some more details. I will update my answer accordingly.
The best I can tell, it relies completely on what action you're performing in the controller. For instance, #object.new would be a POST action, where-as #object.find([:params]) would be a GET action, based upon RESTful practice.
I could be off-base, as I'm in the same boat as you but that's my interpretation of it.

Resources